From 1f1c69607c672c8c08691611ea5bf217e6b19d25 Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Mon, 19 Oct 2026 15:03:45 +0100 Subject: [PATCH] PLAT-12035: stop Tr2InteriorScene re-creating shadow maps on every light change Adding or removing a light, loading the lights list, or setting shadowSize or shadowCount each rebuilt every spotlight shadow map and the shared depth stencil immediately. Loading an interior scene with four lights created and discarded the 1024x1024 targets many times before the first frame. Mark the shadow maps dirty instead and rebuild them lazily in RenderShadows. SetupShadowMaps now keeps existing targets that are valid and the right size, trims or appends to reach the wanted count, and only recreates the depth stencil when its size changes. --- trinity/Interior/Tr2InteriorScene.cpp | 62 +++++++++++++++++++-------- trinity/Interior/Tr2InteriorScene.h | 1 + 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/trinity/Interior/Tr2InteriorScene.cpp b/trinity/Interior/Tr2InteriorScene.cpp index 31eec69c4..1236b147b 100644 --- a/trinity/Interior/Tr2InteriorScene.cpp +++ b/trinity/Interior/Tr2InteriorScene.cpp @@ -137,6 +137,7 @@ Tr2InteriorScene::Tr2InteriorScene( IRoot* lockobj /*= NULL */ ) : m_optimizeShadows( true ), m_renderShadows( true ), m_debugRenderShadowMaps( false ), + m_shadowMapsDirty( true ), m_shadowMap0Var( "SpotlightShadow0", (TriTextureRes*)NULL ), m_shadowMap1Var( "SpotlightShadow1", (TriTextureRes*)NULL ), m_shadowMap2Var( "SpotlightShadow2", (TriTextureRes*)NULL ), @@ -212,14 +213,9 @@ bool Tr2InteriorScene::OnModified( Be::Var* value ) SetBackgroundCubemapResPath(); } - if( IsMatch( value, m_shadowSize ) ) + if( IsMatch( value, m_shadowSize ) || IsMatch( value, m_shadowCount ) ) { - SetupShadowMaps(); - } - - if( IsMatch( value, m_shadowCount ) ) - { - SetupShadowMaps(); + m_shadowMapsDirty = true; } return true; @@ -230,7 +226,7 @@ void Tr2InteriorScene::OnListModified( long event, ssize_t key, ssize_t key2, IR { if( theList == &m_lights ) { - SetupShadowMaps(); + m_shadowMapsDirty = true; } else if( theList == &m_dynamics ) @@ -659,21 +655,49 @@ void Tr2InteriorScene::RenderFullForward( Tr2RenderContext& renderContext ) void Tr2InteriorScene::SetupShadowMaps() { - m_lightRenderTargets.Clear(); + m_shadowMapsDirty = false; - for( int i = 0; i < (int)( m_lights.size() ) && i < m_shadowCount; i++ ) + const unsigned size = m_shadowSize > 0 ? (unsigned)m_shadowSize : 1; + int count = (int)m_lights.size(); + if( count > m_shadowCount ) + { + count = m_shadowCount; + } + if( count < 0 ) + { + count = 0; + } + + if( m_lightDepthStencil && ( !m_lightDepthStencil->IsValid() || m_lightDepthStencil->GetWidth() != size ) ) + { + m_lightDepthStencil = Tr2DepthStencilPtr(); + } + if( !m_lightDepthStencil ) + { + m_lightDepthStencil.CreateInstance(); + m_lightDepthStencil->Create( size, size, Tr2RenderContextEnum::DSFMT_D32, 0, 0 ); + } + + if( !m_lightRenderTargets.empty() ) + { + Tr2RenderTarget* first = m_lightRenderTargets[0]; + if( !first || !first->IsValid() || first->GetWidth() != size ) + { + m_lightRenderTargets.Clear(); + } + } + while( (int)m_lightRenderTargets.size() > count ) + { + m_lightRenderTargets.Remove( -1 ); + } + while( (int)m_lightRenderTargets.size() < count ) { Tr2RenderTargetPtr rt; rt.CreateInstance(); rt->SetName( "ShadowMap" ); - rt->Create( m_shadowSize, m_shadowSize, 1, Tr2RenderContextEnum::PIXEL_FORMAT_R32_FLOAT, 1, 0 ); + rt->Create( size, size, 1, Tr2RenderContextEnum::PIXEL_FORMAT_R32_FLOAT, 1, 0 ); m_lightRenderTargets.Append( rt ); } - - // Setup depth stencil texture - m_lightDepthStencil = Tr2DepthStencilPtr(); - m_lightDepthStencil.CreateInstance(); - m_lightDepthStencil->Create( m_shadowSize, m_shadowSize, Tr2RenderContextEnum::DSFMT_D32, 0, 0 ); } // -------------------------------------------------------------------------------------- @@ -689,7 +713,7 @@ void Tr2InteriorScene::RenderShadows( Tr2RenderContext& renderContext ) return; } - if( !m_lightDepthStencil ) + if( m_shadowMapsDirty || !m_lightDepthStencil ) { SetupShadowMaps(); } @@ -926,7 +950,7 @@ void Tr2InteriorScene::AddLightSource( ITr2InteriorLight* lightSource ) m_lights.Insert( -1, lightSource ); } - SetupShadowMaps(); + m_shadowMapsDirty = true; } // -------------------------------------------------------------------------------------- @@ -956,7 +980,7 @@ void Tr2InteriorScene::RemoveLightSource( ITr2InteriorLight* lightSource ) m_lights.Remove( pos ); - SetupShadowMaps(); + m_shadowMapsDirty = true; } // -------------------------------------------------------------------------------------- diff --git a/trinity/Interior/Tr2InteriorScene.h b/trinity/Interior/Tr2InteriorScene.h index 0e29e2bfa..dcae56bce 100644 --- a/trinity/Interior/Tr2InteriorScene.h +++ b/trinity/Interior/Tr2InteriorScene.h @@ -155,6 +155,7 @@ class Tr2InteriorScene : public IInitialize, private: // A shared depth stencil texture for light shadow maps Tr2DepthStencilPtr m_lightDepthStencil; + bool m_shadowMapsDirty; // Holds the main render batch list for opaques, decals, and transparent batches ITriRenderBatchAccumulator* m_primaryRenderBatches;