From 9cf6f3497db9e59ea431d6b8970f842ef84204cc Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Tue, 7 Apr 2026 21:43:38 +0200 Subject: [PATCH] Fix JUTResFont performance Just store the GXTexObjs in a separately allocated hashmap, so they can be persisted cross-frame. Easy. Fixes #227 --- .../include/JSystem/JUtility/JUTResFont.h | 8 ++++ libs/JSystem/src/JUtility/JUTResFont.cpp | 45 +++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/libs/JSystem/include/JSystem/JUtility/JUTResFont.h b/libs/JSystem/include/JSystem/JUtility/JUTResFont.h index 09d3303da0..8709822d7b 100644 --- a/libs/JSystem/include/JSystem/JUtility/JUTResFont.h +++ b/libs/JSystem/include/JSystem/JUtility/JUTResFont.h @@ -18,6 +18,10 @@ struct BlockHeader { BE(u32) size; }; +#if TARGET_PC +struct GlyphTextures; +#endif + /** * @ingroup jsystem-jutility * @@ -64,7 +68,11 @@ public: // some types uncertain, may need to be fixed /* 0x1C */ int mWidth; /* 0x20 */ int mHeight; +#if TARGET_PC + GlyphTextures* mGlyphTextures; +#else /* 0x24 */ TGXTexObj mTexObj; +#endif /* 0x44 */ int mTexPageIdx; /* 0x48 */ const ResFONT* mResFont; /* 0x4C */ ResFONT::INF1* mInf1Ptr; diff --git a/libs/JSystem/src/JUtility/JUTResFont.cpp b/libs/JSystem/src/JUtility/JUTResFont.cpp index e6410defdc..10443d6404 100644 --- a/libs/JSystem/src/JUtility/JUTResFont.cpp +++ b/libs/JSystem/src/JUtility/JUTResFont.cpp @@ -6,19 +6,39 @@ #include "JSystem/JUtility/JUTAssert.h" #include "JSystem/JUtility/JUTConsole.h" #include +#include "absl/container/node_hash_map.h" + +#if TARGET_PC +struct GlyphTextures { + absl::node_hash_map textures; +}; +#endif JUTResFont::JUTResFont() { +#if TARGET_PC + mGlyphTextures = new GlyphTextures(); +#endif initialize_state(); JUTFont::initialize_state(); } JUTResFont::JUTResFont(const ResFONT* pFont, JKRHeap* pHeap) { +#if TARGET_PC + mGlyphTextures = new GlyphTextures(); +#endif initialize_state(); JUTFont::initialize_state(); initiate(pFont, pHeap); } JUTResFont::~JUTResFont() { +#if TARGET_PC + for (auto& pair : mGlyphTextures->textures) { + pair.second.reset(); + } + delete mGlyphTextures; +#endif + if (mValid) { delete_and_initialize(); JUTFont::initialize_state(); @@ -414,12 +434,30 @@ void JUTResFont::loadImage(int code, GXTexMapID id){ mWidth = cellCol * cellW; mHeight = cellRow * cellH; +#if TARGET_PC + const auto found = mGlyphTextures->textures.find(code); + GXTexObj* texObj; + if (found == mGlyphTextures->textures.end()) { + texObj = &mGlyphTextures->textures[code]; + void* pImg = &mpGlyphBlocks[i]->data[pageIdx * mpGlyphBlocks[i]->textureSize]; + GXInitTexObj(texObj, pImg, mpGlyphBlocks[i]->textureWidth, + mpGlyphBlocks[i]->textureHeight, (GXTexFmt)(u16)mpGlyphBlocks[i]->textureFormat, + GX_CLAMP, GX_CLAMP, 0); + + GXInitTexObjLOD(texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0U, 0U, GX_ANISO_1); + } else { + texObj = &found->second; + } + + GXLoadTexObj(texObj, id); + + // Gets used by some other code. + mTexPageIdx = pageIdx; + field_0x66 = i; +#else if (pageIdx != mTexPageIdx || i != field_0x66) { void* pImg = &mpGlyphBlocks[i]->data[pageIdx * mpGlyphBlocks[i]->textureSize]; -#ifdef TARGET_PC - mTexObj.reset(); -#endif GXInitTexObj(&mTexObj, pImg, mpGlyphBlocks[i]->textureWidth, mpGlyphBlocks[i]->textureHeight, (GXTexFmt)(u16)mpGlyphBlocks[i]->textureFormat, GX_CLAMP, GX_CLAMP, 0); @@ -430,6 +468,7 @@ void JUTResFont::loadImage(int code, GXTexMapID id){ } GXLoadTexObj(&mTexObj, id); +#endif } }