From a8343cc19a3728d4a44c279dff167503a6eaecfc Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 24 Jun 2017 19:43:58 +1000 Subject: Vulkan: Don't save pipeline cache if shader cache is disabled We still create a pipeline cache object, since that speeds up driver's creation of pipelines at runtime. However, we should not save it. --- Source/Core/VideoBackends/Vulkan/ObjectCache.cpp | 85 +++++++++++++++--------- 1 file changed, 53 insertions(+), 32 deletions(-) (limited to 'Source/Core/VideoBackends/Vulkan/ObjectCache.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 4fadbfcfc4..ad138cc754 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -49,9 +49,17 @@ bool ObjectCache::Initialize() if (!CreatePipelineLayouts()) return false; - LoadShaderCaches(); - if (!CreatePipelineCache(true)) - return false; + if (g_ActiveConfig.bShaderCache) + { + LoadShaderCaches(); + if (!LoadPipelineCache()) + return false; + } + else + { + if (!CreatePipelineCache()) + return false; + } if (!CreateUtilityShaderVertexFormat()) return false; @@ -465,26 +473,44 @@ public: void Read(const u32& key, const u8* value, u32 value_size) override {} }; -bool ObjectCache::CreatePipelineCache(bool load_from_disk) +bool ObjectCache::CreatePipelineCache() +{ + m_pipeline_cache_filename = GetDiskCacheFileName("pipeline"); + + VkPipelineCacheCreateInfo info = { + VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType + nullptr, // const void* pNext + 0, // VkPipelineCacheCreateFlags flags + 0, // size_t initialDataSize + nullptr // const void* pInitialData + }; + + VkResult res = + vkCreatePipelineCache(g_vulkan_context->GetDevice(), &info, nullptr, &m_pipeline_cache); + if (res == VK_SUCCESS) + return true; + + LOG_VULKAN_ERROR(res, "vkCreatePipelineCache failed: "); + return false; +} + +bool ObjectCache::LoadPipelineCache() { // We have to keep the pipeline cache file name around since when we save it // we delete the old one, by which time the game's unique ID is already cleared. m_pipeline_cache_filename = GetDiskCacheFileName("pipeline"); std::vector disk_data; - if (load_from_disk) - { - LinearDiskCache disk_cache; - PipelineCacheReadCallback read_callback(&disk_data); - if (disk_cache.OpenAndRead(m_pipeline_cache_filename, read_callback) != 1) - disk_data.clear(); - } + LinearDiskCache disk_cache; + PipelineCacheReadCallback read_callback(&disk_data); + if (disk_cache.OpenAndRead(m_pipeline_cache_filename, read_callback) != 1) + disk_data.clear(); if (!disk_data.empty() && !ValidatePipelineCache(disk_data.data(), disk_data.size())) { // Don't use this data. In fact, we should delete it to prevent it from being used next time. File::Delete(m_pipeline_cache_filename); - disk_data.clear(); + return CreatePipelineCache(); } VkPipelineCacheCreateInfo info = { @@ -492,7 +518,7 @@ bool ObjectCache::CreatePipelineCache(bool load_from_disk) nullptr, // const void* pNext 0, // VkPipelineCacheCreateFlags flags disk_data.size(), // size_t initialDataSize - !disk_data.empty() ? disk_data.data() : nullptr, // const void* pInitialData + disk_data.data() // const void* pInitialData }; VkResult res = @@ -502,14 +528,7 @@ bool ObjectCache::CreatePipelineCache(bool load_from_disk) // Failed to create pipeline cache, try with it empty. LOG_VULKAN_ERROR(res, "vkCreatePipelineCache failed, trying empty cache: "); - info.initialDataSize = 0; - info.pInitialData = nullptr; - res = vkCreatePipelineCache(g_vulkan_context->GetDevice(), &info, nullptr, &m_pipeline_cache); - if (res == VK_SUCCESS) - return true; - - LOG_VULKAN_ERROR(res, "vkCreatePipelineCache failed: "); - return false; + return CreatePipelineCache(); } // Based on Vulkan 1.0 specification, @@ -644,19 +663,16 @@ struct ShaderCacheReader : public LinearDiskCacheReader void ObjectCache::LoadShaderCaches() { - if (g_ActiveConfig.bShaderCache) - { - ShaderCacheReader vs_reader(m_vs_cache.shader_map); - m_vs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("vs"), vs_reader); + ShaderCacheReader vs_reader(m_vs_cache.shader_map); + m_vs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("vs"), vs_reader); - ShaderCacheReader ps_reader(m_ps_cache.shader_map); - m_ps_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("ps"), ps_reader); + ShaderCacheReader ps_reader(m_ps_cache.shader_map); + m_ps_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("ps"), ps_reader); - if (g_vulkan_context->SupportsGeometryShaders()) - { - ShaderCacheReader gs_reader(m_gs_cache.shader_map); - m_gs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("gs"), gs_reader); - } + if (g_vulkan_context->SupportsGeometryShaders()) + { + ShaderCacheReader gs_reader(m_gs_cache.shader_map); + m_gs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("gs"), gs_reader); } SETSTAT(stats.numPixelShadersCreated, static_cast(m_ps_cache.shader_map.size())); @@ -684,6 +700,11 @@ void ObjectCache::DestroyShaderCaches() if (g_vulkan_context->SupportsGeometryShaders()) DestroyShaderCache(m_gs_cache); + + SETSTAT(stats.numPixelShadersCreated, 0); + SETSTAT(stats.numPixelShadersAlive, 0); + SETSTAT(stats.numVertexShadersCreated, 0); + SETSTAT(stats.numVertexShadersAlive, 0); } VkShaderModule ObjectCache::GetVertexShaderForUid(const VertexShaderUid& uid) -- cgit v1.2.3 From b380f292b47c8b1a3e1711a665a3469074715485 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 24 Jun 2017 19:58:14 +1000 Subject: Vulkan: Reload pipeline cache when relevant host config changes --- Source/Core/VideoBackends/Vulkan/ObjectCache.cpp | 41 +++++++++++++++++++----- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'Source/Core/VideoBackends/Vulkan/ObjectCache.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index ad138cc754..d63533b7f4 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -446,10 +446,14 @@ void ObjectCache::ClearPipelineCache() m_compute_pipeline_objects.clear(); } -std::string ObjectCache::GetDiskCacheFileName(const char* type) +std::string ObjectCache::GetDiskCacheFileName(const char* type, bool include_gameid, + bool include_host_config) { - return StringFromFormat("%svulkan-%s-%s.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), - SConfig::GetInstance().GetGameID().c_str(), type); + return StringFromFormat( + "%svulkan-%s%s%s%s%s.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), type, + include_gameid ? "-" : "", include_gameid ? SConfig::GetInstance().GetGameID().c_str() : "", + include_host_config ? "-" : "", + include_host_config ? g_ActiveConfig.GetHostConfigFilename().c_str() : ""); } class PipelineCacheReadCallback : public LinearDiskCacheReader @@ -475,7 +479,10 @@ public: bool ObjectCache::CreatePipelineCache() { - m_pipeline_cache_filename = GetDiskCacheFileName("pipeline"); + // Vulkan pipeline caches can be shared between games for shader compile time reduction. + // This assumes that drivers don't create all pipelines in the cache on load time, only + // when a lookup occurs that matches a pipeline (or pipeline data) in the cache. + m_pipeline_cache_filename = GetDiskCacheFileName("pipeline", false, true); VkPipelineCacheCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType @@ -498,7 +505,7 @@ bool ObjectCache::LoadPipelineCache() { // We have to keep the pipeline cache file name around since when we save it // we delete the old one, by which time the game's unique ID is already cleared. - m_pipeline_cache_filename = GetDiskCacheFileName("pipeline"); + m_pipeline_cache_filename = GetDiskCacheFileName("pipeline", false, true); std::vector disk_data; LinearDiskCache disk_cache; @@ -664,15 +671,15 @@ struct ShaderCacheReader : public LinearDiskCacheReader void ObjectCache::LoadShaderCaches() { ShaderCacheReader vs_reader(m_vs_cache.shader_map); - m_vs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("vs"), vs_reader); + m_vs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("vs", true, true), vs_reader); ShaderCacheReader ps_reader(m_ps_cache.shader_map); - m_ps_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("ps"), ps_reader); + m_ps_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("ps", true, true), ps_reader); if (g_vulkan_context->SupportsGeometryShaders()) { ShaderCacheReader gs_reader(m_gs_cache.shader_map); - m_gs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("gs"), gs_reader); + m_gs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("gs", true, true), gs_reader); } SETSTAT(stats.numPixelShadersCreated, static_cast(m_ps_cache.shader_map.size())); @@ -684,6 +691,7 @@ void ObjectCache::LoadShaderCaches() template static void DestroyShaderCache(T& cache) { + cache.disk_cache.Sync(); cache.disk_cache.Close(); for (const auto& it : cache.shader_map) { @@ -825,6 +833,23 @@ void ObjectCache::RecompileSharedShaders() PanicAlert("Failed to recompile shared shaders."); } +void ObjectCache::ReloadShaderAndPipelineCaches() +{ + SavePipelineCache(); + DestroyShaderCaches(); + DestroyPipelineCache(); + + if (g_ActiveConfig.bShaderCache) + { + LoadShaderCaches(); + LoadPipelineCache(); + } + else + { + CreatePipelineCache(); + } +} + bool ObjectCache::CreateDescriptorSetLayouts() { static const VkDescriptorSetLayoutBinding ubo_set_bindings[] = { -- cgit v1.2.3 From d01b0bf60fba2101e45cfac1e5747edcdbab5fc1 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 19 Jul 2017 20:35:17 +1000 Subject: VideoCommon: Move shader cache filename generation to common --- Source/Core/VideoBackends/Vulkan/ObjectCache.cpp | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'Source/Core/VideoBackends/Vulkan/ObjectCache.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index d63533b7f4..15c73c5098 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -446,16 +446,6 @@ void ObjectCache::ClearPipelineCache() m_compute_pipeline_objects.clear(); } -std::string ObjectCache::GetDiskCacheFileName(const char* type, bool include_gameid, - bool include_host_config) -{ - return StringFromFormat( - "%svulkan-%s%s%s%s%s.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), type, - include_gameid ? "-" : "", include_gameid ? SConfig::GetInstance().GetGameID().c_str() : "", - include_host_config ? "-" : "", - include_host_config ? g_ActiveConfig.GetHostConfigFilename().c_str() : ""); -} - class PipelineCacheReadCallback : public LinearDiskCacheReader { public: @@ -482,7 +472,8 @@ bool ObjectCache::CreatePipelineCache() // Vulkan pipeline caches can be shared between games for shader compile time reduction. // This assumes that drivers don't create all pipelines in the cache on load time, only // when a lookup occurs that matches a pipeline (or pipeline data) in the cache. - m_pipeline_cache_filename = GetDiskCacheFileName("pipeline", false, true); + m_pipeline_cache_filename = + g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "Pipeline", false, true); VkPipelineCacheCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType @@ -505,7 +496,8 @@ bool ObjectCache::LoadPipelineCache() { // We have to keep the pipeline cache file name around since when we save it // we delete the old one, by which time the game's unique ID is already cleared. - m_pipeline_cache_filename = GetDiskCacheFileName("pipeline", false, true); + m_pipeline_cache_filename = + g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "Pipeline", false, true); std::vector disk_data; LinearDiskCache disk_cache; @@ -671,15 +663,18 @@ struct ShaderCacheReader : public LinearDiskCacheReader void ObjectCache::LoadShaderCaches() { ShaderCacheReader vs_reader(m_vs_cache.shader_map); - m_vs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("vs", true, true), vs_reader); + m_vs_cache.disk_cache.OpenAndRead( + g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "VS", true, true), vs_reader); ShaderCacheReader ps_reader(m_ps_cache.shader_map); - m_ps_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("ps", true, true), ps_reader); + m_ps_cache.disk_cache.OpenAndRead( + g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "PS", true, true), ps_reader); if (g_vulkan_context->SupportsGeometryShaders()) { ShaderCacheReader gs_reader(m_gs_cache.shader_map); - m_gs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("gs", true, true), gs_reader); + m_gs_cache.disk_cache.OpenAndRead( + g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "GS", true, true), gs_reader); } SETSTAT(stats.numPixelShadersCreated, static_cast(m_ps_cache.shader_map.size())); -- cgit v1.2.3 From 3ea9d86faa2544b8c1c235db9456f271baf42fec Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 20 Jul 2017 17:10:02 +1000 Subject: ShaderGen: Pass host config to shader generation functions Also moves the host config checks to common. --- Source/Core/VideoBackends/Vulkan/ObjectCache.cpp | 27 ++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'Source/Core/VideoBackends/Vulkan/ObjectCache.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 15c73c5098..7f7dc93ccf 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -472,8 +472,7 @@ bool ObjectCache::CreatePipelineCache() // Vulkan pipeline caches can be shared between games for shader compile time reduction. // This assumes that drivers don't create all pipelines in the cache on load time, only // when a lookup occurs that matches a pipeline (or pipeline data) in the cache. - m_pipeline_cache_filename = - g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "Pipeline", false, true); + m_pipeline_cache_filename = GetDiskShaderCacheFileName(APIType::Vulkan, "Pipeline", false, true); VkPipelineCacheCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType @@ -496,8 +495,7 @@ bool ObjectCache::LoadPipelineCache() { // We have to keep the pipeline cache file name around since when we save it // we delete the old one, by which time the game's unique ID is already cleared. - m_pipeline_cache_filename = - g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "Pipeline", false, true); + m_pipeline_cache_filename = GetDiskShaderCacheFileName(APIType::Vulkan, "Pipeline", false, true); std::vector disk_data; LinearDiskCache disk_cache; @@ -663,18 +661,18 @@ struct ShaderCacheReader : public LinearDiskCacheReader void ObjectCache::LoadShaderCaches() { ShaderCacheReader vs_reader(m_vs_cache.shader_map); - m_vs_cache.disk_cache.OpenAndRead( - g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "VS", true, true), vs_reader); + m_vs_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "VS", true, true), + vs_reader); ShaderCacheReader ps_reader(m_ps_cache.shader_map); - m_ps_cache.disk_cache.OpenAndRead( - g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "PS", true, true), ps_reader); + m_ps_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "PS", true, true), + ps_reader); if (g_vulkan_context->SupportsGeometryShaders()) { ShaderCacheReader gs_reader(m_gs_cache.shader_map); - m_gs_cache.disk_cache.OpenAndRead( - g_ActiveConfig.GetDiskCacheFileName(APIType::Vulkan, "GS", true, true), gs_reader); + m_gs_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "GS", true, true), + gs_reader); } SETSTAT(stats.numPixelShadersCreated, static_cast(m_ps_cache.shader_map.size())); @@ -719,7 +717,8 @@ VkShaderModule ObjectCache::GetVertexShaderForUid(const VertexShaderUid& uid) // Not in the cache, so compile the shader. ShaderCompiler::SPIRVCodeVector spv; VkShaderModule module = VK_NULL_HANDLE; - ShaderCode source_code = GenerateVertexShaderCode(APIType::Vulkan, uid.GetUidData()); + ShaderCode source_code = + GenerateVertexShaderCode(APIType::Vulkan, ShaderHostConfig::GetCurrent(), uid.GetUidData()); if (ShaderCompiler::CompileVertexShader(&spv, source_code.GetBuffer().c_str(), source_code.GetBuffer().length())) { @@ -749,7 +748,8 @@ VkShaderModule ObjectCache::GetGeometryShaderForUid(const GeometryShaderUid& uid // Not in the cache, so compile the shader. ShaderCompiler::SPIRVCodeVector spv; VkShaderModule module = VK_NULL_HANDLE; - ShaderCode source_code = GenerateGeometryShaderCode(APIType::Vulkan, uid.GetUidData()); + ShaderCode source_code = + GenerateGeometryShaderCode(APIType::Vulkan, ShaderHostConfig::GetCurrent(), uid.GetUidData()); if (ShaderCompiler::CompileGeometryShader(&spv, source_code.GetBuffer().c_str(), source_code.GetBuffer().length())) { @@ -774,7 +774,8 @@ VkShaderModule ObjectCache::GetPixelShaderForUid(const PixelShaderUid& uid) // Not in the cache, so compile the shader. ShaderCompiler::SPIRVCodeVector spv; VkShaderModule module = VK_NULL_HANDLE; - ShaderCode source_code = GeneratePixelShaderCode(APIType::Vulkan, uid.GetUidData()); + ShaderCode source_code = + GeneratePixelShaderCode(APIType::Vulkan, ShaderHostConfig::GetCurrent(), uid.GetUidData()); if (ShaderCompiler::CompileFragmentShader(&spv, source_code.GetBuffer().c_str(), source_code.GetBuffer().length())) { -- cgit v1.2.3