From ebcb62a7851d94a4a1105da1e4ef1eaf8e74e58a Mon Sep 17 00:00:00 2001 From: Samuliak Date: Wed, 2 Oct 2024 17:18:20 +0200 Subject: [PATCH] add: an option to turn fast math off --- src/Cafe/CafeSystem.cpp | 3 +- .../Renderer/Metal/RendererShaderMtl.cpp | 10 +++++-- src/config/CemuConfig.cpp | 20 +++++++------ src/config/CemuConfig.h | 1 + src/gui/GeneralSettings2.cpp | 30 +++++++++++++++++-- src/gui/GeneralSettings2.h | 7 ++--- 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index 958a5a57..96e5621d 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -251,6 +251,7 @@ void InfoLog_PrintActiveSettings() if (ActiveSettings::GetGraphicsAPI() == GraphicAPI::kVulkan) { cemuLog_log(LogType::Force, "Async compile: {}", GetConfig().async_compile.GetValue() ? "true" : "false"); + cemuLog_log(LogType::Force, "Fast math: {}", GetConfig().fast_math.GetValue() ? "true" : "false"); if(!GetConfig().vk_accurate_barriers.GetValue()) cemuLog_log(LogType::Force, "Accurate barriers are disabled!"); } @@ -1013,7 +1014,7 @@ namespace CafeSystem { // starting with Cemu 1.27.0 /vol/storage_mlc01/ is virtualized, meaning that it doesn't point to one singular host os folder anymore // instead it now uses a more complex solution to source titles with various formats (folder, wud, wua) from the game paths and host mlc path - + // todo - mount /vol/storage_mlc01/ with base priority to the host mlc? // since mounting titles is an expensive operation we have to avoid mounting all titles at once diff --git a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp index 359b9fd0..4aff3e14 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp @@ -7,8 +7,7 @@ #include "Cemu/Logging/CemuLogging.h" #include "Common/precompiled.h" -#include "HW/Latte/Core/FetchShader.h" -#include "HW/Latte/ISA/RegDefines.h" +#include "config/CemuConfig.h" extern std::atomic_int g_compiled_shaders_total; extern std::atomic_int g_compiled_shaders_async; @@ -16,8 +15,13 @@ extern std::atomic_int g_compiled_shaders_async; RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode) : RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_mtlr{mtlRenderer} { + MTL::CompileOptions* options = MTL::CompileOptions::alloc()->init(); + if (GetConfig().fast_math) + options->setFastMathEnabled(true); + NS::Error* error = nullptr; - MTL::Library* library = m_mtlr->GetDevice()->newLibrary(ToNSString(mslCode), nullptr, &error); + MTL::Library* library = m_mtlr->GetDevice()->newLibrary(ToNSString(mslCode), options, &error); + options->release(); if (error) { cemuLog_log(LogType::Force, "failed to create library: {} -> {}", error->localizedDescription()->utf8String(), mslCode.c_str()); diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index e7920e84..06ad94d5 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -32,7 +32,7 @@ void CemuConfig::Load(XMLConfigParser& parser) mlc_path = mlc; permanent_storage = parser.get("permanent_storage", permanent_storage); - + language = parser.get("language", wxLANGUAGE_DEFAULT); use_discord_presence = parser.get("use_discord_presence", true); fullscreen_menubar = parser.get("fullscreen_menubar", false); @@ -102,7 +102,7 @@ void CemuConfig::Load(XMLConfigParser& parser) cemuLog_log(LogType::Force, "config load error: can't load recently launched game file: {}", path); } } - + recent_nfc_files.clear(); auto nfc_parser = parser.get("RecentNFCFiles"); for (auto element = nfc_parser.get("Entry"); element.valid(); element = nfc_parser.get("Entry", element)) @@ -198,7 +198,7 @@ void CemuConfig::Load(XMLConfigParser& parser) { graphic_pack_entries[path].try_emplace("_disabled", "true"); } - + for (auto preset = element.get("Preset"); preset.valid(); preset = element.get("Preset", preset)) { const std::string category = preset.get("category", ""); @@ -206,7 +206,7 @@ void CemuConfig::Load(XMLConfigParser& parser) graphic_pack_entries[path].try_emplace(category, active_preset); } } - + } // graphics @@ -219,6 +219,7 @@ void CemuConfig::Load(XMLConfigParser& parser) downscale_filter = graphic.get("DownscaleFilter", kLinearFilter); fullscreen_scaling = graphic.get("FullscreenScaling", kKeepAspectRatio); async_compile = graphic.get("AsyncCompile", async_compile); + fast_math = graphic.get("FastMath", fast_math); vk_accurate_barriers = graphic.get("vkAccurateBarriers", true); // this used to be "VulkanAccurateBarriers" but because we changed the default to true in 1.27.1 the option name had to be changed auto overlay_node = graphic.get("Overlay"); @@ -373,7 +374,7 @@ void CemuConfig::Save(XMLConfigParser& parser) // config.set("cpu_mode", cpu_mode.GetValue()); //config.set("console_region", console_region.GetValue()); config.set("console_language", console_language.GetValue()); - + auto wpos = config.set("window_position"); wpos.set("x", window_position.x); wpos.set("y", window_position.y); @@ -408,13 +409,13 @@ void CemuConfig::Save(XMLConfigParser& parser) { launch_files_parser.set("Entry", entry.c_str()); } - + auto nfc_files_parser = config.set("RecentNFCFiles"); for (const auto& entry : recent_nfc_files) { nfc_files_parser.set("Entry", entry.c_str()); } - + // game paths auto game_path_parser = config.set("GamePaths"); for (const auto& entry : game_paths) @@ -455,11 +456,11 @@ void CemuConfig::Save(XMLConfigParser& parser) entry.set_attribute("disabled", true); continue; } - + auto preset = entry.set("Preset"); if(!kv.first.empty()) preset.set("category", kv.first.c_str()); - + preset.set("preset", kv.second.c_str()); } } @@ -475,6 +476,7 @@ void CemuConfig::Save(XMLConfigParser& parser) graphic.set("DownscaleFilter", downscale_filter); graphic.set("FullscreenScaling", fullscreen_scaling); graphic.set("AsyncCompile", async_compile.GetValue()); + graphic.set("FastMath", fast_math.GetValue()); graphic.set("vkAccurateBarriers", vk_accurate_barriers); auto overlay_node = graphic.set("Overlay"); diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index 84235077..c231ae08 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -444,6 +444,7 @@ struct CemuConfig ConfigValue gx2drawdone_sync {true}; ConfigValue render_upside_down{ false }; ConfigValue async_compile{ true }; + ConfigValue fast_math{ true }; ConfigValue vk_accurate_barriers{ true }; diff --git a/src/gui/GeneralSettings2.cpp b/src/gui/GeneralSettings2.cpp index 63121e29..4cd0be9a 100644 --- a/src/gui/GeneralSettings2.cpp +++ b/src/gui/GeneralSettings2.cpp @@ -344,6 +344,10 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook) m_async_compile->SetToolTip(_("Enables async shader and pipeline compilation. Reduces stutter at the cost of objects not rendering for a short time.\nVulkan only")); graphic_misc_row->Add(m_async_compile, 0, wxALL, 5); + m_fast_math = new wxCheckBox(box, wxID_ANY, _("Fast math")); + m_fast_math->SetToolTip(_("Enables fast math for all shaders. May cause minor inaccuracies in some games.\nMetal only")); + graphic_misc_row->Add(m_fast_math, 0, wxALL, 5); + m_gx2drawdone_sync = new wxCheckBox(box, wxID_ANY, _("Full sync at GX2DrawDone()")); m_gx2drawdone_sync->SetToolTip(_("If synchronization is requested by the game, the emulated CPU will wait for the GPU to finish all operations.\nThis is more accurate behavior, but may cause lower performance")); graphic_misc_row->Add(m_gx2drawdone_sync, 0, wxALL, 5); @@ -1038,6 +1042,7 @@ void GeneralSettings2::StoreConfig() config.vsync = m_vsync->GetSelection(); config.gx2drawdone_sync = m_gx2drawdone_sync->IsChecked(); config.async_compile = m_async_compile->IsChecked(); + config.fast_math = m_fast_math->IsChecked(); config.upscale_filter = m_upscale_filter->GetSelection(); config.downscale_filter = m_downscale_filter->GetSelection(); @@ -1500,7 +1505,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() selection = GetConfig().vsync; m_vsync->Clear(); - if(m_graphic_api->GetSelection() == 0) + if (m_graphic_api->GetSelection() == 0) { // OpenGL m_vsync->AppendString(_("Off")); @@ -1515,12 +1520,14 @@ void GeneralSettings2::HandleGraphicsApiSelection() m_gx2drawdone_sync->Enable(); m_async_compile->Disable(); + m_fast_math->Disable(); } - else + else if (m_graphic_api->GetSelection() == 1) { // Vulkan m_gx2drawdone_sync->Disable(); m_async_compile->Enable(); + m_fast_math->Disable(); m_vsync->AppendString(_("Off")); m_vsync->AppendString(_("Double buffering")); @@ -1553,6 +1560,24 @@ void GeneralSettings2::HandleGraphicsApiSelection() } } } + else + { + // Metal + m_gx2drawdone_sync->Disable(); + m_async_compile->Enable(); + m_fast_math->Enable(); + + // TODO: vsync options + m_vsync->AppendString(_("Off")); + m_vsync->AppendString(_("Double buffering")); + m_vsync->AppendString(_("Triple buffering")); + + m_vsync->Select(selection); + + // TODO: add an option to select the graphic device + m_graphic_device->Clear(); + m_graphic_device->Disable(); + } } void GeneralSettings2::ApplyConfig() @@ -1604,6 +1629,7 @@ void GeneralSettings2::ApplyConfig() m_graphic_api->SetSelection(config.graphic_api); m_vsync->SetSelection(config.vsync); m_async_compile->SetValue(config.async_compile); + m_fast_math->SetValue(config.fast_math); m_gx2drawdone_sync->SetValue(config.gx2drawdone_sync); m_upscale_filter->SetSelection(config.upscale_filter); m_downscale_filter->SetSelection(config.downscale_filter); diff --git a/src/gui/GeneralSettings2.h b/src/gui/GeneralSettings2.h index b1ab01e8..01c4845f 100644 --- a/src/gui/GeneralSettings2.h +++ b/src/gui/GeneralSettings2.h @@ -28,7 +28,7 @@ private: bool m_has_account_change = false; // keep track of dirty state of accounts - + wxPanel* AddGeneralPage(wxNotebook* notebook); wxPanel* AddGraphicsPage(wxNotebook* notebook); wxPanel* AddAudioPage(wxNotebook* notebook); @@ -52,7 +52,7 @@ private: // Graphics wxChoice* m_graphic_api, * m_graphic_device; wxChoice* m_vsync; - wxCheckBox *m_async_compile, *m_gx2drawdone_sync; + wxCheckBox *m_async_compile, *m_fast_math, *m_gx2drawdone_sync; wxRadioBox* m_upscale_filter, *m_downscale_filter, *m_fullscreen_scaling; wxChoice* m_overlay_position, *m_notification_position, *m_overlay_scale, *m_notification_scale; wxCheckBox* m_controller_profile_name, *m_controller_low_battery, *m_shader_compiling, *m_friends_data; @@ -106,11 +106,10 @@ private: void UpdateAudioDevice(); // refreshes audio device list for dropdown void UpdateAudioDeviceList(); - + void ResetAccountInformation(); void UpdateAccountInformation(); void UpdateOnlineAccounts(); void HandleGraphicsApiSelection(); void ApplyConfig(); }; -