Fix GPU particles issues with missing sorting keys data when shader is not yet loaded

This commit is contained in:
Wojtek Figat
2025-09-06 23:37:24 +02:00
parent 44e70692a2
commit 576b0710e0
2 changed files with 30 additions and 2 deletions

View File

@@ -49,7 +49,6 @@ void ParticleMaterialShader::Bind(BindParameters& params)
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
auto& drawCall = *params.DrawCall;
const uint32 sortedIndicesOffset = drawCall.Particle.Module->SortedIndicesOffset;
Span<byte> cb(_cbData.Get(), _cbData.Count());
ASSERT_LOW_LAYER(cb.Length() >= sizeof(ParticleMaterialShaderData));
auto materialData = reinterpret_cast<ParticleMaterialShaderData*>(cb.Get());
@@ -103,7 +102,7 @@ void ParticleMaterialShader::Bind(BindParameters& params)
static StringView ParticleModelFacingModeOffset(TEXT("ModelFacingMode"));
materialData->WorldMatrix.SetMatrixTranspose(drawCall.World);
materialData->SortedIndicesOffset = drawCall.Particle.Particles->GPU.SortedIndices && params.RenderContext.View.Pass != DrawPass::Depth ? sortedIndicesOffset : 0xFFFFFFFF;
materialData->SortedIndicesOffset = drawCall.Particle.Particles->GPU.SortedIndices && params.RenderContext.View.Pass != DrawPass::Depth ? drawCall.Particle.Module->SortedIndicesOffset : 0xFFFFFFFF;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
materialData->ParticleStride = drawCall.Particle.Particles->Stride;
materialData->PositionOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticlePosition, ParticleAttribute::ValueTypes::Float3);

View File

@@ -970,6 +970,35 @@ void DrawEmittersGPU(RenderContextBatch& renderContextBatch)
}
}
}
else
{
// Initialize with identity sort indices in case the buffer has been allocated
for (const GPUEmitterDraw& draw : GPUEmitterDraws)
{
if (!draw.Sorting || !draw.Buffer->GPU.SortedIndices)
continue;
const int32 capacity = draw.Buffer->Capacity;
const int32 capacityBytes = capacity * draw.Buffer->GPU.SortedIndices->GetStride();
const int32 indicesBytes = draw.Buffer->GPU.SortedIndices->GetSize();
RenderListAlloc sortedIndicesAlloc;
auto* renderList = renderContextBatch.GetMainContext().List;
void* indices = sortedIndicesAlloc.Init(renderList, indicesBytes, GPU_SHADER_DATA_ALIGNMENT);
switch (draw.Buffer->GPU.SortedIndices->GetFormat())
{
case PixelFormat::R16_UInt:
for (int32 i = 0; i < capacity; i++)
((uint16*)indices)[i] = (uint16)i;
break;
case PixelFormat::R32_UInt:
for (int32 i = 0; i < capacity; i++)
((uint32*)indices)[i] = i;
break;
}
for (int32 i = 1; i < draw.Buffer->Emitter->Graph.SortModules.Count(); i++)
Platform::MemoryCopy((byte*)indices + i * capacityBytes, indices, capacityBytes);
context->UpdateBuffer(draw.Buffer->GPU.SortedIndices, indices, indicesBytes, 0);
}
}
// TODO: transition here SortedIndices into ShaderReadNonPixel and Buffer into ShaderReadGraphics to reduce barriers during particles rendering