Skip to content

Commit 8dab823

Browse files
authored
Merge pull request #18484 from hrydgard/mlb-fix
Fix frozen pitch meters in MLB series games - we were not hashing enough texture data
2 parents 7bf8023 + 877324c commit 8dab823

File tree

6 files changed

+27
-11
lines changed

6 files changed

+27
-11
lines changed

Common/UI/Screen.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "Core/KeyMap.h"
1515

1616
void Screen::focusChanged(ScreenFocusChange focusChange) {
17-
char *eventName = "";
17+
const char *eventName = "";
1818
switch (focusChange) {
1919
case ScreenFocusChange::FOCUS_LOST_TOP: eventName = "FOCUS_LOST_TOP"; break;
2020
case ScreenFocusChange::FOCUS_BECAME_TOP: eventName = "FOCUS_BECAME_TOP"; break;

GPU/Common/TextureCacheCommon.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
494494
// Exponential backoff up to 512 frames. Textures are often reused.
495495
if (entry->numFrames > 32) {
496496
// Also, try to add some "randomness" to avoid rehashing several textures the same frame.
497+
// textureName is unioned with texturePtr and vkTex so will work for the other backends.
497498
entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (((intptr_t)(entry->textureName) >> 12) & 15);
498499
} else {
499500
entry->framesUntilNextFullHash = entry->numFrames;
@@ -2114,7 +2115,8 @@ void TextureCacheCommon::ApplyTexture() {
21142115
// Update the hash on the texture.
21152116
int w = gstate.getTextureWidth(0);
21162117
int h = gstate.getTextureHeight(0);
2117-
entry->fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry);
2118+
bool swizzled = gstate.isTextureSwizzled();
2119+
entry->fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, swizzled, GETextureFormat(entry->format), entry);
21182120

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

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

25522555
if (fullhash == entry->fullhash) {

GPU/Common/TextureCacheCommon.h

+13-3
Original file line numberDiff line numberDiff line change
@@ -438,16 +438,26 @@ class TextureCacheCommon {
438438

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

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

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

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

453463
gpuStats.numTextureDataBytesHashed += sizeInRAM;

GPU/Common/TextureReplacer.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,12 @@ void TextureReplacer::ParseReduceHashRange(const std::string& key, const std::st
457457
reducehashranges_[reducerangeKey] = rhashvalue;
458458
}
459459

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

463+
// TODO: Take swizzled into account, like in QuickTexHash().
464+
// Note: Currently, only the MLB games are known to need this.
465+
463466
if (!LookupHashRange(addr, w, h, &w, &h)) {
464467
// There wasn't any hash range, let's fall back to maxSeenV logic.
465468
if (h == 512 && maxSeenV < 512 && maxSeenV != 0) {

GPU/Common/TextureReplacer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class TextureReplacer {
101101
bool Enabled() const { return enabled_; }
102102
bool AllowVideo() const { return allowVideo_; }
103103

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

106106
// Returns nullptr if not found.
107107
ReplacedTexture *FindReplacement(u64 cachekey, u32 hash, int w, int h);

GPU/Vulkan/TextureCacheVulkan.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -503,11 +503,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
503503
case VULKAN_4444_FORMAT: mapping = &VULKAN_4444_SWIZZLE; break;
504504
case VULKAN_1555_FORMAT: mapping = &VULKAN_1555_SWIZZLE; break;
505505
case VULKAN_565_FORMAT: mapping = &VULKAN_565_SWIZZLE; break;
506-
default: mapping = &VULKAN_8888_SWIZZLE; break; // no swizzle
506+
default: mapping = &VULKAN_8888_SWIZZLE; break; // no channel swizzle
507507
}
508508

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

0 commit comments

Comments
 (0)