Remove TextureAddress struct.

This commit is contained in:
magumagu 2015-02-19 15:19:31 -08:00
parent c0a4760f0e
commit ddc815dd7a
2 changed files with 45 additions and 119 deletions

View File

@ -146,7 +146,7 @@ void TextureCache::Cleanup(int _frameCount)
}
if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount &&
// EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted
!iter->second->IsUnrecoverable())
!iter->second->IsEfbCopy())
{
FreeTexture(iter->second);
iter = textures.erase(iter);
@ -198,14 +198,10 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size)
bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const
{
if (!addr.HasMemAddress())
if (addr + size_in_bytes <= range_address)
return false;
u32 memaddr = addr.GetMemAddress();
if (memaddr + size_in_bytes <= range_address)
return false;
if (memaddr >= range_address + range_size)
if (addr >= range_address + range_size)
return false;
return true;
@ -322,32 +318,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
// e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there
tex_levels = std::min<u32>(IntLog2(std::max(width, height)) + 1, tex_levels);
// Compute a texture ID; this isn't everything about a texture, rather just
// enough to group together textures with related memory addresses.
TextureAddress texID;
TextureAddress paletteDecodedID;
if (from_tmem)
{
u32 tmem_addr = bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE;
if (texformat == GX_TF_RGBA8 && from_tmem)
{
u32 tmem_odd_addr = bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE;
texID = TextureAddress::TMemRGBA8(tmem_addr, tmem_odd_addr);
}
else
{
texID = TextureAddress::TMem(tmem_addr);
if (isPaletteTexture)
paletteDecodedID = TextureAddress::TMemPalette(tmem_addr, tlutaddr);
}
}
else
{
texID = TextureAddress::Mem(address);
if (isPaletteTexture)
paletteDecodedID = TextureAddress::MemPalette(address, tlutaddr);
}
// Find all texture cache entries for the current texture address, and decide whether to use one of
// them, or to create a new one
//
@ -372,16 +342,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
//
// For efb copies, the entry created in CopyRenderTargetToTexture always has to be used, or else it was
// done in vain.
std::pair<TexCache::iterator, TexCache::iterator> iter_range = textures.equal_range(texID);
bool palette_decoded_entry = false;
if (isPaletteTexture && iter_range.first == iter_range.second)
{
iter_range = textures.equal_range(paletteDecodedID);
palette_decoded_entry = true;
}
std::pair <TexCache::iterator, TexCache::iterator> iter_range = textures.equal_range(address);
TexCache::iterator iter = iter_range.first;
TexCache::iterator oldest_entry = iter;
int temp_frameCount = 0x7fffffff;
TexCache::iterator unconverted_copy = textures.end();
while (iter != iter_range.second)
{
@ -398,35 +363,21 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
// format is complicated because EFB copy formats don't exactly match
// texture formats. I'm not sure what effect checking width/height/levels
// would have.
if (!palette_decoded_entry && isPaletteTexture && g_Config.backend_info.bSupportsPaletteConversion)
{
// Perform palette decoding.
// TODO: Skip decoding if we find a match.
std::pair<TexCache::iterator, TexCache::iterator> decoded_iter_range = textures.equal_range(paletteDecodedID);
while (decoded_iter_range.first != decoded_iter_range.second)
{
// Pool this texture and make a new one later.
FreeTexture(decoded_iter_range.first->second);
decoded_iter_range.first = textures.erase(decoded_iter_range.first);
}
if (!isPaletteTexture || !g_Config.backend_info.bSupportsPaletteConversion)
return ReturnEntry(stage, entry);
TCacheEntryBase *decoded_entry = AllocateTexture(entry->config);
decoded_entry->SetGeneralParameters(paletteDecodedID, texture_size, full_format);
decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1);
decoded_entry->SetHashes(TEXHASH_INVALID);
decoded_entry->frameCount = FRAMECOUNT_INVALID;
g_texture_cache->ConvertTexture(decoded_entry, entry, &texMem[tlutaddr], (TlutFormat)tlutfmt);
textures.insert(TexCache::value_type(paletteDecodedID, decoded_entry));
entry = decoded_entry;
}
return ReturnEntry(stage, entry);
// Note that we found an unconverted EFB copy, then continue. We'll
// perform the conversion later. Currently, we only convert EFB copies to
// palette textures; we could do other conversions if it proved to be
// beneficial.
unconverted_copy = iter;
}
else
{
// Keeping an unused entry for an efb copy in the cache is pointless, because a new entry
// will be created in CopyRenderTargetToTexture
// Aggressively prune EFB copies: if it isn't useful here, it will probably
// never be useful again. It's theoretically possible for a game to do
// something weird where the copy could become useful in the future, but in
// practice it doesn't happen.
FreeTexture(entry);
iter = textures.erase(iter);
continue;
@ -451,6 +402,23 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
++iter;
}
if (unconverted_copy != textures.end())
{
// Perform palette decoding.
TCacheEntryBase *entry = unconverted_copy->second;
TCacheEntryBase *decoded_entry = AllocateTexture(entry->config);
decoded_entry->SetGeneralParameters(address, texture_size, full_format);
decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1);
decoded_entry->SetHashes(tex_hash ^ tlut_hash);
decoded_entry->frameCount = FRAMECOUNT_INVALID;
decoded_entry->is_efb_copy = false;
g_texture_cache->ConvertTexture(decoded_entry, entry, &texMem[tlutaddr], (TlutFormat)tlutfmt);
textures.insert(TexCache::value_type(address, decoded_entry));
return ReturnEntry(stage, decoded_entry);
}
// If at least one entry was not used for the same frame, overwrite the oldest one
if (temp_frameCount != 0x7fffffff)
{
@ -513,11 +481,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
TCacheEntryBase* entry = AllocateTexture(config);
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
textures.insert(TexCache::value_type(isPaletteTexture ? paletteDecodedID : texID, entry));
textures.insert(TexCache::value_type(address, entry));
entry->SetGeneralParameters(isPaletteTexture ? paletteDecodedID : texID, texture_size, full_format);
entry->SetGeneralParameters(address, texture_size, full_format);
entry->SetDimensions(nativeW, nativeH, tex_levels);
entry->hash = tex_hash ^ tlut_hash;
entry->is_efb_copy = false;
// load texture
entry->Load(width, height, expandedWidth, 0);
@ -873,7 +842,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h;
// remove all texture cache entries at dstAddr
std::pair <TexCache::iterator, TexCache::iterator> iter_range = textures.equal_range(TextureAddress::Mem(dstAddr));
std::pair <TexCache::iterator, TexCache::iterator> iter_range = textures.equal_range(dstAddr);
TexCache::iterator iter = iter_range.first;
while (iter != iter_range.second)
{
@ -891,15 +860,16 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
TCacheEntryBase* entry = AllocateTexture(config);
// TODO: Using the wrong dstFormat, dumb...
entry->SetGeneralParameters(TextureAddress::Mem(dstAddr), 0, dstFormat);
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->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
textures.insert(TexCache::value_type(TextureAddress::Mem(dstAddr), entry));
textures.insert(TexCache::value_type(dstAddr, entry));
}
TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config)

