Skip to content

Commit 63b120e

Browse files
committed
Temporary textures cleanup
1 parent c60f8a2 commit 63b120e

File tree

5 files changed

+63
-11
lines changed

5 files changed

+63
-11
lines changed

Client/mods/deathmatch/logic/CClientManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ void CClientManager::DoPulse(bool bDoStandardPulses, bool bDoVehicleManagerPulse
218218
m_pColManager->DoPulse();
219219
m_pGUIManager->DoPulse();
220220
m_pWeaponManager->DoPulse();
221+
m_pRenderElementManager->DoPulse();
221222
}
222223
else
223224
{

Client/mods/deathmatch/logic/CClientRenderElementManager.cpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
#include "StdInc.h"
1212
#include "CClientVectorGraphic.h"
1313

14+
namespace
15+
{
16+
const std::int64_t TEMPORARY_TEXTURES_CLEANUP_THRESHOLD = 1000ll;
17+
const std::size_t TEMPORARY_TEXTURES_DELETE_THRESHOLD = 2u;
18+
}
19+
1420
////////////////////////////////////////////////////////////////
1521
//
1622
// CClientRenderElementManager::CClientRenderElementManager
@@ -283,20 +289,22 @@ CClientVectorGraphic* CClientRenderElementManager::CreateVectorGraphic(uint widt
283289
CClientTexture* CClientRenderElementManager::FindAutoTexture(const SString& strFullFilePath, const SString& strUniqueName)
284290
{
285291
// Check if we've already done this file
286-
CClientTexture** ppTextureElement = MapFind(m_AutoTextureMap, strUniqueName);
292+
SAutoTexture* ppTextureElement = MapFind(m_AutoTextureMap, strUniqueName);
287293
if (!ppTextureElement)
288294
{
289295
// Try to create
290296
CClientTexture* pNewTextureElement = CreateTexture(strFullFilePath);
291297
if (!pNewTextureElement)
292-
return NULL;
298+
return nullptr;
293299

294300
// Add to automap if created
295-
MapSet(m_AutoTextureMap, strUniqueName, pNewTextureElement);
301+
MapSet(m_AutoTextureMap, strUniqueName, SAutoTexture{pNewTextureElement});
296302
ppTextureElement = MapFind(m_AutoTextureMap, strUniqueName);
297303
}
298304

299-
return *ppTextureElement;
305+
ppTextureElement->lastUse = CTickCount::Now();
306+
307+
return ppTextureElement->texture;
300308
}
301309

302310
////////////////////////////////////////////////////////////////
@@ -318,9 +326,9 @@ void CClientRenderElementManager::Remove(CClientRenderElement* pElement)
318326
// Remove from auto texture map
319327
if (pElement->IsA(CClientTexture::GetClassId()))
320328
{
321-
for (std::map<SString, CClientTexture*>::iterator iter = m_AutoTextureMap.begin(); iter != m_AutoTextureMap.end(); ++iter)
329+
for (auto iter = m_AutoTextureMap.begin(); iter != m_AutoTextureMap.end(); ++iter)
322330
{
323-
if (iter->second == pElement)
331+
if (iter->second.texture == pElement)
324332
{
325333
m_AutoTextureMap.erase(iter);
326334
break;
@@ -350,3 +358,35 @@ void CClientRenderElementManager::Remove(CClientRenderElement* pElement)
350358
CRenderItem* pRenderItem = pElement->GetRenderItem();
351359
SAFE_RELEASE(pRenderItem);
352360
}
361+
362+
void CClientRenderElementManager::DoPulse()
363+
{
364+
const CTickCount now = CTickCount::Now();
365+
366+
std::vector<CClientTexture*> deleteCandidates;
367+
deleteCandidates.reserve(TEMPORARY_TEXTURES_DELETE_THRESHOLD);
368+
369+
for (const auto& [texName, texInfo] : m_AutoTextureMap)
370+
{
371+
const std::int64_t timeElapsedMs = (now - texInfo.lastUse).ToLongLong();
372+
if (timeElapsedMs < TEMPORARY_TEXTURES_CLEANUP_THRESHOLD)
373+
continue;
374+
375+
CTextureItem* textureItem = texInfo.texture->GetTextureItem();
376+
if (textureItem && textureItem->m_iRefCount > 1)
377+
continue;
378+
379+
// CElementDeleter::Delete causes changes in m_AutoTextureMap
380+
// and we cannot delete a texture while iterating over it
381+
deleteCandidates.push_back(texInfo.texture);
382+
383+
// The deletion procedure can be expensive
384+
// and we're interested in capping on the number of deleted texture at once
385+
if (deleteCandidates.size() == TEMPORARY_TEXTURES_DELETE_THRESHOLD)
386+
break;
387+
}
388+
389+
for (CClientTexture* texture : deleteCandidates)
390+
g_pClientGame->GetElementDeleter()->Delete(texture, true);
391+
392+
}

Client/mods/deathmatch/logic/CClientRenderElementManager.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class CClientRenderElementManager
3939
CClientTexture* FindAutoTexture(const SString& strFullFilePath, const SString& strUniqueName);
4040
void Remove(CClientRenderElement* pElement);
4141

42+
void DoPulse();
43+
4244
uint GetDxFontCount() { return m_uiStatsDxFontCount; }
4345
uint GetGuiFontCount() { return m_uiStatsGuiFontCount; }
4446
uint GetTextureCount() { return m_uiStatsTextureCount; }
@@ -49,9 +51,15 @@ class CClientRenderElementManager
4951
uint GetVectorGraphicCount() { return m_uiStatsVectorGraphicCount; }
5052

5153
protected:
54+
struct SAutoTexture
55+
{
56+
CClientTexture* texture{};
57+
CTickCount lastUse;
58+
};
59+
5260
CClientManager* m_pClientManager;
5361
CRenderItemManagerInterface* m_pRenderItemManager;
54-
std::map<SString, CClientTexture*> m_AutoTextureMap;
62+
std::map<SString, SAutoTexture> m_AutoTextureMap;
5563
std::map<CRenderItem*, CClientRenderElement*> m_ItemElementMap;
5664
uint m_uiStatsGuiFontCount;
5765
uint m_uiStatsDxFontCount;

Client/mods/deathmatch/logic/CElementDeleter.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ CElementDeleter::CElementDeleter()
1919
m_bAllowUnreference = true;
2020
}
2121

22-
void CElementDeleter::Delete(class CClientEntity* pElement)
22+
void CElementDeleter::Delete(class CClientEntity* pElement, bool silent)
2323
{
2424
// Make sure we don't try to delete it twice
2525
if (pElement && !IsBeingDeleted(pElement))
2626
{
2727
// Before we do anything, fire the on-destroy event
28-
CLuaArguments Arguments;
29-
pElement->CallEvent("onClientElementDestroy", Arguments, true);
28+
if (!silent)
29+
{
30+
CLuaArguments Arguments;
31+
pElement->CallEvent("onClientElementDestroy", Arguments, true);
32+
}
3033

3134
// Add it to our list
3235
if (!pElement->IsBeingDeleted())

Client/mods/deathmatch/logic/CElementDeleter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class CElementDeleter
2020
CElementDeleter();
2121
~CElementDeleter() { DoDeleteAll(); };
2222

23-
void Delete(class CClientEntity* pElement);
23+
void Delete(class CClientEntity* pElement, bool silent = false);
2424
void DeleteRecursive(class CClientEntity* pElement);
2525
void DoDeleteAll();
2626
bool IsBeingDeleted(class CClientEntity* pElement);

0 commit comments

Comments
 (0)