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 <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
#if defined(_M_X86) || defined(_M_X86_64)
|
#if defined(_M_X86) || defined(_M_X86_64)
|
||||||
#include <pmmintrin.h>
|
#include <pmmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1303,6 +1304,15 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
||||||
|
|
||||||
u32 numBlocksX = entry_to_update->native_width / tex_info.block_width;
|
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);
|
auto iter = FindOverlappingTextures(entry_to_update->addr, entry_to_update->size_in_bytes);
|
||||||
while (iter.first != iter.second)
|
while (iter.first != iter.second)
|
||||||
{
|
{
|
||||||
|
@ -1313,6 +1323,23 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
||||||
entry->memory_stride == entry_to_update->memory_stride)
|
entry->memory_stride == entry_to_update->memory_stride)
|
||||||
{
|
{
|
||||||
if (entry->hash == entry->CalculateHash())
|
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)
|
if (tex_info.is_palette_texture)
|
||||||
{
|
{
|
||||||
|
@ -1329,7 +1356,6 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++iter.first;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1359,8 +1385,7 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
||||||
dst_y = 0;
|
dst_y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 copy_width =
|
u32 copy_width = std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x);
|
||||||
std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x);
|
|
||||||
u32 copy_height =
|
u32 copy_height =
|
||||||
std::min(entry->native_height - src_y, entry_to_update->native_height - dst_y);
|
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++)
|
for (u32 layer = 0; layer < entry->texture->GetConfig().layers; layer++)
|
||||||
{
|
{
|
||||||
entry_to_update->texture->CopyRectangleFromTexture(entry->texture.get(), srcrect, layer,
|
entry_to_update->texture->CopyRectangleFromTexture(entry->texture.get(), srcrect, layer, 0,
|
||||||
0, dstrect, layer, 0);
|
dstrect, layer, 0);
|
||||||
}
|
}
|
||||||
updated_entry = true;
|
updated_entry = true;
|
||||||
|
|
||||||
|
@ -1415,15 +1440,6 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_
|
||||||
entry->frameCount = FRAMECOUNT_INVALID;
|
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;
|
return updated_entry;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue