Allow creating different buffer sizes in GEVulkanDynamicBuffer

This commit is contained in:
Benau 2022-10-05 11:08:52 +08:00
parent e5318d8ea9
commit 51a1396313
4 changed files with 110 additions and 108 deletions

View File

@ -248,9 +248,9 @@ void GEVulkan2dRenderer::createGraphicsPipeline()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void GEVulkan2dRenderer::createTrisBuffers() 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, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
12000); 12000, GEVulkanDriver::getMaxFrameInFlight(), 0);
} // createTrisBuffers } // createTrisBuffers
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -1024,12 +1024,15 @@ void GEVulkanDrawCall::createVulkanData()
flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
extra_size = 200 * sizeof(VkDrawIndexedIndirectCommand); extra_size = 200 * sizeof(VkDrawIndexedIndirectCommand);
} }
m_dynamic_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM, flags, m_dynamic_data = new GEVulkanDynamicBuffer(flags,
extra_size + sizeof(GEVulkanCameraUBO)); extra_size + sizeof(GEVulkanCameraUBO),
GEVulkanDriver::getMaxFrameInFlight(),
GEVulkanDriver::getMaxFrameInFlight());
flags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; flags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
m_sbo_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM, flags, m_sbo_data = new GEVulkanDynamicBuffer(flags, getInitialSBOSize(),
getInitialSBOSize()); GEVulkanDriver::getMaxFrameInFlight(),
GEVulkanDriver::getMaxFrameInFlight());
} // createVulkanData } // createVulkanData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -11,56 +11,37 @@ namespace GE
{ {
int GEVulkanDynamicBuffer::m_supports_host_transfer = -1; int GEVulkanDynamicBuffer::m_supports_host_transfer = -1;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t, GEVulkanDynamicBuffer::GEVulkanDynamicBuffer(VkBufferUsageFlags usage,
VkBufferUsageFlags usage, size_t initial_size,
size_t initial_size) unsigned host_buffer_size,
unsigned local_buffer_size)
{ {
m_type = t;
m_usage = usage; m_usage = usage;
m_size = m_real_size = initial_size; m_size = m_real_size = initial_size;
m_buffer = new VkBuffer[GEVulkanDriver::getMaxFrameInFlight()]; m_host_buffer.resize(host_buffer_size, VK_NULL_HANDLE);
m_memory = new VmaAllocation[GEVulkanDriver::getMaxFrameInFlight()]; m_host_memory.resize(host_buffer_size, VK_NULL_HANDLE);
m_mapped_addr = new void*[GEVulkanDriver::getMaxFrameInFlight()]; m_mapped_addr.resize(host_buffer_size, VK_NULL_HANDLE);
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;
}
for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++) m_local_buffer.resize(local_buffer_size, VK_NULL_HANDLE);
initPerFrame(i); 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::~GEVulkanDynamicBuffer() GEVulkanDynamicBuffer::~GEVulkanDynamicBuffer()
{ {
destroy(); destroy();
delete [] m_buffer;
delete [] m_memory;
delete [] m_staging_buffer;
delete [] m_staging_memory;
delete [] m_mapped_addr;
} // ~GEVulkanDynamicBuffer } // ~GEVulkanDynamicBuffer
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void GEVulkanDynamicBuffer::initPerFrame(unsigned frame) void GEVulkanDynamicBuffer::initHostBuffer(unsigned frame, bool with_transfer)
{ {
GEVulkanDriver* vk = getVKDriver(); 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: start:
VkMemoryPropertyFlags prop = {}; VkMemoryPropertyFlags prop = {};
VkBuffer host_buffer = VK_NULL_HANDLE; VkBuffer host_buffer = VK_NULL_HANDLE;
@ -70,8 +51,8 @@ start:
host_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | host_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT; VMA_ALLOCATION_CREATE_MAPPED_BIT;
host_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; host_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
if ((m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == 1) || if ((with_transfer && m_supports_host_transfer == 1) ||
(m_type == GVDBT_SYSTEM_RAM && m_supports_host_transfer == -1)) (with_transfer && m_supports_host_transfer == -1))
{ {
host_info.flags |= host_info.flags |=
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT; VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT;
@ -84,7 +65,7 @@ start:
return; 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, vmaGetAllocationMemoryProperties(vk->getVmaAllocator(), host_memory,
&prop); &prop);
@ -100,57 +81,54 @@ start:
VmaAllocationInfo info = {}; VmaAllocationInfo info = {};
vmaGetAllocationInfo(vk->getVmaAllocator(), host_memory, &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; VkBuffer local_buffer = VK_NULL_HANDLE;
VmaAllocation local_memory = VK_NULL_HANDLE; VmaAllocation local_memory = VK_NULL_HANDLE;
VmaAllocationCreateInfo local_info = {}; VmaAllocationCreateInfo local_info = {};
local_info.usage = VMA_MEMORY_USAGE_AUTO; local_info.usage = VMA_MEMORY_USAGE_AUTO;
if (!vk->createBuffer(m_size, m_usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VkBufferUsageFlags flags = m_usage;
local_info, local_buffer, local_memory)) 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); vmaDestroyBuffer(vk->getVmaAllocator(), local_buffer, local_memory);
return; return;
} }
m_buffer[frame] = local_buffer; m_local_buffer[frame] = local_buffer;
m_memory[frame] = local_memory; m_local_memory[frame] = local_memory;
m_staging_buffer[frame] = host_buffer; } // initLocalBuffer
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
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void GEVulkanDynamicBuffer::destroy() void GEVulkanDynamicBuffer::destroy()
{ {
getVKDriver()->waitIdle(); GEVulkanDriver* vk = getVKDriver();
for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++) vk->waitIdle();
destroyPerFrame(i); 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 } // destroy
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -159,7 +137,6 @@ void GEVulkanDynamicBuffer::setCurrentData(const std::vector<
VkCommandBuffer custom_cmd) VkCommandBuffer custom_cmd)
{ {
GEVulkanDriver* vk = getVKDriver(); GEVulkanDriver* vk = getVKDriver();
const unsigned cur_frame = vk->getCurrentFrame();
size_t size = 0; size_t size = 0;
for (auto& p : data) for (auto& p : data)
@ -167,7 +144,11 @@ void GEVulkanDynamicBuffer::setCurrentData(const std::vector<
resizeIfNeeded(size); resizeIfNeeded(size);
m_real_size = 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; return;
uint8_t* addr = (uint8_t*)m_mapped_addr[cur_frame]; 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); memcpy(addr, p.first, p.second);
addr += p.second; addr += p.second;
} }
vmaFlushAllocation(vk->getVmaAllocator(), m_staging_memory != NULL ? vmaFlushAllocation(vk->getVmaAllocator(), m_host_memory[cur_frame], 0,
m_staging_memory[cur_frame] : m_memory[cur_frame], 0, size); 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 = {}; VkBufferCopy copy_region = {};
copy_region.size = size; copy_region.size = size;
vkCmdCopyBuffer(custom_cmd ? custom_cmd : vk->getCurrentCommandBuffer(), vkCmdCopyBuffer(custom_cmd ? custom_cmd : vk->getCurrentCommandBuffer(),
m_staging_buffer[cur_frame], m_buffer[cur_frame], 1, &copy_region); m_host_buffer[cur_frame], m_local_buffer[cur_local_frame], 1,
&copy_region);
} }
} // setCurrentData } // setCurrentData
@ -195,15 +180,29 @@ void GEVulkanDynamicBuffer::resizeIfNeeded(size_t new_size)
{ {
destroy(); destroy();
m_size = new_size + 100; m_size = new_size + 100;
for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++) for (unsigned i = 0; i < m_host_buffer.size(); i++)
initPerFrame(i); initHostBuffer(i, m_local_buffer.size() == 0);
for (unsigned i = 0; i < m_local_buffer.size(); i++)
initLocalBuffer(i);
} }
} // resizeIfNeeded } // resizeIfNeeded
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
VkBuffer GEVulkanDynamicBuffer::getCurrentBuffer() const 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 } // getCurrentBuffer
} }

