From 29b7e33c1466a07db07e796ce9492ee384d4da2c Mon Sep 17 00:00:00 2001 From: Jonathan Hamilton Date: Wed, 16 May 2018 17:12:56 -0700 Subject: [PATCH 1/4] Make arbitrary mipmap detection a config option Under GFX::Enhancements::ArbitraryMipmapDetection - default enabled --- Source/Core/Core/Config/GraphicsSettings.cpp | 2 ++ Source/Core/Core/Config/GraphicsSettings.h | 1 + Source/Core/VideoCommon/TextureCacheBase.cpp | 3 +++ Source/Core/VideoCommon/VideoConfig.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 1 + 5 files changed, 8 insertions(+) diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index 6646cff79e..893bbf1235 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -107,6 +107,8 @@ const ConfigInfo GFX_ENHANCE_FORCE_TRUE_COLOR{{System::GFX, "Enhancements" true}; const ConfigInfo GFX_ENHANCE_DISABLE_COPY_FILTER{ {System::GFX, "Enhancements", "DisableCopyFilter"}, true}; +const ConfigInfo GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION{ + {System::GFX, "Enhancements", "ArbitraryMipmapDetection"}, true}; // Graphics.Stereoscopy diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index c0113ae83e..34f518f5d5 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -85,6 +85,7 @@ extern const ConfigInfo GFX_ENHANCE_MAX_ANISOTROPY; // NOTE - this is x in extern const ConfigInfo GFX_ENHANCE_POST_SHADER; extern const ConfigInfo GFX_ENHANCE_FORCE_TRUE_COLOR; extern const ConfigInfo GFX_ENHANCE_DISABLE_COPY_FILTER; +extern const ConfigInfo GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION; // Graphics.Stereoscopy diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index bf9dc98b9d..00d65c953d 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -500,6 +500,9 @@ public: if (levels.size() < 2) return false; + if (!g_ActiveConfig.bArbitraryMipmapDetection) + return false; + // This is the average per-pixel, per-channel difference in percent between what we // expect a normal blurred mipmap to look like and what we actually received // 4.5% was chosen because it's just below the lowest clearly-arbitrary texture diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 2d7f958d8f..c7ab81d82b 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -120,6 +120,7 @@ void VideoConfig::Refresh() sPostProcessingShader = Config::Get(Config::GFX_ENHANCE_POST_SHADER); bForceTrueColor = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR); bDisableCopyFilter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER); + bArbitraryMipmapDetection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION); stereo_mode = Config::Get(Config::GFX_STEREO_MODE); iStereoDepth = Config::Get(Config::GFX_STEREO_DEPTH); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 03ccfca3ba..faebb31f70 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -74,6 +74,7 @@ struct VideoConfig final std::string sPostProcessingShader; bool bForceTrueColor; bool bDisableCopyFilter; + bool bArbitraryMipmapDetection; // Information bool bShowFPS; From 8be5cdfcad046f084441e71ee8204dfb40a18d2d Mon Sep 17 00:00:00 2001 From: Jonathan Hamilton Date: Wed, 16 May 2018 17:45:10 -0700 Subject: [PATCH 2/4] Make the arbitrary mipmap detection threshold configureable This is likely a "superuser" option at best, but I want to be able to play with it without rebuilding if I want to tweak the heuristics --- Source/Core/Core/Config/GraphicsSettings.cpp | 2 ++ Source/Core/Core/Config/GraphicsSettings.h | 1 + Source/Core/VideoCommon/TextureCacheBase.cpp | 4 ++-- Source/Core/VideoCommon/VideoConfig.cpp | 2 ++ Source/Core/VideoCommon/VideoConfig.h | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index 893bbf1235..98a5c13bcf 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -109,6 +109,8 @@ const ConfigInfo GFX_ENHANCE_DISABLE_COPY_FILTER{ {System::GFX, "Enhancements", "DisableCopyFilter"}, true}; const ConfigInfo GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION{ {System::GFX, "Enhancements", "ArbitraryMipmapDetection"}, true}; +const ConfigInfo GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD{ + {System::GFX, "Enhancements", "ArbitraryMipmapDetectionThreshold"}, 4.5f}; // Graphics.Stereoscopy diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index 34f518f5d5..3e87298f85 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -86,6 +86,7 @@ extern const ConfigInfo GFX_ENHANCE_POST_SHADER; extern const ConfigInfo GFX_ENHANCE_FORCE_TRUE_COLOR; extern const ConfigInfo GFX_ENHANCE_DISABLE_COPY_FILTER; extern const ConfigInfo GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION; +extern const ConfigInfo GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD; // Graphics.Stereoscopy diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 00d65c953d..370bdd836b 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -507,7 +507,7 @@ public: // expect a normal blurred mipmap to look like and what we actually received // 4.5% was chosen because it's just below the lowest clearly-arbitrary texture // I found in my tests, the background clouds in Mario Galaxy's Observatory lobby. - constexpr auto THRESHOLD_PERCENT = 4.5f; + const auto threshold = g_ActiveConfig.fArbitraryMipmapDetectionThreshold; auto* src = downsample_buffer; auto* dst = downsample_buffer + levels[1].shape.row_length * levels[1].shape.height * 4; @@ -533,7 +533,7 @@ public: } auto all_levels = total_diff / (levels.size() - 1); - return all_levels > THRESHOLD_PERCENT; + return all_levels > threshold; } private: diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index c7ab81d82b..a0029df1e7 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -121,6 +121,8 @@ void VideoConfig::Refresh() bForceTrueColor = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR); bDisableCopyFilter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER); bArbitraryMipmapDetection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION); + fArbitraryMipmapDetectionThreshold = + Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD); stereo_mode = Config::Get(Config::GFX_STEREO_MODE); iStereoDepth = Config::Get(Config::GFX_STEREO_DEPTH); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index faebb31f70..97d6429133 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -75,6 +75,7 @@ struct VideoConfig final bool bForceTrueColor; bool bDisableCopyFilter; bool bArbitraryMipmapDetection; + float fArbitraryMipmapDetectionThreshold; // Information bool bShowFPS; From 61a81795e5afe551f5622f146ca52d5331069742 Mon Sep 17 00:00:00 2001 From: Jonathan Hamilton Date: Wed, 16 May 2018 17:50:39 -0700 Subject: [PATCH 3/4] Change the arbitrary mipmap detection to use the square of the error Hopefully this better matches the user's view of a texture - as large changes in colour should be weighted higher than lots of very small changes Note: This likely invalidates the current heuristic threshold default --- Source/Core/VideoCommon/TextureCacheBase.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 370bdd836b..1b385dcbfe 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -608,10 +608,13 @@ private: const auto* row2 = ptr2; for (u32 j = 0; j < shape.width; ++j, row1 += 4, row2 += 4) { - average_diff += std::abs(static_cast(row1[0]) - static_cast(row2[0])); - average_diff += std::abs(static_cast(row1[1]) - static_cast(row2[1])); - average_diff += std::abs(static_cast(row1[2]) - static_cast(row2[2])); - average_diff += std::abs(static_cast(row1[3]) - static_cast(row2[3])); + for (int channel = 0; channel < 4; channel++) + { + const float diff = + std::abs(static_cast(row1[channel]) - static_cast(row2[channel])); + const float diff_squared = diff * diff; + average_diff += diff_squared; + } } ptr1 += shape.row_length; ptr2 += shape.row_length; From b30d56ccc0a03c41c758afcd47f5d19fa34b0a98 Mon Sep 17 00:00:00 2001 From: Jonathan Hamilton Date: Thu, 17 May 2018 09:39:39 -0700 Subject: [PATCH 4/4] Texture AverageDiff: Do more in int space and avoid excessive float conversion Multiplying 2x 8bit values is guaranteed to fit in 16bits, 4 channels then in 18bits, which means an 'int' shouild be sufficient to avoid overflows --- Source/Core/VideoCommon/TextureCacheBase.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 1b385dcbfe..c84bb6ec38 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -608,13 +608,14 @@ private: const auto* row2 = ptr2; for (u32 j = 0; j < shape.width; ++j, row1 += 4, row2 += 4) { + int pixel_diff = 0; for (int channel = 0; channel < 4; channel++) { - const float diff = - std::abs(static_cast(row1[channel]) - static_cast(row2[channel])); - const float diff_squared = diff * diff; - average_diff += diff_squared; + const int diff = static_cast(row1[channel]) - static_cast(row2[channel]); + const int diff_squared = diff * diff; + pixel_diff += diff_squared; } + average_diff += pixel_diff; } ptr1 += shape.row_length; ptr2 += shape.row_length;