Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions Client/game_sa/CModelInfoSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static void* ARRAY_ModelInfo = *(void**)(0x403DA4 + 3);
#define FUNC_CText_Get 0x6A0050
#define FUNC_GetBoundingBox 0x4082F0

#define FUNC_AddRef 0x4C4BA0
#define FUNC_RemoveRef 0x4C4BB0
#define FUNC_IsBoatModel 0x4c5a70
#define FUNC_IsCarModel 0x4c5aa0
Expand Down Expand Up @@ -154,6 +155,9 @@ enum class eModelSpecialType : unsigned char
class CBaseModelInfoSAInterface
{
public:
void AddRef() { ((void(__thiscall*)(CBaseModelInfoSAInterface*))FUNC_AddRef)(this); }
void RemoveRef() { ((void(__thiscall*)(CBaseModelInfoSAInterface*))FUNC_RemoveRef)(this); }

CBaseModelInfo_SA_VTBL* VFTBL; // +0

unsigned long ulHashKey; // +4 Generated by CKeyGen::GetUppercaseKey(char const *) called by CBaseModelInfo::SetModelName(char const *)
Expand Down
33 changes: 12 additions & 21 deletions Client/game_sa/CRendererSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,17 @@ void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix, flo
if (!pModelInfoSAInterface)
return;

// Prevent GC from freeing RwObject during rendering
pModelInfo->ModelAddRef(NON_BLOCKING, "CRendererSA::RenderModel");

// Revalidate interface after AddRef
pModelInfoSAInterface = pModelInfo->GetInterface();
if (!pModelInfoSAInterface)
{
pModelInfo->RemoveRef();
return;
}

// Check and cache pRwObject
RwObject* pRwObject = pModelInfoSAInterface->pRwObject;
if (!pRwObject)
{
// Release reference before early return to prevent leak
pModelInfo->RemoveRef();
return;
}

// Prevent GC from freeing RwObject/TXD during rendering by calling GTA's
// native CBaseModelInfo::AddRef/RemoveRef. These manage usNumberOfRefs and
// texture dictionary refs without going through MTA's ref-counting (which
// triggers Remove() when m_dwReferences drops to 0, unloading the model
// every frame for dxDrawModel3D models with no persistent MTA-side reference
// -- causing visible flickering).
pModelInfoSAInterface->AddRef();

RwFrame* pFrame = RpGetFrame(pRwObject);

Expand All @@ -61,7 +53,6 @@ void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix, flo
rwMatrix.pos = (RwV3d&)matrix.vPos;
RwFrameTransform(pFrame, &rwMatrix, rwCOMBINEREPLACE);

// Ensure reference released on exception
try
{
// Setup ambient light multiplier
Expand All @@ -83,9 +74,9 @@ void CRendererSA::RenderModel(CModelInfo* pModelInfo, const CMatrix& matrix, flo
}
catch (...)
{
// Release reference on rendering exception
pModelInfo->RemoveRef();
pModelInfoSAInterface->RemoveRef();
throw;
} // Release reference - allow GC
pModelInfo->RemoveRef();
}

pModelInfoSAInterface->RemoveRef();
}