Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temporary textures cleanup #3978

Merged
merged 9 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/CClientManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ void CClientManager::DoPulse(bool bDoStandardPulses, bool bDoVehicleManagerPulse
m_pColManager->DoPulse();
m_pGUIManager->DoPulse();
m_pWeaponManager->DoPulse();
m_pRenderElementManager->DoPulse();
}
else
{
Expand Down
48 changes: 42 additions & 6 deletions Client/mods/deathmatch/logic/CClientRenderElementManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "StdInc.h"
#include "CClientVectorGraphic.h"

constexpr std::int64_t TEMPORARY_TEXTURES_CLEANUP_THRESHOLD = 10000ll;
constexpr std::size_t TEMPORARY_TEXTURES_DELETE_THRESHOLD = 10u;

////////////////////////////////////////////////////////////////
//
// CClientRenderElementManager::CClientRenderElementManager
Expand Down Expand Up @@ -283,20 +286,22 @@ CClientVectorGraphic* CClientRenderElementManager::CreateVectorGraphic(uint widt
CClientTexture* CClientRenderElementManager::FindAutoTexture(const SString& strFullFilePath, const SString& strUniqueName)
{
// Check if we've already done this file
CClientTexture** ppTextureElement = MapFind(m_AutoTextureMap, strUniqueName);
SAutoTexture* ppTextureElement = MapFind(m_AutoTextureMap, strUniqueName);
if (!ppTextureElement)
{
// Try to create
CClientTexture* pNewTextureElement = CreateTexture(strFullFilePath);
if (!pNewTextureElement)
return NULL;
return nullptr;

// Add to automap if created
MapSet(m_AutoTextureMap, strUniqueName, pNewTextureElement);
MapSet(m_AutoTextureMap, strUniqueName, SAutoTexture{pNewTextureElement});
ppTextureElement = MapFind(m_AutoTextureMap, strUniqueName);
}

return *ppTextureElement;
ppTextureElement->lastUse = CTickCount::Now();

return ppTextureElement->texture;
}

////////////////////////////////////////////////////////////////
Expand All @@ -318,9 +323,9 @@ void CClientRenderElementManager::Remove(CClientRenderElement* pElement)
// Remove from auto texture map
if (pElement->IsA(CClientTexture::GetClassId()))
{
for (std::map<SString, CClientTexture*>::iterator iter = m_AutoTextureMap.begin(); iter != m_AutoTextureMap.end(); ++iter)
for (auto iter = m_AutoTextureMap.begin(); iter != m_AutoTextureMap.end(); ++iter)
{
if (iter->second == pElement)
if (iter->second.texture == pElement)
{
m_AutoTextureMap.erase(iter);
break;
Expand Down Expand Up @@ -350,3 +355,34 @@ void CClientRenderElementManager::Remove(CClientRenderElement* pElement)
CRenderItem* pRenderItem = pElement->GetRenderItem();
SAFE_RELEASE(pRenderItem);
}

void CClientRenderElementManager::DoPulse()
{
const CTickCount now = CTickCount::Now();

std::vector<CClientTexture*> deleteCandidates;
deleteCandidates.reserve(TEMPORARY_TEXTURES_DELETE_THRESHOLD);

for (const auto& [texName, texInfo] : m_AutoTextureMap)
{
const std::int64_t timeElapsedMs = (now - texInfo.lastUse).ToLongLong();
if (timeElapsedMs < TEMPORARY_TEXTURES_CLEANUP_THRESHOLD)
continue;

CTextureItem* textureItem = texInfo.texture->GetTextureItem();
if (textureItem && textureItem->m_iRefCount > 1)
continue;

// CElementDeleter::Delete causes changes in m_AutoTextureMap
// and we cannot delete a texture while iterating over it
deleteCandidates.push_back(texInfo.texture);

// The deletion procedure can be expensive
// and we're interested in capping on the number of deleted texture at once
if (deleteCandidates.size() == TEMPORARY_TEXTURES_DELETE_THRESHOLD)
break;
}

for (CClientTexture* texture : deleteCandidates)
g_pClientGame->GetElementDeleter()->Delete(texture, true);
}
10 changes: 9 additions & 1 deletion Client/mods/deathmatch/logic/CClientRenderElementManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class CClientRenderElementManager
CClientTexture* FindAutoTexture(const SString& strFullFilePath, const SString& strUniqueName);
void Remove(CClientRenderElement* pElement);

void DoPulse();

uint GetDxFontCount() { return m_uiStatsDxFontCount; }
uint GetGuiFontCount() { return m_uiStatsGuiFontCount; }
uint GetTextureCount() { return m_uiStatsTextureCount; }
Expand All @@ -49,9 +51,15 @@ class CClientRenderElementManager
uint GetVectorGraphicCount() { return m_uiStatsVectorGraphicCount; }

protected:
struct SAutoTexture
{
CClientTexture* texture{};
CTickCount lastUse;
};

CClientManager* m_pClientManager;
CRenderItemManagerInterface* m_pRenderItemManager;
std::map<SString, CClientTexture*> m_AutoTextureMap;
std::map<SString, SAutoTexture> m_AutoTextureMap;
std::map<CRenderItem*, CClientRenderElement*> m_ItemElementMap;
uint m_uiStatsGuiFontCount;
uint m_uiStatsDxFontCount;
Expand Down
9 changes: 6 additions & 3 deletions Client/mods/deathmatch/logic/CElementDeleter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ CElementDeleter::CElementDeleter()
m_bAllowUnreference = true;
}

void CElementDeleter::Delete(class CClientEntity* pElement)
void CElementDeleter::Delete(class CClientEntity* pElement, bool silent)
{
// Make sure we don't try to delete it twice
if (pElement && !IsBeingDeleted(pElement))
{
// Before we do anything, fire the on-destroy event
CLuaArguments Arguments;
pElement->CallEvent("onClientElementDestroy", Arguments, true);
if (!silent)
{
CLuaArguments Arguments;
pElement->CallEvent("onClientElementDestroy", Arguments, true);
}
tederis marked this conversation as resolved.
Show resolved Hide resolved

// Add it to our list
if (!pElement->IsBeingDeleted())
Expand Down
2 changes: 1 addition & 1 deletion Client/mods/deathmatch/logic/CElementDeleter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class CElementDeleter
CElementDeleter();
~CElementDeleter() { DoDeleteAll(); };

void Delete(class CClientEntity* pElement);
void Delete(class CClientEntity* pElement, bool silent = false);
void DeleteRecursive(class CClientEntity* pElement);
void DoDeleteAll();
bool IsBeingDeleted(class CClientEntity* pElement);
Expand Down
Loading