1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-09 12:50:35 +00:00

Merge pull request #102830 from clayjohn/vma-memory-fix

Restore using VMA to create buffers and images
This commit is contained in:
Rémi Verschelde
2025-02-17 09:47:47 +01:00

View File

@@ -1522,6 +1522,9 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie
create_info.usage = p_usage; create_info.usage = p_usage;
create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaMemoryUsage vma_usage = VMA_MEMORY_USAGE_UNKNOWN;
uint32_t vma_flags_to_remove = 0;
VmaAllocationCreateInfo alloc_create_info = {}; VmaAllocationCreateInfo alloc_create_info = {};
switch (p_allocation_type) { switch (p_allocation_type) {
case MEMORY_ALLOCATION_TYPE_CPU: { case MEMORY_ALLOCATION_TYPE_CPU: {
@@ -1531,15 +1534,19 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie
// Looks like a staging buffer: CPU maps, writes sequentially, then GPU copies to VRAM. // Looks like a staging buffer: CPU maps, writes sequentially, then GPU copies to VRAM.
alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
vma_flags_to_remove |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
} }
if (is_dst && !is_src) { if (is_dst && !is_src) {
// Looks like a readback buffer: GPU copies from VRAM, then CPU maps and reads. // Looks like a readback buffer: GPU copies from VRAM, then CPU maps and reads.
alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; alloc_create_info.preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
vma_flags_to_remove |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
} }
vma_usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST;
alloc_create_info.requiredFlags = (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); alloc_create_info.requiredFlags = (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
} break; } break;
case MEMORY_ALLOCATION_TYPE_GPU: { case MEMORY_ALLOCATION_TYPE_GPU: {
vma_usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
if (p_size <= SMALL_ALLOCATION_MAX_SIZE) { if (p_size <= SMALL_ALLOCATION_MAX_SIZE) {
uint32_t mem_type_index = 0; uint32_t mem_type_index = 0;
@@ -1553,12 +1560,19 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie
VmaAllocation allocation = nullptr; VmaAllocation allocation = nullptr;
VmaAllocationInfo alloc_info = {}; VmaAllocationInfo alloc_info = {};
VkResult err = vkCreateBuffer(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER), &vk_buffer); if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {
ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); alloc_create_info.preferredFlags &= ~vma_flags_to_remove;
err = vmaAllocateMemoryForBuffer(allocator, vk_buffer, &alloc_create_info, &allocation, &alloc_info); alloc_create_info.usage = vma_usage;
ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't allocate memory for buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); VkResult err = vmaCreateBuffer(allocator, &create_info, &alloc_create_info, &vk_buffer, &allocation, &alloc_info);
err = vmaBindBufferMemory2(allocator, allocation, 0, vk_buffer, nullptr); ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");
ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't bind memory to buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); } else {
VkResult err = vkCreateBuffer(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER), &vk_buffer);
ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");
err = vmaAllocateMemoryForBuffer(allocator, vk_buffer, &alloc_create_info, &allocation, &alloc_info);
ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't allocate memory for buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");
err = vmaBindBufferMemory2(allocator, allocation, 0, vk_buffer, nullptr);
ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't bind memory to buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");
}
// Bookkeep. // Bookkeep.
BufferInfo *buf_info = VersatileResource::allocate<BufferInfo>(resources_allocator); BufferInfo *buf_info = VersatileResource::allocate<BufferInfo>(resources_allocator);
@@ -1593,8 +1607,12 @@ void RenderingDeviceDriverVulkan::buffer_free(BufferID p_buffer) {
vkDestroyBufferView(vk_device, buf_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER_VIEW)); vkDestroyBufferView(vk_device, buf_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER_VIEW));
} }
vkDestroyBuffer(vk_device, buf_info->vk_buffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER)); if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {
vmaFreeMemory(allocator, buf_info->allocation.handle); vmaDestroyBuffer(allocator, buf_info->vk_buffer, buf_info->allocation.handle);
} else {
vkDestroyBuffer(vk_device, buf_info->vk_buffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER));
vmaFreeMemory(allocator, buf_info->allocation.handle);
}
VersatileResource::free(resources_allocator, buf_info); VersatileResource::free(resources_allocator, buf_info);
} }
@@ -1808,12 +1826,18 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &
VmaAllocation allocation = nullptr; VmaAllocation allocation = nullptr;
VmaAllocationInfo alloc_info = {}; VmaAllocationInfo alloc_info = {};
VkResult err = vkCreateImage(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE), &vk_image); if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {
ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImage failed with error " + itos(err) + "."); alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
err = vmaAllocateMemoryForImage(allocator, vk_image, &alloc_create_info, &allocation, &alloc_info); VkResult err = vmaCreateImage(allocator, &create_info, &alloc_create_info, &vk_image, &allocation, &alloc_info);
ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't allocate memory for image, error: " + itos(err) + "."); ERR_FAIL_COND_V_MSG(err, TextureID(), "vmaCreateImage failed with error " + itos(err) + ".");
err = vmaBindImageMemory2(allocator, allocation, 0, vk_image, nullptr); } else {
ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't bind memory to image, error: " + itos(err) + "."); VkResult err = vkCreateImage(vk_device, &create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE), &vk_image);
ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImage failed with error " + itos(err) + ".");
err = vmaAllocateMemoryForImage(allocator, vk_image, &alloc_create_info, &allocation, &alloc_info);
ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't allocate memory for image, error: " + itos(err) + ".");
err = vmaBindImageMemory2(allocator, allocation, 0, vk_image, nullptr);
ERR_FAIL_COND_V_MSG(err, TextureID(), "Can't bind memory to image, error: " + itos(err) + ".");
}
// Create view. // Create view.
@@ -1845,10 +1869,15 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &
} }
VkImageView vk_image_view = VK_NULL_HANDLE; VkImageView vk_image_view = VK_NULL_HANDLE;
err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view); VkResult err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view);
if (err) { if (err) {
vkDestroyImage(vk_device, vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE)); if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {
vmaFreeMemory(allocator, allocation); vmaDestroyImage(allocator, vk_image, allocation);
} else {
vkDestroyImage(vk_device, vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE));
vmaFreeMemory(allocator, allocation);
}
ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + "."); ERR_FAIL_COND_V_MSG(err, TextureID(), "vkCreateImageView failed with error " + itos(err) + ".");
} }
@@ -2023,8 +2052,12 @@ void RenderingDeviceDriverVulkan::texture_free(TextureID p_texture) {
TextureInfo *tex_info = (TextureInfo *)p_texture.id; TextureInfo *tex_info = (TextureInfo *)p_texture.id;
vkDestroyImageView(vk_device, tex_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW)); vkDestroyImageView(vk_device, tex_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW));
if (tex_info->allocation.handle) { if (tex_info->allocation.handle) {
vkDestroyImage(vk_device, tex_info->vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER)); if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) {
vmaFreeMemory(allocator, tex_info->allocation.handle); vmaDestroyImage(allocator, tex_info->vk_view_create_info.image, tex_info->allocation.handle);
} else {
vkDestroyImage(vk_device, tex_info->vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER));
vmaFreeMemory(allocator, tex_info->allocation.handle);
}
} }
VersatileResource::free(resources_allocator, tex_info); VersatileResource::free(resources_allocator, tex_info);
} }