diff options
Diffstat (limited to 'Source/Core/VideoCommon/ShaderCache.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/ShaderCache.cpp | 99 |
1 files changed, 70 insertions, 29 deletions
diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 6049fd29a7..f281024f22 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -588,10 +588,10 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig( const NativeVertexFormat* vertex_format, const AbstractShader* vertex_shader, const AbstractShader* geometry_shader, const AbstractShader* pixel_shader, const RasterizationState& rasterization_state, const DepthState& depth_state, - const BlendingState& blending_state) + const BlendingState& blending_state, AbstractPipelineUsage usage) { AbstractPipelineConfig config = {}; - config.usage = AbstractPipelineUsage::GX; + config.usage = usage; config.vertex_format = vertex_format; config.vertex_shader = vertex_shader; config.geometry_shader = geometry_shader; @@ -735,7 +735,7 @@ ShaderCache::GetGXPipelineConfig(const GXPipelineUid& config_in) } return GetGXPipelineConfig(config.vertex_format, vs, gs, ps, config.rasterization_state, - config.depth_state, config.blending_state); + config.depth_state, config.blending_state, AbstractPipelineUsage::GX); } /// Edits the UID based on driver bugs and other special configurations @@ -743,6 +743,8 @@ static GXUberPipelineUid ApplyDriverBugs(const GXUberPipelineUid& in) { GXUberPipelineUid out; memcpy(&out, &in, sizeof(out)); // Copy padding + if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader) + out.vertex_format = nullptr; if (g_ActiveConfig.backend_info.bSupportsFramebufferFetch) { // Always blend in shader @@ -798,7 +800,8 @@ ShaderCache::GetGXPipelineConfig(const GXUberPipelineUid& config_in) } return GetGXPipelineConfig(config.vertex_format, vs, gs, ps, config.rasterization_state, - config.depth_state, config.blending_state); + config.depth_state, config.blending_state, + AbstractPipelineUsage::GXUber); } const AbstractPipeline* ShaderCache::InsertGXPipeline(const GXPipelineUid& config, @@ -1233,32 +1236,32 @@ void ShaderCache::QueueUberShaderPipelines() dummy_vertex_decl.stride = sizeof(float) * 4; NativeVertexFormat* dummy_vertex_format = VertexLoaderManager::GetUberVertexFormat(dummy_vertex_decl); - auto QueueDummyPipeline = [&](const UberShader::VertexShaderUid& vs_uid, - const GeometryShaderUid& gs_uid, - const UberShader::PixelShaderUid& ps_uid) { - GXUberPipelineUid config; - config.vertex_format = dummy_vertex_format; - config.vs_uid = vs_uid; - config.gs_uid = gs_uid; - config.ps_uid = ps_uid; - config.rasterization_state = RenderState::GetCullBackFaceRasterizationState( - static_cast<PrimitiveType>(gs_uid.GetUidData()->primitive_type)); - config.depth_state = RenderState::GetNoDepthTestingDepthState(); - config.blending_state = RenderState::GetNoBlendingBlendState(); - if (ps_uid.GetUidData()->uint_output) - { - // uint_output is only ever enabled when logic ops are enabled. - config.blending_state.logicopenable = true; - config.blending_state.logicmode = LogicOp::And; - } + auto QueueDummyPipeline = + [&](const UberShader::VertexShaderUid& vs_uid, const GeometryShaderUid& gs_uid, + const UberShader::PixelShaderUid& ps_uid, const BlendingState& blend) { + GXUberPipelineUid config; + config.vertex_format = dummy_vertex_format; + config.vs_uid = vs_uid; + config.gs_uid = gs_uid; + config.ps_uid = ps_uid; + config.rasterization_state = RenderState::GetCullBackFaceRasterizationState( + static_cast<PrimitiveType>(gs_uid.GetUidData()->primitive_type)); + config.depth_state = RenderState::GetNoDepthTestingDepthState(); + config.blending_state = blend; + if (ps_uid.GetUidData()->uint_output) + { + // uint_output is only ever enabled when logic ops are enabled. + config.blending_state.logicopenable = true; + config.blending_state.logicmode = LogicOp::And; + } - auto iter = m_gx_uber_pipeline_cache.find(config); - if (iter != m_gx_uber_pipeline_cache.end()) - return; + auto iter = m_gx_uber_pipeline_cache.find(config); + if (iter != m_gx_uber_pipeline_cache.end()) + return; - auto& entry = m_gx_uber_pipeline_cache[config]; - entry.second = false; - }; + auto& entry = m_gx_uber_pipeline_cache[config]; + entry.second = false; + }; // Populate the pipeline configs with empty entries, these will be compiled afterwards. UberShader::EnumerateVertexShaderUids([&](const UberShader::VertexShaderUid& vuid) { @@ -1275,7 +1278,45 @@ void ShaderCache::QueueUberShaderPipelines() { return; } - QueueDummyPipeline(vuid, guid, cleared_puid); + BlendingState blend = RenderState::GetNoBlendingBlendState(); + QueueDummyPipeline(vuid, guid, cleared_puid, blend); + if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader) + { + // Not all GPUs need all the pipeline state compiled into shaders, so they tend to key + // compiled shaders based on some subset of the pipeline state. + // Some test results: + // (GPUs tested: AMD Radeon Pro 5600M, Nvidia GT 750M, Intel UHD 630, + // Intel Iris Pro 5200, Apple M1) + // MacOS Metal: + // - AMD, Nvidia, Intel GPUs: Shaders are keyed on vertex layout and whether or not + // dual source blend is enabled. That's it. + // - Apple GPUs: Shaders are keyed on vertex layout and all blending settings. We use + // framebuffer fetch here, so the only blending settings used by ubershaders are the + // alphaupdate and colorupdate ones. Also keyed on primitive type, but Metal supports + // setting it to "unknown" and we do for ubershaders (but MoltenVK won't). + // Windows Vulkan: + // - AMD, Nvidia: Definitely keyed on dual source blend, but the others seem more random + // Changing a setting on one shader will require a recompile, but changing the same + // setting on another won't. Compiling a copy with alphaupdate off, colorupdate off, + // and one with DSB on seems to get pretty good coverage though. + // Windows D3D12: + // - AMD: Keyed on dual source blend and vertex layout + // - Nvidia Kepler: No recompiles for changes to vertex layout or blend + blend.alphaupdate = false; + QueueDummyPipeline(vuid, guid, cleared_puid, blend); + blend.alphaupdate = true; + blend.colorupdate = false; + QueueDummyPipeline(vuid, guid, cleared_puid, blend); + blend.colorupdate = true; + if (!cleared_puid.GetUidData()->no_dual_src && !cleared_puid.GetUidData()->uint_output) + { + blend.blendenable = true; + blend.usedualsrc = true; + blend.srcfactor = SrcBlendFactor::SrcAlpha; + blend.dstfactor = DstBlendFactor::InvSrcAlpha; + QueueDummyPipeline(vuid, guid, cleared_puid, blend); + } + } }); }); }); |
