Skip to content

Commit 4efb26e

Browse files
committed
1.6 (C++ 14 alternative code).. Addendum to 49e5265: Fix crashes introduced, and other pre-existing issues that surfaced, including mem leaks.
Memory fragmentation-related crashes due to texture replacing/allocation spam in loop are also reduced or gone (This wasn't out of mem.. it could happen even with 800MB usage), which is huge for MTA. Also has some bonus fixes ahead of 1.7 master receiving it in a short while
1 parent 33625c2 commit 4efb26e

File tree

9 files changed

+580
-265
lines changed

9 files changed

+580
-265
lines changed

Client/core/DXHook/CDirect3DEvents9.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,8 +1202,19 @@ void CDirect3DEvents9::CloseActiveShader(bool bDeviceOperational)
12021202
if (!pShaderItem)
12031203
return;
12041204

1205+
if (!SharedUtil::IsReadablePointer(pShaderItem, sizeof(void*)))
1206+
return;
1207+
12051208
SResolvedShaderState shaderState;
12061209
bool bHasShaderState = TryResolveShaderState(pShaderItem, shaderState);
1210+
1211+
if (bHasShaderState)
1212+
{
1213+
if (shaderState.pInstance && !SharedUtil::IsReadablePointer(shaderState.pInstance, sizeof(void*)))
1214+
bHasShaderState = false;
1215+
if (bHasShaderState && shaderState.pEffectWrap && !SharedUtil::IsReadablePointer(shaderState.pEffectWrap, sizeof(void*)))
1216+
bHasShaderState = false;
1217+
}
12071218

12081219
ID3DXEffect* pD3DEffect = bHasShaderState ? shaderState.pEffect : nullptr;
12091220
IDirect3DDevice9* pDevice = g_pGraphics ? g_pGraphics->GetDevice() : nullptr;

Client/game_sa/CRenderWareSA.ShaderMatching.cpp

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -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
//////////////////////////////////////////////////////////////////
210219
void 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
//

Client/game_sa/CRenderWareSA.ShaderMatching.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ class CMatchChannelManager
266266
void RemoveClientEntityRefs(CClientEntityBase* pClientEntity);
267267
void RemoveShaderRefs(CSHADERDUMMY* pShaderData);
268268
void GetShaderReplacementStats(SShaderReplacementStats& outStats);
269+
void CleanupInvalidatedShaderCache(); // Cleanup deferred invalidated entries
269270

270271
protected:
271272
void CalcShaderForTexAndEntity(SShaderInfoLayers& outShaderLayers, STexNameInfo* pTexNameInfo, CClientEntityBase* pClientEntity, int iEntityType,

0 commit comments

Comments
 (0)