diff --git a/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp b/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp index c6be51276..771169eed 100644 --- a/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp @@ -248,9 +248,9 @@ void GEVulkan2dRenderer::createGraphicsPipeline() // ---------------------------------------------------------------------------- void GEVulkan2dRenderer::createTrisBuffers() { - g_tris_buffer = new GEVulkanDynamicBuffer(GVDBT_SYSTEM_RAM, + g_tris_buffer = new GEVulkanDynamicBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - 12000); + 12000, GEVulkanDriver::getMaxFrameInFlight(), 0); } // createTrisBuffers // ---------------------------------------------------------------------------- diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp index 81273b44a..d243498b4 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp @@ -1024,12 +1024,15 @@ void GEVulkanDrawCall::createVulkanData() flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; extra_size = 200 * sizeof(VkDrawIndexedIndirectCommand); } - m_dynamic_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM, flags, - extra_size + sizeof(GEVulkanCameraUBO)); + m_dynamic_data = new GEVulkanDynamicBuffer(flags, + extra_size + sizeof(GEVulkanCameraUBO), + GEVulkanDriver::getMaxFrameInFlight(), + GEVulkanDriver::getMaxFrameInFlight()); flags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - m_sbo_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM, flags, - getInitialSBOSize()); + m_sbo_data = new GEVulkanDynamicBuffer(flags, getInitialSBOSize(), + GEVulkanDriver::getMaxFrameInFlight(), + GEVulkanDriver::getMaxFrameInFlight()); } // createVulkanData // ---------------------------------------------------------------------------- diff --git a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp index 9b0fd75e9..8c3611f80 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp @@ -11,56 +11,37 @@ namespace GE { int GEVulkanDynamicBuffer::m_supports_host_transfer = -1; // ---------------------------------------------------------------------------- -GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t, - VkBufferUsageFlags usage, - size_t initial_size) +GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(VkBufferUsageFlags usage, + size_t initial_size, + unsigned host_buffer_size, + unsigned local_buffer_size) { - m_type = t; m_usage = usage; m_size = m_real_size = initial_size; - m_buffer = new VkBuffer[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 VmaAllocation[GEVulkanDriver::getMaxFrameInFlight()]; - } - else - { - m_staging_buffer = NULL; - m_staging_memory = NULL; - } + m_host_buffer.resize(host_buffer_size, VK_NULL_HANDLE); + m_host_memory.resize(host_buffer_size, VK_NULL_HANDLE); + m_mapped_addr.resize(host_buffer_size, VK_NULL_HANDLE); - for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++) - initPerFrame(i); + m_local_buffer.resize(local_buffer_size, VK_NULL_HANDLE); + m_local_memory.resize(local_buffer_size, VK_NULL_HANDLE); + + for (unsigned i = 0; i < m_host_buffer.size(); i++) + initHostBuffer(i, m_local_buffer.size() == 0); + for (unsigned i = 0; i < m_local_buffer.size(); i++) + initLocalBuffer(i); } // GEVulkanDynamicBuffer // ---------------------------------------------------------------------------- GEVulkanDynamicBuffer::~GEVulkanDynamicBuffer() { destroy(); - delete [] m_buffer; - delete [] m_memory; - delete [] m_staging_buffer; - delete [] m_staging_memory; - delete [] m_mapped_addr; } // ~GEVulkanDynamicBuffer // ---------------------------------------------------------------------------- -void GEVulkanDynamicBuffer::initPerFrame(unsigned frame) +void GEVulkanDynamicBuffer::initHostBuffer(unsigned frame, bool with_transfer) { GEVulkanDriver* vk = getVKDriver(); - m_buffer[frame] = VK_NULL_HANDLE; - m_memory[frame] = VK_NULL_HANDLE; - m_mapped_addr[frame] = NULL; - if (m_type == GVDBT_GPU_RAM) - { - m_staging_buffer[frame] = VK_NULL_HANDLE; - m_staging_memory[frame] = VK_NULL_HANDLE; - } - start: VkMemoryPropertyFlags prop = {}; VkBuffer host_buffer = VK_NULL_HANDLE; @@ -70,8 +51,8 @@ start: 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)) + if ((with_transfer && m_supports_host_transfer == 1) || + (with_transfer && m_supports_host_transfer == -1)) { host_info.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT; @@ -84,7 +65,7 @@ start: return; } - if (m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == -1) + if (with_transfer && m_supports_host_transfer == -1) { vmaGetAllocationMemoryProperties(vk->getVmaAllocator(), host_memory, &prop); @@ -100,57 +81,54 @@ start: VmaAllocationInfo info = {}; vmaGetAllocationInfo(vk->getVmaAllocator(), host_memory, &info); - if (m_type == GVDBT_SYSTEM_RAM) - { - m_buffer[frame] = host_buffer; - m_memory[frame] = host_memory; - m_mapped_addr[frame] = info.pMappedData; - return; - } + m_host_buffer[frame] = host_buffer; + m_host_memory[frame] = host_memory; + m_mapped_addr[frame] = info.pMappedData; +} // initHostBuffer + +// ---------------------------------------------------------------------------- +void GEVulkanDynamicBuffer::initLocalBuffer(unsigned frame) +{ + GEVulkanDriver* vk = getVKDriver(); VkBuffer local_buffer = VK_NULL_HANDLE; 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)) + VkBufferUsageFlags flags = m_usage; + if (!m_host_buffer.empty()) + flags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + if (!vk->createBuffer(m_size, flags, local_info, local_buffer, + local_memory)) { - 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; - m_mapped_addr[frame] = info.pMappedData; -} // initPerFrame - -// ---------------------------------------------------------------------------- -void GEVulkanDynamicBuffer::destroyPerFrame(unsigned frame) -{ - 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) - { - 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; - } -} // destroyPerFrame + m_local_buffer[frame] = local_buffer; + m_local_memory[frame] = local_memory; +} // initLocalBuffer // ---------------------------------------------------------------------------- void GEVulkanDynamicBuffer::destroy() { - getVKDriver()->waitIdle(); - for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++) - destroyPerFrame(i); + GEVulkanDriver* vk = getVKDriver(); + vk->waitIdle(); + for (unsigned i = 0; i < m_host_buffer.size(); i++) + { + vmaDestroyBuffer(vk->getVmaAllocator(), m_host_buffer[i], + m_host_memory[i]); + m_host_buffer[i] = VK_NULL_HANDLE; + m_host_memory[i] = VK_NULL_HANDLE; + m_mapped_addr[i] = NULL; + } + for (unsigned i = 0; i < m_local_buffer.size(); i++) + { + vmaDestroyBuffer(vk->getVmaAllocator(), m_local_buffer[i], + m_local_memory[i]); + m_local_buffer[i] = VK_NULL_HANDLE; + m_local_memory[i] = VK_NULL_HANDLE; + } } // destroy // ---------------------------------------------------------------------------- @@ -159,7 +137,6 @@ void GEVulkanDynamicBuffer::setCurrentData(const std::vector< VkCommandBuffer custom_cmd) { GEVulkanDriver* vk = getVKDriver(); - const unsigned cur_frame = vk->getCurrentFrame(); size_t size = 0; for (auto& p : data) @@ -167,7 +144,11 @@ void GEVulkanDynamicBuffer::setCurrentData(const std::vector< resizeIfNeeded(size); m_real_size = size; - if (size == 0 || m_mapped_addr[cur_frame] == NULL) + unsigned cur_frame = getVKDriver()->getCurrentFrame(); + if (cur_frame >= m_mapped_addr.size()) + cur_frame = 0; + + if (size == 0 || m_mapped_addr.empty() || m_mapped_addr[cur_frame] == NULL) return; uint8_t* addr = (uint8_t*)m_mapped_addr[cur_frame]; @@ -176,15 +157,19 @@ void GEVulkanDynamicBuffer::setCurrentData(const std::vector< memcpy(addr, p.first, p.second); addr += p.second; } - vmaFlushAllocation(vk->getVmaAllocator(), m_staging_memory != NULL ? - m_staging_memory[cur_frame] : m_memory[cur_frame], 0, size); + vmaFlushAllocation(vk->getVmaAllocator(), m_host_memory[cur_frame], 0, + size); - if (m_type == GVDBT_GPU_RAM) + if (!m_local_buffer.empty()) { + unsigned cur_local_frame = getVKDriver()->getCurrentFrame(); + if (cur_local_frame >= m_local_buffer.size()) + cur_local_frame = 0; VkBufferCopy copy_region = {}; copy_region.size = size; vkCmdCopyBuffer(custom_cmd ? custom_cmd : vk->getCurrentCommandBuffer(), - m_staging_buffer[cur_frame], m_buffer[cur_frame], 1, ©_region); + m_host_buffer[cur_frame], m_local_buffer[cur_local_frame], 1, + ©_region); } } // setCurrentData @@ -195,15 +180,29 @@ void GEVulkanDynamicBuffer::resizeIfNeeded(size_t new_size) { destroy(); m_size = new_size + 100; - for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++) - initPerFrame(i); + for (unsigned i = 0; i < m_host_buffer.size(); i++) + initHostBuffer(i, m_local_buffer.size() == 0); + for (unsigned i = 0; i < m_local_buffer.size(); i++) + initLocalBuffer(i); } } // resizeIfNeeded // ---------------------------------------------------------------------------- VkBuffer GEVulkanDynamicBuffer::getCurrentBuffer() const { - return m_buffer[getVKDriver()->getCurrentFrame()]; + unsigned cur_frame = getVKDriver()->getCurrentFrame(); + if (m_local_buffer.empty()) + { + if (cur_frame >= m_host_buffer.size()) + cur_frame = 0; + return m_host_buffer[cur_frame]; + } + else + { + if (cur_frame >= m_local_buffer.size()) + cur_frame = 0; + return m_local_buffer[cur_frame]; + } } // getCurrentBuffer } diff --git a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp index 9bcd40f77..a533c4bd2 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.hpp @@ -10,42 +10,31 @@ namespace GE { -enum GEVulkanDynamicBufferType : unsigned -{ - GVDBT_GPU_RAM, - GVDBT_SYSTEM_RAM -}; - class GEVulkanDynamicBuffer { private: - VkBuffer* m_buffer; + std::vector m_host_buffer, m_local_buffer; - VmaAllocation* m_memory; + std::vector m_host_memory, m_local_memory; - VkBuffer* m_staging_buffer; - - VmaAllocation* m_staging_memory; - - void** m_mapped_addr; + std::vector m_mapped_addr; VkBufferUsageFlags m_usage; - GEVulkanDynamicBufferType m_type; - size_t m_size, m_real_size; static int m_supports_host_transfer; // ------------------------------------------------------------------------ - void initPerFrame(unsigned frame); + void initHostBuffer(unsigned frame, bool with_transfer); // ------------------------------------------------------------------------ - void destroyPerFrame(unsigned frame); + void initLocalBuffer(unsigned frame); // ------------------------------------------------------------------------ void destroy(); public: // ------------------------------------------------------------------------ - GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t, - VkBufferUsageFlags usage, size_t initial_size); + GEVulkanDynamicBuffer(VkBufferUsageFlags usage, size_t initial_size, + unsigned host_buffer_size, + unsigned local_buffer_size); // ------------------------------------------------------------------------ ~GEVulkanDynamicBuffer(); // ------------------------------------------------------------------------ @@ -61,6 +50,17 @@ public: void resizeIfNeeded(size_t new_size); // ------------------------------------------------------------------------ size_t getRealSize() const { return m_real_size; } + // ------------------------------------------------------------------------ + std::vector& getHostBuffer() { return m_host_buffer; } + // ------------------------------------------------------------------------ + std::vector& getLocalBuffer() { return m_local_buffer; } + // ------------------------------------------------------------------------ + std::vector& getHostMemory() { return m_host_memory; } + // ------------------------------------------------------------------------ + std::vector& getLocalMemory() { return m_local_memory; } + // ------------------------------------------------------------------------ + std::vector& getMappedAddr() { return m_mapped_addr; } + }; // GEVulkanDynamicBuffer }