Tweak: Improve pause menu dungeon map performance (#3773)

* add map palettes per pulse to leverage shader caching

* use unregister blended with kaleido maps

* use Gfx_TextureCacheDelete for KD lava

* bump lus

* add miss tex clears for KD
This commit is contained in:
Archez 2024-01-15 10:39:54 -05:00 committed by GitHub
parent db02870a05
commit 1da1b1a2bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 66 additions and 40 deletions

@ -1 +1 @@
Subproject commit b4abd7c366b1fb38b2cd80ffb91e129035bee0ea
Subproject commit 96c8a8929c18c1bffd7d92a35a589f74cf16fc59

View File

@ -744,7 +744,6 @@ typedef struct {
/* 0x0134 */ char** doActionSegment;
/* 0x0138 */ u8* iconItemSegment;
/* 0x013C */ char** mapSegment;
char** mapSegmentName;
/* 0x0140 */ u8 mapPalette[32];
/* 0x0160 */ DmaRequest dmaRequest_160;
/* 0x0180 */ DmaRequest dmaRequest_180;
@ -815,6 +814,10 @@ typedef struct {
/* 0x026C */ u8 dinsNayrus; // "m_magic"; din's fire and nayru's love
/* 0x026D */ u8 all; // "another"; enables all item restrictions
} restrictions;
// #region SOH [General]
/* */ char* mapSegmentName[2]; // Tracks the map segment texture by OTR sig name
/* */ u8 mapPalettesPulse[40][32]; // Used to have unique pointers per map pulse color for the shader backend. 40 for map pulse timer x2
// #endregion
} InterfaceContext; // size = 0x270
typedef struct {

View File

@ -2598,6 +2598,24 @@ extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* repla
gfx_register_blended_texture(name, mask, replacement);
}
extern "C" void Gfx_UnregisterBlendedTexture(const char* name) {
gfx_unregister_blended_texture(name);
}
extern "C" void Gfx_TextureCacheDelete(const uint8_t* texAddr) {
char* imgName = (char*)texAddr;
if (texAddr == nullptr) {
return;
}
if (ResourceMgr_OTRSigCheck(imgName)) {
texAddr = (const uint8_t*)GetResourceDataByNameHandlingMQ(imgName);
}
gfx_texture_cache_delete(texAddr);
}
void SoH_ProcessDroppedFiles(std::string filePath) {
try {
std::ifstream configStream(filePath);

View File

@ -173,6 +173,8 @@ void Entrance_InitEntranceTrackingData(void);
void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex);
void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex);
void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement);
void Gfx_UnregisterBlendedTexture(const char* name);
void Gfx_TextureCacheDelete(const uint8_t* addr);
void SaveManager_ThreadPoolWait();
void CheckTracker_OnMessageClose();

View File

