From d93ac5ee0cba52742cdbbeebe7747bfdf844279e Mon Sep 17 00:00:00 2001 From: clayjohn Date: Thu, 13 Feb 2025 14:58:48 -0800 Subject: [PATCH] Restore using VMA to create buffers and images when we don't need to extra gpu memory tracking. VMA handles memory allocation on certain devices better than our custom VK code, so we might as well use it Co-authored-by: Matias N. Goldberg --- .../vulkan/rendering_device_driver_vulkan.cpp | 71 ++++++++++++++----- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index f46015f1fc3..9cebb01eaa3 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -1522,6 +1522,9 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie create_info.usage = p_usage; 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 = {}; switch (p_allocation_type) { 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. alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_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) { // 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.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); } break; case MEMORY_ALLOCATION_TYPE_GPU: { + vma_usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; alloc_create_info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; if (p_size <= SMALL_ALLOCATION_MAX_SIZE) { uint32_t mem_type_index = 0; @@ -1553,12 +1560,19 @@ RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitFie VmaAllocation allocation = nullptr; VmaAllocationInfo alloc_info = {}; - 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) + "."); + if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) { + alloc_create_info.preferredFlags &= ~vma_flags_to_remove; + alloc_create_info.usage = vma_usage; + VkResult err = vmaCreateBuffer(allocator, &create_info, &alloc_create_info, &vk_buffer, &allocation, &alloc_info); + ERR_FAIL_COND_V_MSG(err, BufferID(), "Can't create 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. BufferInfo *buf_info = VersatileResource::allocate(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)); } - vkDestroyBuffer(vk_device, buf_info->vk_buffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER)); - vmaFreeMemory(allocator, buf_info->allocation.handle); + if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) { + 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); } @@ -1808,12 +1826,18 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat & VmaAllocation allocation = nullptr; VmaAllocationInfo alloc_info = {}; - 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) + "."); + if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) { + alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; + VkResult err = vmaCreateImage(allocator, &create_info, &alloc_create_info, &vk_image, &allocation, &alloc_info); + ERR_FAIL_COND_V_MSG(err, TextureID(), "vmaCreateImage failed with error " + itos(err) + "."); + } else { + 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. @@ -1845,10 +1869,15 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat & } 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) { - vkDestroyImage(vk_device, vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE)); - vmaFreeMemory(allocator, allocation); + if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) { + 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) + "."); } @@ -2023,8 +2052,12 @@ void RenderingDeviceDriverVulkan::texture_free(TextureID p_texture) { TextureInfo *tex_info = (TextureInfo *)p_texture.id; vkDestroyImageView(vk_device, tex_info->vk_view, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW)); if (tex_info->allocation.handle) { - vkDestroyImage(vk_device, tex_info->vk_image, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_BUFFER)); - vmaFreeMemory(allocator, tex_info->allocation.handle); + if (!Engine::get_singleton()->is_extra_gpu_memory_tracking_enabled()) { + 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); }