Implement "Skip" ubershader mode

Skip ubershader mode works the same as hybrid ubershaders in that the
shaders are compiled asynchronously. However, instead of using the
ubershader to draw the object, it skips it entirely until the
specialized shader is made available.

This mode will likely result in broken effects where a game creates an
EFB copy, and does not redraw it every frame. Therefore, it is not a
recommended option, however, it may result in better performance on
low-end systems.
This commit is contained in:
Stenzek 2018-03-16 23:10:22 +10:00
parent 5c83e18fbd
commit 2f1a7cbee1
22 changed files with 292 additions and 127 deletions

View File

@ -259,10 +259,14 @@ public final class SettingsFragmentPresenter
{ {
IntSetting videoBackend = new IntSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, getVideoBackendValue()); IntSetting videoBackend = new IntSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, getVideoBackendValue());
Setting showFps = null; Setting showFps = null;
Setting shaderCompilationMode = null;
Setting waitForShaders = null;
if (!mSettings.get(SettingsFile.SETTINGS_GFX).isEmpty()) if (!mSettings.get(SettingsFile.SETTINGS_GFX).isEmpty())
{ {
showFps = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_SHOW_FPS); showFps = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_SHOW_FPS);
shaderCompilationMode = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_SHADER_COMPILATION_MODE);
waitForShaders = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_WAIT_FOR_SHADERS);
} }
else else
{ {
@ -276,6 +280,8 @@ public final class SettingsFragmentPresenter
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.video_backend, R.string.video_backend_descrip, R.array.videoBackendEntries, R.array.videoBackendValues, 0, videoBackend)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_VIDEO_BACKEND_INDEX, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.video_backend, R.string.video_backend_descrip, R.array.videoBackendEntries, R.array.videoBackendValues, 0, videoBackend));
sl.add(new CheckBoxSetting(SettingsFile.KEY_SHOW_FPS, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.show_fps, 0, false, showFps)); sl.add(new CheckBoxSetting(SettingsFile.KEY_SHOW_FPS, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.show_fps, 0, false, showFps));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_SHADER_COMPILATION_MODE, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.shader_compilation_mode, R.string.shader_compilation_mode_descrip, R.array.shaderCompilationModeEntries, R.array.shaderCompilationModeValues, 0, shaderCompilationMode));
sl.add(new CheckBoxSetting(SettingsFile.KEY_WAIT_FOR_SHADERS, SettingsFile.SECTION_GFX_SETTINGS, SettingsFile.SETTINGS_GFX, R.string.wait_for_shaders, 0, false, waitForShaders));
sl.add(new SubmenuSetting(null, null, R.string.enhancements, 0, SettingsFile.SECTION_GFX_ENHANCEMENTS)); sl.add(new SubmenuSetting(null, null, R.string.enhancements, 0, SettingsFile.SECTION_GFX_ENHANCEMENTS));
sl.add(new SubmenuSetting(null, null, R.string.hacks, 0, SettingsFile.SECTION_GFX_HACKS)); sl.add(new SubmenuSetting(null, null, R.string.hacks, 0, SettingsFile.SECTION_GFX_HACKS));
@ -290,7 +296,8 @@ public final class SettingsFragmentPresenter
Setting perPixel = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_PER_PIXEL); 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 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); Setting disableFog = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_FOG);
Setting uberShaderMode = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_UBERSHADER_MODE); Setting shaderCompilationMode = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_SHADER_COMPILATION_MODE);
Setting waitForShaders = mSettings.get(SettingsFile.SETTINGS_GFX).get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_WAIT_FOR_SHADERS);
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_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)); 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));
@ -304,7 +311,6 @@ 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_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_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 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 Check if we support stereo

View File

@ -107,7 +107,8 @@ public final class SettingsFile
public static final String KEY_IMMEDIATE_XFB = "ImmediateXFBEnable"; public static final String KEY_IMMEDIATE_XFB = "ImmediateXFBEnable";
public static final String KEY_FAST_DEPTH = "FastDepthCalc"; public static final String KEY_FAST_DEPTH = "FastDepthCalc";
public static final String KEY_ASPECT_RATIO = "AspectRatio"; public static final String KEY_ASPECT_RATIO = "AspectRatio";
public static final String KEY_UBERSHADER_MODE = "UberShaderMode"; public static final String KEY_SHADER_COMPILATION_MODE = "ShaderCompilationMode";
public static final String KEY_WAIT_FOR_SHADERS = "WaitForShadersBeforeStarting";
public static final String KEY_GCPAD_TYPE = "SIDevice"; public static final String KEY_GCPAD_TYPE = "SIDevice";

View File

@ -92,15 +92,17 @@
</integer-array> </integer-array>
<!-- Ubershader Mode Preference --> <!-- Ubershader Mode Preference -->
<string-array name="uberShaderModeEntries" translatable="false"> <string-array name="shaderCompilationModeEntries" translatable="false">
<item>Disabled</item> <item>Synchronous</item>
<item>Hybrid</item> <item>Synchronous (Ubershaders)</item>
<item>Exclusive</item> <item>Asynchronous (Ubershaders)</item>
<item>Asynchronous (Skip Drawing)</item>
</string-array> </string-array>
<integer-array name="uberShaderModeValues" translatable="false"> <integer-array name="shaderCompilationModeValues" translatable="false">
<item>0</item> <item>0</item>
<item>1</item> <item>1</item>
<item>2</item> <item>2</item>
<item>3</item>
</integer-array> </integer-array>
<!-- Internal Resolution Preference --> <!-- Internal Resolution Preference -->

View File

@ -184,8 +184,9 @@
<string name="fast_depth_calculation_descrip">Uses a less accurate algorithm to calculate depth values.</string> <string name="fast_depth_calculation_descrip">Uses a less accurate algorithm to calculate depth values.</string>
<string name="aspect_ratio">Aspect Ratio</string> <string name="aspect_ratio">Aspect Ratio</string>
<string name="aspect_ratio_descrip">Select what aspect ratio to use when rendering</string> <string name="aspect_ratio_descrip">Select what aspect ratio to use when rendering</string>
<string name="ubershader_mode">Ubershader Mode</string> <string name="shader_compilation_mode">Shader Compilation Mode</string>
<string name="ubershader_mode_descrip">Specifies when to use Ubershaders. Disabled - Never, Hybrid - Use ubershaders while compiling specialized shaders. Exclusive - Use only ubershaders, largest performance impact.</string> <string name="shader_compilation_mode_descrip">Specifies when to use Ubershaders. Disabled - Never, Hybrid - Use ubershaders while compiling specialized shaders. Exclusive - Use only ubershaders, largest performance impact. Skip Drawing - Do not draw objects while shaders are compiling, will cause broken effects.</string>
<string name="wait_for_shaders">Compile Shaders Before Starting</string>
<!-- Miscellaneous --> <!-- Miscellaneous -->
<string name="yes">Yes</string> <string name="yes">Yes</string>

