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;
 	};