Skip to content

Commit

Permalink
Partial texture updates with parts of efb copies
Browse files Browse the repository at this point in the history
As long as an efb copy overlaps a normal texture, copy the overlapping part from the efb copy into the normal texture. Before the pr, this was restricted to efb copies that are completely within the normal texture.

This is supposed to fix the invisible character in Donkey Kong Returns, which was caused by dolphin-emu#3165, because it tries to load smaller textures than the created efb copies.
  • Loading branch information
mimimi085181 committed Nov 21, 2015
1 parent 24c7d23 commit c0083b3
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 29 deletions.
17 changes: 7 additions & 10 deletions Source/Core/VideoBackends/D3D/TextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,13 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(
if (srcrect.GetWidth() == dstrect.GetWidth()
&& srcrect.GetHeight() == dstrect.GetHeight())
{
const D3D11_BOX *psrcbox = nullptr;
D3D11_BOX srcbox;
if (srcrect.left != 0 || srcrect.top != 0)
{
srcbox.left = srcrect.left;
srcbox.top = srcrect.top;
srcbox.right = srcrect.right;
srcbox.bottom = srcrect.bottom;
psrcbox = &srcbox;
}
srcbox.left = srcrect.left;
srcbox.top = srcrect.top;
srcbox.right = srcrect.right;
srcbox.bottom = srcrect.bottom;
srcbox.front = 0;
srcbox.back = 1;
D3D::context->CopySubresourceRegion(
texture->GetTex(),
0,
Expand All @@ -103,7 +100,7 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(
0,
srcentry->texture->GetTex(),
0,
psrcbox);
&srcbox);
return;
}
else if (!config.rendertarget)
Expand Down
65 changes: 46 additions & 19 deletions Source/Core/VideoCommon/TextureCacheBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,35 +223,56 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex

TexCache::iterator iter = textures_by_address.lower_bound(entry_to_update->addr);
TexCache::iterator iterend = textures_by_address.upper_bound(entry_to_update->addr + entry_to_update->size_in_bytes);
bool entry_need_scaling = true;
bool entry_need_scaling = g_ActiveConfig.bCopyEFBScaled;
while (iter != iterend)
{
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 src_x, src_y, dst_x, dst_y;
MathUtil::Rectangle<int> srcrect, dstrect;

u32 block_offset = std::abs((int)((entry->addr - entry_to_update->addr) / block_size));
u32 block_x = block_offset % numBlocksX;
u32 block_y = block_offset / numBlocksX;

u32 x = block_x * block_width;
u32 y = block_y * block_height;
MathUtil::Rectangle<int> srcrect, dstrect;
srcrect.left = 0;
srcrect.top = 0;
dstrect.left = 0;
dstrect.top = 0;
if (entry->addr >= entry_to_update->addr)
{
dst_x = block_x * block_width;
dst_y = block_y * block_height;
src_x = 0;
src_y = 0;
}
else
{
src_x = block_x * block_width;
src_y = block_y * block_height;
dst_x = 0;
dst_y = 0;
}
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);

if (g_ActiveConfig.bCopyEFBScaled)
{
src_x = Renderer::EFBToScaledX(src_x);
src_y = Renderer::EFBToScaledY(src_y);
dst_x = Renderer::EFBToScaledX(dst_x);
dst_y = Renderer::EFBToScaledY(dst_y);
copy_width = Renderer::EFBToScaledX(copy_width);
copy_height = Renderer::EFBToScaledY(copy_height);
}
if (entry_need_scaling)
{
entry_need_scaling = false;
u32 w = entry_to_update->native_width * entry->config.width / entry->native_width;
u32 h = entry_to_update->native_height * entry->config.height / entry->native_height;
u32 w = Renderer::EFBToScaledX(entry_to_update->native_width);
u32 h = Renderer::EFBToScaledX(entry_to_update->native_height);
u32 max = g_renderer->GetMaxTextureSize();
if (max < w || max < h)
{
Expand All @@ -270,8 +291,12 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
newentry->SetHashes(entry_to_update->base_hash, entry_to_update->hash);
newentry->frameCount = frameCount;
newentry->is_efb_copy = false;
srcrect.left = 0;
srcrect.top = 0;
srcrect.right = entry_to_update->config.width;
srcrect.bottom = entry_to_update->config.height;
dstrect.left = 0;
dstrect.top = 0;
dstrect.right = w;
dstrect.bottom = h;
newentry->CopyRectangleFromTexture(entry_to_update, srcrect, dstrect);
Expand All @@ -281,12 +306,14 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
textures_by_address.emplace(key, entry_to_update);
}
}
srcrect.right = entry->config.width;
srcrect.bottom = entry->config.height;
dstrect.left = x * entry_to_update->config.width / entry_to_update->native_width;
dstrect.top = y * entry_to_update->config.height / entry_to_update->native_height;
dstrect.right = (x + entry->native_width) * entry_to_update->config.width / entry_to_update->native_width;
dstrect.bottom = (y + entry->native_height) * entry_to_update->config.height / entry_to_update->native_height;
srcrect.left = src_x;
srcrect.top = src_y;
srcrect.right = (src_x + copy_width);
srcrect.bottom = (src_y + copy_height);
dstrect.left = dst_x;
dstrect.top = dst_y;
dstrect.right = (dst_x + copy_width);
dstrect.bottom = (dst_y + copy_height);
entry_to_update->CopyRectangleFromTexture(entry, srcrect, dstrect);
// Mark the texture update as used, so it isn't applied more than once
entry->frameCount = frameCount;
Expand Down

0 comments on commit c0083b3

Please sign in to comment.