View File

@ -178,17 +178,19 @@ void DolphinAnalytics::MakeBaseBuilder()
m_base_builder = builder; m_base_builder = builder;
} }
static const char* GetUbershaderMode(const VideoConfig& video_config) static const char* GetShaderCompilationMode(const VideoConfig& video_config)
{ {
switch (video_config.iUberShaderMode) switch (video_config.iShaderCompilationMode)
{ {
case UberShaderMode::Exclusive: case ShaderCompilationMode::AsynchronousUberShaders:
return "exclusive"; return "async-ubershaders";
case UberShaderMode::Hybrid: case ShaderCompilationMode::AsynchronousSkipRendering:
return "hybrid"; return "async-skip-rendering";
case UberShaderMode::Disabled: case ShaderCompilationMode::SynchronousUberShaders:
return "sync-ubershaders";
case ShaderCompilationMode::Synchronous:
default: default:
return "disabled"; return "sync";
} }
} }
@ -234,7 +236,8 @@ void DolphinAnalytics::MakePerGameBuilder()
builder.AddData("cfg-gfx-tc-samples", g_Config.iSafeTextureCache_ColorSamples); builder.AddData("cfg-gfx-tc-samples", g_Config.iSafeTextureCache_ColorSamples);
builder.AddData("cfg-gfx-stereo-mode", static_cast<int>(g_Config.stereo_mode)); builder.AddData("cfg-gfx-stereo-mode", static_cast<int>(g_Config.stereo_mode));
builder.AddData("cfg-gfx-per-pixel-lighting", g_Config.bEnablePixelLighting); builder.AddData("cfg-gfx-per-pixel-lighting", g_Config.bEnablePixelLighting);
builder.AddData("cfg-gfx-ubershader-mode", GetUbershaderMode(g_Config)); builder.AddData("cfg-gfx-shader-compilation-mode", GetShaderCompilationMode(g_Config));
builder.AddData("cfg-gfx-wait-for-shaders", g_Config.bWaitForShadersBeforeStarting);
builder.AddData("cfg-gfx-fast-depth", g_Config.bFastDepthCalc); builder.AddData("cfg-gfx-fast-depth", g_Config.bFastDepthCalc);
builder.AddData("cfg-gfx-vertex-rounding", g_Config.UseVertexRounding()); builder.AddData("cfg-gfx-vertex-rounding", g_Config.UseVertexRounding());

View File