@ -524,7 +524,6 @@ void Map_Init(PlayState* play) {
interfaceCtx->unk_25A = -1;
interfaceCtx->mapSegment = GAMESTATE_ALLOC_MC(&play->state, 2 * sizeof(char*));
interfaceCtx->mapSegmentName = GAMESTATE_ALLOC_MC(&play->state, 2 * sizeof(char*));
// " texture initialization scene_data_ID=%d mapSegment=%x"
osSyncPrintf("\n\n\n テクスチャ初期化 scene_data_ID=%d\nmapSegment=%x\n\n", play->sceneNum,
interfaceCtx->mapSegment, play);

View File

@ -10,10 +10,6 @@
#include <stdlib.h> // malloc
#include <string.h> // memcpy
// OTRTODO: Replace usage of this method when we can clear the cache
// for a single texture without the need of a DL opcode in the render code
void gfx_texture_cache_clear();
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
#define LAVA_TEX_WIDTH 32
@ -123,7 +119,9 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() {
sMaskTexLava[i] = maskVal;
}
}
Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, NULL);
Gfx_TextureCacheDelete(sMaskTexLava);
return;
}
@ -165,7 +163,9 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() {
}
}
gfx_texture_cache_clear();
Gfx_TextureCacheDelete(sMaskTexLava);
Gfx_TextureCacheDelete(sLavaWavyTex);
Gfx_TextureCacheDelete(sLavaFloorModifiedTex);
}
void func_808C12C4(u8* arg1, s16 arg2) {
@ -228,6 +228,7 @@ void func_808C1554_Raw(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
}
free(sp54);
Gfx_TextureCacheDelete(sLavaWavyTexRaw);
}
// Modified to support CPU modified texture with the resource system
@ -255,6 +256,8 @@ void func_808C1554(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
temp_s3[i + temp2] = sp54[i + i2];
}
}
Gfx_TextureCacheDelete(sLavaWavyTex);
}
void func_808C17C8(PlayState* play, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, f32 arg4, s16 arg5) {
@ -373,6 +376,13 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) {
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016990, sMaskTex32x16, NULL);
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016E10, sMaskTex32x16, NULL);
// Clear cache for masks
Gfx_TextureCacheDelete(sMaskTex8x16);
Gfx_TextureCacheDelete(sMaskTex8x32);
Gfx_TextureCacheDelete(sMaskTex16x16);
Gfx_TextureCacheDelete(sMaskTex16x32);
Gfx_TextureCacheDelete(sMaskTex32x16);
BossDodongo_RegisterBlendedLavaTextureUpdate();
// Register alt listener to update the blended lava for the replacement texture based on alt path
@ -1206,6 +1216,7 @@ void BossDodongo_Update(Actor* thisx, PlayState* play2) {
}
} else {
sMaskTexLava[new_var] = 1;
Gfx_TextureCacheDelete(sMaskTexLava);
}
this->unk_1C2 += 37;
@ -1345,18 +1356,6 @@ void BossDodongo_Draw(Actor* thisx, PlayState* play) {
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTex32x16);
}
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTexLava);
// Using WORK_DISP to invalidate these textures as they are used in drawing the scene textures which happens
// before actors are drawn. WORK_DISP comes before POLAY_OPA_DISP. It is probably not meant for this, but it
// at least works for now.
// Alternatively, having a way to invalidate just these pointers from the Update func should be sufficient.
if (sLavaFloorModifiedTexRaw != NULL) {
gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTexRaw);
} else {
gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTex);
}
if ((this->unk_1C0 >= 2) && (this->unk_1C0 & 1)) {
POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 255, 255, 0, 900, 1099);
} else {

View File

@ -312,6 +312,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
KaleidoScope_DrawQuadTextureRGBA32(gfxCtx, gQuestIconGoldSkulltulaTex, 24, 24, 8);
}
// Unique index for both pulse phases
uint8_t palettePulseIdx = (mapBgPulseStage ? 40 : 20) - mapBgPulseTimer;
if ((play->sceneNum >= SCENE_DEKU_TREE) && (play->sceneNum <= SCENE_TREASURE_BOX_SHOP)) {
stepR = (mapBgPulseR - mapBgPulseColors[mapBgPulseStage][0]) / mapBgPulseTimer;
stepG = (mapBgPulseG - mapBgPulseColors[mapBgPulseStage][1]) / mapBgPulseTimer;
@ -324,6 +327,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
interfaceCtx->mapPalette[28] = (rgba16 & 0xFF00) >> 8;
interfaceCtx->mapPalette[29] = rgba16 & 0xFF;
interfaceCtx->mapPalettesPulse[palettePulseIdx][28] = (rgba16 & 0xFF00) >> 8;
interfaceCtx->mapPalettesPulse[palettePulseIdx][29] = rgba16 & 0xFF;
mapBgPulseTimer--;
if (mapBgPulseTimer == 0) {
mapBgPulseStage ^= 1;
@ -335,7 +341,8 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
gDPSetTextureFilter(POLY_KAL_DISP++, G_TF_POINT);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha);
gDPLoadTLUT_pal16(POLY_KAL_DISP++, 0, interfaceCtx->mapPalette);
// Use a unique palette address per frame so the renderer/shader can cache all variations
gDPLoadTLUT_pal16(POLY_KAL_DISP++, 0, interfaceCtx->mapPalettesPulse[palettePulseIdx]);
gDPSetTextureLUT(POLY_KAL_DISP++, G_TT_RGBA16);
u8 mirroredWorld = CVarGetInteger("gMirroredWorld", 0);
@ -349,10 +356,6 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
gSPVertex(POLY_KAL_DISP++, &pauseCtx->mapPageVtx[60], 8, 0);
// The dungeon map textures are recreated each frame, so always invalidate them
gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[0]);
gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[1]);
gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_CI, MAP_48x85_TEX_WIDTH,
MAP_48x85_TEX_HEIGHT, 0, G_TX_WRAP | mirrorMode, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);

