summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/TextureCacheBase.cpp
diff options
context:
space:
mode:
authorScott Mansell <phiren@gmail.com>2015-09-07 00:10:42 +1200
committerScott Mansell <phiren@gmail.com>2015-09-07 00:10:42 +1200
commitc08a83a5aae41e7c8904295cfa62f932ea87ce02 (patch)
treeb68a913ead1727132fbbb3f4a1bd472f47b9cb1e /Source/Core/VideoCommon/TextureCacheBase.cpp
parentbe4caa3dc025d18d57cf53b27e505c19bb70544e (diff)
parentd797b5d0b55e6354af6ba66942b9a6766087e5f9 (diff)
Merge pull request #2957 from phire/unify_efbcopy
Cleanup and unify efb copy implemtations into VideoCommon
Diffstat (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp')
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp120
1 files changed, 89 insertions, 31 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index 7d49e698da..9dcd960037 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -182,24 +182,6 @@ void TextureCache::Cleanup(int _frameCount)
}
}
-void TextureCache::MakeRangeDynamic(u32 start_address, u32 size)
-{
- TexCache::iterator
- iter = textures_by_address.begin();
-
- while (iter != textures_by_address.end())
- {
- if (iter->second->OverlapsMemoryRange(start_address, size))
- {
- iter = FreeTexture(iter);
- }
- else
- {
- ++iter;
- }
- }
-}
-
bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const
{
if (addr + size_in_bytes <= range_address)
@@ -243,7 +225,7 @@ TextureCache::TCacheEntryBase* TextureCache::DoPartialTextureUpdates(TexCache::i
&& entry_to_update->addr <= entry->addr
&& entry->addr + entry->size_in_bytes <= entry_to_update->addr + entry_to_update->size_in_bytes
&& entry->frameCount == FRAMECOUNT_INVALID
- && entry->copyMipMapStrideChannels * 32 == numBlocksX * block_size)
+ && entry->memory_stride == numBlocksX * block_size)
{
u32 block_offset = (entry->addr - entry_to_update->addr) / block_size;
u32 block_x = block_offset % numBlocksX;
@@ -372,11 +354,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
return nullptr;
// TexelSizeInNibbles(format) * width * height / 16;
- const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat) - 1;
- const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat) - 1;
+ const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat);
+ const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat);
- unsigned int expandedWidth = (width + bsw) & (~bsw);
- unsigned int expandedHeight = (height + bsh) & (~bsh);
+ unsigned int expandedWidth = ROUND_UP(width, bsw);
+ unsigned int expandedHeight = ROUND_UP(height, bsh);
const unsigned int nativeW = width;
const unsigned int nativeH = height;
@@ -668,8 +650,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
{
const u32 mip_width = CalculateLevelSize(width, level);
const u32 mip_height = CalculateLevelSize(height, level);
- const u32 expanded_mip_width = (mip_width + bsw) & (~bsw);
- const u32 expanded_mip_height = (mip_height + bsh) & (~bsh);
+ const u32 expanded_mip_width = ROUND_UP(mip_width, bsw);
+ const u32 expanded_mip_height = ROUND_UP(mip_height, bsh);
const u8*& mip_src_data = from_tmem
? ((level % 2) ? ptr_odd : ptr_even)
@@ -693,7 +675,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
return ReturnEntry(stage, entry);
}
-void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, PEControl::PixelFormat srcFormat,
+void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, u32 dstStride, PEControl::PixelFormat srcFormat,
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf)
{
// Emulation methods:
@@ -753,9 +735,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 0: // Z4
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f;
cbufid = 0;
+ dstFormat |= _GX_TF_CTF;
break;
+ case 8: // Z8H
+ dstFormat |= _GX_TF_CTF;
case 1: // Z8
- case 8: // Z8
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1.0f;
cbufid = 1;
break;
@@ -768,6 +752,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 11: // Z16 (reverse order)
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
cbufid = 3;
+ dstFormat |= _GX_TF_CTF;
break;
case 6: // Z24X8
@@ -778,11 +763,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
case 9: // Z8M
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
cbufid = 5;
+ dstFormat |= _GX_TF_CTF;
break;
case 10: // Z8L
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
cbufid = 6;
+ dstFormat |= _GX_TF_CTF;
break;
case 12: // Z16L - copy lower 16 depth bits
@@ -790,6 +777,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
// Used e.g. in Zelda: Skyward Sword
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
cbufid = 7;
+ dstFormat |= _GX_TF_CTF;
break;
default:
@@ -798,6 +786,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
cbufid = 8;
break;
}
+
+ dstFormat |= _GX_TF_ZTF;
}
else if (isIntensity)
{
@@ -862,11 +852,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
ColorMask[0] = 15.0f;
ColorMask[4] = 1.0f / 15.0f;
cbufid = 14;
+ dstFormat |= _GX_TF_CTF;
break;
case 1: // R8
case 8: // R8
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
cbufid = 15;
+ dstFormat |= _GX_TF_CTF;
break;
case 2: // RA4
@@ -881,6 +873,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
fConstAdd[3] = 1.0f;
cbufid = 17;
}
+ dstFormat |= _GX_TF_CTF;
break;
case 3: // RA8
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f;
@@ -892,6 +885,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
fConstAdd[3] = 1.0f;
cbufid = 19;
}
+ dstFormat |= _GX_TF_CTF;
break;
case 7: // A8
@@ -907,25 +901,30 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
fConstAdd[3] = 1.0f;
cbufid = 21;
}
+ dstFormat |= _GX_TF_CTF;
break;
case 9: // G8
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
cbufid = 22;
+ dstFormat |= _GX_TF_CTF;
break;
case 10: // B8
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
cbufid = 23;
+ dstFormat |= _GX_TF_CTF;
break;
case 11: // RG8
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
cbufid = 24;
+ dstFormat |= _GX_TF_CTF;
break;
case 12: // GB8
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
cbufid = 25;
+ dstFormat |= _GX_TF_CTF;
break;
case 4: // RGB565
@@ -973,6 +972,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
}
}
+ u8* dst = Memory::GetPointer(dstAddr);
+ if (dst == nullptr)
+ {
+ ERROR_LOG(VIDEO, "Trying to copy from EFB to invalid address 0x%8x", dstAddr);
+ return;
+ }
+
const unsigned int tex_w = scaleByHalf ? srcRect.GetWidth() / 2 : srcRect.GetWidth();
const unsigned int tex_h = scaleByHalf ? srcRect.GetHeight() / 2 : srcRect.GetHeight();
@@ -996,17 +1002,36 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
TCacheEntryBase* entry = AllocateTexture(config);
- // TODO: Using the wrong dstFormat, dumb...
entry->SetGeneralParameters(dstAddr, 0, dstFormat);
entry->SetDimensions(tex_w, tex_h, 1);
entry->SetHashes(TEXHASH_INVALID);
entry->frameCount = FRAMECOUNT_INVALID;
- entry->is_efb_copy = true;
+ entry->SetEfbCopy(dstStride);
entry->is_custom_tex = false;
- entry->copyMipMapStrideChannels = bpmem.copyMipMapStrideChannels;
- entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
+ entry->FromRenderTarget(dst, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
+
+ if (!g_ActiveConfig.bSkipEFBCopyToRam)
+ {
+ entry->hash = GetHash64(dst, (int)entry->size_in_bytes, g_ActiveConfig.iSafeTextureCache_ColorSamples);
+
+ // Invalidate all textures that overlap the range of our texture
+ TexCache::iterator
+ iter = textures_by_address.begin();
+
+ while (iter != textures_by_address.end())
+ {
+ if (iter->second->OverlapsMemoryRange(dstAddr, entry->size_in_bytes))
+ {
+ iter = FreeTexture(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
if (g_ActiveConfig.bDumpEFBTarget)
{
@@ -1052,3 +1077,36 @@ TextureCache::TexCache::iterator TextureCache::FreeTexture(TexCache::iterator it
return textures_by_address.erase(iter);
}
+
+u32 TextureCache::TCacheEntryBase::CacheLinesPerRow() const
+{
+ u32 blockW = TexDecoder_GetBlockWidthInTexels(format);
+ // Round up source height to multiple of block size
+ u32 actualWidth = ROUND_UP(native_width, blockW);
+
+ u32 numBlocksX = actualWidth / blockW;
+
+ // RGBA takes two cache lines per block; all others take one
+ if (format == GX_TF_RGBA8)
+ numBlocksX = numBlocksX * 2;
+ return numBlocksX;
+}
+
+u32 TextureCache::TCacheEntryBase::NumBlocksY() const
+{
+ u32 blockH = TexDecoder_GetBlockHeightInTexels(format);
+ // Round up source height to multiple of block size
+ u32 actualHeight = ROUND_UP(native_height, blockH);
+
+ return actualHeight / blockH;
+}
+
+void TextureCache::TCacheEntryBase::SetEfbCopy(u32 stride)
+{
+ is_efb_copy = true;
+ memory_stride = stride;
+
+ _assert_msg_(VIDEO, memory_stride >= CacheLinesPerRow(), "Memory stride is too small");
+
+ size_in_bytes = memory_stride * NumBlocksY();
+}