Merge pull request #5718 from mimimi085181/partial-updates-update
Update to partial texture updates
This commit is contained in:
commit
425a8cb378
|
@ -242,6 +242,7 @@ TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, TLUTForma
|
|||
decoded_entry->SetHashes(entry->base_hash, entry->hash);
|
||||
decoded_entry->frameCount = FRAMECOUNT_INVALID;
|
||||
decoded_entry->is_efb_copy = false;
|
||||
decoded_entry->may_have_overlapping_textures = entry->may_have_overlapping_textures;
|
||||
|
||||
ConvertTexture(decoded_entry, entry, palette, tlutfmt);
|
||||
textures_by_address.emplace(entry->addr, decoded_entry);
|
||||
|
@ -629,9 +630,10 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
|
|||
continue;
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (entry->IsEfbCopy() && entry->native_width == nativeW && entry->native_height == nativeH &&
|
||||
entry->memory_stride == entry->BytesPerRow())
|
||||
entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures)
|
||||
{
|
||||
// EFB copies have slightly different rules as EFB copy formats have different
|
||||
// meanings from texture formats.
|
||||
|
@ -665,7 +667,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
|
|||
else
|
||||
{
|
||||
// For normal textures, all texture parameters need to match
|
||||
if (entry->hash == full_hash && entry->format == full_format &&
|
||||
if (!entry->IsEfbCopy() && entry->hash == full_hash && entry->format == full_format &&
|
||||
entry->native_levels >= tex_levels && entry->native_width == nativeW &&
|
||||
entry->native_height == nativeH)
|
||||
{
|
||||
|
@ -823,6 +825,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
|
|||
entry->SetHashes(base_hash, full_hash);
|
||||
entry->is_efb_copy = false;
|
||||
entry->is_custom_tex = hires_tex != nullptr;
|
||||
entry->memory_stride = entry->BytesPerRow();
|
||||
|
||||
std::string basename = "";
|
||||
if (g_ActiveConfig.bDumpTextures && !hires_tex)
|
||||
|
@ -1225,22 +1228,6 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF
|
|||
unsigned int scaled_tex_h =
|
||||
g_ActiveConfig.bCopyEFBScaled ? g_renderer->EFBToScaledY(tex_h) : tex_h;
|
||||
|
||||
// Remove all texture cache entries at dstAddr
|
||||
// It's not possible to have two EFB copies at the same address, this makes sure any old efb
|
||||
// copies
|
||||
// (or normal textures) are removed from texture cache. They are also un-linked from any
|
||||
// partially
|
||||
// updated textures, which forces that partially updated texture to be updated.
|
||||
// TODO: This also wipes out non-efb copies, which is counterproductive.
|
||||
{
|
||||
auto iter_range = textures_by_address.equal_range(dstAddr);
|
||||
TexAddrCache::iterator iter = iter_range.first;
|
||||
while (iter != iter_range.second)
|
||||
{
|
||||
iter = InvalidateTexture(iter);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the base (in memory) format of this efb copy.
|
||||
TextureFormat baseFormat = TexDecoder_GetEFBCopyBaseFormat(dstFormat);
|
||||
|
||||
|
@ -1308,23 +1295,35 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF
|
|||
copy_to_vram = false;
|
||||
}
|
||||
|
||||
// Invalidate all textures that overlap the range of our efb copy.
|
||||
// Unless our efb copy has a weird stride, then we mark them to check for partial texture updates.
|
||||
// TODO: This also invalidates partial overlaps, which we currently don't have a better way
|
||||
// of dealing with.
|
||||
bool invalidate_textures = dstStride == bytes_per_row || !copy_to_vram;
|
||||
// Invalidate all textures, if they are either fully overwritten by our efb copy, or if they
|
||||
// have a different stride than our efb copy. Partly overwritten textures with the same stride
|
||||
// as our efb copy are marked to check them for partial texture updates.
|
||||
// TODO: The logic to detect overlapping strided efb copies is not 100% accurate.
|
||||
bool strided_efb_copy = dstStride != bytes_per_row;
|
||||
auto iter = FindOverlappingTextures(dstAddr, covered_range);
|
||||
while (iter.first != iter.second)
|
||||
{
|
||||
TCacheEntry* entry = iter.first->second;
|
||||
if (entry->OverlapsMemoryRange(dstAddr, covered_range))
|
||||
{
|
||||
if (invalidate_textures)
|
||||
u32 overlap_range = std::min(entry->addr + entry->size_in_bytes, dstAddr + covered_range) -
|
||||
std::max(entry->addr, dstAddr);
|
||||
if (!copy_to_vram || entry->memory_stride != dstStride ||
|
||||
(!strided_efb_copy && entry->size_in_bytes == overlap_range) ||
|
||||
(strided_efb_copy && entry->size_in_bytes == overlap_range && entry->addr == dstAddr))
|
||||
{
|
||||
iter.first = InvalidateTexture(iter.first);
|
||||
continue;
|
||||
}
|
||||
entry->may_have_overlapping_textures = true;
|
||||
|
||||
// Do not load textures by hash, if they were at least partly overwritten by an efb copy.
|
||||
// In this case, comparing the hash is not enough to check, if two textures are identical.
|
||||
if (entry->textures_by_hash_iter != textures_by_hash.end())
|
||||
{
|
||||
textures_by_hash.erase(entry->textures_by_hash_iter);
|
||||
entry->textures_by_hash_iter = textures_by_hash.end();
|
||||
}
|
||||
}
|
||||
++iter.first;
|
||||
}
|
||||
|
@ -1347,6 +1346,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF
|
|||
|
||||
entry->frameCount = FRAMECOUNT_INVALID;
|
||||
entry->SetEfbCopy(dstStride);
|
||||
entry->may_have_overlapping_textures = false;
|
||||
entry->is_custom_tex = false;
|
||||
|
||||
CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, cbufid, colmat);
|
||||
|
|
Loading…
Reference in New Issue