From 901bf9c257347c91101ca25e74037684dd519968 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 13 Jun 2017 20:07:09 +1000 Subject: [PATCH] VideoConfig: Add config options for ubershaders --- .../ui/settings/SettingsAdapter.java | 31 ++++++++++++++ .../settings/SettingsFragmentPresenter.java | 27 ++++++++++++ .../dolphinemu/utils/SettingsFile.java | 3 ++ .../app/src/main/res/values/arrays.xml | 12 ++++++ .../app/src/main/res/values/strings.xml | 2 + Source/Core/Core/Config/GraphicsSettings.cpp | 12 ++++++ Source/Core/Core/Config/GraphicsSettings.h | 6 +++ .../Core/ConfigLoaders/IsSettingSaveable.cpp | 4 ++ Source/Core/DolphinWX/VideoConfigDiag.cpp | 41 +++++++++++++++++++ Source/Core/DolphinWX/VideoConfigDiag.h | 1 + Source/Core/VideoCommon/VideoConfig.cpp | 35 ++++++++++++++++ Source/Core/VideoCommon/VideoConfig.h | 33 +++++++++++++++ 12 files changed, 207 insertions(+) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java index 02d36db513..0887a7e68e 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java @@ -274,6 +274,10 @@ public final class SettingsAdapter extends RecyclerView.Adapter sl) { + int uberShaderModeValue = getUberShaderModeValue(); + Setting resolution = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_INTERNAL_RES); Setting fsaa = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_FSAA); Setting anisotropic = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_ANISOTROPY); @@ -283,6 +285,7 @@ public final class SettingsFragmentPresenter Setting perPixel = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_PER_PIXEL); Setting forceFilter = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_FORCE_FILTERING); Setting disableFog = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_FOG); + IntSetting uberShaderMode = new IntSetting(SettingsFile.KEY_UBERSHADER_MODE, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, uberShaderModeValue); sl.add(new SingleChoiceSetting(SettingsFile.KEY_INTERNAL_RES, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.internal_resolution, R.string.internal_resolution_descrip, R.array.internalResolutionEntries, R.array.internalResolutionValues, 0, resolution)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_FSAA, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.FSAA, R.string.FSAA_descrip, R.array.FSAAEntries, R.array.FSAAValues, 0, fsaa)); @@ -296,6 +299,7 @@ public final class SettingsFragmentPresenter sl.add(new CheckBoxSetting(SettingsFile.KEY_PER_PIXEL, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.per_pixel_lighting, R.string.per_pixel_lighting_descrip, false, perPixel)); sl.add(new CheckBoxSetting(SettingsFile.KEY_FORCE_FILTERING, SettingsFile.SECTION_GFX_ENHANCEMENTS, SettingsFile.SETTINGS_GFX, R.string.force_texture_filtering, R.string.force_texture_filtering_descrip, false, forceFilter)); sl.add(new CheckBoxSetting(SettingsFile.KEY_DISABLE_FOG, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.disable_fog, R.string.disable_fog_descrip, false, disableFog)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_UBERSHADER_MODE, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.ubershader_mode, R.string.ubershader_mode_descrip, R.array.uberShaderModeEntries, R.array.uberShaderModeValues, 0, uberShaderMode)); /* Check if we support stereo @@ -903,6 +907,29 @@ public final class SettingsFragmentPresenter return xfbValue; } + private int getUberShaderModeValue() + { + int uberShaderModeValue = 0; + + try + { + boolean backgroundShaderCompiling = ((BooleanSetting) mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_BACKGROUND_SHADER_COMPILING)).getValue(); + boolean disableSpecializedShaders = ((BooleanSetting) mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_SPECIALIZED_SHADERS)).getValue(); + + if (disableSpecializedShaders) + uberShaderModeValue = 2; // Exclusive + else if (backgroundShaderCompiling) + uberShaderModeValue = 1; // Hybrid + else + uberShaderModeValue = 0; // Disabled + } + catch (NullPointerException ex) + { + } + + return uberShaderModeValue; + } + private int getExtensionValue(int wiimoteNumber) { int extensionValue; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java index e8d1cb1b8d..205fffce6c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java @@ -79,6 +79,9 @@ public final class SettingsFile public static final String KEY_XFB_REAL = "UseRealXFB"; public static final String KEY_FAST_DEPTH = "FastDepthCalc"; public static final String KEY_ASPECT_RATIO = "AspectRatio"; + public static final String KEY_UBERSHADER_MODE = "UberShaderMode"; + public static final String KEY_DISABLE_SPECIALIZED_SHADERS = "DisableSpecializedShaders"; + public static final String KEY_BACKGROUND_SHADER_COMPILING = "BackgroundShaderCompiling"; public static final String KEY_GCPAD_TYPE = "SIDevice"; diff --git a/Source/Android/app/src/main/res/values/arrays.xml b/Source/Android/app/src/main/res/values/arrays.xml index 42b5409884..deeba91df3 100644 --- a/Source/Android/app/src/main/res/values/arrays.xml +++ b/Source/Android/app/src/main/res/values/arrays.xml @@ -89,6 +89,18 @@ 2 + + + Disabled + Hybrid + Exclusive + + + 0 + 1 + 2 + + 1x Native (640x528) diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 292a5e7172..0996b2515d 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -179,6 +179,8 @@ Uses a less accurate algorithm to calculate depth values. Aspect Ratio Select what aspect ratio to use when rendering + Ubershader Mode + Specifies when to use Ubershaders. Disabled - Never, Hybrid - Use ubershaders while compiling specialized shaders. Exclusive - Use only ubershaders, largest performance impact. Yes diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index f467c8e911..c827ff3ab8 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -77,6 +77,18 @@ const ConfigInfo GFX_BACKEND_MULTITHREADING{ const ConfigInfo GFX_COMMAND_BUFFER_EXECUTE_INTERVAL{ {System::GFX, "Settings", "CommandBufferExecuteInterval"}, 100}; const ConfigInfo GFX_SHADER_CACHE{{System::GFX, "Settings", "ShaderCache"}, true}; +const ConfigInfo GFX_BACKGROUND_SHADER_COMPILING{ + {System::GFX, "Settings", "BackgroundShaderCompiling"}, false}; +const ConfigInfo GFX_DISABLE_SPECIALIZED_SHADERS{ + {System::GFX, "Settings", "DisableSpecializedShaders"}, false}; +const ConfigInfo GFX_PRECOMPILE_UBER_SHADERS{ + {System::GFX, "Settings", "PrecompileUberShaders"}, true}; +const ConfigInfo GFX_SHADER_COMPILER_THREADS{ + {System::GFX, "Settings", "ShaderCompilerThreads"}, 1}; +const ConfigInfo GFX_FORCE_VERTEX_UBER_SHADERS{ + {System::GFX, "Settings", "ForceVertexUberShaders"}, false}; +const ConfigInfo GFX_FORCE_PIXEL_UBER_SHADERS{ + {System::GFX, "Settings", "ForcePixelUberShaders"}, false}; const ConfigInfo GFX_SW_ZCOMPLOC{{System::GFX, "Settings", "SWZComploc"}, true}; const ConfigInfo GFX_SW_ZFREEZE{{System::GFX, "Settings", "SWZFreeze"}, true}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index af2cf8ed1d..42f4b52bd0 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -59,6 +59,12 @@ extern const ConfigInfo GFX_ENABLE_VALIDATION_LAYER; extern const ConfigInfo GFX_BACKEND_MULTITHREADING; extern const ConfigInfo GFX_COMMAND_BUFFER_EXECUTE_INTERVAL; extern const ConfigInfo GFX_SHADER_CACHE; +extern const ConfigInfo GFX_BACKGROUND_SHADER_COMPILING; +extern const ConfigInfo GFX_DISABLE_SPECIALIZED_SHADERS; +extern const ConfigInfo GFX_PRECOMPILE_UBER_SHADERS; +extern const ConfigInfo GFX_SHADER_COMPILER_THREADS; +extern const ConfigInfo GFX_FORCE_VERTEX_UBER_SHADERS; +extern const ConfigInfo GFX_FORCE_PIXEL_UBER_SHADERS; extern const ConfigInfo GFX_SW_ZCOMPLOC; extern const ConfigInfo GFX_SW_ZFREEZE; diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index 38ea90710f..76a93aad55 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -43,6 +43,10 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) Config::GFX_DISABLE_FOG.location, Config::GFX_BORDERLESS_FULLSCREEN.location, Config::GFX_ENABLE_VALIDATION_LAYER.location, Config::GFX_BACKEND_MULTITHREADING.location, Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL.location, Config::GFX_SHADER_CACHE.location, + Config::GFX_BACKGROUND_SHADER_COMPILING.location, + Config::GFX_DISABLE_SPECIALIZED_SHADERS.location, + Config::GFX_PRECOMPILE_UBER_SHADERS.location, Config::GFX_SHADER_COMPILER_THREADS.location, + Config::GFX_FORCE_VERTEX_UBER_SHADERS.location, Config::GFX_FORCE_PIXEL_UBER_SHADERS.location, Config::GFX_SW_ZCOMPLOC.location, Config::GFX_SW_ZFREEZE.location, Config::GFX_SW_DUMP_OBJECTS.location, Config::GFX_SW_DUMP_TEV_STAGES.location, diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 19af19461e..4ced1d69ae 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -308,6 +308,14 @@ static wxString gpu_texture_decoding_desc = wxTRANSLATE("Enables texture decoding using the GPU instead of the CPU. This may result in " "performance gains in some scenarios, or on systems where the CPU is the " "bottleneck.\n\nIf unsure, leave this unchecked."); +static wxString ubershader_desc = + wxTRANSLATE("Disabled: Ubershaders are never used. Stuttering will occur during shader " + "compilation, but GPU demands are low. Recommended for low-end hardware.\n\n" + "Hybrid: Ubershaders will be used to prevent stuttering during shader " + "compilation, but traditional shaders will be used when they will not cause " + "stuttering. Balances performance and smoothness.\n\n" + "Exclusive: Ubershaders will always be used. Only recommended for high-end " + "systems."); VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) : wxDialog(parent, wxID_ANY, wxString::Format(_("Dolphin %s Graphics Configuration"), @@ -561,6 +569,29 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) row += 1; } + // ubershaders + { + const std::array mode_choices = {{_("Disabled"), _("Hybrid"), _("Exclusive")}}; + + wxChoice* const choice_mode = + new wxChoice(page_enh, wxID_ANY, wxDefaultPosition, wxDefaultSize, + static_cast(mode_choices.size()), mode_choices.data()); + RegisterControl(choice_mode, wxGetTranslation(ubershader_desc)); + szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Ubershaders:")), wxGBPosition(row, 0), + wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + szr_enh->Add(choice_mode, wxGBPosition(row, 1), span2, wxALIGN_CENTER_VERTICAL); + row += 1; + + // Determine ubershader mode + choice_mode->Bind(wxEVT_CHOICE, &VideoConfigDiag::OnUberShaderModeChanged, this); + if (Config::GetBase(Config::GFX_DISABLE_SPECIALIZED_SHADERS)) + choice_mode->SetSelection(2); + else if (Config::GetBase(Config::GFX_BACKGROUND_SHADER_COMPILING)) + choice_mode->SetSelection(1); + else + choice_mode->SetSelection(0); + } + // postproc shader if (vconfig.backend_info.bSupportsPostProcessing) { @@ -1326,3 +1357,13 @@ void VideoConfigDiag::OnAAChanged(wxCommandEvent& ev) Config::SetBaseOrCurrent(Config::GFX_MSAA, vconfig.backend_info.AAModes[mode]); } + +void VideoConfigDiag::OnUberShaderModeChanged(wxCommandEvent& ev) +{ + // 0: No ubershaders + // 1: Hybrid ubershaders + // 2: Only ubershaders + int mode = ev.GetInt(); + Config::SetBaseOrCurrent(Config::GFX_BACKGROUND_SHADER_COMPILING, mode == 1); + Config::SetBaseOrCurrent(Config::GFX_DISABLE_SPECIALIZED_SHADERS, mode == 2); +} diff --git a/Source/Core/DolphinWX/VideoConfigDiag.h b/Source/Core/DolphinWX/VideoConfigDiag.h index 431b6cdae9..1730b19090 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/VideoConfigDiag.h @@ -140,6 +140,7 @@ protected: void PopulatePostProcessingShaders(); void PopulateAAList(); void OnAAChanged(wxCommandEvent& ev); + void OnUberShaderModeChanged(wxCommandEvent& ev); wxChoice* choice_backend; wxChoice* choice_adapter; diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 355d2486b4..96ec61d596 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -4,6 +4,7 @@ #include +#include "Common/CPUDetect.h" #include "Common/CommonTypes.h" #include "Common/StringUtil.h" #include "Core/Config/GraphicsSettings.h" @@ -93,6 +94,12 @@ void VideoConfig::Refresh() bBackendMultithreading = Config::Get(Config::GFX_BACKEND_MULTITHREADING); iCommandBufferExecuteInterval = Config::Get(Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL); bShaderCache = Config::Get(Config::GFX_SHADER_CACHE); + bBackgroundShaderCompiling = Config::Get(Config::GFX_BACKGROUND_SHADER_COMPILING); + bDisableSpecializedShaders = Config::Get(Config::GFX_DISABLE_SPECIALIZED_SHADERS); + bPrecompileUberShaders = Config::Get(Config::GFX_PRECOMPILE_UBER_SHADERS); + iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS); + bForceVertexUberShaders = Config::Get(Config::GFX_FORCE_VERTEX_UBER_SHADERS); + bForcePixelUberShaders = Config::Get(Config::GFX_FORCE_PIXEL_UBER_SHADERS); bZComploc = Config::Get(Config::GFX_SW_ZCOMPLOC); bZFreeze = Config::Get(Config::GFX_SW_ZFREEZE); @@ -188,3 +195,31 @@ bool VideoConfig::IsVSync() { return bVSync && !Core::GetIsThrottlerTempDisabled(); } + +u32 VideoConfig::GetShaderCompilerThreads() const +{ + if (iShaderCompilerThreads >= 0) + return static_cast(iShaderCompilerThreads); + + // Automatic number. We use clamp(cpus - 3, 1, 4). + return static_cast(std::min(std::max(cpu_info.num_cores - 3, 1), 4)); +} + +bool VideoConfig::CanUseUberShaders() const +{ + // Ubershaders are currently incompatible with per-pixel lighting. + return !bEnablePixelLighting; +} + +bool VideoConfig::CanPrecompileUberShaders() const +{ + // We don't want to precompile ubershaders if they're never going to be used. + return bPrecompileUberShaders && (bBackgroundShaderCompiling || bDisableSpecializedShaders) && + CanUseUberShaders(); +} + +bool VideoConfig::CanBackgroundCompileShaders() const +{ + // We require precompiled ubershaders to background compile shaders. + return bBackgroundShaderCompiling && bPrecompileUberShaders && CanUseUberShaders(); +} diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index e6cbfde566..a8a4d9358d 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -168,6 +168,35 @@ struct VideoConfig final // Currently only supported with Vulkan. int iCommandBufferExecuteInterval; + // The following options determine the ubershader mode: + // No ubershaders: + // - bBackgroundShaderCompiling = false + // - bDisableSpecializedShaders = false + // Hybrid/background compiling: + // - bBackgroundShaderCompiling = true + // - bDisableSpecializedShaders = false + // Ubershaders only: + // - bBackgroundShaderCompiling = false + // - bDisableSpecializedShaders = true + + // Enable background shader compiling, use ubershaders while waiting. + bool bBackgroundShaderCompiling; + + // Use ubershaders only, don't compile specialized shaders. + bool bDisableSpecializedShaders; + + // Precompile ubershader variants at boot/config reload time. + bool bPrecompileUberShaders; + + // Number of shader compiler threads. + // 0 disables background compilation. + // -1 uses an automatic number based on the CPU threads. + int iShaderCompilerThreads; + + // Temporary toggling of ubershaders, for debugging + bool bForceVertexUberShaders; + bool bForcePixelUberShaders; + // Static config per API // TODO: Move this out of VideoConfig struct @@ -226,6 +255,10 @@ struct VideoConfig final return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding; } bool UseVertexRounding() const { return bVertexRounding && iEFBScale != SCALE_1X; } + u32 GetShaderCompilerThreads() const; + bool CanUseUberShaders() const; + bool CanPrecompileUberShaders() const; + bool CanBackgroundCompileShaders() const; }; extern VideoConfig g_Config;