From aaf6d5d67766e4fed773d1e54ab0ed67057babd9 Mon Sep 17 00:00:00 2001 From: RedBlackAka <140876408+RedBlackAka@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:43:28 +0100 Subject: [PATCH] UI: Hide Metal only options on non-Apple builds (#1753) --- src/Cafe/CafeSystem.cpp | 2 ++ src/Cafe/GameProfile/GameProfile.cpp | 8 +++++++ src/Cafe/GameProfile/GameProfile.h | 4 ++++ src/config/CemuConfig.cpp | 8 +++++++ src/config/CemuConfig.h | 4 ++++ src/gui/wxgui/GameProfileWindow.cpp | 6 ++++++ src/gui/wxgui/GameProfileWindow.h | 2 ++ src/gui/wxgui/GeneralSettings2.cpp | 31 +++++++++++++++++++++------- src/gui/wxgui/GeneralSettings2.h | 7 ++++++- src/gui/wxgui/MainWindow.cpp | 6 ++++-- 10 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index e5ac4c98..9c915e76 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -252,6 +252,7 @@ void InfoLog_PrintActiveSettings() if (!GetConfig().vk_accurate_barriers.GetValue()) cemuLog_log(LogType::Force, "Accurate barriers are disabled!"); } +#if ENABLE_METAL else if (ActiveSettings::GetGraphicsAPI() == GraphicAPI::kMetal) { cemuLog_log(LogType::Force, "Async compile: {}", GetConfig().async_compile.GetValue() ? "true" : "false"); @@ -262,6 +263,7 @@ void InfoLog_PrintActiveSettings() if (!GetConfig().vk_accurate_barriers.GetValue()) cemuLog_log(LogType::Force, "Accurate barriers are disabled!"); } +#endif cemuLog_log(LogType::Force, "Console language: {}", stdx::to_underlying(config.console_language.GetValue())); } diff --git a/src/Cafe/GameProfile/GameProfile.cpp b/src/Cafe/GameProfile/GameProfile.cpp index b1a0ad70..9ee0a696 100644 --- a/src/Cafe/GameProfile/GameProfile.cpp +++ b/src/Cafe/GameProfile/GameProfile.cpp @@ -226,9 +226,11 @@ bool GameProfile::Load(uint64_t title_id) m_graphics_api = (GraphicAPI)graphicsApi.value; gameProfile_loadEnumOption(iniParser, "accurateShaderMul", m_accurateShaderMul); +#if ENABLE_METAL gameProfile_loadBooleanOption2(iniParser, "shaderFastMath", m_shaderFastMath); gameProfile_loadEnumOption(iniParser, "metalBufferCacheMode2", m_metalBufferCacheMode); gameProfile_loadEnumOption(iniParser, "positionInvariance2", m_positionInvariance); +#endif // legacy support auto option_precompiledShaders = iniParser.FindOption("precompiledShaders"); @@ -309,9 +311,11 @@ void GameProfile::Save(uint64_t title_id) fs->writeLine("[Graphics]"); WRITE_ENTRY(accurateShaderMul); +#if ENABLE_METAL WRITE_ENTRY(shaderFastMath); WRITE_ENTRY_NUMBERED(metalBufferCacheMode, 2); WRITE_ENTRY_NUMBERED(positionInvariance, 2); +#endif WRITE_OPTIONAL_ENTRY(precompiledShaders); WRITE_OPTIONAL_ENTRY(graphics_api); fs->writeLine(""); @@ -342,9 +346,11 @@ void GameProfile::ResetOptional() // graphic settings m_accurateShaderMul = AccurateShaderMulOption::True; +#if ENABLE_METAL m_shaderFastMath = true; m_metalBufferCacheMode = MetalBufferCacheMode::Auto; m_positionInvariance = PositionInvariance::Auto; +#endif // cpu settings m_threadQuantum = kThreadQuantumDefault; m_cpuMode.reset(); // CPUModeOption::kSingleCoreRecompiler; @@ -365,9 +371,11 @@ void GameProfile::Reset() // graphic settings m_accurateShaderMul = AccurateShaderMulOption::True; +#if ENABLE_METAL m_shaderFastMath = true; m_metalBufferCacheMode = MetalBufferCacheMode::Auto; m_positionInvariance = PositionInvariance::Auto; +#endif m_precompiledShaders = PrecompiledShaderOption::Auto; // cpu settings m_threadQuantum = kThreadQuantumDefault; diff --git a/src/Cafe/GameProfile/GameProfile.h b/src/Cafe/GameProfile/GameProfile.h index 4885d4fc..42424957 100644 --- a/src/Cafe/GameProfile/GameProfile.h +++ b/src/Cafe/GameProfile/GameProfile.h @@ -31,9 +31,11 @@ public: [[nodiscard]] const std::optional& GetGraphicsAPI() const { return m_graphics_api; } [[nodiscard]] const AccurateShaderMulOption& GetAccurateShaderMul() const { return m_accurateShaderMul; } +#if ENABLE_METAL [[nodiscard]] bool GetShaderFastMath() const { return m_shaderFastMath; } [[nodiscard]] MetalBufferCacheMode GetBufferCacheMode() const { return m_metalBufferCacheMode; } [[nodiscard]] PositionInvariance GetPositionInvariance() const { return m_positionInvariance; } +#endif [[nodiscard]] const std::optional& GetPrecompiledShadersState() const { return m_precompiledShaders; } [[nodiscard]] uint32 GetThreadQuantum() const { return m_threadQuantum; } @@ -57,9 +59,11 @@ private: // graphic settings std::optional m_graphics_api{}; AccurateShaderMulOption m_accurateShaderMul = AccurateShaderMulOption::True; +#if ENABLE_METAL bool m_shaderFastMath = true; MetalBufferCacheMode m_metalBufferCacheMode = MetalBufferCacheMode::Auto; PositionInvariance m_positionInvariance = PositionInvariance::Auto; +#endif std::optional m_precompiledShaders{}; // cpu settings uint32 m_threadQuantum = kThreadQuantumDefault; // values: 20000 45000 60000 80000 100000 diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index 30e2b8d1..92542fa9 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -143,7 +143,9 @@ XMLConfigParser CemuConfig::Load(XMLConfigParser& parser) fullscreen_scaling = graphic.get("FullscreenScaling", kKeepAspectRatio); async_compile = graphic.get("AsyncCompile", async_compile); 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 +#if ENABLE_METAL force_mesh_shaders = graphic.get("ForceMeshShaders", false); +#endif auto overlay_node = graphic.get("Overlay"); if(overlay_node.valid()) @@ -270,8 +272,10 @@ XMLConfigParser CemuConfig::Load(XMLConfigParser& parser) crash_dump = debug.get("CrashDumpUnix", crash_dump); #endif gdb_port = debug.get("GDBPort", 1337); +#if ENABLE_METAL gpu_capture_dir = debug.get("GPUCaptureDir", ""); framebuffer_fetch = debug.get("FramebufferFetch", true); +#endif // input auto input = parser.get("Input"); @@ -362,7 +366,9 @@ XMLConfigParser CemuConfig::Save(XMLConfigParser& parser) graphic.set("OverrideGammaValue", overrideGammaValue); graphic.set("UserDisplayGamma", userDisplayGamma); graphic.set("GX2DrawdoneSync", gx2drawdone_sync); +#if ENABLE_METAL graphic.set("ForceMeshShaders", force_mesh_shaders); +#endif //graphic.set("PrecompiledShaders", precompiled_shaders.GetValue()); graphic.set("UpscaleFilter", upscale_filter); graphic.set("DownscaleFilter", downscale_filter); @@ -429,8 +435,10 @@ XMLConfigParser CemuConfig::Save(XMLConfigParser& parser) debug.set("CrashDumpUnix", crash_dump.GetValue()); #endif debug.set("GDBPort", gdb_port); +#if ENABLE_METAL debug.set("GPUCaptureDir", gpu_capture_dir); debug.set("FramebufferFetch", framebuffer_fetch); +#endif // input auto input = config.set("Input"); diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index cc0bad12..1134ab96 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -438,7 +438,9 @@ struct CemuConfig ConfigValue gx2drawdone_sync { true }; ConfigValue render_upside_down{ false }; ConfigValue async_compile{ true }; +#if ENABLE_METAL ConfigValue force_mesh_shaders{ false }; +#endif // Gamma ConfigValue overrideAppGammaPreference{ false }; @@ -502,8 +504,10 @@ struct CemuConfig // debug ConfigValueBounds crash_dump{ CrashDump::Disabled }; ConfigValue gdb_port{ 1337 }; +#if ENABLE_METAL ConfigValue gpu_capture_dir{ "" }; ConfigValue framebuffer_fetch{ true }; +#endif XMLConfigParser Load(XMLConfigParser& parser); XMLConfigParser Save(XMLConfigParser& parser); diff --git a/src/gui/wxgui/GameProfileWindow.cpp b/src/gui/wxgui/GameProfileWindow.cpp index 58204868..9d7d1f34 100644 --- a/src/gui/wxgui/GameProfileWindow.cpp +++ b/src/gui/wxgui/GameProfileWindow.cpp @@ -127,6 +127,7 @@ GameProfileWindow::GameProfileWindow(wxWindow* parent, uint64_t title_id) m_shader_mul_accuracy->SetToolTip(_("EXPERT OPTION\nControls the accuracy of floating point multiplication in shaders.\n\nRecommended: true")); first_row->Add(m_shader_mul_accuracy, 0, wxALL, 5); +#if ENABLE_METAL first_row->Add(new wxStaticText(panel, wxID_ANY, _("Shader fast math")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); wxString math_values[] = { _("false"), _("true") }; @@ -147,6 +148,7 @@ GameProfileWindow::GameProfileWindow(wxWindow* parent, uint64_t title_id) m_position_invariance = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, (int)std::size(pos_values), pos_values); m_position_invariance->SetToolTip(_("EXPERT OPTION\nDisables most optimizations for vertex positions. May fix polygon cutouts or flickering in some games.\n\nMetal only\n\nRecommended: auto")); first_row->Add(m_position_invariance, 0, wxALL, 5); +#endif /*first_row->Add(new wxStaticText(panel, wxID_ANY, _("GPU buffer cache accuracy")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); wxString accuarcy_values[] = { _("high"), _("medium"), _("low") }; @@ -294,9 +296,11 @@ void GameProfileWindow::ApplyProfile() else m_graphic_api->SetSelection(1 + m_game_profile.m_graphics_api.value()); // "", OpenGL, Vulkan, Metal m_shader_mul_accuracy->SetSelection((int)m_game_profile.m_accurateShaderMul); +#if ENABLE_METAL m_shader_fast_math->SetSelection((int)m_game_profile.m_shaderFastMath); m_metal_buffer_cache_mode->SetSelection((int)m_game_profile.m_metalBufferCacheMode); m_position_invariance->SetSelection((int)m_game_profile.m_positionInvariance); +#endif //// audio //m_disable_audio->Set3StateValue(GetCheckboxState(m_game_profile.disableAudio)); @@ -358,9 +362,11 @@ void GameProfileWindow::SaveProfile() m_game_profile.m_accurateShaderMul = (AccurateShaderMulOption)m_shader_mul_accuracy->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 +#if ENABLE_METAL m_game_profile.m_shaderFastMath = (bool)m_shader_fast_math->GetSelection(); m_game_profile.m_metalBufferCacheMode = (MetalBufferCacheMode)m_metal_buffer_cache_mode->GetSelection(); m_game_profile.m_positionInvariance = (PositionInvariance)m_position_invariance->GetSelection(); +#endif if (m_graphic_api->GetSelection() == 0) m_game_profile.m_graphics_api = {}; diff --git a/src/gui/wxgui/GameProfileWindow.h b/src/gui/wxgui/GameProfileWindow.h index 6eaed1a1..3cb381d9 100644 --- a/src/gui/wxgui/GameProfileWindow.h +++ b/src/gui/wxgui/GameProfileWindow.h @@ -40,9 +40,11 @@ private: wxChoice* m_graphic_api; wxChoice* m_shader_mul_accuracy; +#if ENABLE_METAL wxChoice* m_shader_fast_math; wxChoice* m_metal_buffer_cache_mode; wxChoice* m_position_invariance; +#endif //wxChoice* m_cache_accuracy; // audio diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index e1630eda..5e447eae 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -359,7 +359,7 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook) choices[api_size++] = "Vulkan"; } #if ENABLE_METAL - choices[api_size++] = "Metal"; + choices[api_size++] = "Metal"; #endif m_graphic_api = new wxChoice(box, wxID_ANY, wxDefaultPosition, wxDefaultSize, api_size, choices); @@ -392,9 +392,11 @@ wxPanel* GeneralSettings2::AddGraphicsPage(wxNotebook* notebook) 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); +#if ENABLE_METAL m_force_mesh_shaders = new wxCheckBox(box, wxID_ANY, _("Force mesh shaders")); - m_force_mesh_shaders->SetToolTip(_("Force mesh shaders on all GPUs that support them. Mesh shaders are disabled by default on Intel GPUs due to potential stability issues")); + m_force_mesh_shaders->SetToolTip(_("Force mesh shaders on all GPUs that support them. Mesh shaders are disabled by default on Intel GPUs due to potential stability issues.\nMetal only")); graphic_misc_row->Add(m_force_mesh_shaders, 0, wxALL, 5); +#endif box_sizer->Add(graphic_misc_row, 1, wxEXPAND, 5); graphics_panel_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5); @@ -1000,6 +1002,7 @@ wxPanel* GeneralSettings2::AddDebugPage(wxNotebook* notebook) debug_panel_sizer->Add(debug_row, 0, wxALL | wxEXPAND, 5); } +#if ENABLE_METAL { auto* debug_row = new wxFlexGridSizer(0, 2, 0, 0); debug_row->SetFlexibleDirection(wxBOTH); @@ -1009,7 +1012,7 @@ wxPanel* GeneralSettings2::AddDebugPage(wxNotebook* notebook) m_gpu_capture_dir = new wxTextCtrl(panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_DONTWRAP); m_gpu_capture_dir->SetMinSize(wxSize(150, -1)); - m_gpu_capture_dir->SetToolTip(_("Cemu will save the GPU captures done by selecting Debug -> GPU capture in the menu bar in this directory. If a debugger with support for GPU captures (like Xcode) is attached, the capture will be opened in that debugger instead. If such debugger is not attached, METAL_CAPTURE_ENABLED must be set to 1 as an environment variable.")); + m_gpu_capture_dir->SetToolTip(_("Cemu will save the GPU captures done by selecting Debug -> GPU capture (Metal) in the menu bar in this directory. If a debugger with support for GPU captures (like Xcode) is attached, the capture will be opened in that debugger instead. If such debugger is not attached, METAL_CAPTURE_ENABLED must be set to 1 as an environment variable.")); debug_row->Add(m_gpu_capture_dir, 0, wxALL | wxEXPAND, 5); debug_panel_sizer->Add(debug_row, 0, wxALL | wxEXPAND, 5); @@ -1021,11 +1024,12 @@ wxPanel* GeneralSettings2::AddDebugPage(wxNotebook* notebook) debug_row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); m_framebuffer_fetch = new wxCheckBox(panel, wxID_ANY, _("Framebuffer fetch")); - m_framebuffer_fetch->SetToolTip(_("Enable framebuffer fetch for eligible textures on supported devices.")); + m_framebuffer_fetch->SetToolTip(_("Enable framebuffer fetch for eligible textures on supported devices.\nMetal only")); debug_row->Add(m_framebuffer_fetch, 0, wxALL | wxEXPAND, 5); debug_panel_sizer->Add(debug_row, 0, wxALL | wxEXPAND, 5); } +#endif panel->SetSizerAndFit(debug_panel_sizer); @@ -1224,7 +1228,9 @@ void GeneralSettings2::StoreConfig() config.overrideGammaValue = m_overrideGammaValue->GetValue(); config.userDisplayGamma = m_userDisplayGamma->GetValue() * !m_userDisplayisSRGB->GetValue(); config.gx2drawdone_sync = m_gx2drawdone_sync->IsChecked(); +#if ENABLE_METAL config.force_mesh_shaders = m_force_mesh_shaders->IsChecked(); +#endif config.async_compile = m_async_compile->IsChecked(); config.upscale_filter = m_upscale_filter->GetSelection(); @@ -1257,8 +1263,10 @@ void GeneralSettings2::StoreConfig() // debug config.crash_dump = (CrashDump)m_crash_dump->GetSelection(); config.gdb_port = m_gdb_port->GetValue(); +#if ENABLE_METAL config.gpu_capture_dir = m_gpu_capture_dir->GetValue().utf8_string(); config.framebuffer_fetch = m_framebuffer_fetch->IsChecked(); +#endif GetConfigHandle().Save(); } @@ -1710,14 +1718,18 @@ void GeneralSettings2::HandleGraphicsApiSelection() m_gx2drawdone_sync->Enable(); m_async_compile->Disable(); +#if ENABLE_METAL m_force_mesh_shaders->Disable(); +#endif } else if (m_graphic_api->GetSelection() == 1) { // Vulkan m_gx2drawdone_sync->Disable(); m_async_compile->Enable(); +#if ENABLE_METAL m_force_mesh_shaders->Disable(); +#endif m_vsync->AppendString(_("Off")); m_vsync->AppendString(_("Double buffering")); @@ -1750,6 +1762,7 @@ void GeneralSettings2::HandleGraphicsApiSelection() } } } +#if ENABLE_METAL else { // Metal @@ -1764,8 +1777,8 @@ void GeneralSettings2::HandleGraphicsApiSelection() m_graphic_device->Enable(); m_graphic_device->Clear(); -#if ENABLE_METAL - auto devices = MetalRenderer::GetDevices(); + + auto devices = MetalRenderer::GetDevices(); if(!devices.empty()) { for (const auto& device : devices) @@ -1784,8 +1797,8 @@ void GeneralSettings2::HandleGraphicsApiSelection() } } } -#endif } +#endif } void GeneralSettings2::ApplyConfig() @@ -1852,7 +1865,9 @@ void GeneralSettings2::ApplyConfig() } m_async_compile->SetValue(config.async_compile); m_gx2drawdone_sync->SetValue(config.gx2drawdone_sync); +#if ENABLE_METAL m_force_mesh_shaders->SetValue(config.force_mesh_shaders); +#endif m_upscale_filter->SetSelection(config.upscale_filter); m_downscale_filter->SetSelection(config.downscale_filter); m_fullscreen_scaling->SetSelection(config.fullscreen_scaling); @@ -1989,8 +2004,10 @@ void GeneralSettings2::ApplyConfig() // debug m_crash_dump->SetSelection((int)config.crash_dump.GetValue()); m_gdb_port->SetValue(config.gdb_port.GetValue()); +#if ENABLE_METAL m_gpu_capture_dir->SetValue(wxString::FromUTF8(config.gpu_capture_dir.GetValue())); m_framebuffer_fetch->SetValue(config.framebuffer_fetch); +#endif } void GeneralSettings2::OnAudioAPISelected(wxCommandEvent& event) diff --git a/src/gui/wxgui/GeneralSettings2.h b/src/gui/wxgui/GeneralSettings2.h index b9f0be2a..e20a3371 100644 --- a/src/gui/wxgui/GeneralSettings2.h +++ b/src/gui/wxgui/GeneralSettings2.h @@ -61,7 +61,10 @@ private: wxSpinCtrlDouble* m_userDisplayGamma; wxCheckBox* m_userDisplayisSRGB; - wxCheckBox *m_async_compile, *m_gx2drawdone_sync, *m_force_mesh_shaders; + wxCheckBox *m_async_compile, *m_gx2drawdone_sync; +#if ENABLE_METAL + wxCheckBox *m_force_mesh_shaders; +#endif 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; @@ -87,8 +90,10 @@ private: // Debug wxChoice* m_crash_dump; wxSpinCtrl* m_gdb_port; +#if ENABLE_METAL wxTextCtrl* m_gpu_capture_dir; wxCheckBox* m_framebuffer_fetch; +#endif void OnAccountCreate(wxCommandEvent& event); void OnAccountDelete(wxCommandEvent& event); diff --git a/src/gui/wxgui/MainWindow.cpp b/src/gui/wxgui/MainWindow.cpp index 48c36fef..20372326 100644 --- a/src/gui/wxgui/MainWindow.cpp +++ b/src/gui/wxgui/MainWindow.cpp @@ -2327,8 +2327,10 @@ void MainWindow::RecreateMenu() auto accurateBarriers = debugMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_VK_ACCURATE_BARRIERS, _("&Accurate barriers (Vulkan)"), wxEmptyString); accurateBarriers->Check(GetConfig().vk_accurate_barriers); - auto gpuCapture = debugMenu->Append(MAINFRAME_MENU_ID_DEBUG_GPU_CAPTURE, _("&GPU capture (Metal)")); - gpuCapture->Enable(m_game_launched && g_renderer->GetType() == RendererAPI::Metal); +#if ENABLE_METAL + auto gpuCapture = debugMenu->Append(MAINFRAME_MENU_ID_DEBUG_GPU_CAPTURE, _("&GPU capture (Metal)")); + gpuCapture->Enable(m_game_launched && g_renderer->GetType() == RendererAPI::Metal); +#endif debugMenu->AppendSeparator();