diff options
| author | Stenzek <stenzek@gmail.com> | 2018-03-01 19:21:06 +1000 |
|---|---|---|
| committer | Stenzek <stenzek@gmail.com> | 2018-03-10 16:11:19 +1000 |
| commit | e31cc1f679db82f6baca1bb3d934e2dd17542d55 (patch) | |
| tree | 0edb0e3947fd0f53c4e682ea102cec7297b5e8e0 /Source/Core/VideoCommon | |
| parent | 9fa24700b69b98b2569f4bd1353482cbfb1ec2d7 (diff) | |
ShaderCache: Implement background shader compilation
This enables shaders to be compiled while the game is starting, instead
of blocking startup. If a shader is needed before it is compiled,
emulation will block.
Diffstat (limited to 'Source/Core/VideoCommon')
| -rw-r--r-- | Source/Core/VideoCommon/AsyncShaderCompiler.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/GXPipelineTypes.h | 75 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/ShaderCache.cpp | 131 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/ShaderCache.h | 90 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VertexManagerBase.h | 4 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoCommon.vcxproj | 3 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoCommon.vcxproj.filters | 9 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoConfig.cpp | 5 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoConfig.h | 1 |
9 files changed, 176 insertions, 143 deletions
diff --git a/Source/Core/VideoCommon/AsyncShaderCompiler.cpp b/Source/Core/VideoCommon/AsyncShaderCompiler.cpp index 59ef9762f1..e605828ed5 100644 --- a/Source/Core/VideoCommon/AsyncShaderCompiler.cpp +++ b/Source/Core/VideoCommon/AsyncShaderCompiler.cpp @@ -18,7 +18,6 @@ AsyncShaderCompiler::~AsyncShaderCompiler() // Pending work can be left at shutdown. // The work item classes are expected to clean up after themselves. _assert_(!HasWorkerThreads()); - _assert_(m_completed_work.empty()); } void AsyncShaderCompiler::QueueWorkItem(WorkItemPtr item) diff --git a/Source/Core/VideoCommon/GXPipelineTypes.h b/Source/Core/VideoCommon/GXPipelineTypes.h new file mode 100644 index 0000000000..165e9c67f8 --- /dev/null +++ b/Source/Core/VideoCommon/GXPipelineTypes.h @@ -0,0 +1,75 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "VideoCommon/GeometryShaderGen.h" +#include "VideoCommon/PixelShaderGen.h" +#include "VideoCommon/RenderState.h" +#include "VideoCommon/UberShaderPixel.h" +#include "VideoCommon/UberShaderVertex.h" +#include "VideoCommon/VertexShaderGen.h" + +class NativeVertexFormat; + +namespace VideoCommon +{ +struct GXPipelineUid +{ + const NativeVertexFormat* vertex_format; + VertexShaderUid vs_uid; + GeometryShaderUid gs_uid; + PixelShaderUid ps_uid; + RasterizationState rasterization_state; + DepthState depth_state; + BlendingState blending_state; + + // We use memcmp() for comparing pipelines as std::tie generates a large number of instructions, + // and this map lookup can happen every draw call. However, as using memcmp() will also compare + // any padding bytes, we have to ensure these are zeroed out. + GXPipelineUid() { std::memset(this, 0, sizeof(*this)); } + GXPipelineUid(const GXPipelineUid& rhs) { std::memcpy(this, &rhs, sizeof(*this)); } + GXPipelineUid& operator=(const GXPipelineUid& rhs) + { + std::memcpy(this, &rhs, sizeof(*this)); + return *this; + } + bool operator<(const GXPipelineUid& rhs) const + { + return std::memcmp(this, &rhs, sizeof(*this)) < 0; + } + bool operator==(const GXPipelineUid& rhs) const + { + return std::memcmp(this, &rhs, sizeof(*this)) == 0; + } + bool operator!=(const GXPipelineUid& rhs) const { return !operator==(rhs); } +}; +struct GXUberPipelineUid +{ + const NativeVertexFormat* vertex_format; + UberShader::VertexShaderUid vs_uid; + GeometryShaderUid gs_uid; + UberShader::PixelShaderUid ps_uid; + RasterizationState rasterization_state; + DepthState depth_state; + BlendingState blending_state; + + GXUberPipelineUid() { std::memset(this, 0, sizeof(*this)); } + GXUberPipelineUid(const GXUberPipelineUid& rhs) { std::memcpy(this, &rhs, sizeof(*this)); } + GXUberPipelineUid& operator=(const GXUberPipelineUid& rhs) + { + std::memcpy(this, &rhs, sizeof(*this)); + return *this; + } + bool operator<(const GXUberPipelineUid& rhs) const + { + return std::memcmp(this, &rhs, sizeof(*this)) < 0; + } + bool operator==(const GXUberPipelineUid& rhs) const + { + return std::memcmp(this, &rhs, sizeof(*this)) == 0; + } + bool operator!=(const GXUberPipelineUid& rhs) const { return !operator==(rhs); } +}; +} // namespace VideoCommon diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 43a31dfd6b..512adbd12a 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -43,6 +43,8 @@ bool ShaderCache::Initialize() // Compile all known UIDs. CompileMissingPipelines(); + if (g_ActiveConfig.bWaitForShadersBeforeStarting) + WaitForAsyncCompiler(); // Switch to the runtime shader compiler thread configuration. m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderCompilerThreads()); @@ -61,9 +63,7 @@ void ShaderCache::SetHostConfig(const ShaderHostConfig& host_config, u32 efb_mul void ShaderCache::Reload() { - m_async_shader_compiler->WaitUntilCompletion(); - m_async_shader_compiler->RetrieveWorkItems(); - + WaitForAsyncCompiler(); InvalidateCachedPipelines(); ClearShaderCaches(); @@ -77,6 +77,8 @@ void ShaderCache::Reload() // UIDs are still be in the map. Therefore, when these are rebuilt, the shaders will also // be recompiled. CompileMissingPipelines(); + if (g_ActiveConfig.bWaitForShadersBeforeStarting) + WaitForAsyncCompiler(); m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderCompilerThreads()); } @@ -87,14 +89,14 @@ void ShaderCache::RetrieveAsyncShaders() void ShaderCache::Shutdown() { + // This may leave shaders uncommitted to the cache, but it's better than blocking shutdown + // until everything has finished compiling. m_async_shader_compiler->StopWorkerThreads(); - m_async_shader_compiler->RetrieveWorkItems(); - ClearShaderCaches(); ClearPipelineCaches(); } -const AbstractPipeline* ShaderCache::GetPipelineForUid(const GXPipelineConfig& uid) +const AbstractPipeline* ShaderCache::GetPipelineForUid(const GXPipelineUid& uid) { auto it = m_gx_pipeline_cache.find(uid); if (it != m_gx_pipeline_cache.end() && !it->second.second) @@ -109,8 +111,7 @@ const AbstractPipeline* ShaderCache::GetPipelineForUid(const GXPipelineConfig& u return InsertGXPipeline(uid, std::move(pipeline)); } -std::optional<const AbstractPipeline*> -ShaderCache::GetPipelineForUidAsync(const GXPipelineConfig& uid) +std::optional<const AbstractPipeline*> ShaderCache::GetPipelineForUidAsync(const GXPipelineUid& uid) { auto it = m_gx_pipeline_cache.find(uid); if (it != m_gx_pipeline_cache.end()) @@ -159,7 +160,7 @@ ShaderCache::GetPipelineForUidAsync(const GXPipelineConfig& uid) return {}; } -const AbstractPipeline* ShaderCache::GetUberPipelineForUid(const GXUberPipelineConfig& uid) +const AbstractPipeline* ShaderCache::GetUberPipelineForUid(const GXUberPipelineUid& uid) { auto it = m_gx_uber_pipeline_cache.find(uid); if (it != m_gx_uber_pipeline_cache.end() && !it->second.second) @@ -172,12 +173,16 @@ const AbstractPipeline* ShaderCache::GetUberPipelineForUid(const GXUberPipelineC return InsertGXUberPipeline(uid, std::move(pipeline)); } -void ShaderCache::WaitForAsyncCompiler(const std::string& msg) +void ShaderCache::WaitForAsyncCompiler() { - m_async_shader_compiler->WaitUntilCompletion([&msg](size_t completed, size_t total) { - Host_UpdateProgressDialog(msg.c_str(), static_cast<int>(completed), static_cast<int>(total)); - }); - m_async_shader_compiler->RetrieveWorkItems(); + while (m_async_shader_compiler->HasPendingWork()) + { + m_async_shader_compiler->WaitUntilCompletion([](size_t completed, size_t total) { + Host_UpdateProgressDialog(GetStringT("Compiling shaders...").c_str(), + static_cast<int>(completed), static_cast<int>(total)); + }); + m_async_shader_compiler->RetrieveWorkItems(); + } Host_UpdateProgressDialog("", -1, -1); } @@ -274,7 +279,7 @@ void ShaderCache::LoadPipelineUIDCache() CacheReader(ShaderCache* shader_cache_) : shader_cache(shader_cache_) {} void Read(const GXPipelineDiskCacheUid& key, const u8* data, u32 data_size) { - GXPipelineConfig config = {}; + GXPipelineUid config = {}; config.vertex_format = VertexLoaderManager::GetOrCreateMatchingFormat(key.vertex_decl); config.vs_uid = key.vs_uid; config.gs_uid = key.gs_uid; @@ -315,8 +320,6 @@ void ShaderCache::CompileMissingPipelines() if (!it.second.second) QueueUberPipelineCompile(it.first); } - - WaitForAsyncCompiler(GetStringT("Compiling shaders...")); } void ShaderCache::InvalidateCachedPipelines() @@ -508,8 +511,7 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig( return config; } -std::optional<AbstractPipelineConfig> -ShaderCache::GetGXPipelineConfig(const GXPipelineConfig& config) +std::optional<AbstractPipelineConfig> ShaderCache::GetGXPipelineConfig(const GXPipelineUid& config) { const AbstractShader* vs; auto vs_iter = m_vs_cache.shader_map.find(config.vs_uid); @@ -545,7 +547,7 @@ ShaderCache::GetGXPipelineConfig(const GXPipelineConfig& config) } std::optional<AbstractPipelineConfig> -ShaderCache::GetGXUberPipelineConfig(const GXUberPipelineConfig& config) +ShaderCache::GetGXUberPipelineConfig(const GXUberPipelineUid& config) { const AbstractShader* vs; auto vs_iter = m_uber_vs_cache.shader_map.find(config.vs_uid); @@ -580,7 +582,7 @@ ShaderCache::GetGXUberPipelineConfig(const GXUberPipelineConfig& config) config.depth_state, config.blending_state); } -const AbstractPipeline* ShaderCache::InsertGXPipeline(const GXPipelineConfig& config, +const AbstractPipeline* ShaderCache::InsertGXPipeline(const GXPipelineUid& config, std::unique_ptr<AbstractPipeline> pipeline) { auto& entry = m_gx_pipeline_cache[config]; @@ -592,7 +594,7 @@ const AbstractPipeline* ShaderCache::InsertGXPipeline(const GXPipelineConfig& co } const AbstractPipeline* -ShaderCache::InsertGXUberPipeline(const GXUberPipelineConfig& config, +ShaderCache::InsertGXUberPipeline(const GXUberPipelineUid& config, std::unique_ptr<AbstractPipeline> pipeline) { auto& entry = m_gx_uber_pipeline_cache[config]; @@ -603,7 +605,7 @@ ShaderCache::InsertGXUberPipeline(const GXUberPipelineConfig& config, return entry.first.get(); } -void ShaderCache::AppendGXPipelineUID(const GXPipelineConfig& config) +void ShaderCache::AppendGXPipelineUID(const GXPipelineUid& config) { // Convert to disk format. GXPipelineDiskCacheUid disk_uid = {}; @@ -633,7 +635,7 @@ void ShaderCache::QueueVertexShaderCompile(const VertexShaderUid& uid) return true; } - virtual void Retrieve() override { shader_cache->InsertVertexShader(uid, std::move(shader)); } + void Retrieve() override { shader_cache->InsertVertexShader(uid, std::move(shader)); } private: ShaderCache* shader_cache; std::unique_ptr<AbstractShader> shader; @@ -661,11 +663,7 @@ void ShaderCache::QueueVertexUberShaderCompile(const UberShader::VertexShaderUid return true; } - virtual void Retrieve() override - { - shader_cache->InsertVertexUberShader(uid, std::move(shader)); - } - + void Retrieve() override { shader_cache->InsertVertexUberShader(uid, std::move(shader)); } private: ShaderCache* shader_cache; std::unique_ptr<AbstractShader> shader; @@ -693,7 +691,7 @@ void ShaderCache::QueuePixelShaderCompile(const PixelShaderUid& uid) return true; } - virtual void Retrieve() override { shader_cache->InsertPixelShader(uid, std::move(shader)); } + void Retrieve() override { shader_cache->InsertPixelShader(uid, std::move(shader)); } private: ShaderCache* shader_cache; std::unique_ptr<AbstractShader> shader; @@ -721,11 +719,7 @@ void ShaderCache::QueuePixelUberShaderCompile(const UberShader::PixelShaderUid& return true; } - virtual void Retrieve() override - { - shader_cache->InsertPixelUberShader(uid, std::move(shader)); - } - + void Retrieve() override { shader_cache->InsertPixelUberShader(uid, std::move(shader)); } private: ShaderCache* shader_cache; std::unique_ptr<AbstractShader> shader; @@ -737,12 +731,12 @@ void ShaderCache::QueuePixelUberShaderCompile(const UberShader::PixelShaderUid& m_async_shader_compiler->QueueWorkItem(std::move(wi)); } -void ShaderCache::QueuePipelineCompile(const GXPipelineConfig& uid) +void ShaderCache::QueuePipelineCompile(const GXPipelineUid& uid) { class PipelineWorkItem final : public AsyncShaderCompiler::WorkItem { public: - PipelineWorkItem(ShaderCache* shader_cache_, const GXPipelineConfig& uid_, + PipelineWorkItem(ShaderCache* shader_cache_, const GXPipelineUid& uid_, const AbstractPipelineConfig& config_) : shader_cache(shader_cache_), uid(uid_), config(config_) { @@ -754,11 +748,11 @@ void ShaderCache::QueuePipelineCompile(const GXPipelineConfig& uid) return true; } - virtual void Retrieve() override { shader_cache->InsertGXPipeline(uid, std::move(pipeline)); } + void Retrieve() override { shader_cache->InsertGXPipeline(uid, std::move(pipeline)); } private: ShaderCache* shader_cache; std::unique_ptr<AbstractPipeline> pipeline; - GXPipelineConfig uid; + GXPipelineUid uid; AbstractPipelineConfig config; }; @@ -775,13 +769,15 @@ void ShaderCache::QueuePipelineCompile(const GXPipelineConfig& uid) m_gx_pipeline_cache[uid].second = true; } -void ShaderCache::QueueUberPipelineCompile(const GXUberPipelineConfig& uid) +void ShaderCache::QueueUberPipelineCompile(const GXUberPipelineUid& uid) { - class UberPipelineWorkItem final : public AsyncShaderCompiler::WorkItem + // Since the shaders may not be compiled at pipelines request time, we do this in two passes. + // This is necessary because we can't access the caches in the worker thread. + class UberPipelineCompilePass final : public AsyncShaderCompiler::WorkItem { public: - UberPipelineWorkItem(ShaderCache* shader_cache_, const GXUberPipelineConfig& uid_, - const AbstractPipelineConfig& config_) + UberPipelineCompilePass(ShaderCache* shader_cache_, const GXUberPipelineUid& uid_, + const AbstractPipelineConfig& config_) : shader_cache(shader_cache_), uid(uid_), config(config_) { } @@ -792,27 +788,43 @@ void ShaderCache::QueueUberPipelineCompile(const GXUberPipelineConfig& uid) return true; } - virtual void Retrieve() override - { - shader_cache->InsertGXUberPipeline(uid, std::move(pipeline)); - } - + void Retrieve() override { shader_cache->InsertGXUberPipeline(uid, std::move(pipeline)); } private: ShaderCache* shader_cache; std::unique_ptr<AbstractPipeline> pipeline; - GXUberPipelineConfig uid; + GXUberPipelineUid uid; AbstractPipelineConfig config; }; - - auto config = GetGXUberPipelineConfig(uid); - if (!config) + class UberPipelinePreparePass final : public AsyncShaderCompiler::WorkItem { - // One or more stages failed to compile. - InsertGXUberPipeline(uid, nullptr); - return; - } + public: + UberPipelinePreparePass(ShaderCache* shader_cache_, const GXUberPipelineUid& uid_) + : shader_cache(shader_cache_), uid(uid_) + { + } + + bool Compile() override { return true; } + void Retrieve() override + { + auto config = shader_cache->GetGXUberPipelineConfig(uid); + if (!config) + { + // One or more stages failed to compile. + shader_cache->InsertGXUberPipeline(uid, nullptr); + return; + } + + auto wi = shader_cache->m_async_shader_compiler->CreateWorkItem<UberPipelineCompilePass>( + shader_cache, uid, *config); + shader_cache->m_async_shader_compiler->QueueWorkItem(std::move(wi)); + } - auto wi = m_async_shader_compiler->CreateWorkItem<UberPipelineWorkItem>(this, uid, *config); + private: + ShaderCache* shader_cache; + GXUberPipelineUid uid; + }; + + auto wi = m_async_shader_compiler->CreateWorkItem<UberPipelinePreparePass>(this, uid); m_async_shader_compiler->QueueWorkItem(std::move(wi)); m_gx_uber_pipeline_cache[uid].second = true; } @@ -841,9 +853,6 @@ void ShaderCache::PrecompileUberShaders() QueuePixelUberShaderCompile(puid); }); - // Wait for shaders to finish compiling. - WaitForAsyncCompiler(GetStringT("Compiling uber shaders...")); - // Create a dummy vertex format with no attributes. // All attributes will be enabled in GetUberVertexFormat. PortableVertexDeclaration dummy_vertex_decl = {}; @@ -856,7 +865,7 @@ void ShaderCache::PrecompileUberShaders() auto QueueDummyPipeline = [&](const UberShader::VertexShaderUid& vs_uid, const GeometryShaderUid& gs_uid, const UberShader::PixelShaderUid& ps_uid) { - GXUberPipelineConfig config; + GXUberPipelineUid config; config.vertex_format = dummy_vertex_format; config.vs_uid = vs_uid; config.gs_uid = gs_uid; diff --git a/Source/Core/VideoCommon/ShaderCache.h b/Source/Core/VideoCommon/ShaderCache.h index 6516edd8d8..8681df19be 100644 --- a/Source/Core/VideoCommon/ShaderCache.h +++ b/Source/Core/VideoCommon/ShaderCache.h @@ -19,10 +19,10 @@ #include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/AbstractShader.h" -#include "VideoCommon/NativeVertexFormat.h" - #include "VideoCommon/AsyncShaderCompiler.h" +#include "VideoCommon/GXPipelineTypes.h" #include "VideoCommon/GeometryShaderGen.h" +#include "VideoCommon/NativeVertexFormat.h" #include "VideoCommon/PixelShaderGen.h" #include "VideoCommon/RenderState.h" #include "VideoCommon/UberShaderPixel.h" @@ -33,64 +33,6 @@ class NativeVertexFormat; namespace VideoCommon { -struct GXPipelineConfig -{ - const NativeVertexFormat* vertex_format; - VertexShaderUid vs_uid; - GeometryShaderUid gs_uid; - PixelShaderUid ps_uid; - RasterizationState rasterization_state; - DepthState depth_state; - BlendingState blending_state; - - // We use memcmp() for comparing pipelines as std::tie generates a large number of instructions, - // and this map lookup can happen every draw call. However, as using memcmp() will also compare - // any padding bytes, we have to ensure these are zeroed out. - GXPipelineConfig() { std::memset(this, 0, sizeof(*this)); } - GXPipelineConfig(const GXPipelineConfig& rhs) { std::memcpy(this, &rhs, sizeof(*this)); } - GXPipelineConfig& operator=(const GXPipelineConfig& rhs) - { - std::memcpy(this, &rhs, sizeof(*this)); - return *this; - } - bool operator<(const GXPipelineConfig& rhs) const - { - return std::memcmp(this, &rhs, sizeof(*this)) < 0; - } - bool operator==(const GXPipelineConfig& rhs) const - { - return std::memcmp(this, &rhs, sizeof(*this)) == 0; - } - bool operator!=(const GXPipelineConfig& rhs) const { return !operator==(rhs); } -}; -struct GXUberPipelineConfig -{ - const NativeVertexFormat* vertex_format; - UberShader::VertexShaderUid vs_uid; - GeometryShaderUid gs_uid; - UberShader::PixelShaderUid ps_uid; - RasterizationState rasterization_state; - DepthState depth_state; - BlendingState blending_state; - - GXUberPipelineConfig() { std::memset(this, 0, sizeof(*this)); } - GXUberPipelineConfig(const GXUberPipelineConfig& rhs) { std::memcpy(this, &rhs, sizeof(*this)); } - GXUberPipelineConfig& operator=(const GXUberPipelineConfig& rhs) - { - std::memcpy(this, &rhs, sizeof(*this)); - return *this; - } - bool operator<(const GXUberPipelineConfig& rhs) const - { - return std::memcmp(this, &rhs, sizeof(*this)) < 0; - } - bool operator==(const GXUberPipelineConfig& rhs) const - { - return std::memcmp(this, &rhs, sizeof(*this)) == 0; - } - bool operator!=(const GXUberPipelineConfig& rhs) const { return !operator==(rhs); } -}; - class ShaderCache final { public: @@ -114,15 +56,15 @@ public: std::string GetUtilityShaderHeader() const; // Accesses ShaderGen shader caches - const AbstractPipeline* GetPipelineForUid(const GXPipelineConfig& uid); - const AbstractPipeline* GetUberPipelineForUid(const GXUberPipelineConfig& uid); + const AbstractPipeline* GetPipelineForUid(const GXPipelineUid& uid); + const AbstractPipeline* GetUberPipelineForUid(const GXUberPipelineUid& uid); // Accesses ShaderGen shader caches asynchronously. // The optional will be empty if this pipeline is now background compiling. - std::optional<const AbstractPipeline*> GetPipelineForUidAsync(const GXPipelineConfig& uid); + std::optional<const AbstractPipeline*> GetPipelineForUidAsync(const GXPipelineUid& uid); private: - void WaitForAsyncCompiler(const std::string& msg); + void WaitForAsyncCompiler(); void LoadShaderCaches(); void ClearShaderCaches(); void LoadPipelineUIDCache(); @@ -155,21 +97,21 @@ private: const AbstractShader* geometry_shader, const AbstractShader* pixel_shader, const RasterizationState& rasterization_state, const DepthState& depth_state, const BlendingState& blending_state); - std::optional<AbstractPipelineConfig> GetGXPipelineConfig(const GXPipelineConfig& uid); - std::optional<AbstractPipelineConfig> GetGXUberPipelineConfig(const GXUberPipelineConfig& uid); - const AbstractPipeline* InsertGXPipeline(const GXPipelineConfig& config, + std::optional<AbstractPipelineConfig> GetGXPipelineConfig(const GXPipelineUid& uid); + std::optional<AbstractPipelineConfig> GetGXUberPipelineConfig(const GXUberPipelineUid& uid); + const AbstractPipeline* InsertGXPipeline(const GXPipelineUid& config, std::unique_ptr<AbstractPipeline> pipeline); - const AbstractPipeline* InsertGXUberPipeline(const GXUberPipelineConfig& config, + const AbstractPipeline* InsertGXUberPipeline(const GXUberPipelineUid& config, std::unique_ptr<AbstractPipeline> pipeline); - void AppendGXPipelineUID(const GXPipelineConfig& config); + void AppendGXPipelineUID(const GXPipelineUid& config); // ASync Compiler Methods void QueueVertexShaderCompile(const VertexShaderUid& uid); void QueueVertexUberShaderCompile(const UberShader::VertexShaderUid& uid); void QueuePixelShaderCompile(const PixelShaderUid& uid); void QueuePixelUberShaderCompile(const UberShader::PixelShaderUid& uid); - void QueuePipelineCompile(const GXPipelineConfig& uid); - void QueueUberPipelineCompile(const GXUberPipelineConfig& uid); + void QueuePipelineCompile(const GXPipelineUid& uid); + void QueueUberPipelineCompile(const GXUberPipelineUid& uid); // Configuration bits. APIType m_api_type = APIType::Nothing; @@ -196,10 +138,8 @@ private: ShaderModuleCache<UberShader::PixelShaderUid> m_uber_ps_cache; // GX Pipeline Caches - .first - pipeline, .second - pending - // TODO: Use unordered_map for speed. - std::map<GXPipelineConfig, std::pair<std::unique_ptr<AbstractPipeline>, bool>> - m_gx_pipeline_cache; - std::map<GXUberPipelineConfig, std::pair<std::unique_ptr<AbstractPipeline>, bool>> + std::map<GXPipelineUid, std::pair<std::unique_ptr<AbstractPipeline>, bool>> m_gx_pipeline_cache; + std::map<GXUberPipelineUid, std::pair<std::unique_ptr<AbstractPipeline>, bool>> m_gx_uber_pipeline_cache; // Disk cache of pipeline UIDs diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index eac95f614f..4d07b08411 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -83,8 +83,8 @@ protected: Slope m_zslope = {}; void CalculateZSlope(NativeVertexFormat* format); - VideoCommon::GXPipelineConfig m_current_pipeline_config; - VideoCommon::GXUberPipelineConfig m_current_uber_pipeline_config; + VideoCommon::GXPipelineUid m_current_pipeline_config; + VideoCommon::GXUberPipelineUid m_current_uber_pipeline_config; const AbstractPipeline* m_current_pipeline_object = nullptr; PrimitiveType m_current_primitive_type = PrimitiveType::Points; bool m_pipeline_config_changed = true; diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index 4cc6611ee8..b84bfb6d66 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -120,6 +120,7 @@ <ClInclude Include="Fifo.h" /> <ClInclude Include="FPSCounter.h" /> <ClInclude Include="FramebufferManagerBase.h" /> + <ClInclude Include="GXPipelineTypes.h" /> <ClInclude Include="ShaderCache.h" /> <ClInclude Include="UberShaderCommon.h" /> <ClInclude Include="UberShaderPixel.h" /> @@ -190,4 +191,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index ca0fe0029b..f356cc9ef4 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -198,7 +198,7 @@ <Filter>Base</Filter> </ClCompile> <ClCompile Include="ShaderCache.cpp"> - <Filter>Shader Managers</Filter> + <Filter>Shader Generators</Filter> </ClCompile> </ItemGroup> <ItemGroup> @@ -381,11 +381,14 @@ <ClInclude Include="AbstractFramebuffer.h"> <Filter>Base</Filter> </ClInclude> + <ClInclude Include="GXPipelineTypes.h"> + <Filter>Shader Generators</Filter> + </ClInclude> <ClInclude Include="ShaderCache.h"> - <Filter>Shader Managers</Filter> + <Filter>Shader Generators</Filter> </ClInclude> </ItemGroup> <ItemGroup> <Text Include="CMakeLists.txt" /> </ItemGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index c14a00757a..271223ba3d 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -102,6 +102,7 @@ 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); + bWaitForShadersBeforeStarting = Config::Get(Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING); iUberShaderMode = static_cast<UberShaderMode>(Config::Get(Config::GFX_UBERSHADER_MODE)); iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS); iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS); @@ -196,6 +197,10 @@ u32 VideoConfig::GetShaderCompilerThreads() const u32 VideoConfig::GetShaderPrecompilerThreads() const { + // When using background compilation, always keep the same thread count. + if (bWaitForShadersBeforeStarting) + return GetShaderCompilerThreads(); + if (!backend_info.bSupportsBackgroundCompiling) return 0; diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 2b69919528..c8bded371b 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -169,6 +169,7 @@ struct VideoConfig final int iCommandBufferExecuteInterval; // Shader compilation settings. + bool bWaitForShadersBeforeStarting; UberShaderMode iUberShaderMode; // Number of shader compiler threads. |
