diff --git a/renderdoc/driver/vulkan/vk_shader_cache.cpp b/renderdoc/driver/vulkan/vk_shader_cache.cpp index 19af5b38a..b5bfb61f6 100644 --- a/renderdoc/driver/vulkan/vk_shader_cache.cpp +++ b/renderdoc/driver/vulkan/vk_shader_cache.cpp @@ -239,7 +239,6 @@ VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver) if(driverVersion.RunningOnMetal()) globalDefines += "#define METAL_BACKEND\n"; - rdcstr src; rdcspv::CompilationSettings compileSettings; compileSettings.lang = rdcspv::InputLanguage::VulkanGLSL; @@ -267,6 +266,8 @@ VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver) if(config.flags & BuiltinShaderFlags::TextureTypeParameterised) textureTypeCount = (size_t)BuiltinShaderTextureType::Count; + compileSettings.stage = config.stage; + // for shaders that aren't parameterised these loops will be a no-op that only iterates once, // and fills in [First][First] entry. for(size_t baseType = (size_t)BuiltinShaderBaseType::First; baseType < baseTypeCount; baseType++) @@ -279,14 +280,37 @@ VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver) defines += rdcstr("#define SHADER_RESTYPE ") + ToStr(textureType) + "\n"; defines += rdcstr("#define SHADER_BASETYPE ") + ToStr(baseType) + "\n"; - src = GenerateGLSLShader(GetDynamicEmbeddedResource(config.resource), ShaderType::Vulkan, - 430, defines); + SPIRVBlob &blob = m_BuiltinShaderBlobs[i][baseType][textureType]; + rdcstr source = GetDynamicEmbeddedResource(config.resource); - compileSettings.stage = config.stage; - rdcstr err = - GetSPIRVBlob(compileSettings, src, m_BuiltinShaderBlobs[i][baseType][textureType]); + uint32_t inputHash = strhash(source.c_str()); + inputHash = strhash(defines.c_str(), inputHash); - if(!err.empty() || m_BuiltinShaderBlobs[i][baseType][textureType] == VK_NULL_HANDLE) + // bump this version if anything inside GenerateGLSLShader changes. This is used to + // determine if we can skip the call to GenerateGLSLShader (which calls out to glslang). + // Otherwise we'll use the cached SPIR-V generated by the previous call using the same + // source & defines. + inputHash = strhash("inputHashVersion1", inputHash); + + rdcstr err; + + if(m_ShaderCache.find(inputHash) != m_ShaderCache.end()) + blob = m_ShaderCache[inputHash]; + + if(blob == NULL) + { + err = GetSPIRVBlob(compileSettings, + GenerateGLSLShader(source, ShaderType::Vulkan, 430, defines), blob); + + // if we missed the inputHash, make a copy there too. + if(m_CacheShaders) + { + m_ShaderCache[inputHash] = new rdcarray(*blob); + m_ShaderCacheDirty = true; + } + } + + if(!err.empty() || blob == VK_NULL_HANDLE) { RDCERR("Error compiling builtin %u (baseType %zu textureType %zu): %s", (uint32_t)i, baseType, textureType, err.c_str()); @@ -297,8 +321,8 @@ VulkanShaderCache::VulkanShaderCache(WrappedVulkan *driver) VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, NULL, 0, - m_BuiltinShaderBlobs[i][baseType][textureType]->size() * sizeof(uint32_t), - m_BuiltinShaderBlobs[i][baseType][textureType]->data(), + blob->size() * sizeof(uint32_t), + blob->data(), }; VkResult vkr = driver->vkCreateShaderModule(