mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
Move common EFB copy code into VideoCommon
Addded a few duplicated depth copy texture formats to the enum in TextureDecoder.h. These texture formats were already implemented in TextureCacheBase and the ogl/dx11 texture cache implementations.
This commit is contained in:
@ -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->copyStride == 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;
|
||||
@ -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->copyStride = dstStride;
|
||||
|
||||
entry->FromRenderTarget(dstAddr, dstFormat, dstStride, 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) - 1;
|
||||
// Round up source height to multiple of block size
|
||||
u32 actualWidth = (native_width + blockW) & ~(blockW);
|
||||
|
||||
u32 numBlocksX = actualWidth / TexDecoder_GetBlockWidthInTexels(format);
|
||||
|
||||
// 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) - 1;
|
||||
// Round up source height to multiple of block size
|
||||
u32 actualHeight = (native_height + blockH) & ~(blockH);
|
||||
|
||||
return actualHeight / TexDecoder_GetBlockHeightInTexels(format);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
u32 format;
|
||||
bool is_efb_copy;
|
||||
bool is_custom_tex;
|
||||
u32 copyStride;
|
||||
u32 memory_stride;
|
||||
|
||||
unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view
|
||||
unsigned int native_levels;
|
||||
@ -76,6 +76,7 @@ public:
|
||||
native_width = _native_width;
|
||||
native_height = _native_height;
|
||||
native_levels = _native_levels;
|
||||
memory_stride = _native_width;
|
||||
}
|
||||
|
||||
void SetHashes(u64 _hash)
|
||||
@ -83,6 +84,8 @@ public:
|
||||
hash = _hash;
|
||||
}
|
||||
|
||||
void SetEfbCopy(u32 stride);
|
||||
|
||||
TCacheEntryBase(const TCacheEntryConfig& c) : config(c) {}
|
||||
virtual ~TCacheEntryBase();
|
||||
|
||||
@ -96,7 +99,7 @@ public:
|
||||
|
||||
virtual void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level) = 0;
|
||||
virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
|
||||
virtual void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
|
||||
PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
const float *colmat) = 0;
|
||||
@ -104,6 +107,11 @@ public:
|
||||
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
|
||||
|
||||
bool IsEfbCopy() const { return is_efb_copy; }
|
||||
|
||||
u32 NumBlocksY() const;
|
||||
u32 CacheLinesPerRow() const;
|
||||
|
||||
void Memset(u8* ptr, u32 tag);
|
||||
};
|
||||
|
||||
virtual ~TextureCache(); // needs virtual for DX11 dtor
|
||||
@ -115,7 +123,6 @@ public:
|
||||
static void Cleanup(int _frameCount);
|
||||
|
||||
static void Invalidate();
|
||||
static void MakeRangeDynamic(u32 start_address, u32 size);
|
||||
|
||||
virtual TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) = 0;
|
||||
|
||||
|
@ -650,9 +650,11 @@ const char *GenerateEncodingShader(u32 format,API_TYPE ApiType)
|
||||
case GX_CTF_GB8:
|
||||
WriteCC8Encoder(p, "gb", ApiType);
|
||||
break;
|
||||
case GX_CTF_Z8H:
|
||||
case GX_TF_Z8:
|
||||
WriteC8Encoder(p, "r", ApiType);
|
||||
break;
|
||||
case GX_CTF_Z16R:
|
||||
case GX_TF_Z16:
|
||||
WriteZ16Encoder(p, ApiType);
|
||||
break;
|
||||
|
@ -35,7 +35,6 @@ enum TextureFormat
|
||||
GX_CTF_R4 = 0x0 | _GX_TF_CTF,
|
||||
GX_CTF_RA4 = 0x2 | _GX_TF_CTF,
|
||||
GX_CTF_RA8 = 0x3 | _GX_TF_CTF,
|
||||
GX_CTF_YUVA8 = 0x6 | _GX_TF_CTF,
|
||||
GX_CTF_A8 = 0x7 | _GX_TF_CTF,
|
||||
GX_CTF_R8 = 0x8 | _GX_TF_CTF,
|
||||
GX_CTF_G8 = 0x9 | _GX_TF_CTF,
|
||||
@ -43,13 +42,17 @@ enum TextureFormat
|
||||
GX_CTF_RG8 = 0xB | _GX_TF_CTF,
|
||||
GX_CTF_GB8 = 0xC | _GX_TF_CTF,
|
||||
|
||||
// Texture formats (which match the color formats above)
|
||||
GX_TF_Z8 = 0x1 | _GX_TF_ZTF,
|
||||
GX_TF_Z16 = 0x3 | _GX_TF_ZTF,
|
||||
GX_TF_Z24X8 = 0x6 | _GX_TF_ZTF,
|
||||
|
||||
// copy only texture formats
|
||||
GX_CTF_Z4 = 0x0 | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z8H = 0x8 | _GX_TF_ZTF | _GX_TF_CTF, // This produces an identical result to to GX_TF_Z8
|
||||
GX_CTF_Z8M = 0x9 | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z8L = 0xA | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z16R = 0xB | _GX_TF_ZTF | _GX_TF_CTF, // Reversed version of GX_TF_Z16
|
||||
GX_CTF_Z16L = 0xC | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ int TexDecoder_GetTexelSizeInNibbles(int format)
|
||||
case GX_CTF_R4: return 1;
|
||||
case GX_CTF_RA4: return 2;
|
||||
case GX_CTF_RA8: return 4;
|
||||
case GX_CTF_YUVA8: return 8;
|
||||
case GX_CTF_A8: return 2;
|
||||
case GX_CTF_R8: return 2;
|
||||
case GX_CTF_G8: return 2;
|
||||
@ -48,10 +47,14 @@ int TexDecoder_GetTexelSizeInNibbles(int format)
|
||||
case GX_TF_Z24X8: return 8;
|
||||
|
||||
case GX_CTF_Z4: return 1;
|
||||
case GX_CTF_Z8H: return 2;
|
||||
case GX_CTF_Z8M: return 2;
|
||||
case GX_CTF_Z8L: return 2;
|
||||
case GX_CTF_Z16R: return 4;
|
||||
case GX_CTF_Z16L: return 4;
|
||||
default: return 1;
|
||||
default:
|
||||
PanicAlert("Unsupported Texture Format (%08x)! (GetTexelSizeInNibbles)", format);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,11 +91,13 @@ int TexDecoder_GetBlockWidthInTexels(u32 format)
|
||||
case GX_TF_Z16: return 4;
|
||||
case GX_TF_Z24X8: return 4;
|
||||
case GX_CTF_Z4: return 8;
|
||||
case GX_CTF_Z8H: return 8;
|
||||
case GX_CTF_Z8M: return 8;
|
||||
case GX_CTF_Z8L: return 8;
|
||||
case GX_CTF_Z16R: return 4;
|
||||
case GX_CTF_Z16L: return 4;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockWidthInTexels)", format);
|
||||
PanicAlert("Unsupported Texture Format (%08x)! (GetBlockWidthInTexels)", format);
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
@ -125,11 +130,13 @@ int TexDecoder_GetBlockHeightInTexels(u32 format)
|
||||
case GX_TF_Z16: return 4;
|
||||
case GX_TF_Z24X8: return 4;
|
||||
case GX_CTF_Z4: return 8;
|
||||
case GX_CTF_Z8H: return 4;
|
||||
case GX_CTF_Z8M: return 4;
|
||||
case GX_CTF_Z8L: return 4;
|
||||
case GX_CTF_Z16R: return 4;
|
||||
case GX_CTF_Z16L: return 4;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockHeightInTexels)", format);
|
||||
PanicAlert("Unsupported Texture Format (%08x)! (GetBlockHeightInTexels)", format);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user