mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
Remove TextureAddress struct.
This commit is contained in:
parent
c0a4760f0e
commit
ddc815dd7a
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user