Optimize SPIR-V binary cache reuse This change removes state from the SPIR-V binary cache's key that isn't used to uniquely identify optimized SPIR-V. Specifically, SPIR-V optimization is done on entire shader modules, and the result can be reused for multiple entry points. The renderpass/subpass information also isn't used to affect SPIR-V optimization. Bug: b/197982536 Change-Id: I4894b40163946836b0f1831d3222fe4dc668f68a Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/57149 Tested-by: Nicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp index ef2da43..0ff6777 100644 --- a/src/Vulkan/VkPipeline.cpp +++ b/src/Vulkan/VkPipeline.cpp
@@ -113,22 +113,6 @@ return code; } -std::shared_ptr<sw::SpirvShader> createShader( - const vk::PipelineCache::SpirvShaderKey &key, - const vk::ShaderModule *module, - const sw::SpirvBinary &spirv, - bool robustBufferAccess, - const std::shared_ptr<vk::dbg::Context> &dbgctx) -{ - // If the pipeline has specialization constants, assume they're unique and - // use a new serial ID so the shader gets recompiled. - uint32_t codeSerialID = (key.getSpecializationInfo() ? vk::ShaderModule::nextSerialID() : module->getSerialID()); - - // TODO(b/119409619): use allocator. - return std::make_shared<sw::SpirvShader>(codeSerialID, key.getPipelineStage(), key.getEntryPointName().c_str(), - spirv, key.getRenderPass(), key.getSubpassIndex(), robustBufferAccess, dbgctx); -} - std::shared_ptr<sw::ComputeProgram> createProgram(vk::Device *device, std::shared_ptr<sw::SpirvShader> shader, const vk::PipelineLayout *layout) { MARL_SCOPED_EVENT("createProgram"); @@ -241,10 +225,7 @@ const bool optimize = !dbgctx; const ShaderModule *module = vk::Cast(pStage->module); - const PipelineCache::SpirvShaderKey key(pStage->stage, pStage->pName, module->getCode(), - vk::Cast(pCreateInfo->renderPass), pCreateInfo->subpass, - pStage->pSpecializationInfo, optimize); - auto pipelineStage = key.getPipelineStage(); + const PipelineCache::SpirvShaderKey key(module->getCode(), pStage->pSpecializationInfo, optimize); sw::SpirvBinary spirv; @@ -259,9 +240,15 @@ spirv = optimizeSpirv(key); } - auto shader = createShader(key, module, spirv, robustBufferAccess, dbgctx); + // If the pipeline has specialization constants, assume they're unique and + // use a new serial ID so the shader gets recompiled. + uint32_t codeSerialID = (key.getSpecializationInfo() ? vk::ShaderModule::nextSerialID() : module->getSerialID()); - setShader(pipelineStage, shader); + // TODO(b/119409619): use allocator. + auto shader = std::make_shared<sw::SpirvShader>(codeSerialID, pStage->stage, pStage->pName, spirv, + vk::Cast(pCreateInfo->renderPass), pCreateInfo->subpass, robustBufferAccess, dbgctx); + + setShader(pStage->stage, shader); } } @@ -295,8 +282,7 @@ // instructions. const bool optimize = !dbgctx; - const PipelineCache::SpirvShaderKey shaderKey( - stage.stage, stage.pName, module->getCode(), nullptr, 0, stage.pSpecializationInfo, optimize); + const PipelineCache::SpirvShaderKey shaderKey(module->getCode(), stage.pSpecializationInfo, optimize); sw::SpirvBinary spirv; @@ -311,7 +297,13 @@ spirv = optimizeSpirv(shaderKey); } - shader = createShader(shaderKey, module, spirv, robustBufferAccess, dbgctx); + // If the pipeline has specialization constants, assume they're unique and + // use a new serial ID so the shader gets recompiled. + uint32_t codeSerialID = (stage.pSpecializationInfo ? vk::ShaderModule::nextSerialID() : module->getSerialID()); + + // TODO(b/119409619): use allocator. + shader = std::make_shared<sw::SpirvShader>(codeSerialID, stage.stage, stage.pName, spirv, + nullptr, 0, robustBufferAccess, dbgctx); const PipelineCache::ComputeProgramKey programKey(shader->getSerialID(), layout->identifier);
diff --git a/src/Vulkan/VkPipelineCache.cpp b/src/Vulkan/VkPipelineCache.cpp index 87b4c89..506e670 100644 --- a/src/Vulkan/VkPipelineCache.cpp +++ b/src/Vulkan/VkPipelineCache.cpp
@@ -18,18 +18,10 @@ namespace vk { -PipelineCache::SpirvShaderKey::SpirvShaderKey(const VkShaderStageFlagBits pipelineStage, - const std::string &entryPointName, - const sw::SpirvBinary &insns, - const vk::RenderPass *renderPass, - const uint32_t subpassIndex, +PipelineCache::SpirvShaderKey::SpirvShaderKey(const sw::SpirvBinary &insns, const vk::SpecializationInfo &specializationInfo, bool optimize) - : pipelineStage(pipelineStage) - , entryPointName(entryPointName) - , insns(insns) - , renderPass(renderPass) - , subpassIndex(subpassIndex) + : insns(insns) , specializationInfo(specializationInfo) , optimize(optimize) { @@ -37,38 +29,12 @@ bool PipelineCache::SpirvShaderKey::operator<(const SpirvShaderKey &other) const { - if(pipelineStage != other.pipelineStage) - { - return pipelineStage < other.pipelineStage; - } - - if(renderPass != other.renderPass) - { - return renderPass < other.renderPass; - } - - if(subpassIndex != other.subpassIndex) - { - return subpassIndex < other.subpassIndex; - } - if(insns.size() != other.insns.size()) { return insns.size() < other.insns.size(); } - if(entryPointName.size() != other.entryPointName.size()) - { - return entryPointName.size() < other.entryPointName.size(); - } - - int cmp = memcmp(entryPointName.c_str(), other.entryPointName.c_str(), entryPointName.size()); - if(cmp != 0) - { - return cmp < 0; - } - - cmp = memcmp(insns.data(), other.insns.data(), insns.size() * sizeof(uint32_t)); + int cmp = memcmp(insns.data(), other.insns.data(), insns.size() * sizeof(uint32_t)); if(cmp != 0) { return cmp < 0;
diff --git a/src/Vulkan/VkPipelineCache.hpp b/src/Vulkan/VkPipelineCache.hpp index 9e950c6..3b00cb6 100644 --- a/src/Vulkan/VkPipelineCache.hpp +++ b/src/Vulkan/VkPipelineCache.hpp
@@ -55,30 +55,18 @@ struct SpirvShaderKey { - SpirvShaderKey(const VkShaderStageFlagBits pipelineStage, - const std::string &entryPointName, - const sw::SpirvBinary &insns, - const vk::RenderPass *renderPass, - const uint32_t subpassIndex, + SpirvShaderKey(const sw::SpirvBinary &insns, const vk::SpecializationInfo &specializationInfo, bool optimize); bool operator<(const SpirvShaderKey &other) const; - const VkShaderStageFlagBits &getPipelineStage() const { return pipelineStage; } - const std::string &getEntryPointName() const { return entryPointName; } const sw::SpirvBinary &getInsns() const { return insns; } - const vk::RenderPass *getRenderPass() const { return renderPass; } - uint32_t getSubpassIndex() const { return subpassIndex; } const VkSpecializationInfo *getSpecializationInfo() const { return specializationInfo.get(); } bool getOptimization() const { return optimize; } private: - const VkShaderStageFlagBits pipelineStage; - const std::string entryPointName; const sw::SpirvBinary insns; - const vk::RenderPass *renderPass; - const uint32_t subpassIndex; const vk::SpecializationInfo specializationInfo; const bool optimize; };