Optimize DynamicTypedBuffer and DynamicStructuredBuffer to use GPU-memory for commonly used single-frame uploads

This commit is contained in:
Wojtek Figat
2024-07-19 14:27:50 +02:00
parent 3296337f40
commit b14ac354bb
2 changed files with 62 additions and 73 deletions

View File

@@ -22,69 +22,43 @@ DynamicBuffer::~DynamicBuffer()
SAFE_DELETE_GPU_RESOURCE(_buffer);
}
void DynamicBuffer::Flush()
{
// Check if has sth to flush
const uint32 size = Data.Count();
if (size > 0)
{
// Check if has no buffer
if (_buffer == nullptr)
_buffer = GPUDevice::Instance->CreateBuffer(_name);
// Check if need to resize buffer
if (_buffer->GetSize() < size)
{
const uint32 numElements = Math::AlignUp<uint32>(static_cast<uint32>((size / _stride) * 1.3f), 32);
GPUBufferDescription desc;
InitDesc(desc, numElements);
if (_buffer->Init(desc))
{
LOG(Fatal, "Cannot setup dynamic buffer '{0}'! Size: {1}", _name, Utilities::BytesToText(size));
return;
}
}
// Upload data to the buffer
if (GPUDevice::Instance->IsRendering())
{
RenderContext::GPULocker.Lock();
GPUDevice::Instance->GetMainContext()->UpdateBuffer(_buffer, Data.Get(), size);
RenderContext::GPULocker.Unlock();
}
else
{
_buffer->SetData(Data.Get(), size);
}
}
}
void DynamicBuffer::Flush(GPUContext* context)
{
// Check if has sth to flush
const uint32 size = Data.Count();
if (size > 0)
if (size == 0)
return;
// Lazy-resize buffer
if (_buffer == nullptr)
_buffer = GPUDevice::Instance->CreateBuffer(_name);
if (_buffer->GetSize() < size)
{
// Check if has no buffer
if (_buffer == nullptr)
_buffer = GPUDevice::Instance->CreateBuffer(_name);
// Check if need to resize buffer
if (_buffer->GetSize() < size)
const int32 numElements = Math::AlignUp<int32>(static_cast<int32>((size / _stride) * 1.3f), 32);
GPUBufferDescription desc;
InitDesc(desc, numElements);
desc.Usage = SingleFrame ? GPUResourceUsage::Default : GPUResourceUsage::Dynamic;
if (_buffer->Init(desc))
{
const uint32 numElements = Math::AlignUp<uint32>(static_cast<uint32>((size / _stride) * 1.3f), 32);
GPUBufferDescription desc;
InitDesc(desc, numElements);
if (_buffer->Init(desc))
{
LOG(Fatal, "Cannot setup dynamic buffer '{0}'! Size: {1}", _name, Utilities::BytesToText(size));
return;
}
LOG(Fatal, "Cannot setup dynamic buffer '{0}'! Size: {1}", _name, Utilities::BytesToText(size));
return;
}
}
// Upload data to the buffer
// Upload data to the buffer
if (context)
{
context->UpdateBuffer(_buffer, Data.Get(), size);
}
else if (GPUDevice::Instance->IsRendering())
{
RenderContext::GPULocker.Lock();
GPUDevice::Instance->GetMainContext()->UpdateBuffer(_buffer, Data.Get(), size);
RenderContext::GPULocker.Unlock();
}
else
{
_buffer->SetData(Data.Get(), size);
}
}
void DynamicBuffer::Dispose()
@@ -93,10 +67,26 @@ void DynamicBuffer::Dispose()
Data.Resize(0);
}
void DynamicVertexBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
{
desc = GPUBufferDescription::Vertex(_stride, numElements, GPUResourceUsage::Dynamic);
}
void DynamicIndexBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
{
desc = GPUBufferDescription::Index(_stride, numElements, GPUResourceUsage::Dynamic);
}
DynamicStructuredBuffer::DynamicStructuredBuffer(uint32 initialCapacity, uint32 stride, bool isUnorderedAccess, const String& name)
: DynamicBuffer(initialCapacity, stride, name)
, _isUnorderedAccess(isUnorderedAccess)
{
SingleFrame = true; // The most common use-case is just for a single upload of data prepared by CPU
}
void DynamicStructuredBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
{
desc = GPUBufferDescription::Structured(numElements, _stride, _isUnorderedAccess);
desc.Usage = GPUResourceUsage::Dynamic;
}
DynamicTypedBuffer::DynamicTypedBuffer(uint32 initialCapacity, PixelFormat format, bool isUnorderedAccess, const String& name)
@@ -104,6 +94,7 @@ DynamicTypedBuffer::DynamicTypedBuffer(uint32 initialCapacity, PixelFormat forma
, _format(format)
, _isUnorderedAccess(isUnorderedAccess)
{
SingleFrame = true; // The most common use-case is just for a single upload of data prepared by CPU
}
void DynamicTypedBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
@@ -111,5 +102,5 @@ void DynamicTypedBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
auto bufferFlags = GPUBufferFlags::ShaderResource;
if (_isUnorderedAccess)
bufferFlags |= GPUBufferFlags::UnorderedAccess;
desc = GPUBufferDescription::Buffer(numElements * _stride, bufferFlags, _format, nullptr, _stride, GPUResourceUsage::Dynamic);
desc = GPUBufferDescription::Buffer(numElements * _stride, bufferFlags, _format, nullptr, _stride);
}