diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp index c33b82edf..8f0fe29ca 100644 --- a/Source/Engine/Particles/Particles.cpp +++ b/Source/Engine/Particles/Particles.cpp @@ -178,6 +178,13 @@ void Particles::OnEffectDestroy(ParticleEffect* effect) #endif } +bool EmitterUseSorting(RenderContextBatch& renderContextBatch, ParticleBuffer* buffer, DrawPass drawModes, const BoundingSphere& bounds) +{ + const RenderView& mainView = renderContextBatch.GetMainContext().View; + drawModes &= mainView.Pass; + return buffer->Emitter->Graph.SortModules.HasItems() && EnumHasAnyFlags(drawModes, DrawPass::Forward) && (mainView.IsCullingDisabled || mainView.CullingFrustum.Intersects(bounds)); +} + void DrawEmitterCPU(RenderContextBatch& renderContextBatch, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, const BoundingSphere& bounds, uint32 renderModulesIndices, int8 sortOrder) { // Skip if CPU buffer is empty @@ -187,7 +194,7 @@ void DrawEmitterCPU(RenderContextBatch& renderContextBatch, ParticleBuffer* buff auto emitter = buffer->Emitter; // Check if need to perform any particles sorting - if (emitter->Graph.SortModules.HasItems() && EnumHasAnyFlags(drawModes, DrawPass::Forward) && (buffer->CPU.Count != 0 || buffer->GPU.SortedIndices)) + if (EmitterUseSorting(renderContextBatch, buffer, drawModes, bounds) && (buffer->CPU.Count != 0 || buffer->GPU.SortedIndices)) { // Prepare sorting data if (!buffer->GPU.SortedIndices) @@ -1006,7 +1013,7 @@ void DrawEmitterGPU(RenderContextBatch& renderContextBatch, ParticleBuffer* buff } if (indirectArgsSize == 0) return; - bool sorting = buffer->Emitter->Graph.SortModules.HasItems() && renderContextBatch.GetMainContext().View.Pass != DrawPass::Depth && buffer->GPU.ParticlesCountMax != 0; + bool sorting = EmitterUseSorting(renderContextBatch, buffer, drawModes, bounds) && (buffer->GPU.ParticlesCountMax != 0 || buffer->GPU.SortedIndices); if (sorting && !buffer->GPU.SortedIndices) buffer->AllocateSortBuffer(); @@ -1016,7 +1023,7 @@ void DrawEmitterGPU(RenderContextBatch& renderContextBatch, ParticleBuffer* buff if (GPUEmitterDraws.Count() == 0) { // The first emitter schedules the drawing of all batched draws - renderContextBatch.GetMainContext().List->AddDelayedDraw([&renderContextBatch](RenderContext& renderContext) + renderContextBatch.GetMainContext().List->AddDelayedDraw([](RenderContextBatch& renderContextBatch, int32 contextIndex) { DrawEmittersGPU(renderContextBatch); }); @@ -1046,8 +1053,10 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf const RenderView& view = renderContextBatch.Contexts.Get()[i].View; const bool visible = (view.Pass & effect->DrawModes) != DrawPass::None && (view.IsCullingDisabled || view.CullingFrustum.Intersects(bounds)); if (visible) + { viewsMask |= 1ull << (uint64)i; - viewsDrawModes |= view.Pass; + viewsDrawModes |= view.Pass; + } } if (viewsMask == 0) return; diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index 136e9cf92..c3989c253 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -262,12 +262,12 @@ void RenderList::AddDelayedDraw(DelayedDraw&& func) MemPoolLocker.Unlock(); } -void RenderList::DrainDelayedDraws(RenderContext& renderContext) +void RenderList::DrainDelayedDraws(RenderContextBatch& renderContextBatch, int32 contextIndex) { if (_delayedDraws.IsEmpty()) return; for (DelayedDraw& e : _delayedDraws) - e(renderContext); + e(renderContextBatch, contextIndex); _delayedDraws.SetCapacity(0); } diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h index 202afadc9..ae02b36a9 100644 --- a/Source/Engine/Renderer/RenderList.h +++ b/Source/Engine/Renderer/RenderList.h @@ -435,9 +435,9 @@ public: /// DynamicTypedBuffer TempObjectBuffer; - typedef Function DelayedDraw; + typedef Function DelayedDraw; void AddDelayedDraw(DelayedDraw&& func); - void DrainDelayedDraws(RenderContext& renderContext); + void DrainDelayedDraws(RenderContextBatch& renderContextBatch, int32 contextIndex); /// /// Adds custom callback (eg. lambda) to invoke after scene draw calls are collected on a main thread (some async draw tasks might be active). Allows for safe usage of GPUContext for draw preparations or to perform GPU-driven drawing. diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 77bfa5305..c775b50e1 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -459,8 +459,8 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont renderContextBatch.WaitLabels.Clear(); // Perform custom post-scene drawing (eg. GPU dispatches used by VFX) - for (RenderContext& e : renderContextBatch.Contexts) - e.List->DrainDelayedDraws(e); + for (int32 i = 0; i < renderContextBatch.Contexts.Count(); i++) + renderContextBatch.Contexts[i].List->DrainDelayedDraws(renderContextBatch, i); #if USE_EDITOR GBufferPass::Instance()->OverrideDrawCalls(renderContext);