Texture_Cache: Corrections and fixes to resolution rescaler
This commit is contained in:
committed by
FernandoS27
parent
0a93394604
commit
28e9c792a8
@@ -375,6 +375,7 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
|
|||||||
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
|
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) {
|
const VideoCore::DiskResourceLoadCallback& callback) {
|
||||||
shader_cache.LoadDiskCache(stop_loading, callback);
|
shader_cache.LoadDiskCache(stop_loading, callback);
|
||||||
|
texture_cache.LoadResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::ConfigureFramebuffers() {
|
void RasterizerOpenGL::ConfigureFramebuffers() {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <json.hpp>
|
#include <json.hpp>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
@@ -18,13 +20,48 @@ namespace VideoCommon::Resolution {
|
|||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
|
|
||||||
ScalingDatabase::ScalingDatabase(Core::System& system) : database{}, blacklist{}, system{system} {
|
ScalingDatabase::ScalingDatabase(Core::System& system) : database{}, blacklist{}, system{system} {
|
||||||
title_id = system.CurrentProcess()->GetTitleID();
|
title_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScalingDatabase::~ScalingDatabase() {
|
ScalingDatabase::~ScalingDatabase() {
|
||||||
SaveDatabase();
|
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<u32>();
|
||||||
|
if (version != DBVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto& entry : in["entries"]) {
|
||||||
|
ResolutionKey key{};
|
||||||
|
key.format = static_cast<PixelFormat>(entry["format"].get<u32>());
|
||||||
|
key.width = entry["width"].get<u32>();
|
||||||
|
key.height = entry["height"].get<u32>();
|
||||||
|
database.emplace(key, true);
|
||||||
|
}
|
||||||
|
for (const auto& entry : in["blacklist"]) {
|
||||||
|
ResolutionKey key{};
|
||||||
|
key.format = static_cast<PixelFormat>(entry["format"].get<u32>());
|
||||||
|
key.width = entry["width"].get<u32>();
|
||||||
|
key.height = entry["height"].get<u32>();
|
||||||
|
blacklist.insert(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScalingDatabase::SaveDatabase() {
|
void ScalingDatabase::SaveDatabase() {
|
||||||
json out;
|
json out;
|
||||||
out["version"] = DBVersion;
|
out["version"] = DBVersion;
|
||||||
@@ -40,7 +77,17 @@ void ScalingDatabase::SaveDatabase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out["entries"] = std::move(entries);
|
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<u32>(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;
|
file << std::setw(4) << out << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,12 +52,19 @@ public:
|
|||||||
~ScalingDatabase();
|
~ScalingDatabase();
|
||||||
|
|
||||||
void SaveDatabase();
|
void SaveDatabase();
|
||||||
|
void LoadDatabase();
|
||||||
|
void Init();
|
||||||
|
|
||||||
bool IsInDatabase(const PixelFormat format, const u32 width, const u32 height) {
|
bool IsInDatabase(const PixelFormat format, const u32 width, const u32 height) {
|
||||||
ResolutionKey key{format, width, height};
|
ResolutionKey key{format, width, height};
|
||||||
return database.count(key) > 0;
|
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 MarkRendered(const PixelFormat format, const u32 width, const u32 height);
|
||||||
void Register(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);
|
void Unregister(const PixelFormat format, const u32 width, const u32 height);
|
||||||
@@ -68,6 +75,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::unordered_map<ResolutionKey, bool> database;
|
std::unordered_map<ResolutionKey, bool> database;
|
||||||
std::unordered_set<ResolutionKey> blacklist;
|
std::unordered_set<ResolutionKey> blacklist;
|
||||||
|
bool initialized{};
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,11 @@ public:
|
|||||||
|
|
||||||
void MarkAsRescaled(const bool is_rescaled) {
|
void MarkAsRescaled(const bool is_rescaled) {
|
||||||
this->is_rescaled = 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_) {
|
void MarkAsPicked(bool is_picked_) {
|
||||||
@@ -234,6 +239,10 @@ public:
|
|||||||
return is_rescaled;
|
return is_rescaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsRescaleCandidate() const {
|
||||||
|
return is_rescale_candidate;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsRegistered() const {
|
bool IsRegistered() const {
|
||||||
return is_registered;
|
return is_registered;
|
||||||
}
|
}
|
||||||
@@ -327,6 +336,7 @@ private:
|
|||||||
bool is_registered{};
|
bool is_registered{};
|
||||||
bool is_picked{};
|
bool is_picked{};
|
||||||
bool is_rescaled{};
|
bool is_rescaled{};
|
||||||
|
bool is_rescale_candidate{};
|
||||||
u32 index{NO_RT};
|
u32 index{NO_RT};
|
||||||
u64 modification_tick{};
|
u64 modification_tick{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadResources() {
|
||||||
|
scaling_database.Init();
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* `Guard` guarantees that rendertargets don't unregister themselves if the
|
* `Guard` guarantees that rendertargets don't unregister themselves if the
|
||||||
* collide. Protection is currently only done on 3D slices.
|
* collide. Protection is currently only done on 3D slices.
|
||||||
@@ -163,6 +167,7 @@ public:
|
|||||||
if (depth_buffer.target) {
|
if (depth_buffer.target) {
|
||||||
depth_buffer.target->MarkAsRenderTarget(true, DEPTH_RT);
|
depth_buffer.target->MarkAsRenderTarget(true, DEPTH_RT);
|
||||||
if (IsResScannerEnabled()) {
|
if (IsResScannerEnabled()) {
|
||||||
|
MarkScanner(depth_buffer.target);
|
||||||
MarkScannerRender(depth_buffer.target);
|
MarkScannerRender(depth_buffer.target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,6 +206,7 @@ public:
|
|||||||
if (render_targets[index].target) {
|
if (render_targets[index].target) {
|
||||||
render_targets[index].target->MarkAsRenderTarget(true, static_cast<u32>(index));
|
render_targets[index].target->MarkAsRenderTarget(true, static_cast<u32>(index));
|
||||||
if (IsResScannerEnabled()) {
|
if (IsResScannerEnabled()) {
|
||||||
|
MarkScanner(render_targets[index].target);
|
||||||
MarkScannerRender(render_targets[index].target);
|
MarkScannerRender(render_targets[index].target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,7 +288,7 @@ public:
|
|||||||
for (const auto& target : render_targets) {
|
for (const auto& target : render_targets) {
|
||||||
if (target.target) {
|
if (target.target) {
|
||||||
enabled_targets++;
|
enabled_targets++;
|
||||||
if (target.target->IsRescaled()) {
|
if (target.target->IsRescaleCandidate()) {
|
||||||
rescaling = true;
|
rescaling = true;
|
||||||
rescaled_targets++;
|
rescaled_targets++;
|
||||||
}
|
}
|
||||||
@@ -290,7 +296,7 @@ public:
|
|||||||
}
|
}
|
||||||
if (depth_buffer.target) {
|
if (depth_buffer.target) {
|
||||||
enabled_targets++;
|
enabled_targets++;
|
||||||
if (depth_buffer.target->IsRescaled()) {
|
if (depth_buffer.target->IsRescaleCandidate()) {
|
||||||
rescaling = true;
|
rescaling = true;
|
||||||
rescaled_targets++;
|
rescaled_targets++;
|
||||||
}
|
}
|
||||||
@@ -374,9 +380,6 @@ protected:
|
|||||||
gpu_addr);
|
gpu_addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (IsResScannerEnabled()) {
|
|
||||||
MarkScanner(surface);
|
|
||||||
}
|
|
||||||
const bool continuous = system.GPU().MemoryManager().IsBlockContinuous(gpu_addr, size);
|
const bool continuous = system.GPU().MemoryManager().IsBlockContinuous(gpu_addr, size);
|
||||||
surface->MarkAsContinuous(continuous);
|
surface->MarkAsContinuous(continuous);
|
||||||
surface->SetCacheAddr(cache_ptr);
|
surface->SetCacheAddr(cache_ptr);
|
||||||
@@ -427,10 +430,14 @@ protected:
|
|||||||
// Must be called by child's create surface
|
// Must be called by child's create surface
|
||||||
void SignalCreatedSurface(TSurface& new_surface) {
|
void SignalCreatedSurface(TSurface& new_surface) {
|
||||||
const auto& params = new_surface->GetSurfaceParams();
|
const auto& params = new_surface->GetSurfaceParams();
|
||||||
if (guard_render_targets && EnabledRescaling()) {
|
if (EnabledRescaling()) {
|
||||||
if (scaling_database.IsInDatabase(params.pixel_format, params.width, params.height)) {
|
if (scaling_database.IsInDatabase(params.pixel_format, params.width, params.height)) {
|
||||||
new_surface->MarkAsRescaled(true);
|
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 none are found, we are done. we just load the surface and create it.
|
||||||
if (overlaps.empty()) {
|
if (overlaps.empty()) {
|
||||||
return InitializeSurface(gpu_addr, params, preserve_contents);
|
return InitializeSurface(gpu_addr, params, preserve_contents && !is_render);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
@@ -925,6 +932,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LoadSurface(const TSurface& surface) {
|
void LoadSurface(const TSurface& surface) {
|
||||||
|
if (IsResScannerEnabled()) {
|
||||||
|
UnmarkScanner(surface);
|
||||||
|
}
|
||||||
staging_cache.GetBuffer(0).resize(surface->GetHostSizeInBytes());
|
staging_cache.GetBuffer(0).resize(surface->GetHostSizeInBytes());
|
||||||
surface->LoadBuffer(system.GPU().MemoryManager(), staging_cache);
|
surface->LoadBuffer(system.GPU().MemoryManager(), staging_cache);
|
||||||
surface->UploadTexture(staging_cache.GetBuffer(0));
|
surface->UploadTexture(staging_cache.GetBuffer(0));
|
||||||
@@ -1031,6 +1041,11 @@ private:
|
|||||||
scaling_database.Register(params.pixel_format, params.width, params.height);
|
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) {
|
void MarkScannerRender(const TSurface& surface) {
|
||||||
const auto params = surface->GetSurfaceParams();
|
const auto params = surface->GetSurfaceParams();
|
||||||
scaling_database.MarkRendered(params.pixel_format, params.width, params.height);
|
scaling_database.MarkRendered(params.pixel_format, params.width, params.height);
|
||||||
|
|||||||
Reference in New Issue
Block a user