summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2018-03-16 23:10:22 +1000
committerStenzek <stenzek@gmail.com>2018-03-26 01:57:41 +1000
commit2f1a7cbee1ffecdd25ebc206ceab55ef934b7256 (patch)
tree1cbf78b64fbf293ede3a9bd47e586a0d4bb03a6b /Source/Core/VideoCommon
parent5c83e18fbd3606587e71a7f1cc54e4cf6473609f (diff)
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.
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.cpp36
-rw-r--r--Source/Core/VideoCommon/VideoConfig.cpp9
-rw-r--r--Source/Core/VideoCommon/VideoConfig.h13
3 files changed, 45 insertions, 13 deletions
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp
index b54b8060b9..8364b039c5 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/VertexManagerBase.cpp
@@ -566,13 +566,25 @@ void VertexManagerBase::UpdatePipelineObject()
m_current_pipeline_object = nullptr;
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.
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.
auto res = g_shader_cache->GetPipelineForUidAsync(m_current_pipeline_config);
@@ -582,8 +594,20 @@ void VertexManagerBase::UpdatePipelineObject()
m_current_pipeline_object = *res;
return;
}
- }
- // Exclusive ubershader mode, or hybrid and shaders are still compiling.
- m_current_pipeline_object = g_shader_cache->GetUberPipelineForUid(m_current_uber_pipeline_config);
+ if (g_ActiveConfig.iShaderCompilationMode == ShaderCompilationMode::AsynchronousUberShaders)
+ {
+ // 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;
+ }
}
diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp
index 55abd69e75..9c90c009a0 100644
--- a/Source/Core/VideoCommon/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/VideoConfig.cpp
@@ -103,7 +103,8 @@ void VideoConfig::Refresh()
iCommandBufferExecuteInterval = Config::Get(Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL);
bShaderCache = Config::Get(Config::GFX_SHADER_CACHE);
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);
iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS);
@@ -178,6 +179,12 @@ bool VideoConfig::IsVSync() const
return bVSync && !Core::GetIsThrottlerTempDisabled();
}
+bool VideoConfig::UsingUberShaders() const
+{
+ return iShaderCompilationMode == ShaderCompilationMode::SynchronousUberShaders ||
+ iShaderCompilationMode == ShaderCompilationMode::AsynchronousUberShaders;
+}
+
static u32 GetNumAutoShaderCompilerThreads()
{
// Automatic number. We use clamp(cpus - 3, 1, 4).
diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h
index c8bded371b..8e22765695 100644
--- a/Source/Core/VideoCommon/VideoConfig.h
+++ b/Source/Core/VideoCommon/VideoConfig.h
@@ -42,11 +42,12 @@ enum class StereoMode : int
Nvidia3DVision
};
-enum class UberShaderMode : int
+enum class ShaderCompilationMode : int
{
- Disabled,
- Hybrid,
- Exclusive
+ Synchronous,
+ SynchronousUberShaders,
+ AsynchronousUberShaders,
+ AsynchronousSkipRendering
};
struct ProjectionHackConfig final
@@ -170,7 +171,7 @@ struct VideoConfig final
// Shader compilation settings.
bool bWaitForShadersBeforeStarting;
- UberShaderMode iUberShaderMode;
+ ShaderCompilationMode iShaderCompilationMode;
// Number of shader compiler threads.
// 0 disables background compilation.
@@ -238,7 +239,7 @@ struct VideoConfig final
return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding;
}
bool UseVertexRounding() const { return bVertexRounding && iEFBScale != 1; }
- bool UsingUberShaders() const { return iUberShaderMode != UberShaderMode::Disabled; }
+ bool UsingUberShaders() const;
u32 GetShaderCompilerThreads() const;
u32 GetShaderPrecompilerThreads() const;
};