diff --git a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp index 6b2e15505..6c780cc55 100644 --- a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp @@ -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 cb(_cbData.Get(), _cbData.Count()); ASSERT_LOW_LAYER(cb.Length() >= sizeof(ParticleMaterialShaderData)); auto materialData = reinterpret_cast(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); diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp index ac02e46d3..bfbf35f29 100644 --- a/Source/Engine/Particles/Particles.cpp +++ b/Source/Engine/Particles/Particles.cpp @@ -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