mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 19:36:20 +03:00
115 lines
2.7 KiB
C++
115 lines
2.7 KiB
C++
#include "rhi.h"
|
|
|
|
namespace engine
|
|
{
|
|
DynamicUniformBuffer::DynamicUniformBuffer(VulkanContext* context, uint32_t frameNum, uint32_t initSize, uint32_t incrementSize)
|
|
: m_context(context)
|
|
, m_frameLoopNum(frameNum)
|
|
, m_totoalSize(initSize * 1024 * 1024)
|
|
, m_currentFrameID(0)
|
|
, m_usedSize(0)
|
|
, m_incrementSize(incrementSize * 1024 * 1024)
|
|
{
|
|
ASSERT(frameNum >= 1, "Frame num at least need one or bigger.");
|
|
m_alginMin = (uint32_t)m_context->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
|
|
|
|
releaseAndInit();
|
|
}
|
|
|
|
DynamicUniformBuffer::~DynamicUniformBuffer()
|
|
{
|
|
for (auto& buffer : m_buffers)
|
|
{
|
|
buffer->unmap();
|
|
}
|
|
}
|
|
|
|
void DynamicUniformBuffer::onFrameStart()
|
|
{
|
|
// Need to reset used size.
|
|
m_usedSize = 0;
|
|
|
|
// FrameID loop.
|
|
m_currentFrameID++;
|
|
if (m_currentFrameID == m_frameLoopNum)
|
|
{
|
|
m_currentFrameID = 0;
|
|
}
|
|
|
|
// Never shrink.
|
|
if (m_bShouldIncSize)
|
|
{
|
|
m_bShouldIncSize = false;
|
|
m_totoalSize += m_incrementSize;
|
|
|
|
m_context->waitDeviceIdle();
|
|
releaseAndInit();
|
|
}
|
|
}
|
|
|
|
uint32_t DynamicUniformBuffer::alloc(uint32_t size)
|
|
{
|
|
uint32_t scrOffset = m_usedSize;
|
|
|
|
// Add align size.
|
|
m_usedSize += getAlignSize(size);
|
|
|
|
// NOTE: We use max uniform buffer range set here, so need to ensure at least it never overflow.
|
|
if (m_usedSize >= (m_totoalSize - m_context->getPhysicalDeviceProperties().limits.maxUniformBufferRange))
|
|
{
|
|
LOG_TRACE("Dynamic uniform buffer overflow, will increment next time loop.");
|
|
m_bShouldIncSize = true;
|
|
|
|
// When overflow, this frame will render error, and will fix in next frame.
|
|
m_usedSize = 0;
|
|
scrOffset = 0;
|
|
}
|
|
|
|
return scrOffset;
|
|
}
|
|
|
|
void DynamicUniformBuffer::releaseAndInit()
|
|
{
|
|
for (auto& buffer : m_buffers)
|
|
{
|
|
buffer->unmap();
|
|
}
|
|
|
|
m_currentFrameID = 0;
|
|
m_usedSize = 0;
|
|
|
|
m_buffers.resize(m_frameLoopNum);
|
|
m_sets.resize(m_frameLoopNum);
|
|
m_layouts.resize(m_frameLoopNum);
|
|
|
|
for (uint32_t i = 0; i < m_frameLoopNum; i ++)
|
|
{
|
|
// Create buffer.
|
|
m_buffers[i] = std::make_unique<VulkanBuffer>(
|
|
m_context,
|
|
std::format("DynamicUniformBuffer{}", i).c_str(),
|
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
VulkanBuffer::getStageCopyForUploadBufferFlags(),
|
|
m_totoalSize,
|
|
nullptr
|
|
);
|
|
|
|
VkDescriptorBufferInfo bufInfo = {};
|
|
bufInfo.buffer = m_buffers[i]->getVkBuffer();
|
|
bufInfo.offset = 0;
|
|
bufInfo.range = m_context->getPhysicalDeviceProperties().limits.maxUniformBufferRange;
|
|
|
|
// default set to binding position zero.
|
|
m_context->descriptorFactoryBegin()
|
|
.bindBuffers(0, 1, &bufInfo, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, kCommonShaderStage)
|
|
.build(m_sets[i], m_layouts[i]);
|
|
|
|
m_buffers[i]->map();
|
|
}
|
|
}
|
|
|
|
uint32_t DynamicUniformBuffer::getAlignSize(uint32_t src) const
|
|
{
|
|
return alignUp(src, m_alginMin);
|
|
}
|
|
} |