@ -78,8 +78,9 @@ const ConfigInfo<int> GFX_COMMAND_BUFFER_EXECUTE_INTERVAL{
const ConfigInfo<bool> GFX_SHADER_CACHE{{System::GFX, "Settings", "ShaderCache"}, true}; const ConfigInfo<bool> GFX_SHADER_CACHE{{System::GFX, "Settings", "ShaderCache"}, true};
const ConfigInfo<bool> GFX_WAIT_FOR_SHADERS_BEFORE_STARTING{ const ConfigInfo<bool> GFX_WAIT_FOR_SHADERS_BEFORE_STARTING{
{System::GFX, "Settings", "WaitForShadersBeforeStarting"}, false}; {System::GFX, "Settings", "WaitForShadersBeforeStarting"}, false};
const ConfigInfo<int> GFX_UBERSHADER_MODE{{System::GFX, "Settings", "UberShaderMode"}, const ConfigInfo<int> GFX_SHADER_COMPILATION_MODE{
static_cast<int>(UberShaderMode::Disabled)}; {System::GFX, "Settings", "ShaderCompilationMode"},
static_cast<int>(ShaderCompilationMode::Synchronous)};
const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS{ const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS{
{System::GFX, "Settings", "ShaderCompilerThreads"}, 1}; {System::GFX, "Settings", "ShaderCompilerThreads"}, 1};
const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS{ const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS{

View File

@ -60,7 +60,7 @@ extern const ConfigInfo<bool> GFX_BACKEND_MULTITHREADING;
extern const ConfigInfo<int> GFX_COMMAND_BUFFER_EXECUTE_INTERVAL; extern const ConfigInfo<int> GFX_COMMAND_BUFFER_EXECUTE_INTERVAL;
extern const ConfigInfo<bool> GFX_SHADER_CACHE; extern const ConfigInfo<bool> GFX_SHADER_CACHE;
extern const ConfigInfo<bool> GFX_WAIT_FOR_SHADERS_BEFORE_STARTING; extern const ConfigInfo<bool> GFX_WAIT_FOR_SHADERS_BEFORE_STARTING;
extern const ConfigInfo<int> GFX_UBERSHADER_MODE; extern const ConfigInfo<int> GFX_SHADER_COMPILATION_MODE;
extern const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS; extern const ConfigInfo<int> GFX_SHADER_COMPILER_THREADS;
extern const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS; extern const ConfigInfo<int> GFX_SHADER_PRECOMPILER_THREADS;

View File

@ -46,8 +46,9 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
Config::GFX_DISABLE_FOG.location, Config::GFX_BORDERLESS_FULLSCREEN.location, Config::GFX_DISABLE_FOG.location, Config::GFX_BORDERLESS_FULLSCREEN.location,
Config::GFX_ENABLE_VALIDATION_LAYER.location, Config::GFX_BACKEND_MULTITHREADING.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_COMMAND_BUFFER_EXECUTE_INTERVAL.location, Config::GFX_SHADER_CACHE.location,
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING.location, Config::GFX_UBERSHADER_MODE.location, Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING.location,
Config::GFX_SHADER_COMPILER_THREADS.location, Config::GFX_SHADER_PRECOMPILER_THREADS.location, Config::GFX_SHADER_COMPILATION_MODE.location, Config::GFX_SHADER_COMPILER_THREADS.location,
Config::GFX_SHADER_PRECOMPILER_THREADS.location,
Config::GFX_SW_ZCOMPLOC.location, Config::GFX_SW_ZFREEZE.location, Config::GFX_SW_ZCOMPLOC.location, Config::GFX_SW_ZFREEZE.location,
Config::GFX_SW_DUMP_OBJECTS.location, Config::GFX_SW_DUMP_TEV_STAGES.location, Config::GFX_SW_DUMP_OBJECTS.location, Config::GFX_SW_DUMP_TEV_STAGES.location,

View File

@ -45,6 +45,7 @@ set(SRCS
Config/Graphics/HacksWidget.cpp Config/Graphics/HacksWidget.cpp
Config/Graphics/GraphicsBool.cpp Config/Graphics/GraphicsBool.cpp
Config/Graphics/GraphicsChoice.cpp Config/Graphics/GraphicsChoice.cpp
Config/Graphics/GraphicsRadio.cpp
Config/Graphics/GraphicsSlider.cpp Config/Graphics/GraphicsSlider.cpp
Config/Graphics/GraphicsWidget.cpp Config/Graphics/GraphicsWidget.cpp
Config/Graphics/GraphicsWindow.cpp Config/Graphics/GraphicsWindow.cpp

View File

@ -63,9 +63,6 @@ void EnhancementsWidget::CreateWidgets()
m_af_combo = new GraphicsChoice({tr("1x"), tr("2x"), tr("4x"), tr("8x"), tr("16x")}, m_af_combo = new GraphicsChoice({tr("1x"), tr("2x"), tr("4x"), tr("8x"), tr("16x")},
Config::GFX_ENHANCE_MAX_ANISOTROPY); Config::GFX_ENHANCE_MAX_ANISOTROPY);
m_ubershader_combo = new GraphicsChoice({tr("Disabled"), tr("Hybrid"), tr("Exclusive")},
Config::GFX_UBERSHADER_MODE);
m_pp_effect = new QComboBox(); m_pp_effect = new QComboBox();
m_configure_pp_effect = new QPushButton(tr("Configure")); m_configure_pp_effect = new QPushButton(tr("Configure"));
m_scaled_efb_copy = new GraphicsBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED); m_scaled_efb_copy = new GraphicsBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED);
@ -85,9 +82,6 @@ void EnhancementsWidget::CreateWidgets()
enhancements_layout->addWidget(new QLabel(tr("Anisotropic Filtering:")), 2, 0); enhancements_layout->addWidget(new QLabel(tr("Anisotropic Filtering:")), 2, 0);
enhancements_layout->addWidget(m_af_combo, 2, 1, 1, -1); enhancements_layout->addWidget(m_af_combo, 2, 1, 1, -1);
enhancements_layout->addWidget(new QLabel(tr("Ubershaders:")), 3, 0);
enhancements_layout->addWidget(m_ubershader_combo, 3, 1, 1, -1);
enhancements_layout->addWidget(new QLabel(tr("Post-Processing Effect:")), 4, 0); enhancements_layout->addWidget(new QLabel(tr("Post-Processing Effect:")), 4, 0);
enhancements_layout->addWidget(m_pp_effect, 4, 1); enhancements_layout->addWidget(m_pp_effect, 4, 1);
enhancements_layout->addWidget(m_configure_pp_effect, 4, 2); enhancements_layout->addWidget(m_configure_pp_effect, 4, 2);
@ -243,15 +237,6 @@ void EnhancementsWidget::AddDescriptions()
"Enable anisotropic filtering.\nEnhances visual quality of textures that are at oblique " "Enable anisotropic filtering.\nEnhances visual quality of textures that are at oblique "
"viewing angles.\nMight cause issues in a small number of games.\n\nIf unsure, select 1x."); "viewing angles.\nMight cause issues in a small number of games.\n\nIf unsure, select 1x.");
static const char* TR_UBERSHADER_DESCRIPTION =
QT_TR_NOOP("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.");
static const char* TR_POSTPROCESSING_DESCRIPTION = QT_TR_NOOP( static const char* TR_POSTPROCESSING_DESCRIPTION = QT_TR_NOOP(
"Apply a post-processing effect after finishing a frame.\n\nIf unsure, select (off)."); "Apply a post-processing effect after finishing a frame.\n\nIf unsure, select (off).");
@ -303,7 +288,6 @@ void EnhancementsWidget::AddDescriptions()
AddDescription(m_ir_combo, TR_INTERNAL_RESOLUTION_DESCRIPTION); AddDescription(m_ir_combo, TR_INTERNAL_RESOLUTION_DESCRIPTION);
AddDescription(m_aa_combo, TR_ANTIALIAS_DESCRIPTION); AddDescription(m_aa_combo, TR_ANTIALIAS_DESCRIPTION);
AddDescription(m_af_combo, TR_ANISOTROPIC_FILTERING_DESCRIPTION); AddDescription(m_af_combo, TR_ANISOTROPIC_FILTERING_DESCRIPTION);
AddDescription(m_ubershader_combo, TR_UBERSHADER_DESCRIPTION);
AddDescription(m_pp_effect, TR_POSTPROCESSING_DESCRIPTION); AddDescription(m_pp_effect, TR_POSTPROCESSING_DESCRIPTION);
AddDescription(m_scaled_efb_copy, TR_SCALED_EFB_COPY_DESCRIPTION); AddDescription(m_scaled_efb_copy, TR_SCALED_EFB_COPY_DESCRIPTION);
AddDescription(m_per_pixel_lighting, TR_PER_PIXEL_LIGHTING_DESCRIPTION); AddDescription(m_per_pixel_lighting, TR_PER_PIXEL_LIGHTING_DESCRIPTION);

View File

@ -30,7 +30,6 @@ private:
QComboBox* m_ir_combo; QComboBox* m_ir_combo;
QComboBox* m_aa_combo; QComboBox* m_aa_combo;
QComboBox* m_af_combo; QComboBox* m_af_combo;
QComboBox* m_ubershader_combo;
QComboBox* m_pp_effect; QComboBox* m_pp_effect;
QPushButton* m_configure_pp_effect; QPushButton* m_configure_pp_effect;
QCheckBox* m_scaled_efb_copy; QCheckBox* m_scaled_efb_copy;

View File

