From cf8bafaab3041ceabaeead01a72538d8a1628ff1 Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 13 Jul 2022 11:23:08 +0800 Subject: [PATCH] Use vma in GEVulkanDynamicBuffer --- .../src/ge_vulkan_dynamic_buffer.cpp | 148 +++++++----------- .../src/ge_vulkan_dynamic_buffer.hpp | 8 +- 2 files changed, 59 insertions(+), 97 deletions(-) diff --git a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp index 51a1eec43..22e4b4c24 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp @@ -9,7 +9,7 @@ namespace GE { -VkMemoryPropertyFlags GEVulkanDynamicBuffer::m_host_flag = (VkMemoryPropertyFlags)-1; +int GEVulkanDynamicBuffer::m_supports_host_transfer = -1; // ---------------------------------------------------------------------------- GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t, VkBufferUsageFlags usage, @@ -20,12 +20,12 @@ GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t, m_size = m_real_size = initial_size; m_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()]; - m_memory = new VkDeviceMemory[GEVulkanDriver::getMaxFrameInFlight()]; + m_memory = new VmaAllocation[GEVulkanDriver::getMaxFrameInFlight()]; m_mapped_addr = new void*[GEVulkanDriver::getMaxFrameInFlight()]; if (t == GVDBT_GPU_RAM) { m_staging_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()]; - m_staging_memory = new VkDeviceMemory[GEVulkanDriver::getMaxFrameInFlight()]; + m_staging_memory = new VmaAllocation[GEVulkanDriver::getMaxFrameInFlight()]; } else { @@ -51,6 +51,7 @@ GEVulkanDynamicBuffer::~GEVulkanDynamicBuffer() // ---------------------------------------------------------------------------- void GEVulkanDynamicBuffer::initPerFrame(unsigned frame) { + GEVulkanDriver* vk = getVKDriver(); m_buffer[frame] = VK_NULL_HANDLE; m_memory[frame] = VK_NULL_HANDLE; m_mapped_addr[frame] = NULL; @@ -60,128 +61,85 @@ void GEVulkanDynamicBuffer::initPerFrame(unsigned frame) m_staging_memory[frame] = VK_NULL_HANDLE; } +start: + VkMemoryPropertyFlags prop = {}; VkBuffer host_buffer = VK_NULL_HANDLE; - VkDeviceMemory host_memory = VK_NULL_HANDLE; - VkMemoryPropertyFlags host_flag = 0; - if (m_host_flag == (VkFlags)-1) + VmaAllocation host_memory = VK_NULL_HANDLE; + VmaAllocationCreateInfo host_info = {}; + host_info.usage = VMA_MEMORY_USAGE_AUTO; + host_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + host_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + if ((m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == 1) || + (m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == -1)) { - // https://zeux.io/2020/02/27/writing-an-efficient-vulkan-renderer/ - m_host_flag = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - bool better_flag_exist = false; - if (getVKDriver()->createBuffer(m_size, - m_usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, m_host_flag, - host_buffer, host_memory)) - { - better_flag_exist = true; - if (m_type == GVDBT_SYSTEM_RAM) - goto succeed; - } - - if (host_buffer != VK_NULL_HANDLE) - vkDestroyBuffer(getVKDriver()->getDevice(), host_buffer, NULL); - host_buffer = VK_NULL_HANDLE; - if (host_memory != VK_NULL_HANDLE) - vkFreeMemory(getVKDriver()->getDevice(), host_memory, NULL); - host_memory = VK_NULL_HANDLE; - - if (!better_flag_exist) - { - m_host_flag = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - } + host_info.flags |= + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT; } - host_flag = m_host_flag; - // From the above website: - // This flag should be used to store staging buffers that are used to - // populate static resources allocated with - // VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with data. - if (m_type == GVDBT_GPU_RAM) + if (!vk->createBuffer(m_size, m_usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + host_info, host_buffer, host_memory)) { - host_flag = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - } - - if (!getVKDriver()->createBuffer(m_size, - m_usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, host_flag, - host_buffer, host_memory)) - { - if (host_buffer != VK_NULL_HANDLE) - vkDestroyBuffer(getVKDriver()->getDevice(), host_buffer, NULL); - if (host_memory != VK_NULL_HANDLE) - vkFreeMemory(getVKDriver()->getDevice(), host_memory, NULL); + vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory); return; } -succeed: + if (m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == -1) + { + vmaGetAllocationMemoryProperties(vk->getVmaAllocator(), host_memory, + &prop); + if ((prop & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + m_supports_host_transfer = 0; + vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory); + goto start; + } + else + m_supports_host_transfer = 1; + } + + VmaAllocationInfo info = {}; + vmaGetAllocationInfo(vk->getVmaAllocator(), host_memory, &info); if (m_type == GVDBT_SYSTEM_RAM) { m_buffer[frame] = host_buffer; m_memory[frame] = host_memory; - - if (vkMapMemory(getVKDriver()->getDevice(), m_memory[frame], 0, m_size, - 0, &m_mapped_addr[frame]) != VK_SUCCESS) - { - destroyPerFrame(frame); - } + m_mapped_addr[frame] = info.pMappedData; return; } VkBuffer local_buffer = VK_NULL_HANDLE; - VkDeviceMemory local_memory = VK_NULL_HANDLE; - if (!getVKDriver()->createBuffer(m_size, - m_usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, local_buffer, local_memory)) + VmaAllocation local_memory = VK_NULL_HANDLE; + VmaAllocationCreateInfo local_info = {}; + local_info.usage = VMA_MEMORY_USAGE_AUTO; + + if (!vk->createBuffer(m_size, m_usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + local_info, local_buffer, local_memory)) { - if (host_buffer != VK_NULL_HANDLE) - vkDestroyBuffer(getVKDriver()->getDevice(), host_buffer, NULL); - if (host_memory != VK_NULL_HANDLE) - vkFreeMemory(getVKDriver()->getDevice(), host_memory, NULL); - if (local_buffer != VK_NULL_HANDLE) - vkDestroyBuffer(getVKDriver()->getDevice(), local_buffer, NULL); - if (local_memory != VK_NULL_HANDLE) - vkFreeMemory(getVKDriver()->getDevice(), local_memory, NULL); + vmaDestroyBuffer(vk->getVmaAllocator(), host_buffer, host_memory); + vmaDestroyBuffer(vk->getVmaAllocator(), local_buffer, local_memory); return; } m_buffer[frame] = local_buffer; m_memory[frame] = local_memory; m_staging_buffer[frame] = host_buffer; m_staging_memory[frame] = host_memory; - - if (vkMapMemory(getVKDriver()->getDevice(), m_staging_memory[frame], 0, - m_size, 0, &m_mapped_addr[frame]) != VK_SUCCESS) - { - destroyPerFrame(frame); - } + m_mapped_addr[frame] = info.pMappedData; } // initPerFrame // ---------------------------------------------------------------------------- void GEVulkanDynamicBuffer::destroyPerFrame(unsigned frame) { - if ((m_staging_memory && m_staging_memory[frame] != VK_NULL_HANDLE) || - m_memory[frame] != VK_NULL_HANDLE) - { - vkUnmapMemory(getVKDriver()->getDevice(), m_type == GVDBT_GPU_RAM ? - m_staging_memory[frame] : m_memory[frame]); - } - - if (m_memory[frame] != VK_NULL_HANDLE) - vkFreeMemory(getVKDriver()->getDevice(), m_memory[frame], NULL); - if (m_buffer[frame] != VK_NULL_HANDLE) - vkDestroyBuffer(getVKDriver()->getDevice(), m_buffer[frame], NULL); - + GEVulkanDriver* vk = getVKDriver(); + vmaDestroyBuffer(vk->getVmaAllocator(), m_buffer[frame], m_memory[frame]); m_buffer[frame] = VK_NULL_HANDLE; m_memory[frame] = VK_NULL_HANDLE; m_mapped_addr[frame] = NULL; if (m_type == GVDBT_GPU_RAM) { - if (m_staging_buffer[frame] != VK_NULL_HANDLE) - vkDestroyBuffer(getVKDriver()->getDevice(), m_staging_buffer[frame], NULL); - if (m_staging_memory[frame] != VK_NULL_HANDLE) - vkFreeMemory(getVKDriver()->getDevice(), m_staging_memory[frame], NULL); + vmaDestroyBuffer(vk->getVmaAllocator(), m_staging_buffer[frame], + m_staging_memory[frame]); m_staging_buffer[frame] = VK_NULL_HANDLE; m_staging_memory[frame] = VK_NULL_HANDLE; } @@ -198,7 +156,8 @@ void GEVulkanDynamicBuffer::destroy() // ---------------------------------------------------------------------------- void GEVulkanDynamicBuffer::setCurrentData(void* data, size_t size) { - const unsigned cur_frame = getVKDriver()->getCurrentFrame(); + GEVulkanDriver* vk = getVKDriver(); + const unsigned cur_frame = vk->getCurrentFrame(); if (size > m_size) { destroy(); @@ -210,11 +169,14 @@ void GEVulkanDynamicBuffer::setCurrentData(void* data, size_t size) if (size == 0 || m_mapped_addr[cur_frame] == NULL) return; memcpy(m_mapped_addr[cur_frame], data, size); + vmaFlushAllocation(vk->getVmaAllocator(), m_staging_memory != NULL ? + m_staging_memory[cur_frame] : m_memory[cur_frame], 0, size); + if (m_type == GVDBT_GPU_RAM) { VkBufferCopy copy_region = {}; copy_region.size = size; - vkCmdCopyBuffer(getVKDriver()->getCurrentCommandBuffer(), + vkCmdCopyBuffer(vk->getCurrentCommandBuffer(), m_staging_buffer[cur_frame], m_buffer[cur_frame], 1, ©_region); } } // setCurrentData diff --git a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp index 2dd22a9c3..91874d1f0 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp @@ -2,6 +2,7 @@ #define HEADER_GE_VULKAN_DYNAMIC_BUFFER_HPP #include "vulkan_wrapper.h" +#include "ge_vma.hpp" namespace GE { @@ -17,11 +18,11 @@ class GEVulkanDynamicBuffer private: VkBuffer* m_buffer; - VkDeviceMemory* m_memory; + VmaAllocation* m_memory; VkBuffer* m_staging_buffer; - VkDeviceMemory* m_staging_memory; + VmaAllocation* m_staging_memory; void** m_mapped_addr; @@ -29,10 +30,9 @@ private: GEVulkanDynamicBufferType m_type; - static VkMemoryPropertyFlags m_host_flag; - size_t m_size, m_real_size; + static int m_supports_host_transfer; // ------------------------------------------------------------------------ void initPerFrame(unsigned frame); // ------------------------------------------------------------------------