View File

@ -10,42 +10,31 @@
namespace GE namespace GE
{ {
enum GEVulkanDynamicBufferType : unsigned
{
GVDBT_GPU_RAM,
GVDBT_SYSTEM_RAM
};
class GEVulkanDynamicBuffer class GEVulkanDynamicBuffer
{ {
private: private:
VkBuffer* m_buffer; std::vector<VkBuffer> m_host_buffer, m_local_buffer;
VmaAllocation* m_memory; std::vector<VmaAllocation> m_host_memory, m_local_memory;
VkBuffer* m_staging_buffer; std::vector<void*> m_mapped_addr;
VmaAllocation* m_staging_memory;
void** m_mapped_addr;
VkBufferUsageFlags m_usage; VkBufferUsageFlags m_usage;
GEVulkanDynamicBufferType m_type;
size_t m_size, m_real_size; size_t m_size, m_real_size;
static int m_supports_host_transfer; 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(); void destroy();
public: public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
GEVulkanDynamicBuffer(GEVulkanDynamicBufferType t, GEVulkanDynamicBuffer(VkBufferUsageFlags usage, size_t initial_size,
VkBufferUsageFlags usage, size_t initial_size); unsigned host_buffer_size,
unsigned local_buffer_size);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
~GEVulkanDynamicBuffer(); ~GEVulkanDynamicBuffer();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -61,6 +50,17 @@ public:
void resizeIfNeeded(size_t new_size); void resizeIfNeeded(size_t new_size);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
size_t getRealSize() const { return m_real_size; } size_t getRealSize() const { return m_real_size; }
// ------------------------------------------------------------------------
std::vector<VkBuffer>& getHostBuffer() { return m_host_buffer; }
// ------------------------------------------------------------------------
std::vector<VkBuffer>& getLocalBuffer() { return m_local_buffer; }
// ------------------------------------------------------------------------
std::vector<VmaAllocation>& getHostMemory() { return m_host_memory; }
// ------------------------------------------------------------------------
std::vector<VmaAllocation>& getLocalMemory() { return m_local_memory; }
// ------------------------------------------------------------------------
std::vector<void*>& getMappedAddr() { return m_mapped_addr; }
}; // GEVulkanDynamicBuffer }; // GEVulkanDynamicBuffer
} }