Merge pull request #7412 from AdmiralCurtiss/xfb-stitch-in-order
Stitch together overlapping XFB regions in order of XFB copy creation.
This commit is contained in:
commit
660fb3fca0
|
@ -8,6 +8,7 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#if defined(_M_X86) || defined(_M_X86_64)
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
|
@ -1303,6 +1304,15 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
|||
|
||||
u32 numBlocksX = entry_to_update->native_width / tex_info.block_width;
|
||||
|
||||
// It is possible that some of the overlapping textures overlap each other.
|
||||
// This behavior has been seen with XFB copies in Rogue Leader.
|
||||
// To get the correct result, we apply the texture updates in the order the textures were
|
||||
// originally loaded. This ensures that the parts of the texture that would have been overwritten
|
||||
// in memory on real hardware get overwritten the same way here too.
|
||||
// This should work, but it may be a better idea to keep track of partial XFB copy invalidations
|
||||
// instead, which would reduce the amount of copying work here.
|
||||
std::vector<TCacheEntry*> candidates;
|
||||
|
||||
auto iter = FindOverlappingTextures(entry_to_update->addr, entry_to_update->size_in_bytes);
|
||||
while (iter.first != iter.second)
|
||||
{
|
||||
|
@ -1313,6 +1323,23 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
|||
entry->memory_stride == entry_to_update->memory_stride)
|
||||
{
|
||||
if (entry->hash == entry->CalculateHash())
|
||||
{
|
||||
candidates.emplace_back(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the hash does not match, this EFB copy will not be used for anything, so remove it
|
||||
iter.first = InvalidateTexture(iter.first);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++iter.first;
|
||||
}
|
||||
|
||||
std::sort(candidates.begin(), candidates.end(),
|
||||
[](const TCacheEntry* a, const TCacheEntry* b) { return a->id < b->id; });
|
||||
|
||||
for (TCacheEntry* entry : candidates)
|
||||
{
|
||||
if (tex_info.is_palette_texture)
|
||||
{
|
||||
|
@ -1329,7 +1356,6 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
|||
}
|
||||
else
|
||||
{
|
||||
++iter.first;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1359,8 +1385,7 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
|||
dst_y = 0;
|
||||
}
|
||||
|
||||
u32 copy_width =
|
||||
std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x);
|
||||
u32 copy_width = std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x);
|
||||
u32 copy_height =
|
||||
std::min(entry->native_height - src_y, entry_to_update->native_height - dst_y);
|
||||
|
||||
|
@ -1396,8 +1421,8 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
|||
|
||||
for (u32 layer = 0; layer < entry->texture->GetConfig().layers; layer++)
|
||||
{
|
||||
entry_to_update->texture->CopyRectangleFromTexture(entry->texture.get(), srcrect, layer,
|
||||
0, dstrect, layer, 0);
|
||||
entry_to_update->texture->CopyRectangleFromTexture(entry->texture.get(), srcrect, layer, 0,
|
||||
dstrect, layer, 0);
|
||||
}
|
||||
updated_entry = true;
|
||||
|
||||
|
@ -1415,15 +1440,6 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
|||
entry->frameCount = FRAMECOUNT_INVALID;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the hash does not match, this EFB copy will not be used for anything, so remove it
|
||||
iter.first = InvalidateTexture(iter.first);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++iter.first;
|
||||
}
|
||||
|
||||
return updated_entry;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue