Skip to content

Commit

Permalink
Merge pull request #18484 from hrydgard/mlb-fix
Browse files Browse the repository at this point in the history
Fix frozen pitch meters in MLB series games - we were not hashing enough texture data
  • Loading branch information
hrydgard committed Dec 7, 2023
2 parents 7bf8023 + 877324c commit 8dab823
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Common/UI/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "Core/KeyMap.h"

void Screen::focusChanged(ScreenFocusChange focusChange) {
char *eventName = "";
const char *eventName = "";
switch (focusChange) {
case ScreenFocusChange::FOCUS_LOST_TOP: eventName = "FOCUS_LOST_TOP"; break;
case ScreenFocusChange::FOCUS_BECAME_TOP: eventName = "FOCUS_BECAME_TOP"; break;
Expand Down
7 changes: 5 additions & 2 deletions GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
// Exponential backoff up to 512 frames. Textures are often reused.
if (entry->numFrames > 32) {
// Also, try to add some "randomness" to avoid rehashing several textures the same frame.
// textureName is unioned with texturePtr and vkTex so will work for the other backends.
entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (((intptr_t)(entry->textureName) >> 12) & 15);
} else {
entry->framesUntilNextFullHash = entry->numFrames;
Expand Down Expand Up @@ -2114,7 +2115,8 @@ void TextureCacheCommon::ApplyTexture() {
// Update the hash on the texture.
int w = gstate.getTextureWidth(0);
int h = gstate.getTextureHeight(0);
entry->fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry);
bool swizzled = gstate.isTextureSwizzled();
entry->fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, swizzled, GETextureFormat(entry->format), entry);

// TODO: Here we could check the secondary cache; maybe the texture is in there?
// We would need to abort the build if so.
Expand Down Expand Up @@ -2535,6 +2537,7 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) {
int w = gstate.getTextureWidth(0);
int h = gstate.getTextureHeight(0);
bool isVideo = IsVideo(entry->addr);
bool swizzled = gstate.isTextureSwizzled();

// Don't even check the texture, just assume it has changed.
if (isVideo && g_Config.bTextureBackoffCache) {
Expand All @@ -2546,7 +2549,7 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) {
u32 fullhash;
{
PROFILE_THIS_SCOPE("texhash");
fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry);
fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, swizzled, GETextureFormat(entry->format), entry);
}

if (fullhash == entry->fullhash) {
Expand Down
16 changes: 13 additions & 3 deletions GPU/Common/TextureCacheCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,16 +438,26 @@ class TextureCacheCommon {

static CheckAlphaResult CheckCLUTAlpha(const uint8_t *pixelData, GEPaletteFormat clutFmt, int w);

inline u32 QuickTexHash(TextureReplacer &replacer, u32 addr, int bufw, int w, int h, GETextureFormat format, const TexCacheEntry *entry) const {
static inline u32 QuickTexHash(TextureReplacer &replacer, u32 addr, int bufw, int w, int h, bool swizzled, GETextureFormat format, const TexCacheEntry *entry) {
if (replacer.Enabled()) {
return replacer.ComputeHash(addr, bufw, w, h, format, entry->maxSeenV);
return replacer.ComputeHash(addr, bufw, w, h, swizzled, format, entry->maxSeenV);
}

if (h == 512 && entry->maxSeenV < 512 && entry->maxSeenV != 0) {
h = (int)entry->maxSeenV;
}

const u32 sizeInRAM = (textureBitsPerPixel[format] * bufw * h) / 8;
u32 sizeInRAM;
if (swizzled) {
// In swizzle mode, textures are stored in rectangular blocks with the height 8.
// That means that for a 64x4 texture, like in issue #9308, we would only hash half of the texture!
// In theory, we should make sure to only hash half of each block, but in reality it's not likely that
// games are using that memory for anything else. So we'll just make sure to compute the full size to hash.
// To do that, we just use the same calculation but round the height upwards to the nearest multiple of 8.
sizeInRAM = (textureBitsPerPixel[format] * bufw * ((h + 7) & ~7)) >> 3;
} else {
sizeInRAM = (textureBitsPerPixel[format] * bufw * h) >> 3;
}
const u32 *checkp = (const u32 *)Memory::GetPointer(addr);

gpuStats.numTextureDataBytesHashed += sizeInRAM;
Expand Down
5 changes: 4 additions & 1 deletion GPU/Common/TextureReplacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,9 +457,12 @@ void TextureReplacer::ParseReduceHashRange(const std::string& key, const std::st
reducehashranges_[reducerangeKey] = rhashvalue;
}

u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV) {
u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, bool swizzled, GETextureFormat fmt, u16 maxSeenV) {
_dbg_assert_msg_(enabled_, "Replacement not enabled");

// TODO: Take swizzled into account, like in QuickTexHash().
// Note: Currently, only the MLB games are known to need this.

if (!LookupHashRange(addr, w, h, &w, &h)) {
// There wasn't any hash range, let's fall back to maxSeenV logic.
if (h == 512 && maxSeenV < 512 && maxSeenV != 0) {
Expand Down
2 changes: 1 addition & 1 deletion GPU/Common/TextureReplacer.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class TextureReplacer {
bool Enabled() const { return enabled_; }
bool AllowVideo() const { return allowVideo_; }

u32 ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV);
u32 ComputeHash(u32 addr, int bufw, int w, int h, bool swizzled, GETextureFormat fmt, u16 maxSeenV);

// Returns nullptr if not found.
ReplacedTexture *FindReplacement(u64 cachekey, u32 hash, int w, int h);
Expand Down
6 changes: 3 additions & 3 deletions GPU/Vulkan/TextureCacheVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,11 +503,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
case VULKAN_4444_FORMAT: mapping = &VULKAN_4444_SWIZZLE; break;
case VULKAN_1555_FORMAT: mapping = &VULKAN_1555_SWIZZLE; break;
case VULKAN_565_FORMAT: mapping = &VULKAN_565_SWIZZLE; break;
default: mapping = &VULKAN_8888_SWIZZLE; break; // no swizzle
default: mapping = &VULKAN_8888_SWIZZLE; break; // no channel swizzle
}

char texName[64]{};
snprintf(texName, sizeof(texName), "tex_%08x_%s", entry->addr, GeTextureFormatToString((GETextureFormat)entry->format, gstate.getClutPaletteFormat()));
char texName[64];
snprintf(texName, sizeof(texName), "tex_%08x_%s_%s", entry->addr, GeTextureFormatToString((GETextureFormat)entry->format, gstate.getClutPaletteFormat()), gstate.isTextureSwizzled() ? "swz" : "lin");
entry->vkTex = new VulkanTexture(vulkan, texName);
VulkanTexture *image = entry->vkTex;
bool allocSuccess = image->CreateDirect(cmdInit, plan.createW, plan.createH, plan.depth, plan.levelsToCreate, actualFmt, imageLayout, usage, mapping);
Expand Down

0 comments on commit 8dab823

Please sign in to comment.