Fix: Vulkan: Memory allocation on no-rebar capable platforms

Memory areas was requested to be preferable host visible. On some
platforms this would fail to allocate. Best is to not add preferable
host visible for typically large allocations.

This PR also gives the caller the responsibility to set the allocation flags.

Pull Request: https://projects.blender.org/blender/blender/pulls/133528
This commit is contained in:
Jeroen Bakker
2025-01-24 11:54:59 +01:00
parent b11316fa3f
commit 2feb435780
11 changed files with 29 additions and 42 deletions

View File

@@ -24,27 +24,11 @@ bool VKBuffer::is_allocated() const
return allocation_ != VK_NULL_HANDLE;
}
static VmaAllocationCreateFlags vma_allocation_flags(GPUUsageType usage)
{
switch (usage) {
case GPU_USAGE_STATIC:
case GPU_USAGE_DEVICE_ONLY:
return 0;
case GPU_USAGE_DYNAMIC:
case GPU_USAGE_STREAM:
return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
case GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY:
break;
}
BLI_assert_msg(false, "Unimplemented GPUUsageType");
return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
}
bool VKBuffer::create(size_t size_in_bytes,
GPUUsageType usage,
VkBufferUsageFlags buffer_usage,
VkMemoryPropertyFlags required_flags,
VkMemoryPropertyFlags preferred_flags)
VkMemoryPropertyFlags preferred_flags,
VmaAllocationCreateFlags allocation_flags)
{
BLI_assert(!is_allocated());
BLI_assert(vk_buffer_ == VK_NULL_HANDLE);
@@ -71,7 +55,7 @@ bool VKBuffer::create(size_t size_in_bytes,
create_info.pQueueFamilyIndices = queue_family_indices;
VmaAllocationCreateInfo vma_create_info = {};
vma_create_info.flags = vma_allocation_flags(usage);
vma_create_info.flags = allocation_flags;
vma_create_info.priority = 1.0f;
vma_create_info.requiredFlags = required_flags;
vma_create_info.preferredFlags = preferred_flags;

View File

@@ -40,10 +40,10 @@ class VKBuffer : public NonCopyable {
* Allocate the buffer.
*/
bool create(size_t size,
GPUUsageType usage,
VkBufferUsageFlags buffer_usage,
VkMemoryPropertyFlags required_flags,
VkMemoryPropertyFlags preferred_flags);
VkMemoryPropertyFlags preferred_flags,
VmaAllocationCreateFlags vma_allocation_flags);
void clear(VKContext &context, uint32_t clear_value);
void update_immediately(const void *data) const;

View File

@@ -198,10 +198,10 @@ void VKDevice::init_memory_allocator()
void VKDevice::init_dummy_buffer()
{
dummy_buffer.create(sizeof(float4x4),
GPU_USAGE_DEVICE_ONLY,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkMemoryPropertyFlags(0),
VmaAllocationCreateFlags(0));
debug::object_label(dummy_buffer.vk_handle(), "DummyBuffer");
/* Default dummy buffer. Set the 4th element to 1 to fix missing orcos. */
float data[16] = {

View File

@@ -167,11 +167,12 @@ VKBuffer &VKImmediate::ensure_space(VkDeviceSize bytes_needed, VkDeviceSize offs
active_buffers_.append(std::make_unique<VKBuffer>());
VKBuffer &result = *active_buffers_.last();
result.create(alloc_size,
GPU_USAGE_DYNAMIC,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_ALLOCATION_CREATE_MAPPED_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
debug::object_label(result.vk_handle(), "Immediate");
return result;

View File

@@ -80,13 +80,12 @@ void VKIndexBuffer::strip_restart_indices()
void VKIndexBuffer::allocate()
{
GPUUsageType usage = data_ == nullptr ? GPU_USAGE_DEVICE_ONLY : GPU_USAGE_STATIC;
buffer_.create(size_get(),
usage,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkMemoryPropertyFlags(0),
VmaAllocationCreateFlags(0));
debug::object_label(buffer_.vk_handle(), "IndexBuffer");
}

View File

@@ -15,10 +15,10 @@ namespace blender::gpu {
VKPixelBuffer::VKPixelBuffer(size_t size) : PixelBuffer(size)
{
buffer_.create(size,
GPU_USAGE_STATIC,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VmaAllocationCreateFlags(0));
debug::object_label(buffer_.vk_handle(), "PixelBuffer");
}

View File

@@ -24,10 +24,11 @@ VKStagingBuffer::VKStagingBuffer(const VKBuffer &device_buffer, Direction direct
}
host_buffer_.create(device_buffer.size_in_bytes(),
GPU_USAGE_STREAM,
usage,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_ALLOCATION_CREATE_MAPPED_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
debug::object_label(host_buffer_.vk_handle(), "StagingBuffer");
}

View File

@@ -43,10 +43,11 @@ void VKStorageBuffer::allocate()
VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT;
buffer_.create(size_in_bytes_,
usage_,
buffer_usage_flags,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkMemoryPropertyFlags(0),
VmaAllocationCreateFlags(0));
BLI_assert(buffer_.is_allocated());
debug::object_label(buffer_.vk_handle(), name_);
}

View File

@@ -195,10 +195,10 @@ void VKTexture::read_sub(
VKBuffer staging_buffer;
size_t device_memory_size = sample_len * to_bytesize(device_format_);
staging_buffer.create(device_memory_size,
GPU_USAGE_DYNAMIC,
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_ALLOCATION_CREATE_MAPPED_BIT);
render_graph::VKCopyImageToBufferNode::CreateInfo copy_image_to_buffer = {};
render_graph::VKCopyImageToBufferNode::Data &node_data = copy_image_to_buffer.node_data;
@@ -311,10 +311,11 @@ void VKTexture::update_sub(int mip,
VkBuffer vk_buffer = VK_NULL_HANDLE;
if (data) {
staging_buffer.create(device_memory_size,
GPU_USAGE_DYNAMIC,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_ALLOCATION_CREATE_MAPPED_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
vk_buffer = staging_buffer.vk_handle();
/* Rows are sequentially stored, when unpack row length is 0, or equal to the extent width. In
* other cases we unpack the rows to reduce the size of the staging buffer and data transfer.

View File

@@ -33,11 +33,11 @@ void VKUniformBuffer::update(const void *data)
void VKUniformBuffer::allocate()
{
buffer_.create(size_in_bytes_,
GPU_USAGE_STATIC,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VmaAllocationCreateFlags(0));
debug::object_label(buffer_.vk_handle(), name_);
}

View File

@@ -192,10 +192,10 @@ void VKVertexBuffer::allocate()
VK_BUFFER_USAGE_TRANSFER_DST_BIT;
buffer_.create(size_alloc_get(),
GPU_USAGE_STATIC,
vk_buffer_usage,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VmaAllocationCreateFlags(0));
debug::object_label(buffer_.vk_handle(), "VertexBuffer");
}