@@ -111,7 +111,7 @@ void CMatchChannelManager::RemoveTexture(STexInfo* pTexInfo)
111111 // Remove association
112112 dassert (MapContains (pTexNameInfo->usedByTexInfoList , pTexInfo));
113113 MapRemove (pTexNameInfo->usedByTexInfoList , pTexInfo);
114- pTexInfo->pAssociatedTexNameInfo = NULL ;
114+ pTexInfo->pAssociatedTexNameInfo = nullptr ;
115115}
116116
117117// ////////////////////////////////////////////////////////////////
@@ -125,24 +125,24 @@ void CMatchChannelManager::FinalizeLayers(SShaderInfoLayers& shaderLayers)
125125{
126126 // Sort layers by priority
127127 std::sort (shaderLayers.layerList .begin (), shaderLayers.layerList .end ());
128- uint uiNumLayers = shaderLayers.layerList . size ( );
128+ const auto uiNumLayers = std::size ( shaderLayers.layerList );
129129
130130 // Set output
131131 shaderLayers.output = SShaderItemLayers ();
132132 shaderLayers.output .layerList .resize (uiNumLayers);
133133
134134 // Copy base
135- SShaderInfo* pShaderInfo = shaderLayers.pBase .pShaderInfo ;
136- if (pShaderInfo)
135+ if (const SShaderInfo* pBaseShaderInfo = shaderLayers.pBase .pShaderInfo )
137136 {
138- shaderLayers.output .pBase = pShaderInfo ->pShaderData ;
139- shaderLayers.output .bUsesVertexShader = pShaderInfo ->bUsesVertexShader ;
137+ shaderLayers.output .pBase = pBaseShaderInfo ->pShaderData ;
138+ shaderLayers.output .bUsesVertexShader = pBaseShaderInfo ->bUsesVertexShader ;
140139 }
141140
142141 // Copy layers
143- for (uint i = 0 ; i < uiNumLayers; i++ )
142+ for (std:: size_t i = 0 ; i < uiNumLayers; ++i )
144143 {
145- SShaderInfo* pShaderInfo = shaderLayers.layerList [i].pShaderInfo ;
144+ const SShaderInfo* pShaderInfo = shaderLayers.layerList [i].pShaderInfo ;
145+ dassert (pShaderInfo); // Layers should always have valid shader info
146146 shaderLayers.output .layerList [i] = pShaderInfo->pShaderData ;
147147 shaderLayers.output .bUsesVertexShader |= pShaderInfo->bUsesVertexShader ;
148148 }
@@ -166,29 +166,38 @@ STexShaderReplacement* CMatchChannelManager::UpdateTexShaderReplacement(STexName
166166 pTexShaderReplacement = MapFind (pTexNameInfo->texEntityShaderMap , pClientEntity);
167167 }
168168
169- if (!pTexShaderReplacement->bSet )
169+ if (!pTexShaderReplacement->bSet || !pTexShaderReplacement-> bValid )
170170 {
171- // If not done yet for this entity, needs to be done
172- dassert (!pTexShaderReplacement->shaderLayers .pBase .pShaderInfo && pTexShaderReplacement->shaderLayers .layerList .empty ());
171+ // If not calculated yet or invalidated, (re)build it
172+ if (!pTexShaderReplacement->bValid )
173+ {
174+ // Clear invalidated data before rebuilding
175+ pTexShaderReplacement->shaderLayers = SShaderInfoLayers ();
176+ }
177+ else
178+ {
179+ // Fresh entry - should be empty
180+ dassert (!pTexShaderReplacement->shaderLayers .pBase .pShaderInfo && pTexShaderReplacement->shaderLayers .layerList .empty ());
181+ }
173182 CalcShaderForTexAndEntity (pTexShaderReplacement->shaderLayers , pTexNameInfo, pClientEntity, iEntityType, false );
174183 pTexShaderReplacement->bSet = true ;
184+ pTexShaderReplacement->bValid = true ;
175185
176186 // texNoEntityShader need to be done also, so we can see what needs to be inherited from it
187+ STexShaderReplacement& texNoEntityShader = pTexNameInfo->GetTexNoEntityShader (iEntityType);
177188 {
178- STexShaderReplacement& texNoEntityShader = pTexNameInfo->GetTexNoEntityShader (iEntityType);
179189 UpdateTexShaderReplacementNoEntity (pTexNameInfo, texNoEntityShader, iEntityType);
180190
181191 // Handle base inheritance
182- if (pTexShaderReplacement->shaderLayers .pBase .pShaderInfo == NULL )
192+ if (pTexShaderReplacement->shaderLayers .pBase .pShaderInfo == nullptr )
183193 {
184194 if (texNoEntityShader.shaderLayers .pBase .bMixEntityAndNonEntity )
185195 pTexShaderReplacement->shaderLayers .pBase = texNoEntityShader.shaderLayers .pBase ;
186196 }
187197
188198 // Handle layer inheritance
189- for (uint i = 0 ; i < texNoEntityShader.shaderLayers .layerList . size (); i++ )
199+ for (const auto & info : texNoEntityShader.shaderLayers .layerList )
190200 {
191- const SShaderInfoInstance& info = texNoEntityShader.shaderLayers .layerList [i];
192201 if (info.bMixEntityAndNonEntity )
193202 pTexShaderReplacement->shaderLayers .layerList .push_back (info);
194203 }
@@ -209,12 +218,22 @@ STexShaderReplacement* CMatchChannelManager::UpdateTexShaderReplacement(STexName
209218// ////////////////////////////////////////////////////////////////
210219void CMatchChannelManager::UpdateTexShaderReplacementNoEntity (STexNameInfo* pTexNameInfo, STexShaderReplacement& texNoEntityShader, int iEntityType)
211220{
212- if (!texNoEntityShader.bSet )
221+ if (!texNoEntityShader.bSet || !texNoEntityShader. bValid )
213222 {
214- // If not done yet, needs to be done
215- dassert (!texNoEntityShader.shaderLayers .pBase .pShaderInfo && texNoEntityShader.shaderLayers .layerList .empty ());
216- CalcShaderForTexAndEntity (texNoEntityShader.shaderLayers , pTexNameInfo, NULL , iEntityType, false );
223+ // If not calculated yet or invalidated, (re)build it
224+ if (!texNoEntityShader.bValid )
225+ {
226+ // Clear invalidated data before rebuilding
227+ texNoEntityShader.shaderLayers = SShaderInfoLayers ();
228+ }
229+ else
230+ {
231+ // Fresh entry - should be empty
232+ dassert (!texNoEntityShader.shaderLayers .pBase .pShaderInfo && texNoEntityShader.shaderLayers .layerList .empty ());
233+ }
234+ CalcShaderForTexAndEntity (texNoEntityShader.shaderLayers , pTexNameInfo, nullptr , iEntityType, false );
217235 texNoEntityShader.bSet = true ;
236+ texNoEntityShader.bValid = true ;
218237
219238 FinalizeLayers (texNoEntityShader.shaderLayers );
220239 }
@@ -237,14 +256,15 @@ SShaderInfoLayers* CMatchChannelManager::GetShaderForTexAndEntity(STexInfo* pTex
237256 // Ignore unknown client entities
238257 if (pClientEntity)
239258 if (!MapContains (m_KnownClientEntities, pClientEntity))
240- pClientEntity = NULL ;
259+ pClientEntity = nullptr ;
241260
242261 if (pClientEntity)
243262 {
244263 // Get entity info for this replace
245264 STexShaderReplacement* pTexShaderReplacement = MapFind (pTexNameInfo->texEntityShaderMap , pClientEntity);
246265
247- if (!pTexShaderReplacement || !pTexShaderReplacement->bSet )
266+ // Rebuild only if: doesn't exist, not yet calculated, or explicitly invalidated
267+ if (!pTexShaderReplacement || !pTexShaderReplacement->bSet || !pTexShaderReplacement->bValid )
248268 {
249269 pTexShaderReplacement = UpdateTexShaderReplacement (pTexNameInfo, pClientEntity, iEntityType);
250270 }
@@ -259,16 +279,15 @@ SShaderInfoLayers* CMatchChannelManager::GetShaderForTexAndEntity(STexInfo* pTex
259279
260280 // Handle base inheritance
261281 STexShaderReplacement& texNoEntityShader = pTexNameInfo->GetTexNoEntityShader (iEntityType);
262- if (shaderLayersCheck1.pBase .pShaderInfo == NULL )
282+ if (shaderLayersCheck1.pBase .pShaderInfo == nullptr )
263283 {
264284 if (texNoEntityShader.shaderLayers .pBase .bMixEntityAndNonEntity )
265285 shaderLayersCheck1.pBase = texNoEntityShader.shaderLayers .pBase ;
266286 }
267287
268288 // Handle layer inheritance
269- for (uint i = 0 ; i < texNoEntityShader.shaderLayers .layerList . size (); i++ )
289+ for (const auto & info : texNoEntityShader.shaderLayers .layerList )
270290 {
271- const SShaderInfoInstance& info = texNoEntityShader.shaderLayers .layerList [i];
272291 if (info.bMixEntityAndNonEntity )
273292 shaderLayersCheck1.layerList .push_back (info);
274293 }
@@ -285,7 +304,7 @@ SShaderInfoLayers* CMatchChannelManager::GetShaderForTexAndEntity(STexInfo* pTex
285304 {
286305 STexShaderReplacement& texNoEntityShader = pTexNameInfo->GetTexNoEntityShader (iEntityType);
287306
288- if (!texNoEntityShader.bSet )
307+ if (!texNoEntityShader.bSet || !texNoEntityShader. bValid )
289308 {
290309 UpdateTexShaderReplacementNoEntity (pTexNameInfo, texNoEntityShader, iEntityType);
291310 }
@@ -296,7 +315,7 @@ SShaderInfoLayers* CMatchChannelManager::GetShaderForTexAndEntity(STexInfo* pTex
296315 // Check cached shader is correct
297316 pTexNameInfo->iDebugCounter2 = rand () % 100 ;
298317 SShaderInfoLayers shaderLayersCheck2;
299- CalcShaderForTexAndEntity (shaderLayersCheck2, pTexNameInfo, NULL , iEntityType, true );
318+ CalcShaderForTexAndEntity (shaderLayersCheck2, pTexNameInfo, nullptr , iEntityType, true );
300319 FinalizeLayers (shaderLayersCheck2);
301320 assert (texNoEntityShader.shaderLayers == shaderLayersCheck2);
302321 }
@@ -368,11 +387,10 @@ void CMatchChannelManager::RemoveClientEntityRefs(CClientEntityBase* pClientEnti
368387 }
369388
370389 // Flag affected textures to re-calc shader results
371- for (CFastHashSet< CMatchChannel*>::iterator iter = affectedChannels. begin (); iter != affectedChannels. end (); ++iter )
390+ for (CMatchChannel* pChannel : affectedChannels)
372391 {
373- CMatchChannel* pChannel = *iter;
374- for (CFastHashSet<STexNameInfo*>::iterator iter = pChannel->m_MatchedTextureList .begin (); iter != pChannel->m_MatchedTextureList .end (); ++iter)
375- (*iter)->ResetReplacementResults ();
392+ for (STexNameInfo* pTexNameInfo : pChannel->m_MatchedTextureList )
393+ pTexNameInfo->ResetReplacementResults ();
376394
377395 // Also delete channel if is not refed anymore
378396 if (pChannel->GetShaderAndEntityCount () == 0 )
@@ -381,9 +399,9 @@ void CMatchChannelManager::RemoveClientEntityRefs(CClientEntityBase* pClientEnti
381399 }
382400
383401 // Need to remove client entity entries that were used even though they had no matches
384- for (CFastHashMap<SString, STexNameInfo*>::const_iterator iter = m_AllTextureList. begin (); iter != m_AllTextureList. end (); ++iter )
402+ for (const auto & pair : m_AllTextureList)
385403 {
386- MapRemove (iter-> second ->texEntityShaderMap , pClientEntity);
404+ MapRemove (pair. second ->texEntityShaderMap , pClientEntity);
387405 }
388406
389407#ifdef SHADER_DEBUG_CHECKS
@@ -599,27 +617,25 @@ void CMatchChannelManager::ProcessRematchTexturesQueue()
599617 m_RematchQueue.clear ();
600618
601619 // For each queued channel
602- for (CFastHashSet< CMatchChannel*>::iterator iter = rematchQueue. begin (); iter != rematchQueue. end (); ++iter )
620+ for (CMatchChannel* pChannel : rematchQueue)
603621 {
604- CMatchChannel* pChannel = *iter;
605622 pChannel->m_bResetReplacements = true ;
606623
607624 OutputDebug (SString (" [ProcessRematchTexturesQueue] - Channel:%s" , GetDebugTag (pChannel)));
608625
609626 // Remove existing matches
610627 CFastHashSet<STexNameInfo*> matchedTextureList = pChannel->m_MatchedTextureList ;
611- for (CFastHashSet< STexNameInfo*>::iterator iter = matchedTextureList. begin (); iter != matchedTextureList. end (); ++iter )
628+ for (STexNameInfo* pTexNameInfo : matchedTextureList)
612629 {
613- STexNameInfo* pTexNameInfo = *iter;
614630 pChannel->RemoveTexture (pTexNameInfo);
615631 MapRemove (pTexNameInfo->matchChannelList , pChannel);
616632 pTexNameInfo->ResetReplacementResults (); // Do this here as it won't get picked up in RecalcEverything now
617633 }
618634
619635 // Rematch against texture list
620- for (CFastHashMap<SString, STexNameInfo*>::iterator iter = m_AllTextureList. begin (); iter != m_AllTextureList. end (); ++iter )
636+ for (auto & pair : m_AllTextureList)
621637 {
622- STexNameInfo* pTexNameInfo = iter-> second ;
638+ STexNameInfo* pTexNameInfo = pair. second ;
623639 if (pChannel->m_MatchChain .IsAdditiveMatch (pTexNameInfo->strTextureName ))
624640 {
625641 pChannel->AddTexture (pTexNameInfo);
@@ -912,6 +928,24 @@ void CMatchChannelManager::GetShaderReplacementStats(SShaderReplacementStats& ou
912928 }
913929}
914930
931+ // //////////////////////////////////////////////////////////////
932+ //
933+ // CMatchChannelManager::CleanupInvalidatedShaderCache
934+ //
935+ // Remove shader cache entries that were marked invalid (deferred cleanup)
936+ // This prevents memory growth from invalidated-but-not-yet-deleted entries
937+ //
938+ // //////////////////////////////////////////////////////////////
939+ void CMatchChannelManager::CleanupInvalidatedShaderCache ()
940+ {
941+ for (CFastHashMap<SString, STexNameInfo*>::iterator iter = m_AllTextureList.begin (); iter != m_AllTextureList.end (); ++iter)
942+ {
943+ STexNameInfo* pTexNameInfo = iter->second ;
944+ if (pTexNameInfo)
945+ pTexNameInfo->CleanupInvalidatedEntries ();
946+ }
947+ }
948+
915949//
916950//
917951//
0 commit comments