From c1fd4a2013d90c65f1f12d83ffbb9720ef463376 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sun, 24 Jul 2022 10:46:05 +1200 Subject: Move TCacheEntry out of TextureCacheBase Allows for fowards declaration --- Source/Core/VideoCommon/TextureCacheBase.cpp | 46 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') 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(); -- cgit v1.2.3 From 606c18210dd4f651655b2c84e9e332e6c6c6e21b Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Mon, 25 Jul 2022 17:20:33 +1200 Subject: TextureCache: Refactor with smart pointers The whole ownership model was getting a bit of a mess, with a some of special cases to deal with. And I'm planning to make it even more complex in the future. So here is some upfront work to convert it over to reference counted pointers. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 343 ++++++++++++++------------- 1 file changed, 174 insertions(+), 169 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 865868bd4c..84208c8094 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -63,7 +63,7 @@ static int xfb_count = 0; std::unique_ptr g_texture_cache; TCacheEntry::TCacheEntry(std::unique_ptr tex, - std::unique_ptr fb) + std::unique_ptr fb) : texture(std::move(tex)), framebuffer(std::move(fb)) { } @@ -72,6 +72,8 @@ TCacheEntry::~TCacheEntry() { for (auto& reference : references) reference->references.erase(this); + ASSERT_MSG(VIDEO, g_texture_cache, "Texture cache destroyed before TCacheEntry was destroyed"); + g_texture_cache->ReleaseToPool(this); } void TextureCacheBase::CheckTempSize(size_t required_size) @@ -99,13 +101,19 @@ TextureCacheBase::TextureCacheBase() TMEM::InvalidateAll(); } -TextureCacheBase::~TextureCacheBase() +void TextureCacheBase::Shutdown() { // Clear pending EFB copies first, so we don't try to flush them. m_pending_efb_copies.clear(); HiresTexture::Shutdown(); + + // For correctness, we need to invalidate textures before the gpu context starts shutting down. Invalidate(); +} + +TextureCacheBase::~TextureCacheBase() +{ Common::FreeAlignedMemory(temp); temp = nullptr; } @@ -126,13 +134,10 @@ void TextureCacheBase::Invalidate() FlushEFBCopies(); TMEM::InvalidateAll(); - bound_textures.fill(nullptr); - for (auto& tex : textures_by_address) - { - delete tex.second; - } - textures_by_address.clear(); + for (auto& bind : bound_textures) + bind.reset(); textures_by_hash.clear(); + textures_by_address.clear(); texture_pool.clear(); } @@ -183,11 +188,7 @@ void TextureCacheBase::Cleanup(int _frameCount) TexAddrCache::iterator tcend = textures_by_address.end(); while (iter != tcend) { - if (iter->second->tmem_only) - { - iter = InvalidateTexture(iter); - } - else if (iter->second->frameCount == FRAMECOUNT_INVALID) + if (iter->second->frameCount == FRAMECOUNT_INVALID) { iter->second->frameCount = _frameCount; ++iter; @@ -268,8 +269,8 @@ void TextureCacheBase::SetBackupConfig(const VideoConfig& config) config.graphics_mod_config ? config.graphics_mod_config->GetChangeCount() : 0; } -TCacheEntry* -TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, const u8* palette, TLUTFormat tlutfmt) +RcTcacheEntry TextureCacheBase::ApplyPaletteToEntry(RcTcacheEntry& entry, const u8* palette, + TLUTFormat tlutfmt) { DEBUG_ASSERT(g_ActiveConfig.backend_info.bSupportsPaletteConversion); @@ -277,16 +278,16 @@ TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, const u8* palette, TLU if (!pipeline) { ERROR_LOG_FMT(VIDEO, "Failed to get conversion pipeline for format {}", tlutfmt); - return nullptr; + return {}; } TextureConfig new_config = entry->texture->GetConfig(); new_config.levels = 1; new_config.flags |= AbstractTextureFlag_RenderTarget; - TCacheEntry* decoded_entry = AllocateCacheEntry(new_config); + RcTcacheEntry decoded_entry = AllocateCacheEntry(new_config); if (!decoded_entry) - return nullptr; + return decoded_entry; decoded_entry->SetGeneralParameters(entry->addr, entry->size_in_bytes, entry->format, entry->should_force_safe_hashing); @@ -337,8 +338,8 @@ TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, const u8* palette, TLU return decoded_entry; } -TCacheEntry* TextureCacheBase::ReinterpretEntry(const TCacheEntry* existing_entry, - TextureFormat new_format) +RcTcacheEntry TextureCacheBase::ReinterpretEntry(const RcTcacheEntry& existing_entry, + TextureFormat new_format) { const AbstractPipeline* pipeline = g_shader_cache->GetTextureReinterpretPipeline(existing_entry->format.texfmt, new_format); @@ -346,16 +347,16 @@ TCacheEntry* TextureCacheBase::ReinterpretEntry(const TCacheEntry* existing_entr { ERROR_LOG_FMT(VIDEO, "Failed to obtain texture reinterpreting pipeline from format {} to {}", existing_entry->format.texfmt, new_format); - return nullptr; + return {}; } TextureConfig new_config = existing_entry->texture->GetConfig(); new_config.levels = 1; new_config.flags |= AbstractTextureFlag_RenderTarget; - TCacheEntry* reinterpreted_entry = AllocateCacheEntry(new_config); + RcTcacheEntry reinterpreted_entry = AllocateCacheEntry(new_config); if (!reinterpreted_entry) - return nullptr; + return {}; reinterpreted_entry->SetGeneralParameters(existing_entry->addr, existing_entry->size_in_bytes, new_format, existing_entry->should_force_safe_hashing); @@ -383,8 +384,7 @@ TCacheEntry* TextureCacheBase::ReinterpretEntry(const TCacheEntry* existing_entr return reinterpreted_entry; } -void TextureCacheBase::ScaleTextureCacheEntryTo(TCacheEntry* entry, u32 new_width, - u32 new_height) +void TextureCacheBase::ScaleTextureCacheEntryTo(RcTcacheEntry& entry, u32 new_width, u32 new_height) { if (entry->GetWidth() == new_width && entry->GetHeight() == new_height) { @@ -559,15 +559,19 @@ void TextureCacheBase::DoState(PointerWrap& p) void TextureCacheBase::DoSaveState(PointerWrap& p) { + // Flush all stale binds + FlushStaleBinds(); + std::map entry_map; std::vector entries_to_save; - auto ShouldSaveEntry = [](const TCacheEntry* entry) { + auto ShouldSaveEntry = [](const RcTcacheEntry& entry) { // We skip non-copies as they can be decoded from RAM when the state is loaded. // Storing them would duplicate data in the save state file, adding to decompression time. - return entry->IsCopy(); + // We also need to store invalidated entires, as they can't be restored from RAM. + return entry->IsCopy() || entry->invalidated; }; - auto AddCacheEntryToMap = [&entry_map, &entries_to_save](TCacheEntry* entry) -> u32 { - auto iter = entry_map.find(entry); + auto AddCacheEntryToMap = [&entry_map, &entries_to_save](const RcTcacheEntry& entry) -> u32 { + auto iter = entry_map.find(entry.get()); if (iter != entry_map.end()) return iter->second; @@ -575,8 +579,8 @@ void TextureCacheBase::DoSaveState(PointerWrap& p) // same order they were collected. This is because of iterating both the address and hash maps. // Therefore, the map is used for fast lookup, and the vector for ordering. u32 id = static_cast(entry_map.size()); - entry_map.emplace(entry, id); - entries_to_save.push_back(entry); + entry_map.emplace(entry.get(), id); + entries_to_save.push_back(entry.get()); return id; }; auto GetCacheEntryId = [&entry_map](const TCacheEntry* entry) -> std::optional { @@ -588,6 +592,7 @@ void TextureCacheBase::DoSaveState(PointerWrap& p) // of address/hash to entry ID. std::vector> textures_by_address_list; std::vector> textures_by_hash_list; + std::vector> bound_textures_list; if (Config::Get(Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE)) { for (const auto& it : textures_by_address) @@ -606,6 +611,15 @@ void TextureCacheBase::DoSaveState(PointerWrap& p) textures_by_hash_list.emplace_back(it.first, id); } } + for (u32 i = 0; i < bound_textures.size(); i++) + { + const auto& tentry = bound_textures[i]; + if (bound_textures[i] && ShouldSaveEntry(tentry)) + { + const u32 id = AddCacheEntryToMap(tentry); + bound_textures_list.emplace_back(i, id); + } + } } // Save the texture cache entries out in the order the were referenced. @@ -641,29 +655,20 @@ void TextureCacheBase::DoSaveState(PointerWrap& p) } } - size = static_cast(reference_pairs.size()); - p.Do(size); - for (const auto& it : reference_pairs) - { - p.Do(it.first); - p.Do(it.second); - } + auto doList = [&p](auto list) { + u32 size = static_cast(list.size()); + p.Do(size); + for (const auto& it : list) + { + p.Do(it.first); + p.Do(it.second); + } + }; - size = static_cast(textures_by_address_list.size()); - p.Do(size); - for (const auto& it : textures_by_address_list) - { - p.Do(it.first); - p.Do(it.second); - } - - size = static_cast(textures_by_hash_list.size()); - p.Do(size); - for (const auto& it : textures_by_hash_list) - { - p.Do(it.first); - p.Do(it.second); - } + doList(reference_pairs); + doList(textures_by_address_list); + doList(textures_by_hash_list); + doList(bound_textures_list); // Free the readback texture to potentially save host-mapped GPU memory, depending on where // the driver mapped the staging buffer. @@ -673,10 +678,11 @@ void TextureCacheBase::DoSaveState(PointerWrap& p) void TextureCacheBase::DoLoadState(PointerWrap& p) { // Helper for getting a cache entry from an ID. - std::map id_map; - auto GetEntry = [&id_map](u32 id) { + std::map id_map; + RcTcacheEntry null_entry; + auto GetEntry = [&id_map, &null_entry](u32 id) -> RcTcacheEntry& { auto iter = id_map.find(id); - return iter == id_map.end() ? nullptr : iter->second; + return iter == id_map.end() ? null_entry : iter->second; }; // Only clear out state when actually restoring/loading. @@ -694,13 +700,11 @@ void TextureCacheBase::DoLoadState(PointerWrap& p) // Even if the texture isn't valid, we still need to create the cache entry object // to update the point in the state state. We'll just throw it away if it's invalid. auto tex = DeserializeTexture(p); - TCacheEntry* entry = new TCacheEntry(std::move(tex->texture), std::move(tex->framebuffer)); + auto entry = Common::make_rc(std::move(tex->texture), std::move(tex->framebuffer)); entry->textures_by_hash_iter = textures_by_hash.end(); entry->DoState(p); if (entry->texture && commit_state) id_map.emplace(i, entry); - else - delete entry; } p.DoMarker("TextureCacheEntries"); @@ -711,10 +715,10 @@ void TextureCacheBase::DoLoadState(PointerWrap& p) u32 id1 = 0, id2 = 0; p.Do(id1); p.Do(id2); - TCacheEntry* e1 = GetEntry(id1); - TCacheEntry* e2 = GetEntry(id2); + auto e1 = GetEntry(id1); + auto e2 = GetEntry(id2); if (e1 && e2) - e1->CreateReference(e2); + e1->CreateReference(e2.get()); } // Fill in address map. @@ -726,7 +730,7 @@ void TextureCacheBase::DoLoadState(PointerWrap& p) p.Do(addr); p.Do(id); - TCacheEntry* entry = GetEntry(id); + auto& entry = GetEntry(id); if (entry) textures_by_address.emplace(addr, entry); } @@ -740,10 +744,28 @@ void TextureCacheBase::DoLoadState(PointerWrap& p) p.Do(hash); p.Do(id); - TCacheEntry* entry = GetEntry(id); + auto& entry = GetEntry(id); if (entry) entry->textures_by_hash_iter = textures_by_hash.emplace(hash, entry); } + + // Clear bound textures + for (u32 i = 0; i < bound_textures.size(); i++) + bound_textures[i].reset(); + + // Fill in bound textures + p.Do(size); + for (u32 i = 0; i < size; i++) + { + u32 index = 0; + u32 id = 0; + p.Do(index); + p.Do(id); + + auto& entry = GetEntry(id); + if (entry) + bound_textures[index] = entry; + } } void TCacheEntry::DoState(PointerWrap& p) @@ -757,7 +779,7 @@ void TCacheEntry::DoState(PointerWrap& p) p.Do(is_efb_copy); p.Do(is_custom_tex); p.Do(may_have_overlapping_textures); - p.Do(tmem_only); + p.Do(invalidated); p.Do(has_arbitrary_mips); p.Do(should_force_safe_hashing); p.Do(is_xfb_copy); @@ -770,9 +792,8 @@ void TCacheEntry::DoState(PointerWrap& p) p.Do(frameCount); } -TCacheEntry* -TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, const u8* palette, - TLUTFormat tlutfmt) +RcTcacheEntry TextureCacheBase::DoPartialTextureUpdates(RcTcacheEntry& entry_to_update, + const u8* palette, TLUTFormat tlutfmt) { // If the flag may_have_overlapping_textures is cleared, there are no overlapping EFB copies, // which aren't applied already. It is set for new textures, and for the affected range @@ -798,9 +819,9 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, const u8 auto iter = FindOverlappingTextures(entry_to_update->addr, entry_to_update->size_in_bytes); while (iter.first != iter.second) { - TCacheEntry* entry = iter.first->second; - if (entry != entry_to_update && entry->IsCopy() && !entry->tmem_only && - entry->references.count(entry_to_update) == 0 && + auto& entry = iter.first->second; + if (entry != entry_to_update && entry->IsCopy() && + entry->references.count(entry_to_update.get()) == 0 && entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes) && entry->memory_stride == numBlocksX * block_size) { @@ -815,20 +836,19 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, const u8 continue; } - TCacheEntry* reinterpreted_entry = - ReinterpretEntry(entry, entry_to_update->format.texfmt); + auto reinterpreted_entry = ReinterpretEntry(entry, entry_to_update->format.texfmt); if (reinterpreted_entry) entry = reinterpreted_entry; } if (isPaletteTexture) { - TCacheEntry* decoded_entry = ApplyPaletteToEntry(entry, palette, tlutfmt); + auto decoded_entry = ApplyPaletteToEntry(entry, palette, tlutfmt); if (decoded_entry) { // Link the efb copy with the partially updated texture, so we won't apply this partial // update again - entry->CreateReference(entry_to_update); + entry->CreateReference(entry_to_update.get()); // Mark the texture update as used, as if it was loaded directly entry->frameCount = FRAMECOUNT_INVALID; entry = decoded_entry; @@ -929,7 +949,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, const u8 else { // Link the two textures together, so we won't apply this partial update again - entry->CreateReference(entry_to_update); + entry->CreateReference(entry_to_update.get()); // Mark the texture update as used, as if it was loaded directly entry->frameCount = FRAMECOUNT_INVALID; } @@ -947,7 +967,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, const u8 return entry_to_update; } -void TextureCacheBase::DumpTexture(TCacheEntry* entry, std::string basename, unsigned int level, +void TextureCacheBase::DumpTexture(RcTcacheEntry& entry, std::string basename, unsigned int level, bool is_arbitrary) { std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + SConfig::GetInstance().GetGameID(); @@ -1065,7 +1085,7 @@ void TextureCacheBase::BindTextures(BitSet32 used_textures) auto& pixel_shader_manager = system.GetPixelShaderManager(); for (u32 i = 0; i < bound_textures.size(); i++) { - const TCacheEntry* tentry = bound_textures[i]; + const RcTcacheEntry& tentry = bound_textures[i]; if (used_textures[i] && tentry) { g_renderer->SetTexture(i, tentry->texture.get()); @@ -1229,9 +1249,16 @@ 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()]) { - TCacheEntry* entry = bound_textures[texture_info.GetStage()]; + TCacheEntry* entry = bound_textures[texture_info.GetStage()].get(); // If the TMEM configuration is such that this texture is more or less guaranteed to still // be in TMEM, then we know we can reuse the old entry without even hashing the memory + // + // It's possible this texture has already been overwritten in emulated memory and therfore + // invalidated from our texture cache, but we want to use it anyway to approximate the + // result of the game using an overwritten texture cached in TMEM. + // + // Spyro: A Hero's Tail is known for (deliberately?) using such overwritten textures + // in it's bloom effect, which breaks without giving it the invalidated texture. if (TMEM::IsCached(texture_info.GetStage())) { return entry; @@ -1239,7 +1266,7 @@ TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture_info) // Otherwise, hash the backing memory and check it's unchanged. // FIXME: this doesn't correctly handle textures from tmem. - if (!entry->tmem_only && entry->base_hash == entry->CalculateHash()) + if (!entry->invalidated && entry->base_hash == entry->CalculateHash()) { return entry; } @@ -1269,12 +1296,11 @@ TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture_info) TMEM::Bind(texture_info.GetStage(), entry->NumBlocksX(), entry->NumBlocksY(), entry->GetNumLevels() > 1, entry->format == TextureFormat::RGBA8); - return entry; + return entry.get(); } -TCacheEntry* -TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, - const TextureInfo& texture_info) +RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, + const TextureInfo& texture_info) { u32 expanded_width = texture_info.GetExpandedWidth(); u32 expanded_height = texture_info.GetExpandedHeight(); @@ -1291,7 +1317,7 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, // Reject invalid tlut format. if (texture_info.GetPaletteSize() && !IsValidTLUTFormat(texture_info.GetTlutFormat())) - return nullptr; + return {}; u32 bytes_per_block = (texture_info.GetBlockWidth() * texture_info.GetBlockHeight() * TexDecoder_GetTexelSizeInNibbles(texture_info.GetTextureFormat())) / @@ -1304,7 +1330,7 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, { ERROR_LOG_FMT(VIDEO, "Trying to use an invalid texture address {:#010x}", texture_info.GetRawAddress()); - return nullptr; + return {}; } // If we are recording a FifoLog, keep track of what memory we read. FifoRecorder does @@ -1368,14 +1394,7 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, while (iter != iter_range.second) { - TCacheEntry* entry = iter->second; - - // Skip entries that are only left in our texture cache for the tmem cache emulation - if (entry->tmem_only) - { - ++iter; - continue; - } + RcTcacheEntry& entry = iter->second; // TODO: Some games (Rogue Squadron 3, Twin Snakes) seem to load a previously made XFB // copy as a regular texture. You can see this particularly well in RS3 whenever the @@ -1478,7 +1497,7 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, if (unreinterpreted_copy != textures_by_address.end()) { - TCacheEntry* decoded_entry = + auto decoded_entry = ReinterpretEntry(unreinterpreted_copy->second, texture_info.GetTextureFormat()); // It's possible to combine reinterpreted textures + palettes. @@ -1492,8 +1511,9 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, if (unconverted_copy != textures_by_address.end()) { - TCacheEntry* decoded_entry = ApplyPaletteToEntry( - unconverted_copy->second, texture_info.GetTlutAddress(), texture_info.GetTlutFormat()); + auto decoded_entry = + ApplyPaletteToEntry(unconverted_copy->second, texture_info.GetTlutAddress(), + texture_info.GetTlutFormat()); if (decoded_entry) { @@ -1515,7 +1535,7 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, TexHashCache::iterator hash_iter = hash_range.first; while (hash_iter != hash_range.second) { - TCacheEntry* entry = hash_iter->second; + RcTcacheEntry& entry = hash_iter->second; // All parameters, except the address, need to match here if (entry->format == full_format && entry->native_levels >= texture_info.GetLevelCount() && entry->native_width == texture_info.GetRawWidth() && @@ -1577,9 +1597,9 @@ TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, // create the entry/texture const TextureConfig config(width, height, texLevels, 1, 1, hires_tex ? hires_tex->GetFormat() : AbstractTextureFormat::RGBA8, 0); - TCacheEntry* entry = AllocateCacheEntry(config); + RcTcacheEntry entry = AllocateCacheEntry(config); if (!entry) - return nullptr; + return entry; ArbitraryMipmapDetector arbitrary_mip_detector; if (hires_tex) @@ -1739,9 +1759,8 @@ static void GetDisplayRectForXFBEntry(TCacheEntry* entry, u32 width, u32 height, display_rect->bottom = static_cast(height * entry->GetHeight() / entry->native_height); } -TCacheEntry* -TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, - MathUtil::Rectangle* display_rect) +RcTcacheEntry TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, + MathUtil::Rectangle* display_rect) { auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); @@ -1749,11 +1768,11 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, if (!src_data) { ERROR_LOG_FMT(VIDEO, "Trying to load XFB texture from invalid address {:#010x}", address); - return nullptr; + return {}; } // Do we currently have a version of this XFB copy in VRAM? - TCacheEntry* entry = GetXFBFromCache(address, width, height, stride); + RcTcacheEntry entry = GetXFBFromCache(address, width, height, stride); if (entry) { if (entry->is_xfb_container) @@ -1762,7 +1781,7 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, entry->texture->FinishedRendering(); } - GetDisplayRectForXFBEntry(entry, width, height, display_rect); + GetDisplayRectForXFBEntry(entry.get(), width, height, display_rect); return entry; } @@ -1818,19 +1837,18 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, } } - GetDisplayRectForXFBEntry(entry, width, height, display_rect); + GetDisplayRectForXFBEntry(entry.get(), width, height, display_rect); return entry; } -TCacheEntry* TextureCacheBase::GetXFBFromCache(u32 address, u32 width, u32 height, - u32 stride) +RcTcacheEntry TextureCacheBase::GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride) { auto iter_range = textures_by_address.equal_range(address); TexAddrCache::iterator iter = iter_range.first; while (iter != iter_range.second) { - TCacheEntry* entry = iter->second; + auto& entry = iter->second; // The only thing which has to match exactly is the stride. We can use a partial rectangle if // the VI width/height differs from that of the XFB copy. @@ -1854,10 +1872,10 @@ TCacheEntry* TextureCacheBase::GetXFBFromCache(u32 address, u32 width, u32 heigh ++iter; } - return nullptr; + return {}; } -void TextureCacheBase::StitchXFBCopy(TCacheEntry* stitched_entry) +void TextureCacheBase::StitchXFBCopy(RcTcacheEntry& stitched_entry) { // It is possible that some of the overlapping textures overlap each other. This behavior has been // seen with XFB copies in Rogue Leader. To get the correct result, we apply the texture updates @@ -1876,8 +1894,8 @@ void TextureCacheBase::StitchXFBCopy(TCacheEntry* stitched_entry) // our force progressive hack means that an XFB copy should always have a matching stride. If // the hack is disabled, XFB2RAM should also be enabled. Should we wish to implement interlaced // stitching in the future, this would require a shader which grabs every second line. - TCacheEntry* entry = iter.first->second; - if (entry != stitched_entry && entry->IsCopy() && !entry->tmem_only && + auto& entry = iter.first->second; + if (entry != stitched_entry && entry->IsCopy() && entry->OverlapsMemoryRange(stitched_entry->addr, stitched_entry->size_in_bytes) && entry->memory_stride == stitched_entry->memory_stride) { @@ -1887,7 +1905,7 @@ void TextureCacheBase::StitchXFBCopy(TCacheEntry* stitched_entry) if (entry->native_width != entry->GetWidth()) create_upscaled_copy = true; - candidates.emplace_back(entry); + candidates.emplace_back(entry.get()); } else { @@ -1997,7 +2015,7 @@ void TextureCacheBase::StitchXFBCopy(TCacheEntry* stitched_entry) } // Link the two textures together, so we won't apply this partial update again - entry->CreateReference(stitched_entry); + entry->CreateReference(stitched_entry.get()); // Mark the texture update as used, as if it was loaded directly entry->frameCount = FRAMECOUNT_INVALID; @@ -2223,7 +2241,7 @@ void TextureCacheBase::CopyRenderTargetToTexture( const bool linear_filter = !is_depth_copy && (scaleByHalf || g_renderer->GetEFBScale() != 1 || y_scale > 1.0f); - TCacheEntry* entry = nullptr; + RcTcacheEntry entry; if (copy_to_vram) { // create the texture @@ -2247,8 +2265,8 @@ void TextureCacheBase::CopyRenderTargetToTexture( entry->may_have_overlapping_textures = false; entry->is_custom_tex = false; - CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter, dstFormat, - isIntensity, gamma, clamp_top, clamp_bottom, + CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter, + dstFormat, isIntensity, gamma, clamp_top, clamp_bottom, GetVRAMCopyFilterCoefficients(filter_coefficients)); if (is_xfb_copy && (g_ActiveConfig.bDumpXFBTarget || g_ActiveConfig.bGraphicMods)) @@ -2314,7 +2332,6 @@ void TextureCacheBase::CopyRenderTargetToTexture( entry->pending_efb_copy = std::move(staging_texture); entry->pending_efb_copy_width = bytes_per_row / sizeof(u32); entry->pending_efb_copy_height = num_blocks_y; - entry->pending_efb_copy_invalidated = false; m_pending_efb_copies.push_back(entry); } } @@ -2339,7 +2356,7 @@ void TextureCacheBase::CopyRenderTargetToTexture( auto iter = FindOverlappingTextures(dstAddr, covered_range); while (iter.first != iter.second) { - TCacheEntry* overlapping_entry = iter.first->second; + RcTcacheEntry& overlapping_entry = iter.first->second; if (overlapping_entry->addr == dstAddr && overlapping_entry->is_xfb_copy) { @@ -2412,7 +2429,7 @@ void TextureCacheBase::CopyRenderTargetToTexture( { const u64 hash = entry->CalculateHash(); entry->SetHashes(hash, hash); - textures_by_address.emplace(dstAddr, entry); + textures_by_address.emplace(dstAddr, std::move(entry)); } } @@ -2421,11 +2438,20 @@ void TextureCacheBase::FlushEFBCopies() if (m_pending_efb_copies.empty()) return; - for (TCacheEntry* entry : m_pending_efb_copies) - FlushEFBCopy(entry); + for (auto& entry : m_pending_efb_copies) + FlushEFBCopy(entry.get()); m_pending_efb_copies.clear(); } +void TextureCacheBase::FlushStaleBinds() +{ + for (u32 i = 0; i < bound_textures.size(); i++) + { + if (!TMEM::IsCached(i)) + bound_textures[i].reset(); + } +} + void TextureCacheBase::WriteEFBCopyToRAM(u8* dst_ptr, u32 width, u32 height, u32 stride, std::unique_ptr staging_texture) { @@ -2443,14 +2469,10 @@ void TextureCacheBase::FlushEFBCopy(TCacheEntry* entry) WriteEFBCopyToRAM(dst, entry->pending_efb_copy_width, entry->pending_efb_copy_height, entry->memory_stride, std::move(entry->pending_efb_copy)); - // If the EFB copy was invalidated (e.g. the bloom case mentioned in InvalidateTexture), now is - // the time to clean up the TCacheEntry. In which case, we don't need to compute the new hash of - // the RAM copy. But we need to clean up the TCacheEntry, as InvalidateTexture doesn't free it. - if (entry->pending_efb_copy_invalidated) - { - delete entry; + // If the EFB copy was invalidated (e.g. the bloom case mentioned in InvalidateTexture), we don't + // need to do anything more. The entry will be automatically deleted by smart pointers + if (entry->invalidated) return; - } // Re-hash the texture now that the guest memory is populated. // This should be safe because we'll catch any writes before the game can modify it. @@ -2465,7 +2487,7 @@ void TextureCacheBase::FlushEFBCopy(TCacheEntry* entry) auto range = FindOverlappingTextures(entry->addr, covered_range); for (auto iter = range.first; iter != range.second; ++iter) { - TCacheEntry* overlapping_entry = iter->second; + auto& overlapping_entry = iter->second; if (overlapping_entry->may_have_overlapping_textures && overlapping_entry->is_xfb_copy && overlapping_entry->OverlapsMemoryRange(entry->addr, covered_range)) { @@ -2555,14 +2577,14 @@ void TextureCacheBase::UninitializeXFBMemory(u8* dst, u32 stride, u32 bytes_per_ } } -TCacheEntry* TextureCacheBase::AllocateCacheEntry(const TextureConfig& config) +RcTcacheEntry TextureCacheBase::AllocateCacheEntry(const TextureConfig& config) { std::optional alloc = AllocateTexture(config); if (!alloc) - return nullptr; + return {}; - TCacheEntry* cacheEntry = - new TCacheEntry(std::move(alloc->texture), std::move(alloc->framebuffer)); + auto cacheEntry = + Common::make_rc(std::move(alloc->texture), std::move(alloc->framebuffer)); cacheEntry->textures_by_hash_iter = textures_by_hash.end(); cacheEntry->id = last_entry_id++; return cacheEntry; @@ -2618,14 +2640,13 @@ TextureCacheBase::FindMatchingTextureFromPool(const TextureConfig& config) return matching_iter != range.second ? matching_iter : texture_pool.end(); } -TextureCacheBase::TexAddrCache::iterator -TextureCacheBase::GetTexCacheIter(TCacheEntry* entry) +TextureCacheBase::TexAddrCache::iterator TextureCacheBase::GetTexCacheIter(TCacheEntry* entry) { auto iter_range = textures_by_address.equal_range(entry->addr); TexAddrCache::iterator iter = iter_range.first; while (iter != iter_range.second) { - if (iter->second == entry) + if (iter->second.get() == entry) { return iter; } @@ -2657,7 +2678,7 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter, bool discard_pe if (iter == textures_by_address.end()) return textures_by_address.end(); - TCacheEntry* entry = iter->second; + RcTcacheEntry& entry = iter->second; if (entry->textures_by_hash_iter != textures_by_hash.end()) { @@ -2665,26 +2686,6 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter, bool discard_pe entry->textures_by_hash_iter = textures_by_hash.end(); } - for (size_t i = 0; i < bound_textures.size(); ++i) - { - if (bound_textures[i] == entry) - { - if (TMEM::IsCached(static_cast(i))) - { - // If the entry is currently bound and tmem has it recorded as cached, keep it, but mark it - // as invalidated. This way it can still be used via tmem cache emulation, but nothing else. - // Spyro: A Hero's Tail is known for using such overwritten textures. - bound_textures[i]->tmem_only = true; - return ++iter; - } - else - { - // Otherwise, delete the reference to it from bound_textures - bound_textures[i] = nullptr; - } - } - } - // If this is a pending EFB copy, we don't want to flush it here. // Why? Because let's say a game is rendering a bloom-type effect, using EFB copies to essentially // downscale the framebuffer. Copy from EFB->Texture, draw texture to EFB, copy EFB->Texture, @@ -2707,19 +2708,23 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter, bool discard_pe } else { - entry->pending_efb_copy_invalidated = true; + // The texture data has already been copied into the staging texture, so it's valid to + // optimistically release the texture data. Will slightly lower VRAM usage. + ReleaseToPool(entry.get()); } } + entry->invalidated = true; + + return textures_by_address.erase(iter); +} +void TextureCacheBase::ReleaseToPool(TCacheEntry* entry) +{ + if (!entry->texture) + return; auto config = entry->texture->GetConfig(); texture_pool.emplace(config, TexPoolEntry(std::move(entry->texture), std::move(entry->framebuffer))); - - // Don't delete if there's a pending EFB copy, as we need the TCacheEntry alive. - if (!entry->pending_efb_copy) - delete entry; - - return textures_by_address.erase(iter); } bool TextureCacheBase::CreateUtilityTextures() @@ -2748,7 +2753,7 @@ bool TextureCacheBase::CreateUtilityTextures() return true; } -void TextureCacheBase::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, +void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_copy, const MathUtil::Rectangle& src_rect, bool scale_by_half, bool linear_filter, EFBCopyFormat dst_format, bool is_intensity, float gamma, @@ -2904,7 +2909,7 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& g_vertex_manager->OnEFBCopyToRAM(); } -bool TextureCacheBase::DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data, +bool TextureCacheBase::DecodeTextureOnGPU(RcTcacheEntry& entry, u32 dst_level, const u8* data, u32 data_size, TextureFormat format, u32 width, u32 height, u32 aligned_width, u32 aligned_height, u32 row_stride, const u8* palette, -- cgit v1.2.3 From a01d5283ec1dc6a4dc50e4b8da48e6de1c6ac1dd Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Wed, 27 Jul 2022 19:35:51 +1200 Subject: TextureCache: Add content locking Texture cache occasionally mutates textures for efficiency. Which is awkward if we want to borrow those textures from texture cache to do something else, such as a graphics debugger, or async presentation on another thread. Content locking provides a way to signal that the contents of a texture cache entry should not change. Texture cache will be forced to use alternative strategies. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 42 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 84208c8094..6102767e70 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -700,7 +700,8 @@ void TextureCacheBase::DoLoadState(PointerWrap& p) // Even if the texture isn't valid, we still need to create the cache entry object // to update the point in the state state. We'll just throw it away if it's invalid. auto tex = DeserializeTexture(p); - auto entry = Common::make_rc(std::move(tex->texture), std::move(tex->framebuffer)); + auto entry = + std::make_shared(std::move(tex->texture), std::move(tex->framebuffer)); entry->textures_by_hash_iter = textures_by_hash.end(); entry->DoState(p); if (entry->texture && commit_state) @@ -809,6 +810,13 @@ RcTcacheEntry TextureCacheBase::DoPartialTextureUpdates(RcTcacheEntry& entry_to_ if (entry_to_update->IsCopy()) return entry_to_update; + if (entry_to_update->IsLocked()) + { + // TODO: Shouldn't be too hard, just need to clone the texture entry + texture contents. + PanicAlertFmt("TextureCache: PartialTextureUpdates of locked textures is not implemented"); + return {}; + } + u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format.texfmt); u32 block_height = TexDecoder_GetBlockHeightInTexels(entry_to_update->format.texfmt); u32 block_size = block_width * block_height * @@ -1474,8 +1482,11 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp { entry = DoPartialTextureUpdates(iter->second, texture_info.GetTlutAddress(), texture_info.GetTlutFormat()); - entry->texture->FinishedRendering(); - return entry; + if (entry) + { + entry->texture->FinishedRendering(); + return entry; + } } } @@ -1511,9 +1522,8 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp if (unconverted_copy != textures_by_address.end()) { - auto decoded_entry = - ApplyPaletteToEntry(unconverted_copy->second, texture_info.GetTlutAddress(), - texture_info.GetTlutFormat()); + auto decoded_entry = ApplyPaletteToEntry( + unconverted_copy->second, texture_info.GetTlutAddress(), texture_info.GetTlutFormat()); if (decoded_entry) { @@ -1543,8 +1553,11 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp { entry = DoPartialTextureUpdates(hash_iter->second, texture_info.GetTlutAddress(), texture_info.GetTlutFormat()); - entry->texture->FinishedRendering(); - return entry; + if (entry) + { + entry->texture->FinishedRendering(); + return entry; + } } ++hash_iter; } @@ -1771,9 +1784,9 @@ RcTcacheEntry TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height return {}; } - // Do we currently have a version of this XFB copy in VRAM? + // Do we currently have a mutable version of this XFB copy in VRAM? RcTcacheEntry entry = GetXFBFromCache(address, width, height, stride); - if (entry) + if (entry && !entry->IsLocked()) { if (entry->is_xfb_container) { @@ -2265,8 +2278,8 @@ void TextureCacheBase::CopyRenderTargetToTexture( entry->may_have_overlapping_textures = false; entry->is_custom_tex = false; - CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter, - dstFormat, isIntensity, gamma, clamp_top, clamp_bottom, + CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter, dstFormat, + isIntensity, gamma, clamp_top, clamp_bottom, GetVRAMCopyFilterCoefficients(filter_coefficients)); if (is_xfb_copy && (g_ActiveConfig.bDumpXFBTarget || g_ActiveConfig.bGraphicMods)) @@ -2584,7 +2597,7 @@ RcTcacheEntry TextureCacheBase::AllocateCacheEntry(const TextureConfig& config) return {}; auto cacheEntry = - Common::make_rc(std::move(alloc->texture), std::move(alloc->framebuffer)); + std::make_shared(std::move(alloc->texture), std::move(alloc->framebuffer)); cacheEntry->textures_by_hash_iter = textures_by_hash.end(); cacheEntry->id = last_entry_id++; return cacheEntry; @@ -2710,7 +2723,8 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter, bool discard_pe { // The texture data has already been copied into the staging texture, so it's valid to // optimistically release the texture data. Will slightly lower VRAM usage. - ReleaseToPool(entry.get()); + if (!entry->IsLocked()) + ReleaseToPool(entry.get()); } } entry->invalidated = true; -- cgit v1.2.3 From 8a236293455e9a71aa6fb400a6253c27540e403b Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Fri, 27 Jan 2023 11:34:59 +1300 Subject: Split AbstractGfx out of Renderer Almost all the virtual functions in Renderer are part of dolphin's "graphics api abstraction layer", which has slowly formed over the last decade or two. Most of the work was done previously with the introduction of the various "AbstractX" classes, associated with texture cache cleanups and implementation of newer graphics APIs (Direct3D 12, Vulkan, Metal). We are simply taking the last step and yeeting these functions out of Renderer. This "AbstractGfx" class is now completely agnostic of any details from the flipper/hollywood GPU we are emulating, though somewhat specialized. (Will not build, this commit only contains changes outside VideoBackends) --- Source/Core/VideoCommon/TextureCacheBase.cpp | 110 +++++++++++++-------------- 1 file changed, 54 insertions(+), 56 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6102767e70..e991669950 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -34,6 +34,7 @@ #include "Core/System.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/FramebufferManager.h" @@ -298,7 +299,7 @@ RcTcacheEntry TextureCacheBase::ApplyPaletteToEntry(RcTcacheEntry& entry, const decoded_entry->SetNotCopy(); decoded_entry->may_have_overlapping_textures = entry->may_have_overlapping_textures; - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); const u32 palette_size = entry->format == TextureFormat::I4 ? 32 : 512; u32 texel_buffer_offset; @@ -318,19 +319,19 @@ RcTcacheEntry TextureCacheBase::ApplyPaletteToEntry(RcTcacheEntry& entry, const uniforms.texel_buffer_offset = texel_buffer_offset; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); - g_renderer->SetAndDiscardFramebuffer(decoded_entry->framebuffer.get()); - g_renderer->SetViewportAndScissor(decoded_entry->texture->GetRect()); - g_renderer->SetPipeline(pipeline); - g_renderer->SetTexture(1, entry->texture.get()); - g_renderer->SetSamplerState(1, RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(decoded_entry->framebuffer.get()); + g_gfx->SetViewportAndScissor(decoded_entry->texture->GetRect()); + g_gfx->SetPipeline(pipeline); + g_gfx->SetTexture(1, entry->texture.get()); + g_gfx->SetSamplerState(1, RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); decoded_entry->texture->FinishedRendering(); } else { ERROR_LOG_FMT(VIDEO, "Texel buffer upload of {} bytes failed", palette_size); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); } textures_by_address.emplace(decoded_entry->addr, decoded_entry); @@ -369,14 +370,14 @@ RcTcacheEntry TextureCacheBase::ReinterpretEntry(const RcTcacheEntry& existing_e reinterpreted_entry->may_have_overlapping_textures = existing_entry->may_have_overlapping_textures; - g_renderer->BeginUtilityDrawing(); - g_renderer->SetAndDiscardFramebuffer(reinterpreted_entry->framebuffer.get()); - g_renderer->SetViewportAndScissor(reinterpreted_entry->texture->GetRect()); - g_renderer->SetPipeline(pipeline); - g_renderer->SetTexture(0, existing_entry->texture.get()); - g_renderer->SetSamplerState(1, RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(reinterpreted_entry->framebuffer.get()); + g_gfx->SetViewportAndScissor(reinterpreted_entry->texture->GetRect()); + g_gfx->SetPipeline(pipeline); + g_gfx->SetTexture(0, existing_entry->texture.get()); + g_gfx->SetSamplerState(1, RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); reinterpreted_entry->texture->FinishedRendering(); textures_by_address.emplace(reinterpreted_entry->addr, reinterpreted_entry); @@ -408,9 +409,8 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(RcTcacheEntry& entry, u32 new_wi } // No need to convert the coordinates here since they'll be the same. - g_renderer->ScaleTexture(new_texture->framebuffer.get(), - new_texture->texture->GetConfig().GetRect(), entry->texture.get(), - entry->texture->GetConfig().GetRect()); + g_gfx->ScaleTexture(new_texture->framebuffer.get(), new_texture->texture->GetConfig().GetRect(), + entry->texture.get(), entry->texture->GetConfig().GetRect()); entry->texture.swap(new_texture->texture); entry->framebuffer.swap(new_texture->framebuffer); @@ -432,8 +432,7 @@ bool TextureCacheBase::CheckReadbackTexture(u32 width, u32 height, AbstractTextu TextureConfig staging_config(std::max(width, 128u), std::max(height, 128u), 1, 1, 1, format, 0); m_readback_texture.reset(); - m_readback_texture = - g_renderer->CreateStagingTexture(StagingTextureType::Readback, staging_config); + m_readback_texture = g_gfx->CreateStagingTexture(StagingTextureType::Readback, staging_config); return m_readback_texture != nullptr; } @@ -1081,7 +1080,7 @@ static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex, state.tm0.anisotropic_filtering = false; } - g_renderer->SetSamplerState(index, state); + g_gfx->SetSamplerState(index, state); auto& system = Core::System::GetInstance(); auto& pixel_shader_manager = system.GetPixelShaderManager(); pixel_shader_manager.SetSamplerState(index, state.tm0.hex, state.tm1.hex); @@ -1096,7 +1095,7 @@ void TextureCacheBase::BindTextures(BitSet32 used_textures) const RcTcacheEntry& tentry = bound_textures[i]; if (used_textures[i] && tentry) { - g_renderer->SetTexture(i, tentry->texture.get()); + g_gfx->SetTexture(i, tentry->texture.get()); pixel_shader_manager.SetTexDims(i, tentry->native_width, tentry->native_height); const float custom_tex_scale = tentry->GetWidth() / float(tentry->native_width); @@ -2013,8 +2012,8 @@ void TextureCacheBase::StitchXFBCopy(RcTcacheEntry& stitched_entry) // We may have to scale if one of the copies is not internal resolution. if (srcrect.GetWidth() != dstrect.GetWidth() || srcrect.GetHeight() != dstrect.GetHeight()) { - g_renderer->ScaleTexture(stitched_entry->framebuffer.get(), dstrect, entry->texture.get(), - srcrect); + g_gfx->ScaleTexture(stitched_entry->framebuffer.get(), dstrect, entry->texture.get(), + srcrect); } else { @@ -2521,7 +2520,7 @@ std::unique_ptr TextureCacheBase::GetEFBCopyStagingTextu return ptr; } - std::unique_ptr tex = g_renderer->CreateStagingTexture( + std::unique_ptr tex = g_gfx->CreateStagingTexture( StagingTextureType::Readback, m_efb_encoding_texture->GetConfig()); if (!tex) WARN_LOG_FMT(VIDEO, "Failed to create EFB copy staging texture"); @@ -2614,7 +2613,7 @@ TextureCacheBase::AllocateTexture(const TextureConfig& config) return std::move(entry); } - std::unique_ptr texture = g_renderer->CreateTexture(config); + std::unique_ptr texture = g_gfx->CreateTexture(config); if (!texture) { WARN_LOG_FMT(VIDEO, "Failed to allocate a {}x{}x{} texture", config.width, config.height, @@ -2625,7 +2624,7 @@ TextureCacheBase::AllocateTexture(const TextureConfig& config) std::unique_ptr framebuffer; if (config.IsRenderTarget()) { - framebuffer = g_renderer->CreateFramebuffer(texture.get(), nullptr); + framebuffer = g_gfx->CreateFramebuffer(texture.get(), nullptr); if (!framebuffer) { WARN_LOG_FMT(VIDEO, "Failed to allocate a {}x{}x{} framebuffer", config.width, config.height, @@ -2745,12 +2744,11 @@ bool TextureCacheBase::CreateUtilityTextures() { constexpr TextureConfig encoding_texture_config( EFB_WIDTH * 4, 1024, 1, 1, 1, AbstractTextureFormat::BGRA8, AbstractTextureFlag_RenderTarget); - m_efb_encoding_texture = - g_renderer->CreateTexture(encoding_texture_config, "EFB encoding texture"); + m_efb_encoding_texture = g_gfx->CreateTexture(encoding_texture_config, "EFB encoding texture"); if (!m_efb_encoding_texture) return false; - m_efb_encoding_framebuffer = g_renderer->CreateFramebuffer(m_efb_encoding_texture.get(), nullptr); + m_efb_encoding_framebuffer = g_gfx->CreateFramebuffer(m_efb_encoding_texture.get(), nullptr); if (!m_efb_encoding_framebuffer) return false; @@ -2759,7 +2757,7 @@ bool TextureCacheBase::CreateUtilityTextures() constexpr TextureConfig decoding_texture_config( 1024, 1024, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_ComputeImage); m_decoding_texture = - g_renderer->CreateTexture(decoding_texture_config, "GPU texture decoding texture"); + g_gfx->CreateTexture(decoding_texture_config, "GPU texture decoding texture"); if (!m_decoding_texture) return false; } @@ -2788,14 +2786,14 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c } const auto scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); - const auto framebuffer_rect = g_renderer->ConvertFramebufferRectangle( + const auto framebuffer_rect = g_gfx->ConvertFramebufferRectangle( scaled_src_rect, g_framebuffer_manager->GetEFBFramebuffer()); AbstractTexture* src_texture = is_depth_copy ? g_framebuffer_manager->ResolveEFBDepthTexture(framebuffer_rect) : g_framebuffer_manager->ResolveEFBColorTexture(framebuffer_rect); src_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); // Fill uniform buffer. struct Uniforms @@ -2832,14 +2830,14 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); // Use the copy pipeline to render the VRAM copy. - g_renderer->SetAndDiscardFramebuffer(entry->framebuffer.get()); - g_renderer->SetViewportAndScissor(entry->framebuffer->GetRect()); - g_renderer->SetPipeline(copy_pipeline); - g_renderer->SetTexture(0, src_texture); - g_renderer->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : - RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(entry->framebuffer.get()); + g_gfx->SetViewportAndScissor(entry->framebuffer->GetRect()); + g_gfx->SetPipeline(copy_pipeline); + g_gfx->SetTexture(0, src_texture); + g_gfx->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : + RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); entry->texture->FinishedRendering(); } @@ -2862,14 +2860,14 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& } const auto scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); - const auto framebuffer_rect = g_renderer->ConvertFramebufferRectangle( + const auto framebuffer_rect = g_gfx->ConvertFramebufferRectangle( scaled_src_rect, g_framebuffer_manager->GetEFBFramebuffer()); AbstractTexture* src_texture = params.depth ? g_framebuffer_manager->ResolveEFBDepthTexture(framebuffer_rect) : g_framebuffer_manager->ResolveEFBColorTexture(framebuffer_rect); src_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); // Fill uniform buffer. struct Uniforms @@ -2909,15 +2907,15 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& const auto encode_rect = MathUtil::Rectangle(0, 0, render_width, render_height); // Render to GPU texture, and then copy to CPU-accessible texture. - g_renderer->SetAndDiscardFramebuffer(m_efb_encoding_framebuffer.get()); - g_renderer->SetViewportAndScissor(encode_rect); - g_renderer->SetPipeline(copy_pipeline); - g_renderer->SetTexture(0, src_texture); - g_renderer->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : - RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); + g_gfx->SetAndDiscardFramebuffer(m_efb_encoding_framebuffer.get()); + g_gfx->SetViewportAndScissor(encode_rect); + g_gfx->SetPipeline(copy_pipeline); + g_gfx->SetTexture(0, src_texture); + g_gfx->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : + RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); dst->CopyFromTexture(m_efb_encoding_texture.get(), encode_rect, 0, 0, encode_rect); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); // Flush if there's sufficient draws between this copy and the last. g_vertex_manager->OnEFBCopyToRAM(); @@ -2970,12 +2968,12 @@ bool TextureCacheBase::DecodeTextureOnGPU(RcTcacheEntry& entry, u32 dst_level, c aligned_height, src_offset, row_stride / bytes_per_buffer_elem, palette_offset}; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); - g_renderer->SetComputeImageTexture(m_decoding_texture.get(), false, true); + g_gfx->SetComputeImageTexture(m_decoding_texture.get(), false, true); auto dispatch_groups = TextureConversionShaderTiled::GetDispatchCount(info, aligned_width, aligned_height); - g_renderer->DispatchComputeShader(shader, info->group_size_x, info->group_size_y, 1, - dispatch_groups.first, dispatch_groups.second, 1); + g_gfx->DispatchComputeShader(shader, info->group_size_x, info->group_size_y, 1, + dispatch_groups.first, dispatch_groups.second, 1); // Copy from decoding texture -> final texture // This is because we don't want to have to create compute view for every layer -- cgit v1.2.3 From ca5ec13e138d60d2fbac114450527c654caed702 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Mon, 30 Jan 2023 05:01:05 +1300 Subject: Move GraphicsMod out of RenderBase --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index e991669950..21b58d931e 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -40,6 +40,7 @@ #include "VideoCommon/FramebufferManager.h" #include "VideoCommon/GraphicsModSystem/Runtime/FBInfo.h" #include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h" +#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.h" #include "VideoCommon/HiresTextures.h" #include "VideoCommon/OpcodeDecoding.h" #include "VideoCommon/PixelShaderManager.h" @@ -1291,7 +1292,7 @@ TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture_info) GraphicsModActionData::TextureLoad texture_load{entry->texture_info_name}; for (const auto action : - g_renderer->GetGraphicsModManager().GetTextureLoadActions(entry->texture_info_name)) + g_graphics_mod_manager->GetTextureLoadActions(entry->texture_info_name)) { action->OnTextureLoad(&texture_load); } @@ -2210,7 +2211,7 @@ void TextureCacheBase::CopyRenderTargetToTexture( info.m_texture_format = baseFormat; if (is_xfb_copy) { - for (const auto action : g_renderer->GetGraphicsModManager().GetXFBActions(info)) + for (const auto action : g_graphics_mod_manager->GetXFBActions(info)) { action->OnXFB(); } @@ -2219,7 +2220,7 @@ void TextureCacheBase::CopyRenderTargetToTexture( { bool skip = false; GraphicsModActionData::EFB efb{tex_w, tex_h, &skip, &scaled_tex_w, &scaled_tex_h}; - for (const auto action : g_renderer->GetGraphicsModManager().GetEFBActions(info)) + for (const auto action : g_graphics_mod_manager->GetEFBActions(info)) { action->OnEFB(&efb); } -- cgit v1.2.3 From 0da69055d9f41d838bdf94b66805540c746eaa7d Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Tue, 31 Jan 2023 00:46:10 +1300 Subject: Split out everying remaining from Swap --- Source/Core/VideoCommon/TextureCacheBase.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 21b58d931e..6029f09c5c 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -769,6 +769,23 @@ void TextureCacheBase::DoLoadState(PointerWrap& p) } } +void TextureCacheBase::OnFrameEnd() +{ + if (m_force_reload_textures.TestAndClear()) + { + ForceReload(); + } + else + { + // Flush any outstanding EFB copies to RAM, in case the game is running at an uncapped frame + // rate and not waiting for vblank. Otherwise, we'd end up with a huge list of pending + // copies. + g_texture_cache->FlushEFBCopies(); + } + + g_texture_cache->Cleanup(g_renderer->m_frame_count); +} + void TCacheEntry::DoState(PointerWrap& p) { p.Do(addr); -- cgit v1.2.3 From ec8f46b02c21fec9b24518e6788a4df413baf8f9 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Tue, 31 Jan 2023 01:03:46 +1300 Subject: Expose Renderer's Framecount We don't want to move it, because we want to complete this refactor without changing savestate version --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6029f09c5c..947b2e5965 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -783,7 +783,7 @@ void TextureCacheBase::OnFrameEnd() g_texture_cache->FlushEFBCopies(); } - g_texture_cache->Cleanup(g_renderer->m_frame_count); + g_texture_cache->Cleanup(g_renderer->FrameCount()); } void TCacheEntry::DoState(PointerWrap& p) -- cgit v1.2.3 From 11de923dcb7e6a7e1b29e5b15cb2bf71ede22b97 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Tue, 31 Jan 2023 17:26:46 +1300 Subject: Move xfb tracking and IR scaling out of RenderBase --- Source/Core/VideoCommon/TextureCacheBase.cpp | 58 ++++++++++++++-------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 947b2e5965..02601baaf4 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -44,7 +44,7 @@ #include "VideoCommon/HiresTextures.h" #include "VideoCommon/OpcodeDecoding.h" #include "VideoCommon/PixelShaderManager.h" -#include "VideoCommon/RenderBase.h" +#include "VideoCommon/Present.h" #include "VideoCommon/ShaderCache.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/TMEM.h" @@ -783,7 +783,7 @@ void TextureCacheBase::OnFrameEnd() g_texture_cache->FlushEFBCopies(); } - g_texture_cache->Cleanup(g_renderer->FrameCount()); + g_texture_cache->Cleanup(g_presenter->FrameCount()); } void TCacheEntry::DoState(PointerWrap& p) @@ -921,17 +921,17 @@ RcTcacheEntry TextureCacheBase::DoPartialTextureUpdates(RcTcacheEntry& entry_to_ entry->native_width != entry->GetWidth() || entry->native_height != entry->GetHeight()) { ScaleTextureCacheEntryTo(entry_to_update, - g_renderer->EFBToScaledX(entry_to_update->native_width), - g_renderer->EFBToScaledY(entry_to_update->native_height)); - ScaleTextureCacheEntryTo(entry, g_renderer->EFBToScaledX(entry->native_width), - g_renderer->EFBToScaledY(entry->native_height)); - - src_x = g_renderer->EFBToScaledX(src_x); - src_y = g_renderer->EFBToScaledY(src_y); - dst_x = g_renderer->EFBToScaledX(dst_x); - dst_y = g_renderer->EFBToScaledY(dst_y); - copy_width = g_renderer->EFBToScaledX(copy_width); - copy_height = g_renderer->EFBToScaledY(copy_height); + g_framebuffer_manager->EFBToScaledX(entry_to_update->native_width), + g_framebuffer_manager->EFBToScaledY(entry_to_update->native_height)); + ScaleTextureCacheEntryTo(entry, g_framebuffer_manager->EFBToScaledX(entry->native_width), + g_framebuffer_manager->EFBToScaledY(entry->native_height)); + + src_x = g_framebuffer_manager->EFBToScaledX(src_x); + src_y = g_framebuffer_manager->EFBToScaledY(src_y); + dst_x = g_framebuffer_manager->EFBToScaledX(dst_x); + dst_y = g_framebuffer_manager->EFBToScaledY(dst_y); + copy_width = g_framebuffer_manager->EFBToScaledX(copy_width); + copy_height = g_framebuffer_manager->EFBToScaledY(copy_height); } // If the source rectangle is outside of what we actually have in VRAM, skip the copy. @@ -1091,7 +1091,7 @@ static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex, // that have arbitrary contents, eg. are used for fog effects where the // distance they kick in at is important to preserve at any resolution. // Correct this with the upscaling factor of custom textures. - s32 lod_offset = std::log2(g_renderer->GetEFBScale() / custom_tex_scale) * 256.f; + s32 lod_offset = std::log2(g_framebuffer_manager->GetEFBScale() / custom_tex_scale) * 256.f; state.tm0.lod_bias = std::clamp(state.tm0.lod_bias + lod_offset, -32768, 32767); // Anisotropic also pushes mips farther away so it cannot be used either @@ -1957,8 +1957,8 @@ void TextureCacheBase::StitchXFBCopy(RcTcacheEntry& stitched_entry) // copies to be stitched together. if (create_upscaled_copy) { - ScaleTextureCacheEntryTo(stitched_entry, g_renderer->EFBToScaledX(stitched_entry->native_width), - g_renderer->EFBToScaledY(stitched_entry->native_height)); + ScaleTextureCacheEntryTo(stitched_entry, g_framebuffer_manager->EFBToScaledX(stitched_entry->native_width), + g_framebuffer_manager->EFBToScaledY(stitched_entry->native_height)); } for (TCacheEntry* entry : candidates) @@ -1993,17 +1993,17 @@ void TextureCacheBase::StitchXFBCopy(RcTcacheEntry& stitched_entry) // Scale to internal resolution. if (entry->native_width != entry->GetWidth()) { - src_x = g_renderer->EFBToScaledX(src_x); - src_y = g_renderer->EFBToScaledY(src_y); - src_width = g_renderer->EFBToScaledX(src_width); - src_height = g_renderer->EFBToScaledY(src_height); + src_x = g_framebuffer_manager->EFBToScaledX(src_x); + src_y = g_framebuffer_manager->EFBToScaledY(src_y); + src_width = g_framebuffer_manager->EFBToScaledX(src_width); + src_height = g_framebuffer_manager->EFBToScaledY(src_height); } if (create_upscaled_copy) { - dst_x = g_renderer->EFBToScaledX(dst_x); - dst_y = g_renderer->EFBToScaledY(dst_y); - dst_width = g_renderer->EFBToScaledX(dst_width); - dst_height = g_renderer->EFBToScaledY(dst_height); + dst_x = g_framebuffer_manager->EFBToScaledX(dst_x); + dst_y = g_framebuffer_manager->EFBToScaledY(dst_y); + dst_width = g_framebuffer_manager->EFBToScaledX(dst_width); + dst_height = g_framebuffer_manager->EFBToScaledY(dst_height); } // If the source rectangle is outside of what we actually have in VRAM, skip the copy. @@ -2183,8 +2183,8 @@ void TextureCacheBase::CopyRenderTargetToTexture( // For the latter, we keep the EFB resolution for the virtual XFB blit. u32 tex_w = width; u32 tex_h = height; - u32 scaled_tex_w = g_renderer->EFBToScaledX(width); - u32 scaled_tex_h = g_renderer->EFBToScaledY(height); + u32 scaled_tex_w = g_framebuffer_manager->EFBToScaledX(width); + u32 scaled_tex_h = g_framebuffer_manager->EFBToScaledY(height); if (scaleByHalf) { @@ -2269,7 +2269,7 @@ void TextureCacheBase::CopyRenderTargetToTexture( // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more // complex down filtering to average all pixels and produce the correct result. const bool linear_filter = - !is_depth_copy && (scaleByHalf || g_renderer->GetEFBScale() != 1 || y_scale > 1.0f); + !is_depth_copy && (scaleByHalf || g_framebuffer_manager->GetEFBScale() != 1 || y_scale > 1.0f); RcTcacheEntry entry; if (copy_to_vram) @@ -2803,7 +2803,7 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c return; } - const auto scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); + const auto scaled_src_rect = g_framebuffer_manager->ConvertEFBRectangle(src_rect); const auto framebuffer_rect = g_gfx->ConvertFramebufferRectangle( scaled_src_rect, g_framebuffer_manager->GetEFBFramebuffer()); AbstractTexture* src_texture = @@ -2877,7 +2877,7 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& return; } - const auto scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); + const auto scaled_src_rect = g_framebuffer_manager->ConvertEFBRectangle(src_rect); const auto framebuffer_rect = g_gfx->ConvertFramebufferRectangle( scaled_src_rect, g_framebuffer_manager->GetEFBFramebuffer()); AbstractTexture* src_texture = -- cgit v1.2.3 From 31cfe8250d5a27bd586136d0b71b09736861ad7d Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Tue, 31 Jan 2023 17:29:16 +1300 Subject: Lint fixes --- Source/Core/VideoCommon/TextureCacheBase.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 02601baaf4..ce14075552 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -773,7 +773,7 @@ void TextureCacheBase::OnFrameEnd() { if (m_force_reload_textures.TestAndClear()) { - ForceReload(); + ForceReload(); } else { @@ -920,9 +920,9 @@ RcTcacheEntry TextureCacheBase::DoPartialTextureUpdates(RcTcacheEntry& entry_to_ entry_to_update->native_height != entry_to_update->GetHeight() || entry->native_width != entry->GetWidth() || entry->native_height != entry->GetHeight()) { - ScaleTextureCacheEntryTo(entry_to_update, - g_framebuffer_manager->EFBToScaledX(entry_to_update->native_width), - g_framebuffer_manager->EFBToScaledY(entry_to_update->native_height)); + ScaleTextureCacheEntryTo( + entry_to_update, g_framebuffer_manager->EFBToScaledX(entry_to_update->native_width), + g_framebuffer_manager->EFBToScaledY(entry_to_update->native_height)); ScaleTextureCacheEntryTo(entry, g_framebuffer_manager->EFBToScaledX(entry->native_width), g_framebuffer_manager->EFBToScaledY(entry->native_height)); @@ -1957,7 +1957,8 @@ void TextureCacheBase::StitchXFBCopy(RcTcacheEntry& stitched_entry) // copies to be stitched together. if (create_upscaled_copy) { - ScaleTextureCacheEntryTo(stitched_entry, g_framebuffer_manager->EFBToScaledX(stitched_entry->native_width), + ScaleTextureCacheEntryTo(stitched_entry, + g_framebuffer_manager->EFBToScaledX(stitched_entry->native_width), g_framebuffer_manager->EFBToScaledY(stitched_entry->native_height)); } @@ -2269,7 +2270,8 @@ void TextureCacheBase::CopyRenderTargetToTexture( // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more // complex down filtering to average all pixels and produce the correct result. const bool linear_filter = - !is_depth_copy && (scaleByHalf || g_framebuffer_manager->GetEFBScale() != 1 || y_scale > 1.0f); + !is_depth_copy && + (scaleByHalf || g_framebuffer_manager->GetEFBScale() != 1 || y_scale > 1.0f); RcTcacheEntry entry; if (copy_to_vram) -- cgit v1.2.3 From 60f2b5af7b5b5748f672e968d99338d503b5272e Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Fri, 3 Feb 2023 13:18:37 +1300 Subject: Apply suggestions from code review Co-authored-by: Mai Co-authored-by: BhaaL Co-authored-by: iwubcode --- Source/Core/VideoCommon/TextureCacheBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ce14075552..8b5e56af37 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -780,10 +780,10 @@ void TextureCacheBase::OnFrameEnd() // Flush any outstanding EFB copies to RAM, in case the game is running at an uncapped frame // rate and not waiting for vblank. Otherwise, we'd end up with a huge list of pending // copies. - g_texture_cache->FlushEFBCopies(); + FlushEFBCopies(); } - g_texture_cache->Cleanup(g_presenter->FrameCount()); + Cleanup(g_presenter->FrameCount()); } void TCacheEntry::DoState(PointerWrap& p) -- cgit v1.2.3