From 8e0d1f28732a0f7d372f3814aec6aafecb3d17e6 Mon Sep 17 00:00:00 2001 From: Hyper <34012267+hyperbx@users.noreply.github.com> Date: Mon, 24 Mar 2025 17:57:50 +0000 Subject: [PATCH] Added MSAA level availability checks (#1446) --- UnleashedRecomp/gpu/video.cpp | 15 +++++++++ UnleashedRecomp/ui/options_menu.cpp | 3 +- UnleashedRecomp/user/config.cpp | 48 +++++++++++++++++++++++++++++ UnleashedRecomp/user/config.h | 11 +++---- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 19c7fb64..2b693adb 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -1741,6 +1741,21 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver) ApplyLowEndDefaults(); } + const RenderSampleCounts colourSampleCount = g_device->getSampleCountsSupported(RenderFormat::R16G16B16A16_FLOAT); + const RenderSampleCounts depthSampleCount = g_device->getSampleCountsSupported(RenderFormat::D32_FLOAT); + const RenderSampleCounts commonSampleCount = colourSampleCount & depthSampleCount; + + // Disable specific MSAA levels if they are not supported. + if ((commonSampleCount & RenderSampleCount::COUNT_2) == 0) + Config::AntiAliasing.InaccessibleValues.emplace(EAntiAliasing::MSAA2x); + if ((commonSampleCount & RenderSampleCount::COUNT_4) == 0) + Config::AntiAliasing.InaccessibleValues.emplace(EAntiAliasing::MSAA4x); + if ((commonSampleCount & RenderSampleCount::COUNT_8) == 0) + Config::AntiAliasing.InaccessibleValues.emplace(EAntiAliasing::MSAA8x); + + // Set Anti-Aliasing to nearest supported level. + Config::AntiAliasing.SnapToNearestAccessibleValue(false); + g_queue = g_device->createCommandQueue(RenderCommandListType::DIRECT); for (auto& commandList : g_commandLists) diff --git a/UnleashedRecomp/ui/options_menu.cpp b/UnleashedRecomp/ui/options_menu.cpp index a9955d23..451c4f4f 100644 --- a/UnleashedRecomp/ui/options_menu.cpp +++ b/UnleashedRecomp/ui/options_menu.cpp @@ -1043,6 +1043,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf } config->Value = it->first; + config->SnapToNearestAccessibleValue(rightTapped); if (increment || decrement) Game_PlaySound("sys_actstg_pausecursor"); @@ -1271,7 +1272,7 @@ static void DrawConfigOptions() DrawConfigOption(rowCount++, yOffset, &Config::VSync, true); DrawConfigOption(rowCount++, yOffset, &Config::FPS, true, nullptr, FPS_MIN, 120, FPS_MAX); DrawConfigOption(rowCount++, yOffset, &Config::Brightness, true); - DrawConfigOption(rowCount++, yOffset, &Config::AntiAliasing, true); + DrawConfigOption(rowCount++, yOffset, &Config::AntiAliasing, Config::AntiAliasing.InaccessibleValues.size() != 3, &Localise("Options_Desc_NotAvailableHardware")); DrawConfigOption(rowCount++, yOffset, &Config::TransparencyAntiAliasing, Config::AntiAliasing != EAntiAliasing::None, &Localise("Options_Desc_NotAvailableMSAA")); DrawConfigOption(rowCount++, yOffset, &Config::ShadowResolution, true); DrawConfigOption(rowCount++, yOffset, &Config::GITextureFiltering, true); diff --git a/UnleashedRecomp/user/config.cpp b/UnleashedRecomp/user/config.cpp index dddcf5a5..bd622b7f 100644 --- a/UnleashedRecomp/user/config.cpp +++ b/UnleashedRecomp/user/config.cpp @@ -494,6 +494,9 @@ template void ConfigDef::MakeDefault() { Value = DefaultValue; + + if constexpr (std::is_enum_v) + SnapToNearestAccessibleValue(false); } template @@ -696,6 +699,51 @@ void ConfigDef::GetLocaleStrings(std::vector& loc } } +template +void ConfigDef::SnapToNearestAccessibleValue(bool searchUp) +{ + if constexpr (std::is_enum_v) + { + if (EnumTemplateReverse.empty() || InaccessibleValues.empty()) + return; + + if (EnumTemplateReverse.size() == InaccessibleValues.size()) + { + assert(false && "All enum values are marked inaccessible and the nearest accessible value cannot be determined."); + return; + } + + auto it = EnumTemplateReverse.find(Value); + + if (it == EnumTemplateReverse.end()) + { + assert(false && "Enum value does not exist in the template."); + return; + } + + // Skip the enum value if it's marked as inaccessible. + while (InaccessibleValues.find(it->first) != InaccessibleValues.end()) + { + if (searchUp) + { + ++it; + + if (it == EnumTemplateReverse.end()) + it = EnumTemplateReverse.begin(); + } + else + { + if (it == EnumTemplateReverse.begin()) + it = EnumTemplateReverse.end(); + + --it; + } + } + + Value = it->first; + } +} + std::filesystem::path Config::GetConfigPath() { return GetUserPath() / "config.toml"; diff --git a/UnleashedRecomp/user/config.h b/UnleashedRecomp/user/config.h index 5cda9d9d..9e87d12e 100644 --- a/UnleashedRecomp/user/config.h +++ b/UnleashedRecomp/user/config.h @@ -20,6 +20,7 @@ public: virtual std::string GetDefinition(bool withSection = false) const = 0; virtual std::string ToString(bool strWithQuotes = true) const = 0; virtual void GetLocaleStrings(std::vector& localeStrings) const = 0; + virtual void SnapToNearestAccessibleValue(bool searchUp) = 0; }; #define CONFIG_LOCALE std::unordered_map> @@ -158,7 +159,8 @@ public: CONFIG_LOCALE* Locale{}; T DefaultValue{}; T Value{ DefaultValue }; - std::unordered_map* EnumTemplate; + std::set InaccessibleValues{}; + std::unordered_map* EnumTemplate{}; std::map EnumTemplateReverse{}; CONFIG_ENUM_LOCALE(T)* EnumLocale{}; std::function*)> Callback; @@ -183,25 +185,20 @@ public: ~ConfigDef(); bool IsHidden() override; - void ReadValue(toml::v3::ex::parse_result& toml) override; void MakeDefault() override; - std::string_view GetSection() const override; std::string_view GetName() const override; std::string GetNameLocalised(ELanguage language) const override; std::string GetDescription(ELanguage language) const override; - bool IsDefaultValue() const override; const void* GetValue() const override; - std::string GetValueLocalised(ELanguage language) const override; std::string GetValueDescription(ELanguage language) const override; - std::string GetDefinition(bool withSection = false) const override; std::string ToString(bool strWithQuotes = true) const override; - void GetLocaleStrings(std::vector& localeStrings) const override; + void SnapToNearestAccessibleValue(bool searchUp) override; operator T() const {