summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authoriwubcode <iwubcode@users.noreply.github.com>2021-05-06 20:55:39 -0500
committeriwubcode <iwubcode@users.noreply.github.com>2021-05-08 01:29:48 -0500
commit6fd7867c5647bafca5eb5ccfd30ec054307cbc63 (patch)
tree7b5db0289b858a975f95acc2e166632932c43165 /Source
parent19580c38410f0c83c94e000dba0164bf54f088ef (diff)
VideoCommon: simplify TextureCacheBase by comparing a xfb's hash against a newly calculated one. This fixes games like Teenage Mutant Ninja Turtles (Wii) which use oversized textures where the stride doesn't match the BytesPerRow and that resulted in a different hash algorithm being used. By not hashing the texture before, we improve performance by hashing at most once in all direct XFB lookup scenarios.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp41
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.h2
2 files changed, 19 insertions, 24 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index b791d259f1..e11b2d6341 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -1722,12 +1722,8 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride,
return nullptr;
}
- // Compute total texture size. XFB textures aren't tiled, so this is simple.
- const u32 total_size = height * stride;
- const u64 hash = Common::GetHash64(src_data, total_size, 0);
-
// Do we currently have a version of this XFB copy in VRAM?
- TCacheEntry* entry = GetXFBFromCache(address, width, height, stride, hash);
+ TCacheEntry* entry = GetXFBFromCache(address, width, height, stride);
if (entry)
{
if (entry->is_xfb_container)
@@ -1743,11 +1739,16 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride,
// Create a new VRAM texture, and fill it with the data from guest RAM.
entry = AllocateCacheEntry(TextureConfig(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8,
AbstractTextureFlag_RenderTarget));
+
+ // Compute total texture size. XFB textures aren't tiled, so this is simple.
+ const u32 total_size = height * stride;
entry->SetGeneralParameters(address, total_size,
TextureAndTLUTFormat(TextureFormat::XFB, TLUTFormat::IA8), true);
entry->SetDimensions(width, height, 1);
- entry->SetHashes(hash, hash);
entry->SetXfbCopy(stride);
+
+ const u64 hash = entry->CalculateHash();
+ entry->SetHashes(hash, hash);
entry->is_xfb_container = true;
entry->is_custom_tex = false;
entry->may_have_overlapping_textures = false;
@@ -1784,7 +1785,7 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride,
}
TextureCacheBase::TCacheEntry* TextureCacheBase::GetXFBFromCache(u32 address, u32 width, u32 height,
- u32 stride, u64 hash)
+ u32 stride)
{
auto iter_range = textures_by_address.equal_range(address);
TexAddrCache::iterator iter = iter_range.first;
@@ -1798,15 +1799,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetXFBFromCache(u32 address, u3
if (entry->is_xfb_copy && entry->memory_stride == stride && entry->native_width >= width &&
entry->native_height >= height && !entry->may_have_overlapping_textures)
{
- // But if the dimensions do differ, we must compute the hash on the sub-rectangle.
- u64 check_hash = hash;
- if (entry->native_width != width || entry->native_height != height)
- {
- check_hash = Common::GetHash64(Memory::GetPointer(entry->addr),
- entry->memory_stride * entry->native_height, 0);
- }
-
- if (entry->hash == check_hash && !entry->reference_changed)
+ if (entry->hash == entry->CalculateHash() && !entry->reference_changed)
{
return entry;
}
@@ -2916,29 +2909,31 @@ int TextureCacheBase::TCacheEntry::HashSampleSize() const
u64 TextureCacheBase::TCacheEntry::CalculateHash() const
{
+ const u32 bytes_per_row = BytesPerRow();
+ const u32 hash_sample_size = HashSampleSize();
u8* ptr = Memory::GetPointer(addr);
- if (memory_stride == BytesPerRow())
+ if (memory_stride == bytes_per_row)
{
- return Common::GetHash64(ptr, size_in_bytes, HashSampleSize());
+ return Common::GetHash64(ptr, size_in_bytes, hash_sample_size);
}
else
{
- u32 blocks = NumBlocksY();
+ const u32 num_blocks_y = NumBlocksY();
u64 temp_hash = size_in_bytes;
u32 samples_per_row = 0;
- if (HashSampleSize() != 0)
+ if (hash_sample_size != 0)
{
// Hash at least 4 samples per row to avoid hashing in a bad pattern, like just on the left
// side of the efb copy
- samples_per_row = std::max(HashSampleSize() / blocks, 4u);
+ samples_per_row = std::max(hash_sample_size / num_blocks_y, 4u);
}
- for (u32 i = 0; i < blocks; i++)
+ for (u32 i = 0; i < num_blocks_y; i++)
{
// Multiply by a prime number to mix the hash up a bit. This prevents identical blocks from
// canceling each other out
- temp_hash = (temp_hash * 397) ^ Common::GetHash64(ptr, BytesPerRow(), samples_per_row);
+ temp_hash = (temp_hash * 397) ^ Common::GetHash64(ptr, bytes_per_row, samples_per_row);
ptr += memory_stride;
}
return temp_hash;
diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h
index 599f1c2a79..f07feadde5 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.h
+++ b/Source/Core/VideoCommon/TextureCacheBase.h
@@ -284,7 +284,7 @@ private:
void SetBackupConfig(const VideoConfig& config);
- TCacheEntry* GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride, u64 hash);
+ TCacheEntry* GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride);
TCacheEntry* ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, TLUTFormat tlutfmt);