From bae4ca9f0184772e2175e1ed5c22bbaa68ae4f3d Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Mon, 30 Dec 2024 18:55:23 +0300 Subject: [PATCH] Make engineRestreamWorld more aggressive (PR #3685) Second approach for previous PR #3602 --- Client/game_sa/CGameSA.cpp | 27 ++++++++++++++++++++ Client/game_sa/CGameSA.h | 2 ++ Client/game_sa/CModelInfoSA.cpp | 7 ++--- Client/game_sa/CModelInfoSA.h | 2 +- Client/game_sa/CPoolSAInterface.h | 2 +- Client/game_sa/CTxdPoolSA.cpp | 9 +++++++ Client/game_sa/CTxdPoolSA.h | 1 + Client/mods/deathmatch/logic/CClientGame.cpp | 2 ++ Client/sdk/game/CGame.h | 1 + Client/sdk/game/CModelInfo.h | 2 +- Client/sdk/game/CTxdPool.h | 1 + 11 files changed, 48 insertions(+), 8 deletions(-) diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 77c78333f3..fbb9dd98a5 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -1102,6 +1102,33 @@ bool CGameSA::SetBuildingPoolSize(size_t size) return status; } +void CGameSA::UnloadUnusedModels() +{ + // Unload DFF's + // CJ should not be unloaded + const std::size_t baseIdForTxd = GetBaseIDforTXD(); + for (std::size_t id = 1; id < baseIdForTxd; id++) + { + CStreamingInfo* streamingInfo = m_pStreaming->GetStreamingInfo(id); + if (streamingInfo->loadState != eModelLoadState::LOADSTATE_NOT_LOADED && streamingInfo->sizeInBlocks > 0) + { + CModelInfoSA& model = ModelInfo[id]; + if (model.GetRefCount() == 0) + model.UnloadUnused(); + }; + } + // Unload TXD + for (std::size_t id = baseIdForTxd; id < GetBaseIDforCOL(); id++) + { + CStreamingInfo* streamingInfo = m_pStreaming->GetStreamingInfo(id); + std::size_t refsCount = GetPools()->GetTxdPool().GetRefsCount(id - baseIdForTxd); + if (streamingInfo->loadState != eModelLoadState::LOADSTATE_NOT_LOADED && streamingInfo->sizeInBlocks > 0 && refsCount == 0) + { + GetStreaming()->RemoveModel(id); + } + } +} + // Ensure models have the default lod distances void CGameSA::ResetModelLodDistances() { diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 2133d7d9a5..9a5b5ccd05 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -312,6 +312,8 @@ class CGameSA : public CGame bool SetBuildingPoolSize(size_t size); + void UnloadUnusedModels(); + private: std::unique_ptr m_Pools; CPlayerInfo* m_pPlayerInfo; diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index 0b5ff312b3..a41194438a 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -452,6 +452,8 @@ void CModelInfoSA::Remove() bool CModelInfoSA::UnloadUnused() { + m_pInterface = ppModelInfo[m_dwModelID]; + if (m_pInterface->usNumberOfRefs == 0 && !m_pCustomClump && !m_pCustomColModel) { pGame->GetStreaming()->RemoveModel(m_dwModelID); @@ -1094,11 +1096,6 @@ void CModelInfoSA::ModelAddRef(EModelRequestType requestType, const char* szTag) m_dwReferences++; } -int CModelInfoSA::GetRefCount() -{ - return static_cast(m_dwReferences); -} - void CModelInfoSA::RemoveRef(bool bRemoveExtraGTARef) { // Decrement the references diff --git a/Client/game_sa/CModelInfoSA.h b/Client/game_sa/CModelInfoSA.h index 6fc7b04811..be6811b8d9 100644 --- a/Client/game_sa/CModelInfoSA.h +++ b/Client/game_sa/CModelInfoSA.h @@ -397,7 +397,7 @@ class CModelInfoSA : public CModelInfo static void StaticResetAlphaTransparencies(); void ModelAddRef(EModelRequestType requestType, const char* szTag); - int GetRefCount(); + int GetRefCount() const override { return static_cast(m_dwReferences); }; void RemoveRef(bool bRemoveExtraGTARef = false); bool ForceUnload(); diff --git a/Client/game_sa/CPoolSAInterface.h b/Client/game_sa/CPoolSAInterface.h index 9f48bc63d3..f879775b3b 100644 --- a/Client/game_sa/CPoolSAInterface.h +++ b/Client/game_sa/CPoolSAInterface.h @@ -122,7 +122,7 @@ class CPoolSAInterface return !IsEmpty(index); } - B* GetObject(std::int32_t objectIndex) { return &m_pObjects[objectIndex]; } + B* GetObject(std::int32_t objectIndex) const { return &m_pObjects[objectIndex]; } uint GetObjectIndex(B* pObject) { return ((DWORD)pObject - (DWORD)m_pObjects) / sizeof(B); } diff --git a/Client/game_sa/CTxdPoolSA.cpp b/Client/game_sa/CTxdPoolSA.cpp index 248f825836..36be04fce5 100644 --- a/Client/game_sa/CTxdPoolSA.cpp +++ b/Client/game_sa/CTxdPoolSA.cpp @@ -55,3 +55,12 @@ std::uint16_t CTxdPoolSA::GetFreeTextureDictonarySlot() { return (*m_ppTxdPoolInterface)->GetFreeSlot(); } + +std::uint16_t CTxdPoolSA::GetRefsCount(std::uint16_t slot) const +{ + CTextureDictonarySAInterface* pTxd = (*m_ppTxdPoolInterface)->GetObject(slot); + if (!pTxd) + return -1; + + return pTxd->usUsagesCount; +} diff --git a/Client/game_sa/CTxdPoolSA.h b/Client/game_sa/CTxdPoolSA.h index c1f0ed8ece..daaf3a1ccb 100644 --- a/Client/game_sa/CTxdPoolSA.h +++ b/Client/game_sa/CTxdPoolSA.h @@ -25,6 +25,7 @@ class CTxdPoolSA final : public CTxdPool bool IsFreeTextureDictonarySlot(std::uint32_t uiTxdId); std::uint16_t GetFreeTextureDictonarySlot(); + std::uint16_t GetRefsCount(std::uint16_t slot) const; private: CPoolSAInterface** m_ppTxdPoolInterface; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 99eb78de34..116fbbd8ca 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6764,6 +6764,8 @@ void CClientGame::RestreamWorld() g_pGame->GetStreaming()->RemoveBigBuildings(); g_pGame->GetStreaming()->ReinitStreaming(); + + g_pGame->UnloadUnusedModels(); } void CClientGame::ReinitMarkers() diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 51f94c9d77..b35e5e858f 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -278,4 +278,5 @@ class __declspec(novtable) CGame virtual bool SetBuildingPoolSize(size_t size) = 0; + virtual void UnloadUnusedModels() = 0; }; diff --git a/Client/sdk/game/CModelInfo.h b/Client/sdk/game/CModelInfo.h index c578be1990..785fe81b40 100644 --- a/Client/sdk/game/CModelInfo.h +++ b/Client/sdk/game/CModelInfo.h @@ -181,7 +181,7 @@ class CModelInfo virtual void ModelAddRef(EModelRequestType requestType, const char* szTag /* = NULL*/) = 0; virtual void RemoveRef(bool bRemoveExtraGTARef = false) = 0; - virtual int GetRefCount() = 0; + virtual int GetRefCount() const = 0; virtual bool ForceUnload() = 0; virtual bool UnloadUnused() = 0; virtual void DeallocateModel() = 0; diff --git a/Client/sdk/game/CTxdPool.h b/Client/sdk/game/CTxdPool.h index 1e4ff3493b..f186d8dff9 100644 --- a/Client/sdk/game/CTxdPool.h +++ b/Client/sdk/game/CTxdPool.h @@ -19,4 +19,5 @@ class CTxdPool virtual bool IsFreeTextureDictonarySlot(std::uint32_t uiTxdID) = 0; virtual std::uint16_t GetFreeTextureDictonarySlot() = 0; + virtual std::uint16_t GetRefsCount(std::uint16_t slot) const = 0; };