From fa004a33c6cbadeb4447b82f836e02239488406f Mon Sep 17 00:00:00 2001 From: Samuliak Date: Wed, 18 Dec 2024 16:38:55 +0100 Subject: [PATCH] add an option to preserve position invariance --- src/Cafe/CafeSystem.cpp | 1 + src/Cafe/GameProfile/GameProfile.cpp | 4 ++++ src/Cafe/GameProfile/GameProfile.h | 4 +++- .../LatteDecompilerEmitMSLHeader.hpp | 2 +- src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp | 2 ++ src/gui/GameProfileWindow.cpp | 9 +++++++++ src/gui/GameProfileWindow.h | 1 + 7 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index f2e576f4..d1de472e 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -259,6 +259,7 @@ void InfoLog_PrintActiveSettings() cemuLog_log(LogType::Force, "Async compile: {}", GetConfig().async_compile.GetValue() ? "true" : "false"); cemuLog_log(LogType::Force, "Fast math: {}", g_current_game_profile->GetFastMath() ? "true" : "false"); cemuLog_log(LogType::Force, "Buffer cache type: {}", g_current_game_profile->GetBufferCacheMode()); + cemuLog_log(LogType::Force, "Position invariance: {}", g_current_game_profile->GetPositionInvariance() ? "true" : "false"); if (!GetConfig().vk_accurate_barriers.GetValue()) cemuLog_log(LogType::Force, "Accurate barriers are disabled!"); } diff --git a/src/Cafe/GameProfile/GameProfile.cpp b/src/Cafe/GameProfile/GameProfile.cpp index f8e1305c..d06a32dc 100644 --- a/src/Cafe/GameProfile/GameProfile.cpp +++ b/src/Cafe/GameProfile/GameProfile.cpp @@ -228,6 +228,7 @@ bool GameProfile::Load(uint64_t title_id) gameProfile_loadEnumOption(iniParser, "accurateShaderMul", m_accurateShaderMul); gameProfile_loadBooleanOption2(iniParser, "fastMath", m_fastMath); gameProfile_loadEnumOption(iniParser, "bufferCacheMode", m_bufferCacheMode); + gameProfile_loadBooleanOption2(iniParser, "positionInvariance", m_positionInvariance); // legacy support auto option_precompiledShaders = iniParser.FindOption("precompiledShaders"); @@ -312,6 +313,7 @@ void GameProfile::Save(uint64_t title_id) WRITE_ENTRY(accurateShaderMul); WRITE_ENTRY(fastMath); WRITE_ENTRY(bufferCacheMode); + WRITE_ENTRY(positionInvariance); WRITE_OPTIONAL_ENTRY(precompiledShaders); WRITE_OPTIONAL_ENTRY(graphics_api); fs->writeLine(""); @@ -343,6 +345,7 @@ void GameProfile::ResetOptional() m_accurateShaderMul = AccurateShaderMulOption::True; m_fastMath = true; m_bufferCacheMode = BufferCacheMode::DevicePrivate; + m_positionInvariance = false; // cpu settings m_threadQuantum = kThreadQuantumDefault; m_cpuMode.reset(); // CPUModeOption::kSingleCoreRecompiler; @@ -365,6 +368,7 @@ void GameProfile::Reset() m_accurateShaderMul = AccurateShaderMulOption::True; m_fastMath = true; m_bufferCacheMode = BufferCacheMode::DevicePrivate; + m_positionInvariance = false; m_precompiledShaders = PrecompiledShaderOption::Auto; // cpu settings m_threadQuantum = kThreadQuantumDefault; diff --git a/src/Cafe/GameProfile/GameProfile.h b/src/Cafe/GameProfile/GameProfile.h index 078a70a2..359e6a0a 100644 --- a/src/Cafe/GameProfile/GameProfile.h +++ b/src/Cafe/GameProfile/GameProfile.h @@ -33,6 +33,7 @@ public: [[nodiscard]] const AccurateShaderMulOption& GetAccurateShaderMul() const { return m_accurateShaderMul; } [[nodiscard]] bool GetFastMath() const { return m_fastMath; } [[nodiscard]] BufferCacheMode GetBufferCacheMode() const { return m_bufferCacheMode; } + [[nodiscard]] bool GetPositionInvariance() const { return m_positionInvariance; } [[nodiscard]] const std::optional& GetPrecompiledShadersState() const { return m_precompiledShaders; } [[nodiscard]] uint32 GetThreadQuantum() const { return m_threadQuantum; } @@ -56,8 +57,9 @@ private: // graphic settings std::optional m_graphics_api{}; AccurateShaderMulOption m_accurateShaderMul = AccurateShaderMulOption::True; - bool m_fastMath = false; + bool m_fastMath = true; BufferCacheMode m_bufferCacheMode = BufferCacheMode::DevicePrivate; + bool m_positionInvariance = false; std::optional m_precompiledShaders{}; // cpu settings uint32 m_threadQuantum = kThreadQuantumDefault; // values: 20000 45000 60000 80000 100000 diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp index 395b2421..1a2dfa3c 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp @@ -180,7 +180,7 @@ namespace LatteDecompiler auto* src = shaderContext->shaderSource; src->add("struct VertexOut {" _CRLF); - src->add("float4 position [[position]];" _CRLF); + src->add("float4 position [[position]] [[invariant]];" _CRLF); if (shaderContext->analyzer.outputPointSize) src->add("float pointSize [[point_size]];" _CRLF); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp index c77443c8..c4492e3c 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp @@ -178,6 +178,8 @@ void RendererShaderMtl::CompileInternal() // TODO: always disable fast math for problematic shaders if (g_current_game_profile->GetFastMath()) options->setFastMathEnabled(true); + if (g_current_game_profile->GetPositionInvariance()) + options->setPreserveInvariance(true); NS::Error* error = nullptr; MTL::Library* library = m_mtlr->GetDevice()->newLibrary(ToNSString(m_mslCode), options, &error); diff --git a/src/gui/GameProfileWindow.cpp b/src/gui/GameProfileWindow.cpp index 120dd5e9..c46f0f25 100644 --- a/src/gui/GameProfileWindow.cpp +++ b/src/gui/GameProfileWindow.cpp @@ -142,6 +142,13 @@ GameProfileWindow::GameProfileWindow(wxWindow* parent, uint64_t title_id) m_buffer_cache_mode->SetToolTip(_("EXPERT OPTION\nDecides how the buffer cache memory will be managed.\n\nMetal only\n\nRecommended: device private")); first_row->Add(m_buffer_cache_mode, 0, wxALL, 5); + first_row->Add(new wxStaticText(panel, wxID_ANY, _("Position invariance")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); + + wxString pos_values[] = { _("false"), _("true") }; + m_position_invariance = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, (int)std::size(pos_values), pos_values); + m_position_invariance->SetToolTip(_("Disables most optimizations for vertex positions. May fix polygon cutouts in some games.\n\nMetal only\n\nRecommended: false")); + first_row->Add(m_position_invariance, 0, wxALL, 5); + /*first_row->Add(new wxStaticText(panel, wxID_ANY, _("GPU buffer cache accuracy")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); wxString accuarcy_values[] = { _("high"), _("medium"), _("low") }; m_cache_accuracy = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, (int)std::size(accuarcy_values), accuarcy_values); @@ -290,6 +297,7 @@ void GameProfileWindow::ApplyProfile() m_shader_mul_accuracy->SetSelection((int)m_game_profile.m_accurateShaderMul); m_fast_math->SetSelection((int)m_game_profile.m_fastMath); m_buffer_cache_mode->SetSelection((int)m_game_profile.m_bufferCacheMode); + m_position_invariance->SetSelection((int)m_game_profile.m_positionInvariance); //// audio //m_disable_audio->Set3StateValue(GetCheckboxState(m_game_profile.disableAudio)); @@ -351,6 +359,7 @@ void GameProfileWindow::SaveProfile() m_game_profile.m_accurateShaderMul = (AccurateShaderMulOption)m_shader_mul_accuracy->GetSelection(); m_game_profile.m_fastMath = (bool)m_fast_math->GetSelection(); m_game_profile.m_bufferCacheMode = (BufferCacheMode)m_buffer_cache_mode->GetSelection(); + m_game_profile.m_positionInvariance = (bool)m_position_invariance->GetSelection(); if (m_game_profile.m_accurateShaderMul != AccurateShaderMulOption::False && m_game_profile.m_accurateShaderMul != AccurateShaderMulOption::True) m_game_profile.m_accurateShaderMul = AccurateShaderMulOption::True; // force a legal value diff --git a/src/gui/GameProfileWindow.h b/src/gui/GameProfileWindow.h index 8bf0c91c..ddd72c77 100644 --- a/src/gui/GameProfileWindow.h +++ b/src/gui/GameProfileWindow.h @@ -42,6 +42,7 @@ private: wxChoice* m_shader_mul_accuracy; wxChoice* m_fast_math; wxChoice* m_buffer_cache_mode; + wxChoice* m_position_invariance; //wxChoice* m_cache_accuracy; // audio