Optimize GPU particles Bitonic sort to use separate buffers for indices and keys to avoid additional buffer copy

This commit is contained in:
Wojtek Figat
2025-08-08 18:24:44 +02:00
parent 519a9c0a14
commit 854f3acd4c
9 changed files with 115 additions and 169 deletions

View File

@@ -98,7 +98,7 @@ ParticleBuffer::~ParticleBuffer()
{
SAFE_DELETE_GPU_RESOURCE(GPU.Buffer);
SAFE_DELETE_GPU_RESOURCE(GPU.BufferSecondary);
SAFE_DELETE_GPU_RESOURCE(GPU.SortingKeysBuffer);
SAFE_DELETE_GPU_RESOURCE(GPU.SortingKeys);
SAFE_DELETE_GPU_RESOURCE(GPU.SortedIndices);
SAFE_DELETE(GPU.RibbonIndexBufferDynamic);
SAFE_DELETE(GPU.RibbonVertexBufferDynamic);
@@ -161,7 +161,7 @@ bool ParticleBuffer::Init(ParticleEmitter* emitter)
bool ParticleBuffer::AllocateSortBuffer()
{
ASSERT(Emitter && GPU.SortedIndices == nullptr && GPU.SortingKeysBuffer == nullptr);
ASSERT(Emitter && GPU.SortedIndices == nullptr && GPU.SortingKeys == nullptr);
if (Emitter->Graph.SortModules.IsEmpty())
return false;
@@ -170,7 +170,7 @@ bool ParticleBuffer::AllocateSortBuffer()
case ParticlesSimulationMode::CPU:
{
const int32 sortedIndicesSize = Capacity * sizeof(uint32) * Emitter->Graph.SortModules.Count();
GPU.SortedIndices = GPUDevice::Instance->CreateBuffer(TEXT("SortedIndices"));
GPU.SortedIndices = GPUDevice::Instance->CreateBuffer(TEXT("ParticleSortedIndices"));
if (GPU.SortedIndices->Init(GPUBufferDescription::Buffer(sortedIndicesSize, GPUBufferFlags::ShaderResource, PixelFormat::R32_UInt, nullptr, sizeof(uint32), GPUResourceUsage::Dynamic)))
return true;
break;
@@ -178,12 +178,12 @@ bool ParticleBuffer::AllocateSortBuffer()
#if COMPILE_WITH_GPU_PARTICLES
case ParticlesSimulationMode::GPU:
{
const int32 sortedIndicesSize = Capacity * sizeof(uint32) * Emitter->Graph.SortModules.Count();
GPU.SortingKeysBuffer = GPUDevice::Instance->CreateBuffer(TEXT("ParticleSortingKeysBuffer"));
if (GPU.SortingKeysBuffer->Init(GPUBufferDescription::Structured(Capacity, sizeof(float) + sizeof(uint32), true)))
const int32 sortedIndicesCount = Capacity * Emitter->Graph.SortModules.Count();
GPU.SortingKeys = GPUDevice::Instance->CreateBuffer(TEXT("ParticleSortingKeys"));
if (GPU.SortingKeys->Init(GPUBufferDescription::Buffer(sortedIndicesCount * sizeof(float), GPUBufferFlags::UnorderedAccess, PixelFormat::R32_Float, nullptr, sizeof(float))))
return true;
GPU.SortedIndices = GPUDevice::Instance->CreateBuffer(TEXT("SortedIndices"));
if (GPU.SortedIndices->Init(GPUBufferDescription::Buffer(sortedIndicesSize, GPUBufferFlags::ShaderResource | GPUBufferFlags::UnorderedAccess, PixelFormat::R32_UInt, nullptr, sizeof(uint32))))
GPU.SortedIndices = GPUDevice::Instance->CreateBuffer(TEXT("ParticleSortedIndices"));
if (GPU.SortedIndices->Init(GPUBufferDescription::Buffer(sortedIndicesCount * sizeof(uint32), GPUBufferFlags::ShaderResource | GPUBufferFlags::UnorderedAccess, PixelFormat::R32_UInt, nullptr, sizeof(uint32))))
return true;
break;
}