diff options
| author | Stenzek <stenzek@users.noreply.github.com> | 2017-07-27 13:30:38 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-27 13:30:38 +1000 |
| commit | a11bde7d167c65bb693e5138e47dd4586683c092 (patch) | |
| tree | 84f9128b0478b0b18e271e0426fceb499c9e72e3 /Source/Core/VideoBackends/Vulkan/ObjectCache.cpp | |
| parent | 10db1bcbca947a56e872ed4b6625d9d3de31b298 (diff) | |
| parent | 3ea9d86faa2544b8c1c235db9456f271baf42fec (diff) | |
Merge pull request #5679 from stenzek/no-host-state-in-uids
ShaderGen: Decouple host state from shader UIDs
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/ObjectCache.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/ObjectCache.cpp | 126 |
1 files changed, 84 insertions, 42 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 4fadbfcfc4..7f7dc93ccf 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; @@ -438,12 +446,6 @@ void ObjectCache::ClearPipelineCache() m_compute_pipeline_objects.clear(); } -std::string ObjectCache::GetDiskCacheFileName(const char* type) -{ - return StringFromFormat("%svulkan-%s-%s.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), - SConfig::GetInstance().GetGameID().c_str(), type); -} - class PipelineCacheReadCallback : public LinearDiskCacheReader<u32, u8> { public: @@ -465,26 +467,47 @@ public: void Read(const u32& key, const u8* value, u32 value_size) override {} }; -bool ObjectCache::CreatePipelineCache(bool load_from_disk) +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 = GetDiskShaderCacheFileName(APIType::Vulkan, "Pipeline", false, true); + + 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"); + m_pipeline_cache_filename = GetDiskShaderCacheFileName(APIType::Vulkan, "Pipeline", false, true); std::vector<u8> disk_data; - if (load_from_disk) - { - LinearDiskCache<u32, u8> disk_cache; - PipelineCacheReadCallback read_callback(&disk_data); - if (disk_cache.OpenAndRead(m_pipeline_cache_filename, read_callback) != 1) - disk_data.clear(); - } + LinearDiskCache<u32, u8> 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 +515,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 +525,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 +660,19 @@ struct ShaderCacheReader : public LinearDiskCacheReader<Uid, u32> void ObjectCache::LoadShaderCaches() { - if (g_ActiveConfig.bShaderCache) - { - ShaderCacheReader<VertexShaderUid> vs_reader(m_vs_cache.shader_map); - m_vs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("vs"), vs_reader); + ShaderCacheReader<VertexShaderUid> vs_reader(m_vs_cache.shader_map); + m_vs_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "VS", true, true), + vs_reader); - ShaderCacheReader<PixelShaderUid> ps_reader(m_ps_cache.shader_map); - m_ps_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("ps"), ps_reader); + ShaderCacheReader<PixelShaderUid> ps_reader(m_ps_cache.shader_map); + m_ps_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "PS", true, true), + ps_reader); - if (g_vulkan_context->SupportsGeometryShaders()) - { - ShaderCacheReader<GeometryShaderUid> gs_reader(m_gs_cache.shader_map); - m_gs_cache.disk_cache.OpenAndRead(GetDiskCacheFileName("gs"), gs_reader); - } + if (g_vulkan_context->SupportsGeometryShaders()) + { + ShaderCacheReader<GeometryShaderUid> gs_reader(m_gs_cache.shader_map); + m_gs_cache.disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::Vulkan, "GS", true, true), + gs_reader); } SETSTAT(stats.numPixelShadersCreated, static_cast<int>(m_ps_cache.shader_map.size())); @@ -668,6 +684,7 @@ void ObjectCache::LoadShaderCaches() template <typename T> static void DestroyShaderCache(T& cache) { + cache.disk_cache.Sync(); cache.disk_cache.Close(); for (const auto& it : cache.shader_map) { @@ -684,6 +701,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) @@ -695,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())) { @@ -725,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())) { @@ -750,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())) { @@ -804,6 +829,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[] = { |
