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()
{
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
// ----------------------------------------------------------------------------

View File

@ -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
// ----------------------------------------------------------------------------

View File

@ -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, &copy_region);
m_host_buffer[cur_frame], m_local_buffer[cur_local_frame], 1,
&copy_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
}

View File

@ -10,42 +10,31 @@
namespace GE
{
enum GEVulkanDynamicBufferType : unsigned
{
GVDBT_GPU_RAM,
GVDBT_SYSTEM_RAM
};
class GEVulkanDynamicBuffer
{
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;
VmaAllocation* m_staging_memory;
void** m_mapped_addr;
std::vector<void*> 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<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
}