View File

@ -43,59 +43,16 @@ public:
};
};
class TextureAddress
{
u32 address1;
u32 address2;
enum AddressKind
{
// A texture in RAM
RAM,
// A texture loaded into TMEM
TMEM,
// A texture in RAM, fully decoded using a palette.
RAM_PALETTE,
// An RGBA8 texture in TMEM.
TMEM_RGBA8,
// A palette texture in TMEM.
TMEM_PALETTE,
// Uninitialized address.
INVALID
};
AddressKind kind;
TextureAddress(u32 a, u32 b, AddressKind k) : address1(a), address2(b), kind(k) {}
public:
TextureAddress() : kind(INVALID), address1(0), address2(0) {}
static TextureAddress Mem(u32 a) { return TextureAddress(a, 0, RAM); }
static TextureAddress MemPalette(u32 a, u32 b) { return TextureAddress(a, b, RAM_PALETTE); }
static TextureAddress TMem(u32 a) { return TextureAddress(a, 0, TMEM); }
static TextureAddress TMemRGBA8(u32 a, u32 b) { return TextureAddress(a, b, TMEM_RGBA8); }
static TextureAddress TMemPalette(u32 a, u32 b) { return TextureAddress(a, b, TMEM_PALETTE); }
bool operator == (const TextureAddress& b) const
{
return kind == b.kind && address1 == b.address1 && address2 == b.address2;
}
bool operator < (const TextureAddress& b) const
{
if (kind != b.kind)
return kind < b.kind;
if (address1 != b.address1)
return address1 < b.address1;
return address2 < b.address2;
}
bool IsMemOnlyAddress() const { return kind == RAM; }
bool HasMemAddress() const { return kind == RAM || kind == RAM_PALETTE; }
u32 GetMemAddress() const { return address1; }
};
struct TCacheEntryBase
{
const TCacheEntryConfig config;
// common members
TextureAddress addr;
u32 addr;
u32 size_in_bytes;
u64 hash;
u32 format;
bool is_efb_copy;
unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view
unsigned int native_levels;
@ -104,7 +61,7 @@ public:
int frameCount;
void SetGeneralParameters(TextureAddress _addr, u32 _size, u32 _format)
void SetGeneralParameters(u32 _addr, u32 _size, u32 _format)
{
addr = _addr;
size_in_bytes = _size;
@ -138,8 +95,7 @@ public:
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
bool IsEfbCopy() { return config.rendertarget; }
bool IsUnrecoverable() { return IsEfbCopy() && addr.IsMemOnlyAddress(); }
bool IsEfbCopy() { return is_efb_copy; }
};
virtual ~TextureCache(); // needs virtual for DX11 dtor
@ -183,7 +139,7 @@ private:
static TCacheEntryBase* ReturnEntry(unsigned int stage, TCacheEntryBase* entry);
typedef std::multimap<TextureAddress, TCacheEntryBase*> TexCache;
typedef std::multimap<u32, TCacheEntryBase*> TexCache;
typedef std::unordered_multimap<TCacheEntryConfig, TCacheEntryBase*, TCacheEntryConfig::Hasher> TexPool;
static TexCache textures;