diff --git a/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp b/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp index 94886136f..e2dc78d59 100644 --- a/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp +++ b/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp @@ -133,7 +133,6 @@ void GPUParticles::CopyParticlesCount(GPUContext* context, ParticleEmitter* emit void GPUParticles::Execute(GPUContext* context, ParticleEmitter* emitter, ParticleEffect* effect, int32 emitterIndex, ParticleEmitterInstance& data) { PROFILE_CPU_ASSET(emitter); - PROFILE_GPU("GPUParticles"); ASSERT(emitter->Graph.Version == data.Version); ASSERT(emitter->Graph.Version == data.Buffer->Version); uint32 counterDefaultValue = 0; diff --git a/Source/Engine/Particles/ParticleEffect.cpp b/Source/Engine/Particles/ParticleEffect.cpp index 4df492fe2..183438ba2 100644 --- a/Source/Engine/Particles/ParticleEffect.cpp +++ b/Source/Engine/Particles/ParticleEffect.cpp @@ -576,8 +576,21 @@ void ParticleEffect::Draw(RenderContext& renderContext) { if (renderContext.View.Pass == DrawPass::GlobalSDF || renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas) return; - _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(GetPosition(), renderContext.View.Position)); - Particles::DrawParticles(renderContext, this); + _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(GetPosition(), renderContext.View.WorldPosition)); + RenderContextBatch renderContextBatch(renderContext); + Particles::DrawParticles(renderContextBatch, this); +} + +void ParticleEffect::Draw(RenderContextBatch& renderContextBatch) +{ + Particles::DrawParticles(renderContextBatch, this); + + // Cull again against the main context (if using multiple ones) to skip caching draw distance from shadow projections + const RenderView& mainView = renderContextBatch.GetMainContext().View; + const BoundingSphere bounds(_sphere.Center - mainView.Origin, _sphere.Radius); + if (renderContextBatch.Contexts.Count() > 1 && !mainView.CullingFrustum.Intersects(bounds)) + return; + _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(bounds.Center, mainView.Position)); } #if USE_EDITOR diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h index 2964012f6..4ec06e82b 100644 --- a/Source/Engine/Particles/ParticleEffect.h +++ b/Source/Engine/Particles/ParticleEffect.h @@ -404,6 +404,7 @@ public: // [Actor] bool HasContentLoaded() const override; void Draw(RenderContext& renderContext) override; + void Draw(RenderContextBatch& renderContextBatch) override; #if USE_EDITOR void OnDebugDrawSelected() override; void OnDebugDraw() override; diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp index 71b0f2c30..d20f3cb55 100644 --- a/Source/Engine/Particles/Particles.cpp +++ b/Source/Engine/Particles/Particles.cpp @@ -178,9 +178,7 @@ void Particles::OnEffectDestroy(ParticleEffect* effect) #endif } -typedef Array> RenderModulesIndices; - -void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, ParticleEmitterInstance& emitterData, const RenderModulesIndices& renderModulesIndices, int8 sortOrder) +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 if (buffer->CPU.Count == 0) @@ -189,7 +187,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa auto emitter = buffer->Emitter; // Check if need to perform any particles sorting - if (emitter->Graph.SortModules.HasItems() && renderContext.View.Pass != DrawPass::Depth && (buffer->CPU.Count != 0 || buffer->GPU.SortedIndices)) + if (emitter->Graph.SortModules.HasItems() && EnumHasAnyFlags(drawModes, DrawPass::Forward) && (buffer->CPU.Count != 0 || buffer->GPU.SortedIndices)) { // Prepare sorting data if (!buffer->GPU.SortedIndices) @@ -210,10 +208,11 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa if (listSize < 500) { // Use fast stack allocator from RenderList - sortingKeys[0] = renderContext.List->Memory.Allocate(listSize); - sortingKeys[1] = renderContext.List->Memory.Allocate(listSize); - sortingIndices[0] = renderContext.List->Memory.Allocate(listSize); - sortingIndices[1] = renderContext.List->Memory.Allocate(listSize); + auto& memory = renderContextBatch.GetMainContext().List->Memory; + sortingKeys[0] = memory.Allocate(listSize); + sortingKeys[1] = memory.Allocate(listSize); + sortingIndices[0] = memory.Allocate(listSize); + sortingIndices[1] = memory.Allocate(listSize); } else { @@ -236,7 +235,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa const int32 positionOffset = emitter->Graph.GetPositionAttributeOffset(); if (positionOffset == -1) break; - const Matrix viewProjection = renderContext.View.ViewProjection(); + const Matrix viewProjection = renderContextBatch.GetMainContext().View.ViewProjection(); const byte* positionPtr = buffer->CPU.Buffer.Get() + positionOffset; if (emitter->SimulationSpace == ParticlesSimulationSpace::Local) { @@ -262,7 +261,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa const int32 positionOffset = emitter->Graph.GetPositionAttributeOffset(); if (positionOffset == -1) break; - const Float3 viewPosition = renderContext.View.Position; + const Float3 viewPosition = renderContextBatch.GetMainContext().View.Position; const byte* positionPtr = buffer->CPU.Buffer.Get() + positionOffset; if (emitter->SimulationSpace == ParticlesSimulationSpace::Local) { @@ -356,9 +355,10 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa auto& vertexBuffer = buffer->GPU.RibbonVertexBufferDynamic->Data; // Setup all ribbon modules - for (int32 index = 0; index < renderModulesIndices.Count(); index++) + for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.RenderModules.Count(); moduleIndex++) { - const int32 moduleIndex = renderModulesIndices[index]; + if ((renderModulesIndices & (1u << moduleIndex)) == 0) + continue; auto module = emitter->Graph.RenderModules[moduleIndex]; if (module->TypeID != 404 || ribbonModuleIndex >= PARTICLE_EMITTER_MAX_RIBBONS) continue; @@ -454,7 +454,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa // Setup ribbon data ribbonModulesSegmentCount[ribbonModuleIndex] = segmentCount; - ribbonModulesDrawIndicesCount[index] = indices; + ribbonModulesDrawIndicesCount[ribbonModuleIndex] = indices; ribbonModulesDrawIndicesPos += indices; ribbonModuleIndex++; @@ -472,9 +472,10 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa // Execute all rendering modules ribbonModuleIndex = 0; - for (int32 index = 0; index < renderModulesIndices.Count(); index++) + for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.RenderModules.Count(); moduleIndex++) { - const int32 moduleIndex = renderModulesIndices[index]; + if ((renderModulesIndices & (1u << moduleIndex)) == 0) + continue; auto module = emitter->Graph.RenderModules[moduleIndex]; drawCall.Particle.Module = module; @@ -493,7 +494,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa // Submit draw call SpriteRenderer.SetupDrawCall(drawCall); drawCall.InstanceCount = buffer->CPU.Count; - renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder); + renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, dp, staticFlags, ShadowsCastingMode::DynamicOnly, bounds, drawCall, false, sortOrder); break; } @@ -521,7 +522,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa // Submit draw call mesh.GetDrawCallGeometry(drawCall); drawCall.InstanceCount = buffer->CPU.Count; - renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder); + renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, dp, staticFlags, ShadowsCastingMode::DynamicOnly, bounds, drawCall, false, sortOrder); } break; @@ -580,7 +581,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa drawCall.Draw.StartIndex = ribbonModulesDrawIndicesStart[ribbonModuleIndex]; drawCall.Draw.IndicesCount = ribbonModulesDrawIndicesCount[ribbonModuleIndex]; drawCall.InstanceCount = 1; - renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder); + renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, dp, staticFlags, ShadowsCastingMode::DynamicOnly, bounds, drawCall, false, sortOrder); ribbonModuleIndex++; @@ -610,7 +611,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa Float3::Transform(drawCall.Particle.VolumetricFog.Position, drawCall.World, drawCall.Particle.VolumetricFog.Position); drawCall.Particle.VolumetricFog.Radius = hasRadius ? radiusData[i] : 100.0f; drawCall.Particle.VolumetricFog.ParticleIndex = i; - renderContext.List->VolumetricFogParticles.Add(drawCall); + renderContextBatch.GetMainContext().List->VolumetricFogParticles.Add(drawCall); } break; } @@ -649,7 +650,7 @@ void CleanupGPUParticlesSorting() GPUParticlesSorting = nullptr; } -void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, const RenderModulesIndices& renderModulesIndices, int8 sortOrder) +void DrawEmitterGPU(RenderContextBatch& renderContextBatch, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, const BoundingSphere& bounds, uint32 renderModulesIndices, int8 sortOrder) { if (!IsInMainThread()) { @@ -659,9 +660,9 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa // When rendering in async, delay GPU particles drawing to be in sync by moving drawing into delayed callback post scene drawing to use GPUContext safely // Move drawing into delayed callback post scene drawing to use GPUContext safely - renderContext.List->AddDelayedDraw([buffer, drawCallCopy, drawModes, staticFlags, renderModulesIndices, sortOrder](RenderContext& renderContext) + renderContextBatch.GetMainContext().List->AddDelayedDraw([&renderContextBatch, buffer, drawCallCopy, drawModes, staticFlags, bounds, renderModulesIndices, sortOrder](RenderContext& renderContext) { - DrawEmitterGPU(renderContext, buffer, *(DrawCall*)drawCallCopy, drawModes, staticFlags, renderModulesIndices, sortOrder); + DrawEmitterGPU(renderContextBatch, buffer, *(DrawCall*)drawCallCopy, drawModes, staticFlags, bounds, renderModulesIndices, sortOrder); }); return; } @@ -669,7 +670,7 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa auto emitter = buffer->Emitter; // Check if need to perform any particles sorting - if (emitter->Graph.SortModules.HasItems() && renderContext.View.Pass != DrawPass::Depth && buffer->GPU.ParticlesCountMax != 0) + if (emitter->Graph.SortModules.HasItems() && renderContextBatch.GetMainContext().View.Pass != DrawPass::Depth && buffer->GPU.ParticlesCountMax != 0) { PROFILE_GPU_CPU_NAMED("Sort Particles"); @@ -720,7 +721,7 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa permutationIndex = 0; sortAscending = false; data.PositionOffset = emitter->Graph.GetPositionAttributeOffset(); - const Matrix viewProjection = renderContext.View.ViewProjection(); + const Matrix viewProjection = renderContextBatch.GetMainContext().View.ViewProjection(); if (emitter->SimulationSpace == ParticlesSimulationSpace::Local) { Matrix matrix; @@ -738,7 +739,7 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa permutationIndex = 1; sortAscending = false; data.PositionOffset = emitter->Graph.GetPositionAttributeOffset(); - data.ViewPosition = renderContext.View.Position; + data.ViewPosition = renderContextBatch.GetMainContext().View.Position; if (emitter->SimulationSpace == ParticlesSimulationSpace::Local) { Matrix::Transpose(drawCall.World, data.PositionTransform); @@ -780,9 +781,10 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa // Count draw calls to perform during this emitter rendering int32 drawCalls = 0; - for (int32 index = 0; index < renderModulesIndices.Count(); index++) + for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.RenderModules.Count(); moduleIndex++) { - int32 moduleIndex = renderModulesIndices.Get()[index]; + if ((renderModulesIndices & (1u << moduleIndex)) == 0) + continue; auto module = emitter->Graph.RenderModules.Get()[moduleIndex]; switch (module->TypeID) { @@ -835,9 +837,10 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa // Execute all rendering modules using indirect draw arguments int32 indirectDrawCallIndex = 0; - for (int32 index = 0; index < renderModulesIndices.Count(); index++) + for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.RenderModules.Count(); moduleIndex++) { - int32 moduleIndex = renderModulesIndices.Get()[index]; + if ((renderModulesIndices & (1u << moduleIndex)) == 0) + continue; auto module = emitter->Graph.RenderModules.Get()[moduleIndex]; drawCall.Particle.Module = module; switch (module->TypeID) @@ -863,7 +866,7 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa drawCall.InstanceCount = 0; drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer; drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs); - renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder); + renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, dp, staticFlags, ShadowsCastingMode::DynamicOnly, bounds, drawCall, false, sortOrder); indirectDrawCallIndex++; break; } @@ -897,7 +900,7 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa drawCall.InstanceCount = 0; drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer; drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs); - renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder); + renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, dp, staticFlags, ShadowsCastingMode::DynamicOnly, bounds, drawCall, false, sortOrder); indirectDrawCallIndex++; } break; @@ -920,43 +923,65 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa #endif -void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effect) +void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEffect* effect) { - // Setup - auto& view = renderContext.View; - const DrawPass drawModes = view.Pass & effect->DrawModes; - if (drawModes == DrawPass::None) - return; + PROFILE_CPU(); PROFILE_MEM(Particles); + + // Drawing assumes that all views within a batch have the same Origin + const Vector3& viewOrigin = renderContextBatch.GetMainContext().View.Origin; + BoundingSphere bounds = effect->GetSphere(); + bounds.Center -= viewOrigin; + + // Cull particles against all views + uint64 viewsMask = 0; + ASSERT_LOW_LAYER(renderContextBatch.Contexts.Count() <= 64); + DrawPass viewsDrawModes = DrawPass::None; + for (int32 i = 0; i < renderContextBatch.Contexts.Count(); i++) + { + 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; + } + if (viewsMask == 0) + return; + viewsDrawModes &= effect->DrawModes; + + // Setup ConcurrentSystemLocker::ReadScope systemScope(SystemLocker); Matrix worlds[2]; - Matrix::Translation(-renderContext.View.Origin, worlds[0]); // World - renderContext.View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local + Matrix::Translation(-viewOrigin, worlds[0]); // World + renderContextBatch.GetMainContext().View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local float worldDeterminantSigns[2]; worldDeterminantSigns[0] = Math::FloatSelect(worlds[0].RotDeterminant(), 1, -1); worldDeterminantSigns[1] = Math::FloatSelect(worlds[1].RotDeterminant(), 1, -1); const StaticFlags staticFlags = effect->GetStaticFlags(); const int8 sortOrder = effect->SortOrder; - // Draw lights - for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++) + // Draw lights (only to into the main view) + if ((viewsMask & 1) == 1 && renderContextBatch.GetMainContext().View.Pass != DrawPass::Depth) { - auto& emitterData = effect->Instance.Emitters[emitterIndex]; - const auto buffer = emitterData.Buffer; - if (!buffer || (buffer->Mode == ParticlesSimulationMode::CPU && buffer->CPU.Count == 0)) - continue; - auto emitter = buffer->Emitter; - if (!emitter || !emitter->IsLoaded()) - continue; + for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++) + { + auto& emitterData = effect->Instance.Emitters[emitterIndex]; + const auto buffer = emitterData.Buffer; + if (!buffer || (buffer->Mode == ParticlesSimulationMode::CPU && buffer->CPU.Count == 0)) + continue; + auto emitter = buffer->Emitter; + if (!emitter || !emitter->IsLoaded()) + continue; - buffer->Emitter->GraphExecutorCPU.Draw(buffer->Emitter, effect, emitterData, renderContext, worlds[(int32)emitter->SimulationSpace]); + buffer->Emitter->GraphExecutorCPU.Draw(buffer->Emitter, effect, emitterData, renderContextBatch.GetMainContext(), worlds[(int32)emitter->SimulationSpace]); + } } // Setup a draw call common data DrawCall drawCall; drawCall.PerInstanceRandom = effect->GetPerInstanceRandom(); - drawCall.ObjectPosition = effect->GetSphere().Center - view.Origin; - drawCall.ObjectRadius = (float)effect->GetSphere().Radius; + drawCall.ObjectPosition = bounds.Center; + drawCall.ObjectRadius = (float)bounds.Radius; // Draw all emitters for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++) @@ -974,8 +999,8 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe drawCall.Particle.Particles = buffer; // Check if need to render any module - RenderModulesIndices renderModulesIndices; - for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.RenderModules.Count() && renderModulesIndices.Count() < PARTICLE_EMITTER_MAX_MODULES; moduleIndex++) + uint32 renderModulesIndices = 0; + for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.RenderModules.Count() && moduleIndex < 32; moduleIndex++) { auto module = emitter->Graph.RenderModules[moduleIndex]; @@ -989,10 +1014,10 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe if (!material || !material->IsReady() || !material->IsParticle() || - (view.Pass & material->GetDrawModes() & moduleDrawModes) == DrawPass::None + (viewsDrawModes & material->GetDrawModes() & moduleDrawModes) == DrawPass::None ) break; - renderModulesIndices.Add(moduleIndex); + renderModulesIndices |= 1u << moduleIndex; break; } // Model Rendering @@ -1008,10 +1033,10 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe if (!material || !material->IsReady() || !material->IsParticle() || - (view.Pass & material->GetDrawModes() & moduleDrawModes) == DrawPass::None + (viewsDrawModes & material->GetDrawModes() & moduleDrawModes) == DrawPass::None ) break; - renderModulesIndices.Add(moduleIndex); + renderModulesIndices |= 1u << moduleIndex; break; } // Ribbon Rendering @@ -1022,10 +1047,10 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe if (!material || !material->IsReady() || !material->IsParticle() || - (view.Pass & material->GetDrawModes() & moduleDrawModes) == DrawPass::None + (viewsDrawModes & material->GetDrawModes() & moduleDrawModes) == DrawPass::None ) break; - renderModulesIndices.Add(moduleIndex); + renderModulesIndices |= 1u << moduleIndex; break; } // Volumetric Fog Rendering @@ -1035,26 +1060,27 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe if (!material || !material->IsReady() || material->GetInfo().Domain != MaterialDomain::VolumeParticle || - (view.Flags & ViewFlags::Fog) == ViewFlags::None + (renderContextBatch.GetMainContext().View.Flags & ViewFlags::Fog) == ViewFlags::None || + (viewsMask & 1) == 0 ) break; - renderModulesIndices.Add(moduleIndex); + renderModulesIndices |= 1u << moduleIndex; break; } } } - if (renderModulesIndices.IsEmpty()) + if (renderModulesIndices == 0) continue; // Draw switch (buffer->Mode) { case ParticlesSimulationMode::CPU: - DrawEmitterCPU(renderContext, buffer, drawCall, drawModes, staticFlags, emitterData, renderModulesIndices, sortOrder); + DrawEmitterCPU(renderContextBatch, buffer, drawCall, viewsDrawModes, staticFlags, bounds, renderModulesIndices, sortOrder); break; #if COMPILE_WITH_GPU_PARTICLES case ParticlesSimulationMode::GPU: - DrawEmitterGPU(renderContext, buffer, drawCall, drawModes, staticFlags, renderModulesIndices, sortOrder); + DrawEmitterGPU(renderContextBatch, buffer, drawCall, viewsDrawModes, staticFlags, bounds, renderModulesIndices, sortOrder); break; #endif } @@ -1090,6 +1116,7 @@ void UpdateGPU(RenderTask* task, GPUContext* context) ScopeLock lock(GpuUpdateListLocker); if (GpuUpdateList.IsEmpty()) return; + PROFILE_CPU_NAMED("GPUParticles"); PROFILE_GPU("GPU Particles"); PROFILE_MEM(Particles); diff --git a/Source/Engine/Particles/Particles.h b/Source/Engine/Particles/Particles.h index 77f651cfa..38ec39d2d 100644 --- a/Source/Engine/Particles/Particles.h +++ b/Source/Engine/Particles/Particles.h @@ -6,7 +6,7 @@ #include "Engine/Threading/ConcurrentSystemLocker.h" class TaskGraphSystem; -struct RenderContext; +struct RenderContextBatch; struct RenderView; class ParticleEmitter; class ParticleSystemInstance; @@ -48,9 +48,9 @@ public: /// /// Draws the particles. /// - /// The rendering context. + /// The rendering context. /// The owning actor. - static void DrawParticles(RenderContext& renderContext, ParticleEffect* effect); + static void DrawParticles(RenderContextBatch& renderContextBatch, ParticleEffect* effect); #if USE_EDITOR ///