From 097725e1e0b4fd0a650559c284f0967d18e8382d Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Sun, 6 Nov 2022 11:31:05 +0000 Subject: [PATCH] Moves particles data uploading out of framebuffer pass. Comments By: phosit Differential Revision: https://code.wildfiregames.com/D4820 This was SVN commit r27207. --- source/graphics/ParticleEmitter.cpp | 11 ++++++----- source/graphics/ParticleEmitter.h | 6 ++++++ source/renderer/ParticleRenderer.cpp | 25 ++++++++++++++++--------- source/renderer/ParticleRenderer.h | 7 +++++++ source/renderer/SceneRenderer.cpp | 2 ++ 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/source/graphics/ParticleEmitter.cpp b/source/graphics/ParticleEmitter.cpp index c9e994bc2f..77dca14644 100644 --- a/source/graphics/ParticleEmitter.cpp +++ b/source/graphics/ParticleEmitter.cpp @@ -174,6 +174,12 @@ void CParticleEmitter::PrepareForRendering() m_VertexArray.PrepareForRendering(); } +void CParticleEmitter::UploadData( + Renderer::Backend::IDeviceCommandContext* deviceCommandContext) +{ + m_VertexArray.UploadIfNeeded(deviceCommandContext); +} + void CParticleEmitter::Bind( Renderer::Backend::IDeviceCommandContext* deviceCommandContext, Renderer::Backend::IShaderProgram* shader) @@ -206,9 +212,6 @@ void CParticleEmitter::RenderArray( if (m_Particles.empty()) return; - m_VertexArray.UploadIfNeeded(deviceCommandContext); - m_IndexArray.UploadIfNeeded(deviceCommandContext); - const uint32_t stride = m_VertexArray.GetStride(); const uint32_t firstVertexOffset = m_VertexArray.GetOffset() * stride; @@ -260,8 +263,6 @@ void CParticleEmitter::SetEntityVariable(const std::string& name, float value) m_EntityVariables[name] = value; } - - CModelParticleEmitter::CModelParticleEmitter(const CParticleEmitterTypePtr& type) : m_Type(type) { diff --git a/source/graphics/ParticleEmitter.h b/source/graphics/ParticleEmitter.h index aa62033f5f..87541de265 100644 --- a/source/graphics/ParticleEmitter.h +++ b/source/graphics/ParticleEmitter.h @@ -119,6 +119,12 @@ public: */ void PrepareForRendering(); + /** + * Upload the vertex data to the backend. + */ + void UploadData( + Renderer::Backend::IDeviceCommandContext* deviceCommandContext); + /** * Bind rendering state (textures and blend modes). */ diff --git a/source/renderer/ParticleRenderer.cpp b/source/renderer/ParticleRenderer.cpp index 4208ccb0a4..c0be7a970f 100644 --- a/source/renderer/ParticleRenderer.cpp +++ b/source/renderer/ParticleRenderer.cpp @@ -58,8 +58,8 @@ void ParticleRenderer::Submit(int cullGroup, CParticleEmitter* emitter) void ParticleRenderer::EndFrame() { - for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup) - m->emitters[cullGroup].clear(); + for (std::vector& cullGroupEmitters : m->emitters) + cullGroupEmitters.clear(); // this should leave the capacity unchanged, which is okay since it // won't be very large or very variable } @@ -103,29 +103,36 @@ void ParticleRenderer::PrepareForRendering(const CShaderDefines& context) ++m->frameNumber; - for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup) + for (std::vector& cullGroupEmitters : m->emitters) { PROFILE("update emitters"); - for (size_t i = 0; i < m->emitters[cullGroup].size(); ++i) + for (CParticleEmitter* emitter : cullGroupEmitters) { - CParticleEmitter* emitter = m->emitters[cullGroup][i]; emitter->UpdateArrayData(m->frameNumber); emitter->PrepareForRendering(); } } - for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup) + CMatrix3D worldToCamera; + g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetInverse(worldToCamera); + for (std::vector& cullGroupEmitters : m->emitters) { // Sort back-to-front by distance from camera PROFILE("sort emitters"); - CMatrix3D worldToCam; - g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetInverse(worldToCam); - std::stable_sort(m->emitters[cullGroup].begin(), m->emitters[cullGroup].end(), SortEmitterDistance(worldToCam)); + std::stable_sort(cullGroupEmitters.begin(), cullGroupEmitters.end(), SortEmitterDistance(worldToCamera)); } // TODO: should batch by texture here when possible, maybe } +void ParticleRenderer::Upload( + Renderer::Backend::IDeviceCommandContext* deviceCommandContext) +{ + for (std::vector& cullGroupEmitters : m->emitters) + for (CParticleEmitter* emitter : cullGroupEmitters) + emitter->UploadData(deviceCommandContext); +} + void ParticleRenderer::RenderParticles( Renderer::Backend::IDeviceCommandContext* deviceCommandContext, int cullGroup, bool wireframe) diff --git a/source/renderer/ParticleRenderer.h b/source/renderer/ParticleRenderer.h index c080dc5ef1..725c7cdaae 100644 --- a/source/renderer/ParticleRenderer.h +++ b/source/renderer/ParticleRenderer.h @@ -47,6 +47,13 @@ public: */ void PrepareForRendering(const CShaderDefines& context); + /** + * Upload internal data to the backend. Must be called after the data is + * prepared and before any rendering calls. + */ + void Upload( + Renderer::Backend::IDeviceCommandContext* deviceCommandContext); + /** * Reset the list of submitted overlays. */ diff --git a/source/renderer/SceneRenderer.cpp b/source/renderer/SceneRenderer.cpp index d8c592ed39..baadc53f13 100644 --- a/source/renderer/SceneRenderer.cpp +++ b/source/renderer/SceneRenderer.cpp @@ -808,6 +808,8 @@ void CSceneRenderer::RenderSubmissions( m->overlayRenderer.Upload(deviceCommandContext); + m->particleRenderer.Upload(deviceCommandContext); + if (g_RenderingOptions.GetShadows()) { RenderShadowMap(deviceCommandContext, context);