Merge pull request #3266 from mimimi085181/partial-updates-with-parts-of-efb-copies

Partial texture updates with parts of efb copies
This commit is contained in:
Pierre Bourdon 2016-03-18 01:11:59 +01:00
commit 647fec92a0
2 changed files with 31 additions and 30 deletions

View File

@ -106,18 +106,13 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(
if (src_rect.GetWidth() == dst_rect.GetWidth()
&& src_rect.GetHeight() == dst_rect.GetHeight())
{
const D3D12_BOX* src_box_pointer = nullptr;
D3D12_BOX src_box;
if (src_rect.left != 0 || src_rect.top != 0)
{
src_box.front = 0;
src_box.back = 1;
src_box.left = src_rect.left;
src_box.top = src_rect.top;
src_box.right = src_rect.right;
src_box.bottom = src_rect.bottom;
src_box_pointer = &src_box;
}
D3D12_BOX srcbox;
srcbox.left = src_rect.left;
srcbox.top = src_rect.top;
srcbox.right = src_rect.right;
srcbox.bottom = src_rect.bottom;
srcbox.front = 0;
srcbox.back = srcentry->config.layers;
if (static_cast<u32>(src_rect.GetHeight()) > config.height ||
static_cast<u32>(src_rect.GetWidth()) > config.width)
@ -137,7 +132,7 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(
m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST);
srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE);
D3D::current_command_list->CopyTextureRegion(&dst_location, dst_rect.left, dst_rect.top, 0, &src_location, src_box_pointer);
D3D::current_command_list->CopyTextureRegion(&dst_location, dst_rect.left, dst_rect.top, 0, &src_location, &srcbox);
m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

View File

@ -236,7 +236,7 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBas
newentry->SetDimensions((*entry)->native_width, (*entry)->native_height, 1);
newentry->SetHashes((*entry)->base_hash, (*entry)->hash);
newentry->frameCount = frameCount;
newentry->is_efb_copy = false;
newentry->is_efb_copy = (*entry)->is_efb_copy;
MathUtil::Rectangle<int> srcrect, dstrect;
srcrect.left = 0;
srcrect.top = 0;
@ -289,7 +289,6 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
// Efb copies and paletted textures are excluded from these updates, until there's an example where a game would
// benefit from this. Both would require more work to be done.
// TODO: Implement upscaling support for normal textures, and then remove the efb to ram and the scaled efb restrictions
if (entry_to_update->IsEfbCopy()
|| isPaletteTexture)
return entry_to_update;
@ -307,28 +306,35 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
TCacheEntryBase* entry = iter->second;
if (entry != entry_to_update
&& entry->IsEfbCopy()
&& entry_to_update->addr <= entry->addr
&& entry->addr + entry->size_in_bytes <= entry_to_update->addr + entry_to_update->size_in_bytes
&& entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes)
&& entry->frameCount == FRAMECOUNT_INVALID
&& entry->memory_stride == numBlocksX * block_size)
{
if (entry->hash == entry->CalculateHash())
{
u32 block_offset = (entry->addr - entry_to_update->addr) / block_size;
u32 block_x = block_offset % numBlocksX;
u32 block_y = block_offset / numBlocksX;
u32 src_x, src_y, dst_x, dst_y;
u32 dst_x = block_x * block_width;
u32 dst_y = block_y * block_height;
u32 src_x = 0;
u32 src_y = 0;
// If the EFB copy doesn't fully fit, cancel the copy process
if (entry->native_width - src_x > entry_to_update->native_width - dst_x
|| entry->native_height - src_y > entry_to_update->native_height - dst_y)
// Note for understanding the math:
// Normal textures can't be strided, so the 2 missing cases with src_x > 0 don't exist
if (entry->addr >= entry_to_update->addr)
{
iter++;
continue;
u32 block_offset = (entry->addr - entry_to_update->addr) / block_size;
u32 block_x = block_offset % numBlocksX;
u32 block_y = block_offset / numBlocksX;
src_x = 0;
src_y = 0;
dst_x = block_x * block_width;
dst_y = block_y * block_height;
}
else
{
u32 block_offset = (entry_to_update->addr - entry->addr) / block_size;
u32 block_x = (~block_offset + 1) % numBlocksX;
u32 block_y = (block_offset + block_x) / numBlocksX;
src_x = 0;
src_y = block_y * block_height;
dst_x = block_x * block_width;
dst_y = 0;
}
u32 copy_width = std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x);