Skip to content

Commit

Permalink
fix: unload all created materials and textures
Browse files Browse the repository at this point in the history
This fixes multiple issues in the overlay render. When creating a
material it was unnecessary to increment the reference count since
the material system does it automatically. When destroying the material
we not only want decrement the reference count but also remove it from
the material dictionary before it gets deleted. Since the material
system returns only a wrapper (`CMaterial_QueueFriendly`) we have to
work with the real material pointer. Otherwise we would end up queueing
operations after SAR has been unloaded. Created textures can now be
destroyed which also releases the custom texture generator.
  • Loading branch information
NeKzor authored and ThisAMJ committed Mar 12, 2024
1 parent 2ec26ae commit d937171
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 11 deletions.
19 changes: 12 additions & 7 deletions src/Features/OverlayRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,21 +225,25 @@ void OverlayRender::addText(Vector pos, const std::string &text, float x_height,
}

static IMaterial *createMaterial(KeyValues *kv, const char *name) {
IMaterial *mat = (IMaterial *)materialSystem->CreateMaterial(materialSystem->materials->ThisPtr(), name, kv);
auto IncrementReferenceCount = Memory::VMT<void (__rescall *)(IMaterial *thisptr)>(mat, 12);
IncrementReferenceCount(mat);
return mat;
return materialSystem->CreateMaterial(materialSystem->materials->ThisPtr(), name, kv);
}

static void destroyMaterial(IMaterial *mat) {
if (!mat) return;
auto DecrementReferenceCount = Memory::VMT<void (__rescall *)(IMaterial *thisptr)>(mat, 13);
DecrementReferenceCount(mat);

auto material = reinterpret_cast<CMaterial_QueueFriendly*>(mat)->m_pRealTimeVersion;

auto DecrementReferenceCount = Memory::VMT<void (__rescall *)(IMaterialInternal *thisptr)>(material, Offsets::DecrementReferenceCount);
DecrementReferenceCount(material);

materialSystem->RemoveMaterial(materialSystem->materials->ThisPtr(), material);
mat = nullptr;
}

static IMaterial *g_mat_solid_opaque, *g_mat_solid_opaque_noz, *g_mat_solid_alpha, *g_mat_solid_alpha_noz;
static IMaterial *g_mat_wireframe_opaque, *g_mat_wireframe_opaque_noz, *g_mat_wireframe_alpha, *g_mat_wireframe_alpha_noz;
static IMaterial *g_mat_font, *g_mat_font_noz;
static ITexture *g_tex_font_atlas;

