GPU: Force texture invalidation for ZHP minimap.

See #14069, our texture hash misses this change.
This commit is contained in:
Unknown W. Brackets 2021-02-07 09:02:28 -08:00
parent 5d60fa0d0d
commit ec3bfe08ae
4 changed files with 35 additions and 10 deletions

View file

@ -20,6 +20,7 @@
#include <unordered_map>
#include "Common/Common.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Log.h"
#include "Core/Config.h"
#include "Core/Debugger/Breakpoints.h"
@ -1053,6 +1054,20 @@ static int Hook_youkosohitsujimura_download_frame() {
return 0;
}
static int Hook_zettai_hero_update_minimap_tex() {
const MIPSOpcode storeOffset = Memory::Read_Instruction(currentMIPS->pc + 4, true);
const uint32_t texAddr = currentMIPS->r[MIPS_REG_A0] + SignExtend16ToS32(storeOffset);
const uint32_t texSize = 64 * 64 * 1;
const uint32_t writeAddr = currentMIPS->r[MIPS_REG_V1] + SignExtend16ToS32(storeOffset);
if (Memory::IsValidRange(texAddr, texSize) && writeAddr >= texAddr && writeAddr < texAddr + texSize) {
const uint8_t currentValue = Memory::Read_U8(writeAddr);
if (currentValue != currentMIPS->r[MIPS_REG_A3]) {
gpu->InvalidateCache(texAddr, texSize, GPU_INVALIDATE_FORCE);
}
}
return 0;
}
static int Hook_tonyhawkp8_upload_tutorial_frame() {
const u32 fb_address = currentMIPS->r[MIPS_REG_A0];
if (Memory::IsVRAMAddress(fb_address)) {
@ -1323,6 +1338,7 @@ static const ReplacementTableEntry entries[] = {
{ "photokano_download_frame_2", &Hook_photokano_download_frame_2, 0, REPFLAG_HOOKENTER, },
{ "gakuenheaven_download_frame", &Hook_gakuenheaven_download_frame, 0, REPFLAG_HOOKENTER, },
{ "youkosohitsujimura_download_frame", &Hook_youkosohitsujimura_download_frame, 0, REPFLAG_HOOKENTER, 0x94 },
{ "zettai_hero_update_minimap_tex", &Hook_zettai_hero_update_minimap_tex, 0, REPFLAG_HOOKEXIT, },
{ "tonyhawkp8_upload_tutorial_frame", &Hook_tonyhawkp8_upload_tutorial_frame, 0, REPFLAG_HOOKENTER, },
{ "sdgundamggenerationportable_download_frame", &Hook_sdgundamggenerationportable_download_frame, 0, REPFLAG_HOOKENTER, 0x34 },
{ "atvoffroadfurypro_download_frame", &Hook_atvoffroadfurypro_download_frame, 0, REPFLAG_HOOKENTER, 0xA0 },

View file

@ -102,6 +102,7 @@ static const HardHashTableEntry hardcodedHashes[] = {
{ 0x030507c9a1f0fc85, 92, "matrix_rot_x", },
{ 0x0483fceefa4557ff, 1360, "__udivdi3", },
{ 0x0558ad5c5be00ca1, 76, "vtfm_t", },
{ 0x05aceb23092fd6a1, 36, "zettai_hero_update_minimap_tex", }, // Zettai Hero Project (US)
{ 0x05aedd0c04b451a1, 356, "sqrt", },
{ 0x0654fc8adbe16ef7, 28, "vmul_q", },
{ 0x06628f6052cda3c1, 1776, "toheart2_download_frame", }, // To Heart 2 Portable

View file

@ -1795,7 +1795,7 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type
}
// If we're hashing every use, without backoff, then this isn't needed.
if (!g_Config.bTextureBackoffCache) {
if (!g_Config.bTextureBackoffCache && type != GPU_INVALIDATE_FORCE) {
return;
}
@ -1806,28 +1806,34 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type
}
for (TexCache::iterator iter = cache_.lower_bound(startKey), end = cache_.upper_bound(endKey); iter != end; ++iter) {
u32 texAddr = iter->second->addr;
u32 texEnd = iter->second->addr + iter->second->sizeInRAM;
auto &entry = iter->second;
u32 texAddr = entry->addr;
u32 texEnd = entry->addr + entry->sizeInRAM;
// Quick check for overlap. Yes the check is right.
if (addr < texEnd && addr_end > texAddr) {
if (iter->second->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) {
iter->second->SetHashStatus(TexCacheEntry::STATUS_HASHING);
if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) {
entry->SetHashStatus(TexCacheEntry::STATUS_HASHING);
}
if (type == GPU_INVALIDATE_FORCE) {
// Just random values to force the hash not to match.
entry->fullhash = (entry->fullhash ^ 0x12345678) + 13;
entry->hash = (entry->hash ^ 0x89ABCDEF) + 89;
}
if (type != GPU_INVALIDATE_ALL) {
gpuStats.numTextureInvalidations++;
// Start it over from 0 (unless it's safe.)
iter->second->numFrames = type == GPU_INVALIDATE_SAFE ? 256 : 0;
entry->numFrames = type == GPU_INVALIDATE_SAFE ? 256 : 0;
if (type == GPU_INVALIDATE_SAFE) {
u32 diff = gpuStats.numFlips - iter->second->lastFrame;
u32 diff = gpuStats.numFlips - entry->lastFrame;
// We still need to mark if the texture is frequently changing, even if it's safely changing.
if (diff < TEXCACHE_FRAME_CHANGE_FREQUENT) {
iter->second->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT;
entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT;
}
}
iter->second->framesUntilNextFullHash = 0;
entry->framesUntilNextFullHash = 0;
} else {
iter->second->invalidHint++;
entry->invalidHint++;
}
}
}

View file

@ -153,6 +153,8 @@ enum GPUInvalidationType {
GPU_INVALIDATE_HINT,
// Reliable invalidation (where any hashing, etc. is unneeded, it'll always invalidate.)
GPU_INVALIDATE_SAFE,
// Forced invalidation for when the texture hash may not catch changes.
GPU_INVALIDATE_FORCE,
};
namespace Draw {