View File

@ -1205,8 +1205,6 @@ Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, void** textures) {
return gfx;
}
static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT];
void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
static Color_RGB8 D_8082ACF4[12] = {
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 },
@ -1375,10 +1373,6 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
}
}
// Need to invalidate the blend mask every frame. Ideally this would be done in KaleidoScope_DrawDungeonMap
// but the reference is not shared between files
gSPInvalidateTexCache(POLY_KAL_DISP++, mapBlendMask);
if (pauseCtx->pageIndex) { // pageIndex != PAUSE_ITEM
gDPPipeSync(OVERLAY_DISP++);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA, G_CC_MODULATEIA);
@ -3326,6 +3320,7 @@ static uint8_t mapLeftTexModified[MAP_48x85_TEX_SIZE];
static uint8_t mapRightTexModified[MAP_48x85_TEX_SIZE];
static uint8_t* mapLeftTexModifiedRaw = NULL;
static uint8_t* mapRightTexModifiedRaw = NULL;
static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT];
// Load dungeon maps into the interface context
// SoH [General] - Modified to account for our resource system and HD textures
@ -3357,19 +3352,16 @@ void KaleidoScope_LoadDungeonMap(PlayState* play) {
size_t size = (width * height) / 2; // account for CI4 size
// Resource size being larger than the calculated CI size means it is most likely not a CI4 texture
// Abort early end undo the blended effect by clearing the mask to avoid crashing
// Abort early and unregister the blended effect to avoid crashing
if (size < ResourceGetTexSizeByName(interfaceCtx->mapSegmentName[0])) {
if (mapBlendMask[0] != 0) {
for (size_t i = 0; i < ARRAY_COUNT(mapBlendMask); i++) {
mapBlendMask[i] = 0;
}
}
interfaceCtx->mapSegment[0] = NULL;
interfaceCtx->mapSegment[1] = NULL;
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, NULL);
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, NULL);
Gfx_UnregisterBlendedTexture(interfaceCtx->mapSegmentName[0]);
Gfx_UnregisterBlendedTexture(interfaceCtx->mapSegmentName[1]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[0]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[1]);
return;
}
@ -3404,6 +3396,11 @@ void KaleidoScope_LoadDungeonMap(PlayState* play) {
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, interfaceCtx->mapSegment[0]);
Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, interfaceCtx->mapSegment[1]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[0]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[1]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegment[0]);
Gfx_TextureCacheDelete(interfaceCtx->mapSegment[1]);
}
static uint8_t registeredDungeonMapTextureHook = false;
@ -3444,6 +3441,11 @@ void KaleidoScope_UpdateDungeonMap(PlayState* play) {
KaleidoScope_LoadDungeonMap(play);
Map_SetFloorPalettesData(play, pauseCtx->dungeonMapSlot - 3);
// Copy the map palette values to all pulse palettes
for (uint8_t i = 0; i < ARRAY_COUNT(interfaceCtx->mapPalettesPulse); i++) {
memcpy(interfaceCtx->mapPalettesPulse[i], interfaceCtx->mapPalette, sizeof(interfaceCtx->mapPalette));
}
s32 size = MAP_48x85_TEX_SIZE;
if (ResourceMgr_TexIsRaw(interfaceCtx->mapSegmentName[0])) {