Add an additional flag fo 'XFB Copy'

This commit is contained in:
iwubcode 2017-06-26 12:06:50 -05:00
parent 65cd085f9b
commit 2cd9565b18
3 changed files with 44 additions and 12 deletions

View File

@ -150,7 +150,7 @@ TextureConverter::GetCommandBufferForTextureConversion(const TextureCache::TCach
// EFB copies can be used as paletted textures as well. For these, we can't assume them to be // EFB copies can be used as paletted textures as well. For these, we can't assume them to be
// contain the correct data before the frame begins (when the init command buffer is executed), // contain the correct data before the frame begins (when the init command buffer is executed),
// so we must convert them at the appropriate time, during the drawing command buffer. // so we must convert them at the appropriate time, during the drawing command buffer.
if (src_entry->IsEfbCopy()) if (src_entry->IsCopy())
{ {
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
StateTracker::GetInstance()->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();

View File

@ -158,7 +158,7 @@ void TextureCacheBase::Cleanup(int _frameCount)
} }
else if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) else if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount)
{ {
if (iter->second->IsEfbCopy()) if (iter->second->IsCopy())
{ {
// Only remove EFB copies when they wouldn't be used anymore(changed hash), because EFB // Only remove EFB copies when they wouldn't be used anymore(changed hash), because EFB
// copies living on the // copies living on the
@ -243,7 +243,8 @@ TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, TLUTForma
decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1);
decoded_entry->SetHashes(entry->base_hash, entry->hash); decoded_entry->SetHashes(entry->base_hash, entry->hash);
decoded_entry->frameCount = FRAMECOUNT_INVALID; decoded_entry->frameCount = FRAMECOUNT_INVALID;
decoded_entry->is_efb_copy = false; decoded_entry->should_force_safe_hashing = false;
decoded_entry->SetNotCopy();
decoded_entry->may_have_overlapping_textures = entry->may_have_overlapping_textures; decoded_entry->may_have_overlapping_textures = entry->may_have_overlapping_textures;
ConvertTexture(decoded_entry, entry, palette, tlutfmt); ConvertTexture(decoded_entry, entry, palette, tlutfmt);
@ -307,7 +308,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale
// EFB copies are excluded from these updates, until there's an example where a game would // EFB copies are excluded from these updates, until there's an example where a game would
// benefit from updating. This would require more work to be done. // benefit from updating. This would require more work to be done.
if (entry_to_update->IsEfbCopy()) if (entry_to_update->IsCopy())
return entry_to_update; return entry_to_update;
u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format.texfmt); u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format.texfmt);
@ -321,7 +322,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale
while (iter.first != iter.second) while (iter.first != iter.second)
{ {
TCacheEntry* entry = iter.first->second; TCacheEntry* entry = iter.first->second;
if (entry != entry_to_update && entry->IsEfbCopy() && !entry->tmem_only && if (entry != entry_to_update && entry->IsCopy() && !entry->tmem_only &&
entry->references.count(entry_to_update) == 0 && entry->references.count(entry_to_update) == 0 &&
entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes) && entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes) &&
entry->memory_stride == numBlocksX * block_size) entry->memory_stride == numBlocksX * block_size)
@ -793,7 +794,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid
// Do not load strided EFB copies, they are not meant to be used directly. // Do not load strided EFB copies, they are not meant to be used directly.
// Also do not directly load EFB copies, which were partly overwritten. // Also do not directly load EFB copies, which were partly overwritten.
if (entry->IsEfbCopy() && entry->native_width == nativeW && entry->native_height == nativeH && if (entry->IsCopy() && entry->native_width == nativeW && entry->native_height == nativeH &&
entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures) entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures)
{ {
// EFB copies have slightly different rules as EFB copy formats have different // EFB copies have slightly different rules as EFB copy formats have different
@ -828,7 +829,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid
else else
{ {
// For normal textures, all texture parameters need to match // For normal textures, all texture parameters need to match
if (!entry->IsEfbCopy() && entry->hash == full_hash && entry->format == full_format && if (!entry->IsCopy() && entry->hash == full_hash && entry->format == full_format &&
entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_levels >= tex_levels && entry->native_width == nativeW &&
entry->native_height == nativeH) entry->native_height == nativeH)
{ {
@ -844,7 +845,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid
// Example: Sonic the Fighters (inside Sonic Gems Collection) // Example: Sonic the Fighters (inside Sonic Gems Collection)
// Skip EFB copies here, so they can be used for partial texture updates // Skip EFB copies here, so they can be used for partial texture updates
if (entry->frameCount != FRAMECOUNT_INVALID && entry->frameCount < temp_frameCount && if (entry->frameCount != FRAMECOUNT_INVALID && entry->frameCount < temp_frameCount &&
!entry->IsEfbCopy() && !(isPaletteTexture && entry->base_hash == base_hash)) !entry->IsCopy() && !(isPaletteTexture && entry->base_hash == base_hash))
{ {
temp_frameCount = entry->frameCount; temp_frameCount = entry->frameCount;
oldest_entry = iter; oldest_entry = iter;
@ -1016,9 +1017,9 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid
entry->SetGeneralParameters(address, texture_size, full_format, false); entry->SetGeneralParameters(address, texture_size, full_format, false);
entry->SetDimensions(nativeW, nativeH, tex_levels); entry->SetDimensions(nativeW, nativeH, tex_levels);
entry->SetHashes(base_hash, full_hash); entry->SetHashes(base_hash, full_hash);
entry->is_efb_copy = false;
entry->is_custom_tex = hires_tex != nullptr; entry->is_custom_tex = hires_tex != nullptr;
entry->memory_stride = entry->BytesPerRow(); entry->memory_stride = entry->BytesPerRow();
entry->SetNotCopy();
std::string basename = ""; std::string basename = "";
if (g_ActiveConfig.bDumpTextures && !hires_tex) if (g_ActiveConfig.bDumpTextures && !hires_tex)
@ -1557,7 +1558,15 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF
entry->SetDimensions(tex_w, tex_h, 1); entry->SetDimensions(tex_w, tex_h, 1);
entry->frameCount = FRAMECOUNT_INVALID; entry->frameCount = FRAMECOUNT_INVALID;
entry->SetEfbCopy(dstStride); if (is_xfb_copy)
{
entry->should_force_safe_hashing = is_xfb_copy;
entry->SetXfbCopy(dstStride);
}
else
{
entry->SetEfbCopy(dstStride);
}
entry->may_have_overlapping_textures = false; entry->may_have_overlapping_textures = false;
entry->is_custom_tex = false; entry->is_custom_tex = false;
@ -1727,9 +1736,10 @@ u32 TextureCacheBase::TCacheEntry::NumBlocksY() const
return actualHeight / blockH; return actualHeight / blockH;
} }
void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride) void TextureCacheBase::TCacheEntry::SetXfbCopy(u32 stride)
{ {
is_efb_copy = true; is_efb_copy = false;
is_xfb_copy = true;
memory_stride = stride; memory_stride = stride;
_assert_msg_(VIDEO, memory_stride >= BytesPerRow(), "Memory stride is too small"); _assert_msg_(VIDEO, memory_stride >= BytesPerRow(), "Memory stride is too small");
@ -1737,6 +1747,23 @@ void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride)
size_in_bytes = memory_stride * NumBlocksY(); size_in_bytes = memory_stride * NumBlocksY();
} }
void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride)
{
is_efb_copy = true;
is_xfb_copy = false;
memory_stride = stride;
_assert_msg_(VIDEO, memory_stride >= BytesPerRow(), "Memory stride is too small");
size_in_bytes = memory_stride * NumBlocksY();
}
void TextureCacheBase::TCacheEntry::SetNotCopy()
{
is_xfb_copy = false;
is_efb_copy = false;
}
int TextureCacheBase::TCacheEntry::HashSampleSize() const int TextureCacheBase::TCacheEntry::HashSampleSize() const
{ {
if (should_force_safe_hashing) if (should_force_safe_hashing)

View File

@ -85,6 +85,7 @@ public:
bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary
// content, aren't just downscaled // content, aren't just downscaled
bool should_force_safe_hashing = false; // for XFB bool should_force_safe_hashing = false; // for XFB
bool is_xfb_copy = false;
unsigned int native_width, unsigned int native_width,
native_height; // Texture dimensions from the GameCube's point of view native_height; // Texture dimensions from the GameCube's point of view
@ -137,11 +138,15 @@ public:
other_entry->references.emplace(this); other_entry->references.emplace(this);
} }
void SetXfbCopy(u32 stride);
void SetEfbCopy(u32 stride); void SetEfbCopy(u32 stride);
void SetNotCopy();
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const; bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
bool IsEfbCopy() const { return is_efb_copy; } bool IsEfbCopy() const { return is_efb_copy; }
bool IsCopy() const { return is_xfb_copy || is_efb_copy; }
u32 NumBlocksY() const; u32 NumBlocksY() const;
u32 BytesPerRow() const; u32 BytesPerRow() const;