Store the SPIR-V binary of a vk::ShaderModule in an sw::SpirvBinary

Previously we stored it as a raw block of memory, but SPIRV-Tools and
SpirvShader expect an std::vector<uint32_t> so we would copy it on each
access.

This change eliminates the copy, and prepares for making the serial ID a
part of SpirvBinary to improve pipeline cache reuse.

Bug: b/172839674
Change-Id: I052bb10a35fb863f835e316e4f648b26575bc398
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/58269
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 7fad7b5..168f6a3 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -219,7 +219,7 @@
 		const bool optimize = !dbgctx;
 
 		const ShaderModule *module = vk::Cast(pStage->module);
-		const PipelineCache::SpirvBinaryKey key(module->getCode(), pStage->pSpecializationInfo, optimize);
+		const PipelineCache::SpirvBinaryKey key(module->getBinary(), pStage->pSpecializationInfo, optimize);
 
 		sw::SpirvBinary spirv;
 
@@ -238,7 +238,7 @@
 		// 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.
+		// TODO(b/201798871): use allocator.
 		auto shader = std::make_shared<sw::SpirvShader>(codeSerialID, pStage->stage, pStage->pName, spirv,
 		                                                vk::Cast(pCreateInfo->renderPass), pCreateInfo->subpass, robustBufferAccess, dbgctx);
 
@@ -276,7 +276,7 @@
 	// instructions.
 	const bool optimize = !dbgctx;
 
-	const PipelineCache::SpirvBinaryKey shaderKey(module->getCode(), stage.pSpecializationInfo, optimize);
+	const PipelineCache::SpirvBinaryKey shaderKey(module->getBinary(), stage.pSpecializationInfo, optimize);
 
 	sw::SpirvBinary spirv;
 
@@ -295,7 +295,7 @@
 	// 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.
+	// TODO(b/201798871): use allocator.
 	shader = std::make_shared<sw::SpirvShader>(codeSerialID, stage.stage, stage.pName, spirv,
 	                                           nullptr, 0, robustBufferAccess, dbgctx);
 
diff --git a/src/Vulkan/VkShaderModule.cpp b/src/Vulkan/VkShaderModule.cpp
index a49f824..b49151d 100644
--- a/src/Vulkan/VkShaderModule.cpp
+++ b/src/Vulkan/VkShaderModule.cpp
@@ -24,29 +24,21 @@
 
 ShaderModule::ShaderModule(const VkShaderModuleCreateInfo *pCreateInfo, void *mem)
     : serialID(nextSerialID())
-    , code(reinterpret_cast<uint32_t *>(mem))
+    , binary(pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t))
 {
-	memcpy(code, pCreateInfo->pCode, pCreateInfo->codeSize);
-	wordCount = static_cast<uint32_t>(pCreateInfo->codeSize / sizeof(uint32_t));
-
 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
 	spvtools::SpirvTools spirvTools(SPIRV_VERSION);
 	spvtools::ValidatorOptions validatorOptions = {};
 	validatorOptions.SetScalarBlockLayout(true);            // VK_EXT_scalar_block_layout
 	validatorOptions.SetUniformBufferStandardLayout(true);  // VK_KHR_uniform_buffer_standard_layout
 
-	ASSERT(spirvTools.Validate(code, wordCount, validatorOptions));  // The SPIR-V code passed to vkCreateShaderModule must be valid (b/158228522)
+	ASSERT(spirvTools.Validate(binary.data(), binary.size(), validatorOptions));  // The SPIR-V code passed to vkCreateShaderModule must be valid (b/158228522)
 #endif
 }
 
-void ShaderModule::destroy(const VkAllocationCallbacks *pAllocator)
-{
-	vk::freeHostMemory(code, pAllocator);
-}
-
 size_t ShaderModule::ComputeRequiredAllocationSize(const VkShaderModuleCreateInfo *pCreateInfo)
 {
-	return pCreateInfo->codeSize;
+	return 0;
 }
 
 }  // namespace vk
diff --git a/src/Vulkan/VkShaderModule.hpp b/src/Vulkan/VkShaderModule.hpp
index 2081f07..611aebf 100644
--- a/src/Vulkan/VkShaderModule.hpp
+++ b/src/Vulkan/VkShaderModule.hpp
@@ -19,11 +19,6 @@
 #include "Pipeline/SpirvBinary.hpp"
 
 #include <atomic>
-#include <vector>
-
-namespace rr {
-class Routine;
-}
 
 namespace vk {
 
@@ -31,12 +26,9 @@
 {
 public:
 	ShaderModule(const VkShaderModuleCreateInfo *pCreateInfo, void *mem);
-	void destroy(const VkAllocationCallbacks *pAllocator);
 
 	static size_t ComputeRequiredAllocationSize(const VkShaderModuleCreateInfo *pCreateInfo);
-	// TODO: reconsider boundary of ShaderModule class; try to avoid 'expose the
-	// guts' operations, and this copy.
-	sw::SpirvBinary getCode() const { return sw::SpirvBinary(code, wordCount); }
+	const sw::SpirvBinary &getBinary() const { return binary; }
 
 	uint32_t getSerialID() const { return serialID; }
 	static uint32_t nextSerialID() { return serialCounter++; }
@@ -45,8 +37,7 @@
 	const uint32_t serialID;
 	static std::atomic<uint32_t> serialCounter;
 
-	uint32_t *code = nullptr;
-	uint32_t wordCount = 0;
+	sw::SpirvBinary binary;
 };
 
 static inline ShaderModule *Cast(VkShaderModule object)