@ -11,6 +11,7 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QMessageBox> #include <QMessageBox>
#include <QRadioButton>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "Core/Config/GraphicsSettings.h" #include "Core/Config/GraphicsSettings.h"
@ -18,6 +19,7 @@
#include "Core/Core.h" #include "Core/Core.h"
#include "DolphinQt2/Config/Graphics/GraphicsBool.h" #include "DolphinQt2/Config/Graphics/GraphicsBool.h"
#include "DolphinQt2/Config/Graphics/GraphicsChoice.h" #include "DolphinQt2/Config/Graphics/GraphicsChoice.h"
#include "DolphinQt2/Config/Graphics/GraphicsRadio.h"
#include "DolphinQt2/Config/Graphics/GraphicsWindow.h" #include "DolphinQt2/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt2/Settings.h" #include "DolphinQt2/Settings.h"
#include "UICommon/VideoUtils.h" #include "UICommon/VideoUtils.h"
@ -87,8 +89,6 @@ void GeneralWidget::CreateWidgets()
m_keep_window_top = new QCheckBox(tr("Keep Window on Top")); m_keep_window_top = new QCheckBox(tr("Keep Window on Top"));
m_hide_cursor = new QCheckBox(tr("Hide Mouse Cursor")); m_hide_cursor = new QCheckBox(tr("Hide Mouse Cursor"));
m_render_main_window = new QCheckBox(tr("Render to Main Window")); m_render_main_window = new QCheckBox(tr("Render to Main Window"));
m_wait_for_shaders = new GraphicsBool(tr("Immediately Compile Shaders"),
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);
m_options_box->setLayout(m_options_layout); m_options_box->setLayout(m_options_layout);
@ -103,10 +103,30 @@ void GeneralWidget::CreateWidgets()
m_options_layout->addWidget(m_hide_cursor, 3, 0); m_options_layout->addWidget(m_hide_cursor, 3, 0);
m_options_layout->addWidget(m_render_main_window, 3, 1); m_options_layout->addWidget(m_render_main_window, 3, 1);
m_options_layout->addWidget(m_wait_for_shaders, 4, 0);
// Other
auto* shader_compilation_box = new QGroupBox(tr("Shader Compilation"));
auto* shader_compilation_layout = new QGridLayout();
const std::array<const char*, 4> modes = {{
"Synchronous", "Synchronous (Ubershaders)", "Asynchronous (Ubershaders)",
"Asynchronous (Skip Drawing)",
}};
for (size_t i = 0; i < modes.size(); i++)
{
m_shader_compilation_mode[i] = new GraphicsRadioInt(
tr(modes[i]), Config::GFX_SHADER_COMPILATION_MODE, static_cast<int>(i));
shader_compilation_layout->addWidget(m_shader_compilation_mode[i], static_cast<int>(i / 2),
static_cast<int>(i % 2));
}
m_wait_for_shaders = new GraphicsBool(tr("Compile Shaders Before Starting"),
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);
shader_compilation_layout->addWidget(m_wait_for_shaders);
shader_compilation_box->setLayout(shader_compilation_layout);
main_layout->addWidget(m_video_box); main_layout->addWidget(m_video_box);
main_layout->addWidget(m_options_box); main_layout->addWidget(m_options_box);
main_layout->addWidget(shader_compilation_box);
main_layout->addStretch(); main_layout->addStretch();
setLayout(main_layout); setLayout(main_layout);
@ -268,12 +288,27 @@ void GeneralWidget::AddDescriptions()
static const char* TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION = static const char* TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION =
QT_TR_NOOP("When playing on NetPlay, show chat messages, buffer changes and " QT_TR_NOOP("When playing on NetPlay, show chat messages, buffer changes and "
"desync alerts.\n\nIf unsure, leave this unchecked."); "desync alerts.\n\nIf unsure, leave this unchecked.");
static const char* TR_WAIT_FOR_SHADERS_DESCRIPTION = QT_TR_NOOP( static const char* TR_SHADER_COMPILE_SYNC_DESCRIPTION =
"Waits for all shaders to finish compiling before starting a game. Enabling this " QT_TR_NOOP("Ubershaders are never used. Stuttering will occur during shader "
"option may reduce stuttering or hitching for a short time after the game is " "compilation, but GPU demands are low. Recommended for low-end hardware.\n\nIf "
"started, at the cost of a longer delay before the game starts.\n\nFor systems " "unsure, select this mode.");
"with two or fewer cores, it is recommended to enable this option, as a large " static const char* TR_SHADER_COMPILE_UBER_ONLY_DESCRIPTION =
"shader queue may reduce frame rates. Otherwise, if unsure, leave this unchecked."); QT_TR_NOOP("Ubershaders will always be used. Provides a near stutter-free experience at the "
"cost of high GPU requirements. Only recommended for high-end systems.");
static const char* TR_SHADER_COMPILE_ASYNC_UBER_DESCRIPTION =
QT_TR_NOOP("Ubershaders will be used to prevent stuttering during shader compilation, but "
"specialized shaders will be used when they will not cause stuttering.");
static const char* TR_SHADER_COMPILE_ASYNC_SKIP_DESCRIPTION =
QT_TR_NOOP("Instead of using ubershaders during shader compilation, objects which use these "
"shaders will be not be rendered. This can further reduce stuttering and "
"performance requirements, compared to ubershaders, at the cost of introducing "
"visual glitches and broken effects. Not recommended.");
static const char* TR_SHADER_COMPILE_BEFORE_START_DESCRIPTION =
QT_TR_NOOP("Waits for all shaders to finish compiling before starting a game. Enabling this "
"option may reduce stuttering or hitching for a short time after the game is "
"started, at the cost of a longer delay before the game starts. For systems with "
"two or fewer cores, it is recommended to enable this option, as a large shader "
"queue may reduce frame rates. Otherwise, if unsure, leave this unchecked.");
AddDescription(m_backend_combo, TR_BACKEND_DESCRIPTION); AddDescription(m_backend_combo, TR_BACKEND_DESCRIPTION);
#ifdef _WIN32 #ifdef _WIN32
@ -291,7 +326,11 @@ void GeneralWidget::AddDescriptions()
AddDescription(m_show_messages, TR_SHOW_FPS_DESCRIPTION); AddDescription(m_show_messages, TR_SHOW_FPS_DESCRIPTION);
AddDescription(m_keep_window_top, TR_KEEP_WINDOW_ON_TOP_DESCRIPTION); AddDescription(m_keep_window_top, TR_KEEP_WINDOW_ON_TOP_DESCRIPTION);
AddDescription(m_show_messages, TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION); AddDescription(m_show_messages, TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION);
AddDescription(m_wait_for_shaders, TR_WAIT_FOR_SHADERS_DESCRIPTION); AddDescription(m_shader_compilation_mode[0], TR_SHADER_COMPILE_SYNC_DESCRIPTION);
AddDescription(m_shader_compilation_mode[1], TR_SHADER_COMPILE_UBER_ONLY_DESCRIPTION);
AddDescription(m_shader_compilation_mode[2], TR_SHADER_COMPILE_ASYNC_UBER_DESCRIPTION);
AddDescription(m_shader_compilation_mode[3], TR_SHADER_COMPILE_ASYNC_SKIP_DESCRIPTION);
AddDescription(m_wait_for_shaders, TR_SHADER_COMPILE_BEFORE_START_DESCRIPTION);
} }
void GeneralWidget::OnBackendChanged(const QString& backend_name) void GeneralWidget::OnBackendChanged(const QString& backend_name)
{ {

View File

@ -4,11 +4,13 @@
#pragma once #pragma once
#include <array>
#include "DolphinQt2/Config/Graphics/GraphicsWidget.h" #include "DolphinQt2/Config/Graphics/GraphicsWidget.h"
class GraphicsWindow; class GraphicsWindow;
class QCheckBox; class QCheckBox;
class QComboBox; class QComboBox;
class QRadioButton;
class QGridLayout; class QGridLayout;
namespace X11Utils namespace X11Utils
@ -52,6 +54,7 @@ private:
QCheckBox* m_keep_window_top; QCheckBox* m_keep_window_top;
QCheckBox* m_hide_cursor; QCheckBox* m_hide_cursor;
QCheckBox* m_render_main_window; QCheckBox* m_render_main_window;
std::array<QRadioButton*, 4> m_shader_compilation_mode{};
QCheckBox* m_wait_for_shaders; QCheckBox* m_wait_for_shaders;
X11Utils::XRRConfiguration* m_xrr_config; X11Utils::XRRConfiguration* m_xrr_config;

View File

@ -0,0 +1,24 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "DolphinQt2/Config/Graphics/GraphicsRadio.h"
#include "Common/Config/Config.h"
#include "DolphinQt2/Settings.h"
GraphicsRadioInt::GraphicsRadioInt(const QString& label, const Config::ConfigInfo<int>& setting,
int value)
: QRadioButton(label), m_setting(setting), m_value(value)
{
setChecked(Config::Get(m_setting) == m_value);
connect(this, &QRadioButton::toggled, this, &GraphicsRadioInt::Update);
}
void GraphicsRadioInt::Update()
{
if (!isChecked())
return;
Config::SetBaseOrCurrent(m_setting, m_value);
}

View File

@ -0,0 +1,26 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <QRadioButton>
namespace Config
{
template <typename T>
struct ConfigInfo;
}
class GraphicsRadioInt : public QRadioButton
{
Q_OBJECT
public:
GraphicsRadioInt(const QString& label, const Config::ConfigInfo<int>& setting, int value);
private:
void Update();
const Config::ConfigInfo<int>& m_setting;
int m_value;
};

View File

@ -79,6 +79,7 @@
<QtMoc Include="Config\Graphics\GeneralWidget.h" /> <QtMoc Include="Config\Graphics\GeneralWidget.h" />
<QtMoc Include="Config\Graphics\GraphicsBool.h" /> <QtMoc Include="Config\Graphics\GraphicsBool.h" />
<QtMoc Include="Config\Graphics\GraphicsChoice.h" /> <QtMoc Include="Config\Graphics\GraphicsChoice.h" />
<QtMoc Include="Config\Graphics\GraphicsRadio.h" />
<QtMoc Include="Config\Graphics\GraphicsSlider.h" /> <QtMoc Include="Config\Graphics\GraphicsSlider.h" />
<QtMoc Include="Config\Graphics\GraphicsWidget.h" /> <QtMoc Include="Config\Graphics\GraphicsWidget.h" />
<QtMoc Include="Config\Graphics\GraphicsWindow.h" /> <QtMoc Include="Config\Graphics\GraphicsWindow.h" />
@ -161,6 +162,7 @@
<ClCompile Include="$(QtMocOutPrefix)GeneralWidget.cpp" /> <ClCompile Include="$(QtMocOutPrefix)GeneralWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)GraphicsBool.cpp" /> <ClCompile Include="$(QtMocOutPrefix)GraphicsBool.cpp" />
<ClCompile Include="$(QtMocOutPrefix)GraphicsChoice.cpp" /> <ClCompile Include="$(QtMocOutPrefix)GraphicsChoice.cpp" />
<ClCompile Include="$(QtMocOutPrefix)GraphicsRadio.cpp" />
<ClCompile Include="$(QtMocOutPrefix)GraphicsSlider.cpp" /> <ClCompile Include="$(QtMocOutPrefix)GraphicsSlider.cpp" />
<ClCompile Include="$(QtMocOutPrefix)GraphicsWidget.cpp" /> <ClCompile Include="$(QtMocOutPrefix)GraphicsWidget.cpp" />
<ClCompile Include="$(QtMocOutPrefix)GraphicsWindow.cpp" /> <ClCompile Include="$(QtMocOutPrefix)GraphicsWindow.cpp" />
@ -212,6 +214,7 @@
<ClCompile Include="Config\Graphics\GeneralWidget.cpp" /> <ClCompile Include="Config\Graphics\GeneralWidget.cpp" />
<ClCompile Include="Config\Graphics\GraphicsBool.cpp" /> <ClCompile Include="Config\Graphics\GraphicsBool.cpp" />
<ClCompile Include="Config\Graphics\GraphicsChoice.cpp" /> <ClCompile Include="Config\Graphics\GraphicsChoice.cpp" />
<ClCompile Include="Config\Graphics\GraphicsRadio.cpp" />
<ClCompile Include="Config\Graphics\GraphicsSlider.cpp" /> <ClCompile Include="Config\Graphics\GraphicsSlider.cpp" />
<ClCompile Include="Config\Graphics\GraphicsWidget.cpp" /> <ClCompile Include="Config\Graphics\GraphicsWidget.cpp" />
<ClCompile Include="Config\Graphics\GraphicsWindow.cpp" /> <ClCompile Include="Config\Graphics\GraphicsWindow.cpp" />

View File

@ -44,7 +44,6 @@
// template instantiation // template instantiation
template class BoolSetting<wxCheckBox>; template class BoolSetting<wxCheckBox>;
template class BoolSetting<wxRadioButton>;
template <> template <>
SettingCheckBox::BoolSetting(wxWindow* parent, const wxString& label, const wxString& tooltip, SettingCheckBox::BoolSetting(wxWindow* parent, const wxString& label, const wxString& tooltip,
@ -59,19 +58,6 @@ SettingCheckBox::BoolSetting(wxWindow* parent, const wxString& label, const wxSt
Bind(wxEVT_CHECKBOX, &SettingCheckBox::UpdateValue, this); Bind(wxEVT_CHECKBOX, &SettingCheckBox::UpdateValue, this);
} }
template <>
SettingRadioButton::BoolSetting(wxWindow* parent, const wxString& label, const wxString& tooltip,
const Config::ConfigInfo<bool>& setting, bool reverse, long style)
: wxRadioButton(parent, wxID_ANY, label, wxDefaultPosition, wxDefaultSize, style),
m_setting(setting), m_reverse(reverse)
{
SetToolTip(tooltip);
SetValue(Config::Get(m_setting) ^ m_reverse);
if (Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base)
SetFont(GetFont().MakeBold());
Bind(wxEVT_RADIOBUTTON, &SettingRadioButton::UpdateValue, this);
}
template <> template <>
RefBoolSetting<wxCheckBox>::RefBoolSetting(wxWindow* parent, const wxString& label, RefBoolSetting<wxCheckBox>::RefBoolSetting(wxWindow* parent, const wxString& label,
const wxString& tooltip, bool& setting, bool reverse, const wxString& tooltip, bool& setting, bool reverse,
@ -311,18 +297,35 @@ static wxString gpu_texture_decoding_desc =
"bottleneck.\n\nIf unsure, leave this unchecked."); "bottleneck.\n\nIf unsure, leave this unchecked.");
static wxString ubershader_desc = static wxString ubershader_desc =
wxTRANSLATE("Disabled: Ubershaders are never used. Stuttering will occur during shader " wxTRANSLATE("Disabled: Ubershaders are never used. Stuttering will occur during shader "
"compilation, but GPU demands are low. Recommended for low-end hardware.\n\n" "compilation, but GPU demands are low. Recommended for low-end hardware.\n"
"Hybrid: Ubershaders will be used to prevent stuttering during shader " "Hybrid: Ubershaders will be used to prevent stuttering during shader "
"compilation, but traditional shaders will be used when they will not cause " "compilation, but traditional shaders will be used when they will not cause "
"stuttering. Balances performance and smoothness.\n\n" "stuttering. Balances performance and smoothness.\n"
"Exclusive: Ubershaders will always be used. Only recommended for high-end " "Exclusive: Ubershaders will always be used. Only recommended for high-end "
"systems."); "systems.\n"
static wxString wait_for_shaders_desc = "Skip Drawing: Does not draw objects during shader compilation. Reduces "
"stuttering at the cost of missing objects, or broken effects.");
static wxString shader_compile_sync_desc =
wxTRANSLATE("Ubershaders are never used. Stuttering will occur during shader "
"compilation, but GPU demands are low. Recommended for low-end hardware.\n\nIf "
"unsure, select this mode.");
static wxString shader_compile_uber_only_desc =
wxTRANSLATE("Ubershaders will always be used. Provides a near stutter-free experience at the "
"cost of high GPU requirements. Only recommended for high-end systems.");
static wxString shader_compile_async_uber_desc =
wxTRANSLATE("Ubershaders will be used to prevent stuttering during shader compilation, but "
"specialized shaders will be used when they will not cause stuttering.");
static wxString shader_compile_async_skip_desc =
wxTRANSLATE("Instead of using ubershaders during shader compilation, objects which use these "
"shaders will be not be rendered. This can further reduce stuttering and "
"performance requirements, compared to ubershaders, at the cost of introducing "
"visual glitches and broken effects. Not recommended.");
static wxString shader_compile_before_start_desc =
wxTRANSLATE("Waits for all shaders to finish compiling before starting a game. Enabling this " wxTRANSLATE("Waits for all shaders to finish compiling before starting a game. Enabling this "
"option may reduce stuttering or hitching for a short time after the game is " "option may reduce stuttering or hitching for a short time after the game is "
"started, at the cost of a longer delay before the game starts.\n\nFor systems " "started, at the cost of a longer delay before the game starts. For systems with "
"with two or fewer cores, it is recommended to enable this option, as a large " "two or fewer cores, it is recommended to enable this option, as a large shader "
"shader queue may reduce frame rates. Otherwise, if unsure, leave this unchecked."); "queue may reduce frame rates. Otherwise, if unsure, leave this unchecked.");
VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
: wxDialog(parent, wxID_ANY, wxString::Format(_("Dolphin %s Graphics Configuration"), : wxDialog(parent, wxID_ANY, wxString::Format(_("Dolphin %s Graphics Configuration"),
@ -448,10 +451,29 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
wxGetTranslation(backend_multithreading_desc), wxGetTranslation(backend_multithreading_desc),
Config::GFX_BACKEND_MULTITHREADING)); Config::GFX_BACKEND_MULTITHREADING));
} }
}
szr_other->Add(CreateCheckBox(page_general, _("Immediately Compile Shaders"), // - shader compilation
wxGetTranslation(wait_for_shaders_desc), wxGridBagSizer* const szr_shader_compilation = new wxGridBagSizer(space5, space5);
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING)); {
const std::array<std::pair<wxString, wxString>, 4> modes = {
{{_("Synchronous"), wxGetTranslation(shader_compile_sync_desc)},
{_("Synchronous (Ubershaders)"), wxGetTranslation(shader_compile_uber_only_desc)},
{_("Asynchronous (Ubershaders)"), wxGetTranslation(shader_compile_async_uber_desc)},
{_("Asynchronous (Skip Drawing)"), wxGetTranslation(shader_compile_async_skip_desc)}}};
for (size_t i = 0; i < modes.size(); i++)
{
szr_shader_compilation->Add(
CreateRadioButton(page_general, modes[i].first, modes[i].second,
Config::GFX_SHADER_COMPILATION_MODE, static_cast<int>(i)),
wxGBPosition(static_cast<int>(i / 2), static_cast<int>(i % 2)), wxDefaultSpan,
wxALIGN_CENTER_VERTICAL);
}
szr_shader_compilation->Add(
CreateCheckBox(page_general, _("Compile Shaders Before Starting"),
wxGetTranslation(shader_compile_before_start_desc),
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING),
wxGBPosition(2, 0), wxGBSpan(1, 2));
} }
wxStaticBoxSizer* const group_basic = wxStaticBoxSizer* const group_basic =
@ -469,12 +491,19 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT, space5); group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
group_other->AddSpacer(space5); group_other->AddSpacer(space5);
wxStaticBoxSizer* const group_shader_compilation =
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Shader Compilation"));
group_shader_compilation->Add(szr_shader_compilation, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
group_shader_compilation->AddSpacer(space5);
szr_general->AddSpacer(space5); szr_general->AddSpacer(space5);
szr_general->Add(group_basic, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); szr_general->Add(group_basic, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
szr_general->AddSpacer(space5); szr_general->AddSpacer(space5);
szr_general->Add(group_display, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); szr_general->Add(group_display, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
szr_general->AddSpacer(space5); szr_general->AddSpacer(space5);
szr_general->Add(group_other, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); szr_general->Add(group_other, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
szr_general->AddSpacer(space5);
szr_general->Add(group_shader_compilation, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
} }
szr_general->AddSpacer(space5); szr_general->AddSpacer(space5);
@ -541,18 +570,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
row += 1; row += 1;
} }
// ubershaders
{
const std::array<wxString, 3> mode_choices = {{_("Disabled"), _("Hybrid"), _("Exclusive")}};
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Ubershaders:")), wxGBPosition(row, 0),
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
szr_enh->Add(CreateChoice(page_enh, Config::GFX_UBERSHADER_MODE,
wxGetTranslation(ubershader_desc), mode_choices.size(),
mode_choices.data()),
wxGBPosition(row, 1), span2, wxALIGN_CENTER_VERTICAL);
row += 1;
}
// postproc shader // postproc shader
if (vconfig.backend_info.bSupportsPostProcessing) if (vconfig.backend_info.bSupportsPostProcessing)
{ {
@ -1111,17 +1128,6 @@ SettingChoice* VideoConfigDiag::CreateChoice(wxWindow* parent,
return ch; return ch;
} }
SettingRadioButton* VideoConfigDiag::CreateRadioButton(wxWindow* parent, const wxString& label,
const wxString& description,
const Config::ConfigInfo<bool>& setting,
bool reverse, long style)
{
SettingRadioButton* const rb =
new SettingRadioButton(parent, label, wxString(), setting, reverse, style);
RegisterControl(rb, description);
return rb;
}
/* Use this to register descriptions for controls which have NOT been created using the Create* /* Use this to register descriptions for controls which have NOT been created using the Create*
* functions from above */ * functions from above */
wxControl* VideoConfigDiag::RegisterControl(wxControl* const control, const wxString& description) wxControl* VideoConfigDiag::RegisterControl(wxControl* const control, const wxString& description)

View File

@ -64,7 +64,6 @@ private:
}; };
typedef BoolSetting<wxCheckBox> SettingCheckBox; typedef BoolSetting<wxCheckBox> SettingCheckBox;
typedef BoolSetting<wxRadioButton> SettingRadioButton;
class IntegerSetting : public wxSpinCtrl class IntegerSetting : public wxSpinCtrl
{ {
@ -93,6 +92,33 @@ private:
Config::ConfigInfo<int> m_setting; Config::ConfigInfo<int> m_setting;
}; };
template <typename ValueType>
class SettingRadioButton : public wxRadioButton
{
public:
SettingRadioButton(wxWindow* parent, const wxString& label, const wxString& tooltip,
const Config::ConfigInfo<ValueType>& setting, const ValueType& value,
long style = 0)
: wxRadioButton(parent, wxID_ANY, label, wxDefaultPosition, wxDefaultSize, style),
m_setting(setting), m_value(value)
{
SetToolTip(tooltip);
SetValue(Config::Get(m_setting) == m_value);
Bind(wxEVT_RADIOBUTTON, &SettingRadioButton::UpdateValue, this);
}
void UpdateValue(wxCommandEvent& ev)
{
if (ev.IsChecked())
Config::SetBaseOrCurrent(m_setting, m_value);
ev.Skip();
}
private:
Config::ConfigInfo<ValueType> m_setting;
ValueType m_value;
};
class VideoConfigDiag : public wxDialog class VideoConfigDiag : public wxDialog
{ {
public: public:
@ -125,10 +151,17 @@ protected:
SettingChoice* CreateChoice(wxWindow* parent, const Config::ConfigInfo<int>& setting, SettingChoice* CreateChoice(wxWindow* parent, const Config::ConfigInfo<int>& setting,
const wxString& description, int num = 0, const wxString& description, int num = 0,
const wxString choices[] = nullptr, long style = 0); const wxString choices[] = nullptr, long style = 0);
SettingRadioButton* CreateRadioButton(wxWindow* parent, const wxString& label, template <typename ValueType>
const wxString& description, SettingRadioButton<ValueType>* CreateRadioButton(wxWindow* parent, const wxString& label,
const Config::ConfigInfo<bool>& setting, const wxString& description,
bool reverse = false, long style = 0); const Config::ConfigInfo<ValueType>& setting,
const ValueType& value, long style = 0)
{
auto* const rb =
new SettingRadioButton<ValueType>(parent, label, wxString(), setting, value, style);
RegisterControl(rb, description);
return rb;
}
// Same as above but only connects enter/leave window events // Same as above but only connects enter/leave window events
wxControl* RegisterControl(wxControl* const control, const wxString& description); wxControl* RegisterControl(wxControl* const control, const wxString& description);
@ -157,9 +190,6 @@ protected:
SettingCheckBox* borderless_fullscreen; SettingCheckBox* borderless_fullscreen;
RefBoolSetting<wxCheckBox>* render_to_main_checkbox; RefBoolSetting<wxCheckBox>* render_to_main_checkbox;
SettingRadioButton* virtual_xfb;
SettingRadioButton* real_xfb;
SettingCheckBox* cache_hires_textures; SettingCheckBox* cache_hires_textures;
wxCheckBox* progressive_scan_checkbox; wxCheckBox* progressive_scan_checkbox;

View File

@ -166,16 +166,19 @@ void VertexManager::vFlush()
} }
// Bind all pending state to the command buffer // Bind all pending state to the command buffer
g_renderer->SetPipeline(m_current_pipeline_object); if (m_current_pipeline_object)
if (!StateTracker::GetInstance()->Bind())
{ {
WARN_LOG(VIDEO, "Skipped draw of %u indices", index_count); g_renderer->SetPipeline(m_current_pipeline_object);
return; if (!StateTracker::GetInstance()->Bind())
} {
WARN_LOG(VIDEO, "Skipped draw of %u indices", index_count);
return;
}
// Execute the draw // Execute the draw
vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), index_count, 1, vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), index_count, 1,
m_current_draw_base_index, m_current_draw_base_vertex, 0); m_current_draw_base_index, m_current_draw_base_vertex, 0);
}
StateTracker::GetInstance()->OnDraw(); StateTracker::GetInstance()->OnDraw();
} }

