From 28e9c792a86a31dd62de76d24da6f3b884002818 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 6 Jul 2019 22:25:55 -0400 Subject: [PATCH] Texture_Cache: Corrections and fixes to resolution rescaler --- .../renderer_opengl/gl_rasterizer.cpp | 1 + .../resolution_scaling/database.cpp | 51 ++++++++++++++++++- .../resolution_scaling/database.h | 8 +++ src/video_core/texture_cache/surface_base.h | 10 ++++ src/video_core/texture_cache/texture_cache.h | 29 ++++++++--- 5 files changed, 90 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c05518216b..2c9f7fb706 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -375,6 +375,7 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback) { shader_cache.LoadDiskCache(stop_loading, callback); + texture_cache.LoadResources(); } void RasterizerOpenGL::ConfigureFramebuffers() { diff --git a/src/video_core/texture_cache/resolution_scaling/database.cpp b/src/video_core/texture_cache/resolution_scaling/database.cpp index da560437a0..d4f908d6d0 100644 --- a/src/video_core/texture_cache/resolution_scaling/database.cpp +++ b/src/video_core/texture_cache/resolution_scaling/database.cpp @@ -2,7 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include +#include #include #include "common/assert.h" @@ -18,13 +20,48 @@ namespace VideoCommon::Resolution { using namespace nlohmann; ScalingDatabase::ScalingDatabase(Core::System& system) : database{}, blacklist{}, system{system} { - title_id = system.CurrentProcess()->GetTitleID(); + title_id = 0; } ScalingDatabase::~ScalingDatabase() { SaveDatabase(); } +void ScalingDatabase::Init() { + title_id = system.CurrentProcess()->GetTitleID(); + LoadDatabase(); + initialized = true; +} + +void ScalingDatabase::LoadDatabase() { + const std::string path = GetProfilePath(); + bool exists = FileUtil::Exists(path); + if (!exists) { + return; + } + std::ifstream file(path); + json in; + file >> in; + u32 version = in["version"].get(); + if (version != DBVersion) { + return; + } + for (const auto& entry : in["entries"]) { + ResolutionKey key{}; + key.format = static_cast(entry["format"].get()); + key.width = entry["width"].get(); + key.height = entry["height"].get(); + database.emplace(key, true); + } + for (const auto& entry : in["blacklist"]) { + ResolutionKey key{}; + key.format = static_cast(entry["format"].get()); + key.width = entry["width"].get(); + key.height = entry["height"].get(); + blacklist.insert(key); + } +} + void ScalingDatabase::SaveDatabase() { json out; out["version"] = DBVersion; @@ -40,7 +77,17 @@ void ScalingDatabase::SaveDatabase() { } } out["entries"] = std::move(entries); - std::ofstream file(GetProfilePath()); + auto blacklist_entries = json::array(); + for (const auto& key : blacklist) { + blacklist_entries.push_back({ + {"format", static_cast(key.format)}, + {"width", key.width}, + {"height", key.height}, + }); + } + out["blacklist"] = blacklist_entries; + const std::string path = GetProfilePath(); + std::ofstream file(path); file << std::setw(4) << out << std::endl; } diff --git a/src/video_core/texture_cache/resolution_scaling/database.h b/src/video_core/texture_cache/resolution_scaling/database.h index 854a560d83..c3c142323d 100644 --- a/src/video_core/texture_cache/resolution_scaling/database.h +++ b/src/video_core/texture_cache/resolution_scaling/database.h @@ -52,12 +52,19 @@ public: ~ScalingDatabase(); void SaveDatabase(); + void LoadDatabase(); + void Init(); bool IsInDatabase(const PixelFormat format, const u32 width, const u32 height) { ResolutionKey key{format, width, height}; return database.count(key) > 0; } + bool IsBlacklisted(const PixelFormat format, const u32 width, const u32 height) { + ResolutionKey key{format, width, height}; + return blacklist.count(key) > 0; + } + void MarkRendered(const PixelFormat format, const u32 width, const u32 height); void Register(const PixelFormat format, const u32 width, const u32 height); void Unregister(const PixelFormat format, const u32 width, const u32 height); @@ -68,6 +75,7 @@ public: private: std::unordered_map database; std::unordered_set blacklist; + bool initialized{}; u64 title_id; Core::System& system; diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index d7fcc9de5f..0ba928a56e 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -207,6 +207,11 @@ public: void MarkAsRescaled(const bool is_rescaled) { this->is_rescaled = is_rescaled; + this->is_rescale_candidate = is_rescaled; + } + + void MarkAsRescaleCandidate(const bool is_rescale_candidate) { + this->is_rescale_candidate = is_rescale_candidate; } void MarkAsPicked(bool is_picked_) { @@ -234,6 +239,10 @@ public: return is_rescaled; } + bool IsRescaleCandidate() const { + return is_rescale_candidate; + } + bool IsRegistered() const { return is_registered; } @@ -327,6 +336,7 @@ private: bool is_registered{}; bool is_picked{}; bool is_rescaled{}; + bool is_rescale_candidate{}; u32 index{NO_RT}; u64 modification_tick{}; }; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index bc9aa95521..550aa6be73 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -71,6 +71,10 @@ public: } } + void LoadResources() { + scaling_database.Init(); + } + /*** * `Guard` guarantees that rendertargets don't unregister themselves if the * collide. Protection is currently only done on 3D slices. @@ -163,6 +167,7 @@ public: if (depth_buffer.target) { depth_buffer.target->MarkAsRenderTarget(true, DEPTH_RT); if (IsResScannerEnabled()) { + MarkScanner(depth_buffer.target); MarkScannerRender(depth_buffer.target); } } @@ -201,6 +206,7 @@ public: if (render_targets[index].target) { render_targets[index].target->MarkAsRenderTarget(true, static_cast(index)); if (IsResScannerEnabled()) { + MarkScanner(render_targets[index].target); MarkScannerRender(render_targets[index].target); } } @@ -282,7 +288,7 @@ public: for (const auto& target : render_targets) { if (target.target) { enabled_targets++; - if (target.target->IsRescaled()) { + if (target.target->IsRescaleCandidate()) { rescaling = true; rescaled_targets++; } @@ -290,7 +296,7 @@ public: } if (depth_buffer.target) { enabled_targets++; - if (depth_buffer.target->IsRescaled()) { + if (depth_buffer.target->IsRescaleCandidate()) { rescaling = true; rescaled_targets++; } @@ -374,9 +380,6 @@ protected: gpu_addr); return; } - if (IsResScannerEnabled()) { - MarkScanner(surface); - } const bool continuous = system.GPU().MemoryManager().IsBlockContinuous(gpu_addr, size); surface->MarkAsContinuous(continuous); surface->SetCacheAddr(cache_ptr); @@ -427,10 +430,14 @@ protected: // Must be called by child's create surface void SignalCreatedSurface(TSurface& new_surface) { const auto& params = new_surface->GetSurfaceParams(); - if (guard_render_targets && EnabledRescaling()) { + if (EnabledRescaling()) { if (scaling_database.IsInDatabase(params.pixel_format, params.width, params.height)) { new_surface->MarkAsRescaled(true); } + } else if (IsResScannerEnabled()) { + if (scaling_database.IsInDatabase(params.pixel_format, params.width, params.height)) { + new_surface->MarkAsRescaleCandidate(true); + } } } @@ -726,7 +733,7 @@ private: // If none are found, we are done. we just load the surface and create it. if (overlaps.empty()) { - return InitializeSurface(gpu_addr, params, preserve_contents); + return InitializeSurface(gpu_addr, params, preserve_contents && !is_render); } // Step 3 @@ -925,6 +932,9 @@ private: } void LoadSurface(const TSurface& surface) { + if (IsResScannerEnabled()) { + UnmarkScanner(surface); + } staging_cache.GetBuffer(0).resize(surface->GetHostSizeInBytes()); surface->LoadBuffer(system.GPU().MemoryManager(), staging_cache); surface->UploadTexture(staging_cache.GetBuffer(0)); @@ -1031,6 +1041,11 @@ private: scaling_database.Register(params.pixel_format, params.width, params.height); } + bool IsBlackListed(const TSurface& surface) { + const auto params = surface->GetSurfaceParams(); + return scaling_database.IsBlackListed(params.pixel_format, params.width, params.height); + } + void MarkScannerRender(const TSurface& surface) { const auto params = surface->GetSurfaceParams(); scaling_database.MarkRendered(params.pixel_format, params.width, params.height);