diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 14cf207034..865868bd4c 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -62,13 +62,13 @@ static int xfb_count = 0; std::unique_ptr g_texture_cache; -TextureCacheBase::TCacheEntry::TCacheEntry(std::unique_ptr tex, +TCacheEntry::TCacheEntry(std::unique_ptr tex, std::unique_ptr fb) : texture(std::move(tex)), framebuffer(std::move(fb)) { } -TextureCacheBase::TCacheEntry::~TCacheEntry() +TCacheEntry::~TCacheEntry() { for (auto& reference : references) reference->references.erase(this); @@ -240,7 +240,7 @@ void TextureCacheBase::Cleanup(int _frameCount) } } -bool TextureCacheBase::TCacheEntry::OverlapsMemoryRange(u32 range_address, u32 range_size) const +bool TCacheEntry::OverlapsMemoryRange(u32 range_address, u32 range_size) const { if (addr + size_in_bytes <= range_address) return false; @@ -268,7 +268,7 @@ void TextureCacheBase::SetBackupConfig(const VideoConfig& config) config.graphics_mod_config ? config.graphics_mod_config->GetChangeCount() : 0; } -TextureCacheBase::TCacheEntry* +TCacheEntry* TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, const u8* palette, TLUTFormat tlutfmt) { DEBUG_ASSERT(g_ActiveConfig.backend_info.bSupportsPaletteConversion); @@ -337,7 +337,7 @@ TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, const u8* palette, TLU return decoded_entry; } -TextureCacheBase::TCacheEntry* TextureCacheBase::ReinterpretEntry(const TCacheEntry* existing_entry, +TCacheEntry* TextureCacheBase::ReinterpretEntry(const TCacheEntry* existing_entry, TextureFormat new_format) { const AbstractPipeline* pipeline = @@ -383,7 +383,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::ReinterpretEntry(const TCacheEn return reinterpreted_entry; } -void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntry* entry, u32 new_width, +void TextureCacheBase::ScaleTextureCacheEntryTo(TCacheEntry* entry, u32 new_width, u32 new_height) { if (entry->GetWidth() == new_width && entry->GetHeight() == new_height) @@ -746,7 +746,7 @@ void TextureCacheBase::DoLoadState(PointerWrap& p) } } -void TextureCacheBase::TCacheEntry::DoState(PointerWrap& p) +void TCacheEntry::DoState(PointerWrap& p) { p.Do(addr); p.Do(size_in_bytes); @@ -770,7 +770,7 @@ void TextureCacheBase::TCacheEntry::DoState(PointerWrap& p) p.Do(frameCount); } -TextureCacheBase::TCacheEntry* +TCacheEntry* TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, const u8* palette, TLUTFormat tlutfmt) { @@ -1224,7 +1224,7 @@ private: std::vector levels; }; -TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture_info) +TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture_info) { // if this stage was not invalidated by changes to texture registers, keep the current texture if (TMEM::IsValid(texture_info.GetStage()) && bound_textures[texture_info.GetStage()]) @@ -1272,7 +1272,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture return entry; } -TextureCacheBase::TCacheEntry* +TCacheEntry* TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, const TextureInfo& texture_info) { @@ -1729,7 +1729,7 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, return entry; } -static void GetDisplayRectForXFBEntry(TextureCacheBase::TCacheEntry* entry, u32 width, u32 height, +static void GetDisplayRectForXFBEntry(TCacheEntry* entry, u32 width, u32 height, MathUtil::Rectangle* display_rect) { // Scale the sub-rectangle to the full resolution of the texture. @@ -1739,7 +1739,7 @@ static void GetDisplayRectForXFBEntry(TextureCacheBase::TCacheEntry* entry, u32 display_rect->bottom = static_cast(height * entry->GetHeight() / entry->native_height); } -TextureCacheBase::TCacheEntry* +TCacheEntry* TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, MathUtil::Rectangle* display_rect) { @@ -1822,7 +1822,7 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, return entry; } -TextureCacheBase::TCacheEntry* TextureCacheBase::GetXFBFromCache(u32 address, u32 width, u32 height, +TCacheEntry* TextureCacheBase::GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride) { auto iter_range = textures_by_address.equal_range(address); @@ -2555,7 +2555,7 @@ void TextureCacheBase::UninitializeXFBMemory(u8* dst, u32 stride, u32 bytes_per_ } } -TextureCacheBase::TCacheEntry* TextureCacheBase::AllocateCacheEntry(const TextureConfig& config) +TCacheEntry* TextureCacheBase::AllocateCacheEntry(const TextureConfig& config) { std::optional alloc = AllocateTexture(config); if (!alloc) @@ -2619,7 +2619,7 @@ TextureCacheBase::FindMatchingTextureFromPool(const TextureConfig& config) } TextureCacheBase::TexAddrCache::iterator -TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntry* entry) +TextureCacheBase::GetTexCacheIter(TCacheEntry* entry) { auto iter_range = textures_by_address.equal_range(entry->addr); TexAddrCache::iterator iter = iter_range.first; @@ -2967,7 +2967,7 @@ bool TextureCacheBase::DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, con return true; } -u32 TextureCacheBase::TCacheEntry::BytesPerRow() const +u32 TCacheEntry::BytesPerRow() const { // RGBA takes two cache lines per block; all others take one const u32 bytes_per_block = format == TextureFormat::RGBA8 ? 64 : 32; @@ -2975,7 +2975,7 @@ u32 TextureCacheBase::TCacheEntry::BytesPerRow() const return NumBlocksX() * bytes_per_block; } -u32 TextureCacheBase::TCacheEntry::NumBlocksX() const +u32 TCacheEntry::NumBlocksX() const { const u32 blockW = TexDecoder_GetBlockWidthInTexels(format.texfmt); @@ -2985,7 +2985,7 @@ u32 TextureCacheBase::TCacheEntry::NumBlocksX() const return actualWidth / blockW; } -u32 TextureCacheBase::TCacheEntry::NumBlocksY() const +u32 TCacheEntry::NumBlocksY() const { u32 blockH = TexDecoder_GetBlockHeightInTexels(format.texfmt); // Round up source height to multiple of block size @@ -2994,7 +2994,7 @@ u32 TextureCacheBase::TCacheEntry::NumBlocksY() const return actualHeight / blockH; } -void TextureCacheBase::TCacheEntry::SetXfbCopy(u32 stride) +void TCacheEntry::SetXfbCopy(u32 stride) { is_efb_copy = false; is_xfb_copy = true; @@ -3006,7 +3006,7 @@ void TextureCacheBase::TCacheEntry::SetXfbCopy(u32 stride) size_in_bytes = memory_stride * NumBlocksY(); } -void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride) +void TCacheEntry::SetEfbCopy(u32 stride) { is_efb_copy = true; is_xfb_copy = false; @@ -3018,14 +3018,14 @@ void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride) size_in_bytes = memory_stride * NumBlocksY(); } -void TextureCacheBase::TCacheEntry::SetNotCopy() +void TCacheEntry::SetNotCopy() { is_efb_copy = false; is_xfb_copy = false; is_xfb_container = false; } -int TextureCacheBase::TCacheEntry::HashSampleSize() const +int TCacheEntry::HashSampleSize() const { if (should_force_safe_hashing) { @@ -3035,7 +3035,7 @@ int TextureCacheBase::TCacheEntry::HashSampleSize() const return g_ActiveConfig.iSafeTextureCache_ColorSamples; } -u64 TextureCacheBase::TCacheEntry::CalculateHash() const +u64 TCacheEntry::CalculateHash() const { const u32 bytes_per_row = BytesPerRow(); const u32 hash_sample_size = HashSampleSize(); diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 4fe11a64f4..cfcb4afe9e 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -33,6 +33,8 @@ struct VideoConfig; constexpr std::string_view EFB_DUMP_PREFIX = "efb1"; constexpr std::string_view XFB_DUMP_PREFIX = "xfb1"; +static constexpr int FRAMECOUNT_INVALID = 0; + struct TextureAndTLUTFormat { TextureAndTLUTFormat(TextureFormat texfmt_ = TextureFormat::I4, @@ -103,121 +105,118 @@ struct fmt::formatter } }; +struct TCacheEntry +{ + // common members + std::unique_ptr texture; + std::unique_ptr framebuffer; + u32 addr = 0; + u32 size_in_bytes = 0; + u64 base_hash = 0; + u64 hash = 0; // for paletted textures, hash = base_hash ^ palette_hash + TextureAndTLUTFormat format; + u32 memory_stride = 0; + bool is_efb_copy = false; + bool is_custom_tex = false; + bool may_have_overlapping_textures = true; + bool tmem_only = false; // indicates that this texture only exists in the tmem cache + bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary + // content, aren't just downscaled + bool should_force_safe_hashing = false; // for XFB + bool is_xfb_copy = false; + bool is_xfb_container = false; + u64 id = 0; + + bool reference_changed = false; // used by xfb to determine when a reference xfb changed + + // Texture dimensions from the GameCube's point of view + u32 native_width = 0; + u32 native_height = 0; + u32 native_levels = 0; + + // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames + int frameCount = FRAMECOUNT_INVALID; + + // Keep an iterator to the entry in textures_by_hash, so it does not need to be searched when + // removing the cache entry + std::multimap::iterator textures_by_hash_iter; + + // This is used to keep track of both: + // * efb copies used by this partially updated texture + // * partially updated textures which refer to this efb copy + std::unordered_set references; + + // Pending EFB copy + std::unique_ptr pending_efb_copy; + u32 pending_efb_copy_width = 0; + u32 pending_efb_copy_height = 0; + bool pending_efb_copy_invalidated = false; + + std::string texture_info_name = ""; + + explicit TCacheEntry(std::unique_ptr tex, + std::unique_ptr fb); + + ~TCacheEntry(); + + void SetGeneralParameters(u32 _addr, u32 _size, TextureAndTLUTFormat _format, + bool force_safe_hashing) + { + addr = _addr; + size_in_bytes = _size; + format = _format; + should_force_safe_hashing = force_safe_hashing; + } + + void SetDimensions(unsigned int _native_width, unsigned int _native_height, + unsigned int _native_levels) + { + native_width = _native_width; + native_height = _native_height; + native_levels = _native_levels; + memory_stride = _native_width; + } + + void SetHashes(u64 _base_hash, u64 _hash) + { + base_hash = _base_hash; + hash = _hash; + } + + // This texture entry is used by the other entry as a sub-texture + void CreateReference(TCacheEntry* other_entry) + { + // References are two-way, so they can easily be destroyed later + this->references.emplace(other_entry); + other_entry->references.emplace(this); + } + + void SetXfbCopy(u32 stride); + void SetEfbCopy(u32 stride); + void SetNotCopy(); + + bool OverlapsMemoryRange(u32 range_address, u32 range_size) const; + + bool IsEfbCopy() const { return is_efb_copy; } + bool IsCopy() const { return is_xfb_copy || is_efb_copy; } + u32 NumBlocksX() const; + u32 NumBlocksY() const; + u32 BytesPerRow() const; + + u64 CalculateHash() const; + + int HashSampleSize() const; + u32 GetWidth() const { return texture->GetConfig().width; } + u32 GetHeight() const { return texture->GetConfig().height; } + u32 GetNumLevels() const { return texture->GetConfig().levels; } + u32 GetNumLayers() const { return texture->GetConfig().layers; } + AbstractTextureFormat GetFormat() const { return texture->GetConfig().format; } + void DoState(PointerWrap& p); +}; + class TextureCacheBase { -private: - static const int FRAMECOUNT_INVALID = 0; - public: - struct TCacheEntry - { - // common members - std::unique_ptr texture; - std::unique_ptr framebuffer; - u32 addr = 0; - u32 size_in_bytes = 0; - u64 base_hash = 0; - u64 hash = 0; // for paletted textures, hash = base_hash ^ palette_hash - TextureAndTLUTFormat format; - u32 memory_stride = 0; - bool is_efb_copy = false; - bool is_custom_tex = false; - bool may_have_overlapping_textures = true; - bool tmem_only = false; // indicates that this texture only exists in the tmem cache - bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary - // content, aren't just downscaled - bool should_force_safe_hashing = false; // for XFB - bool is_xfb_copy = false; - bool is_xfb_container = false; - u64 id = 0; - - bool reference_changed = false; // used by xfb to determine when a reference xfb changed - - // Texture dimensions from the GameCube's point of view - u32 native_width = 0; - u32 native_height = 0; - u32 native_levels = 0; - - // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames - int frameCount = FRAMECOUNT_INVALID; - - // Keep an iterator to the entry in textures_by_hash, so it does not need to be searched when - // removing the cache entry - std::multimap::iterator textures_by_hash_iter; - - // This is used to keep track of both: - // * efb copies used by this partially updated texture - // * partially updated textures which refer to this efb copy - std::unordered_set references; - - // Pending EFB copy - std::unique_ptr pending_efb_copy; - u32 pending_efb_copy_width = 0; - u32 pending_efb_copy_height = 0; - bool pending_efb_copy_invalidated = false; - - std::string texture_info_name = ""; - - explicit TCacheEntry(std::unique_ptr tex, - std::unique_ptr fb); - - ~TCacheEntry(); - - void SetGeneralParameters(u32 _addr, u32 _size, TextureAndTLUTFormat _format, - bool force_safe_hashing) - { - addr = _addr; - size_in_bytes = _size; - format = _format; - should_force_safe_hashing = force_safe_hashing; - } - - void SetDimensions(unsigned int _native_width, unsigned int _native_height, - unsigned int _native_levels) - { - native_width = _native_width; - native_height = _native_height; - native_levels = _native_levels; - memory_stride = _native_width; - } - - void SetHashes(u64 _base_hash, u64 _hash) - { - base_hash = _base_hash; - hash = _hash; - } - - // This texture entry is used by the other entry as a sub-texture - void CreateReference(TCacheEntry* other_entry) - { - // References are two-way, so they can easily be destroyed later - this->references.emplace(other_entry); - other_entry->references.emplace(this); - } - - void SetXfbCopy(u32 stride); - void SetEfbCopy(u32 stride); - void SetNotCopy(); - - bool OverlapsMemoryRange(u32 range_address, u32 range_size) const; - - bool IsEfbCopy() const { return is_efb_copy; } - bool IsCopy() const { return is_xfb_copy || is_efb_copy; } - u32 NumBlocksX() const; - u32 NumBlocksY() const; - u32 BytesPerRow() const; - - u64 CalculateHash() const; - - int HashSampleSize() const; - u32 GetWidth() const { return texture->GetConfig().width; } - u32 GetHeight() const { return texture->GetConfig().height; } - u32 GetNumLevels() const { return texture->GetConfig().levels; } - u32 GetNumLayers() const { return texture->GetConfig().layers; } - AbstractTextureFormat GetFormat() const { return texture->GetConfig().format; } - void DoState(PointerWrap& p); - }; - // Minimal version of TCacheEntry just for TexPool struct TexPoolEntry {