View File

@ -566,13 +566,25 @@ void VertexManagerBase::UpdatePipelineObject()
m_current_pipeline_object = nullptr; m_current_pipeline_object = nullptr;
m_pipeline_config_changed = false; m_pipeline_config_changed = false;
if (g_ActiveConfig.iUberShaderMode == UberShaderMode::Disabled) switch (g_ActiveConfig.iShaderCompilationMode)
{
case ShaderCompilationMode::Synchronous:
{ {
// Ubershaders disabled? Block and compile the specialized shader. // Ubershaders disabled? Block and compile the specialized shader.
m_current_pipeline_object = g_shader_cache->GetPipelineForUid(m_current_pipeline_config); m_current_pipeline_object = g_shader_cache->GetPipelineForUid(m_current_pipeline_config);
return;
} }
else if (g_ActiveConfig.iUberShaderMode == UberShaderMode::Hybrid) break;
case ShaderCompilationMode::SynchronousUberShaders:
{
// Exclusive ubershader mode, always use ubershaders.
m_current_pipeline_object =
g_shader_cache->GetUberPipelineForUid(m_current_uber_pipeline_config);
}
break;
case ShaderCompilationMode::AsynchronousUberShaders:
case ShaderCompilationMode::AsynchronousSkipRendering:
{ {
// Can we background compile shaders? If so, get the pipeline asynchronously. // Can we background compile shaders? If so, get the pipeline asynchronously.
auto res = g_shader_cache->GetPipelineForUidAsync(m_current_pipeline_config); auto res = g_shader_cache->GetPipelineForUidAsync(m_current_pipeline_config);
@ -582,8 +594,20 @@ void VertexManagerBase::UpdatePipelineObject()
m_current_pipeline_object = *res; m_current_pipeline_object = *res;
return; return;
} }
}
// Exclusive ubershader mode, or hybrid and shaders are still compiling. if (g_ActiveConfig.iShaderCompilationMode == ShaderCompilationMode::AsynchronousUberShaders)
m_current_pipeline_object = g_shader_cache->GetUberPipelineForUid(m_current_uber_pipeline_config); {
// Specialized shaders not ready, use the ubershaders.
m_current_pipeline_object =
g_shader_cache->GetUberPipelineForUid(m_current_uber_pipeline_config);
}
else
{
// Ensure we try again next draw. Otherwise, if no registers change between frames, the
// object will never be drawn, even when the shader is ready.
m_pipeline_config_changed = true;
}
}
break;
}
} }

