Fix specializing graphics routines for the pipeline layout

Shader modules can be used by different pipelines, even with incompatible
layouts. The generated code differs based on the layout, so we must use
it as part of the cache key.

This change conservatively assumes each pipeline layout to be unique, so
a serial ID is used to differentiate between them.

Bug: b/154660947
Change-Id: I65cce79d7780d8b9eab1752a5005202263dc3c1d
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/44228
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index 6d49315..7f9706e 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -19,6 +19,7 @@
 #include "Pipeline/PixelProgram.hpp"
 #include "System/Debug.hpp"
 #include "Vulkan/VkImageView.hpp"
+#include "Vulkan/VkPipelineLayout.hpp"
 
 #include <cstring>
 
@@ -99,10 +100,12 @@
 	if(context->pixelShader)
 	{
 		state.shaderID = context->pixelShader->getSerialID();
+		state.pipelineLayoutIdentifier = context->pipelineLayout->identifier;
 	}
 	else
 	{
 		state.shaderID = 0;
+		state.pipelineLayoutIdentifier = 0;
 	}
 
 	state.alphaToCoverage = context->alphaToCoverage;
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index 3ba54d8..309fa4e 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -63,6 +63,7 @@
 		uint32_t computeHash();
 
 		uint64_t shaderID;
+		uint32_t pipelineLayoutIdentifier;
 
 		unsigned int numClipDistances;
 		unsigned int numCullDistances;
diff --git a/src/Device/VertexProcessor.cpp b/src/Device/VertexProcessor.cpp
index 54d5df8..f069c1c 100644
--- a/src/Device/VertexProcessor.cpp
+++ b/src/Device/VertexProcessor.cpp
@@ -18,6 +18,7 @@
 #include "Pipeline/VertexProgram.hpp"
 #include "System/Debug.hpp"
 #include "System/Math.hpp"
+#include "Vulkan/VkPipelineLayout.hpp"
 
 #include <cstring>
 
@@ -77,6 +78,7 @@
 	State state;
 
 	state.shaderID = context->vertexShader->getSerialID();
+	state.pipelineLayoutIdentifier = context->pipelineLayout->identifier;
 	state.robustBufferAccess = context->robustBufferAccess;
 	state.isPoint = context->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
 
diff --git a/src/Device/VertexProcessor.hpp b/src/Device/VertexProcessor.hpp
index d8acdd9..44a7be7 100644
--- a/src/Device/VertexProcessor.hpp
+++ b/src/Device/VertexProcessor.hpp
@@ -63,6 +63,7 @@
 		uint32_t computeHash();
 
 		uint64_t shaderID;
+		uint32_t pipelineLayoutIdentifier;
 
 		struct Input
 		{
diff --git a/src/Vulkan/VkPipelineLayout.cpp b/src/Vulkan/VkPipelineLayout.cpp
index dfd106c..ba9a777 100644
--- a/src/Vulkan/VkPipelineLayout.cpp
+++ b/src/Vulkan/VkPipelineLayout.cpp
@@ -13,12 +13,17 @@
 // limitations under the License.
 
 #include "VkPipelineLayout.hpp"
+
+#include <atomic>
 #include <cstring>
 
 namespace vk {
 
+static std::atomic<uint32_t> layoutIdentifierSerial = { 1 };  // Start at 1. 0 is invalid/void layout.
+
 PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, void *mem)
-    : setLayoutCount(pCreateInfo->setLayoutCount)
+    : identifier(layoutIdentifierSerial++)
+    , setLayoutCount(pCreateInfo->setLayoutCount)
     , pushConstantRangeCount(pCreateInfo->pushConstantRangeCount)
 {
 	char *hostMem = reinterpret_cast<char *>(mem);
diff --git a/src/Vulkan/VkPipelineLayout.hpp b/src/Vulkan/VkPipelineLayout.hpp
index a1b4ac8..59a4283 100644
--- a/src/Vulkan/VkPipelineLayout.hpp
+++ b/src/Vulkan/VkPipelineLayout.hpp
@@ -34,6 +34,8 @@
 	// the given descriptor set.
 	uint32_t getDynamicOffsetBase(size_t descriptorSet) const;
 
+	const uint32_t identifier;
+
 private:
 	uint32_t setLayoutCount = 0;
 	DescriptorSetLayout **setLayouts = nullptr;