void OverlayRender::initMaterials() {
KeyValues *kv;
Expand Down Expand Up @@ -284,7 +288,7 @@ void OverlayRender::initMaterials() {
kv->SetInt("$ignorez", 1);
g_mat_wireframe_alpha_noz = createMaterial(kv, "_SAR_UnlitWireframeAlphaNoDepth");

materialSystem->CreateTexture("_SAR_FontAtlasTex", FONT_ATLAS_WIDTH, FONT_ATLAS_HEIGHT, FONT_ATLAS_DATA);
g_tex_font_atlas = materialSystem->CreateTexture("_SAR_FontAtlasTex", FONT_ATLAS_WIDTH, FONT_ATLAS_HEIGHT, FONT_ATLAS_DATA);

kv = new KeyValues("unlitgeneric");
kv->SetInt("$vertexcolor", 1);
Expand Down Expand Up @@ -313,6 +317,7 @@ ON_EVENT(SAR_UNLOAD) {
destroyMaterial(g_mat_wireframe_opaque_noz);
destroyMaterial(g_mat_font);
destroyMaterial(g_mat_font_noz);
materialSystem->DestroyTexture(g_tex_font_atlas);
}

static void drawVerts(IMaterial *mat, bool lines, Vector *verts, int nverts, Color col) {
Expand Down
7 changes: 7 additions & 0 deletions src/Games/ApertureTag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ void ApertureTag::LoadOffsets() {

// client.dll
m_pCommands = 228; // CInput::DecodeUserCmdFromBuffer

// materialsystem.dll
RemoveMaterial = 155;
#else
// client.so
m_pCommands = 228; // CInput::DecodeUserCmdFromBuffer
Expand All @@ -54,6 +57,10 @@ void ApertureTag::LoadOffsets() {
#define OFFSET_EMPTY(name)
#define OFFSET_LINMOD(name, off) name = off;
#include "OffsetsData.hpp"

// materialsystem.so
RemoveMaterial = 156;
g_pTextureManager = 10;
#endif
}
const char *ApertureTag::Version() {
Expand Down
16 changes: 12 additions & 4 deletions src/Modules/MaterialSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ DETOUR(MaterialSystem::UncacheUnusedMaterials, bool bRecomputeStateSnapshots) {
bool MaterialSystem::Init() {
this->materials = Interface::Create(this->Name(), "VMaterialSystem080");
if (this->materials) {
this->materials->Hook(MaterialSystem::UncacheUnusedMaterials_Hook, MaterialSystem::UncacheUnusedMaterials, 77);
this->materials->Hook(MaterialSystem::UncacheUnusedMaterials_Hook, MaterialSystem::UncacheUnusedMaterials, Offsets::UncacheUnusedMaterials);

this->CreateMaterial = this->materials->Original<_CreateMaterial>(81);
this->CreateMaterial = this->materials->Original<_CreateMaterial>(Offsets::CreateMaterial);
this->RemoveMaterial = this->materials->Original<_RemoveMaterial>(Offsets::RemoveMaterial);

#if _WIN32
this->KeyValues_SetString = (_KeyValues_SetString)Memory::Scan(this->Name(), "55 8B EC 8B 45 08 6A 01 50 E8 ? ? ? ? 85 C0 74 0B");
Expand Down Expand Up @@ -95,8 +96,15 @@ ITexture *MaterialSystem::CreateTexture(const char *name, int w, int h, uint8_t
tex->Download();

return tex;

// TODO: destroy textures
}
void MaterialSystem::DestroyTexture(ITexture *tex) {
if (tex) {
auto CreateProceduralTexture = this->materials->Current(Offsets::CreateProceduralTexture);
auto g_pTextureManager = Memory::DerefDeref(CreateProceduralTexture + Offsets::g_pTextureManager);
auto RemoveTexture = Memory::VMT<void(__rescall*)(void*, ITexture*)>(g_pTextureManager, Offsets::RemoveTexture);
RemoveTexture(g_pTextureManager, tex);
tex = nullptr;
}
}
IMatRenderContext *MaterialSystem::GetRenderContext() {
auto func = (IMatRenderContext *(__rescall *)(void *))this->materials->Current(Offsets::GetRenderContext);
Expand Down
4 changes: 4 additions & 0 deletions src/Modules/MaterialSystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class MaterialSystem : public Module {

using _CreateMaterial = IMaterial*(__rescall*)(void* thisptr, const char *pMaterialName, void *pVMTKeyValues);
_CreateMaterial CreateMaterial = nullptr;

using _RemoveMaterial = void(__rescall*)(void* thisptr, IMaterialInternal* pMaterial);
_RemoveMaterial RemoveMaterial = nullptr;

using _KeyValues_SetString = void(__rescall*)(void* thistpr, const char *key, const char *val);
_KeyValues_SetString KeyValues_SetString = nullptr;
Expand All @@ -26,6 +29,7 @@ class MaterialSystem : public Module {

IMaterial *FindMaterial(const char *materialName, const char *textureGroupName);
ITexture *CreateTexture(const char *name, int w, int h, uint8_t *bgra);
void DestroyTexture(ITexture *tex);
IMatRenderContext *GetRenderContext();
};

Expand Down
6 changes: 6 additions & 0 deletions src/OffsetsData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,14 @@ OFFSET_DEFAULT(snd_linear_count, 63, 69)
OFFSET_DEFAULT(snd_p, 98, 116)
OFFSET_DEFAULT(snd_vol, 108, 122)
OFFSET_DEFAULT(StartTouch, 102, 103)
OFFSET_DEFAULT(UncacheUnusedMaterials, 77, 77)
OFFSET_DEFAULT(CreateMaterial, 81, 81)
OFFSET_DEFAULT(FindMaterial, 82, 82)
OFFSET_DEFAULT(CreateProceduralTexture, 91, 91)
OFFSET_DEFAULT(RemoveMaterial, 156, 157)
OFFSET_DEFAULT(DecrementReferenceCount, 13, 13)
OFFSET_DEFAULT(g_pTextureManager, 8, 4)
OFFSET_DEFAULT(RemoveTexture, 30, 30)
OFFSET_DEFAULT(GetRenderContext, 113, 113)
OFFSET_DEFAULT(CreateDebugMesh, 41, 42)
OFFSET_DEFAULT(DestroyDebugMesh, 42, 43)
Expand Down
7 changes: 7 additions & 0 deletions src/Utils/SDK/Other.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ enum {


class IMaterial;
class IMaterialInternal;

class CMaterial_QueueFriendly {
public:
void* vtable;
IMaterialInternal* m_pRealTimeVersion;
};

struct CFontAmalgam {
struct TFontRange {
Expand Down

0 comments on commit d937171

Please sign in to comment.