View File

@ -103,7 +103,8 @@ void VideoConfig::Refresh()
iCommandBufferExecuteInterval = Config::Get(Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL); iCommandBufferExecuteInterval = Config::Get(Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL);
bShaderCache = Config::Get(Config::GFX_SHADER_CACHE); bShaderCache = Config::Get(Config::GFX_SHADER_CACHE);
bWaitForShadersBeforeStarting = Config::Get(Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING); bWaitForShadersBeforeStarting = Config::Get(Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);
iUberShaderMode = static_cast<UberShaderMode>(Config::Get(Config::GFX_UBERSHADER_MODE)); iShaderCompilationMode =
static_cast<ShaderCompilationMode>(Config::Get(Config::GFX_SHADER_COMPILATION_MODE));
iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS); iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS);
iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS); iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS);
@ -178,6 +179,12 @@ bool VideoConfig::IsVSync() const
return bVSync && !Core::GetIsThrottlerTempDisabled(); return bVSync && !Core::GetIsThrottlerTempDisabled();
} }
bool VideoConfig::UsingUberShaders() const
{
return iShaderCompilationMode == ShaderCompilationMode::SynchronousUberShaders ||
iShaderCompilationMode == ShaderCompilationMode::AsynchronousUberShaders;
}
static u32 GetNumAutoShaderCompilerThreads() static u32 GetNumAutoShaderCompilerThreads()
{ {
// Automatic number. We use clamp(cpus - 3, 1, 4). // Automatic number. We use clamp(cpus - 3, 1, 4).

View File

@ -42,11 +42,12 @@ enum class StereoMode : int
Nvidia3DVision Nvidia3DVision
}; };
enum class UberShaderMode : int enum class ShaderCompilationMode : int
{ {
Disabled, Synchronous,
Hybrid, SynchronousUberShaders,
Exclusive AsynchronousUberShaders,
AsynchronousSkipRendering
}; };
struct ProjectionHackConfig final struct ProjectionHackConfig final
@ -170,7 +171,7 @@ struct VideoConfig final
// Shader compilation settings. // Shader compilation settings.
bool bWaitForShadersBeforeStarting; bool bWaitForShadersBeforeStarting;
UberShaderMode iUberShaderMode; ShaderCompilationMode iShaderCompilationMode;
// Number of shader compiler threads. // Number of shader compiler threads.
// 0 disables background compilation. // 0 disables background compilation.
@ -238,7 +239,7 @@ struct VideoConfig final
return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding; return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding;
} }
bool UseVertexRounding() const { return bVertexRounding && iEFBScale != 1; } bool UseVertexRounding() const { return bVertexRounding && iEFBScale != 1; }
bool UsingUberShaders() const { return iUberShaderMode != UberShaderMode::Disabled; } bool UsingUberShaders() const;
u32 GetShaderCompilerThreads() const; u32 GetShaderCompilerThreads() const;
u32 GetShaderPrecompilerThreads() const; u32 GetShaderPrecompilerThreads() const;
}; };