Fix use of deleted shader during compute execution

ComputeProgram::run() uses the `shader` member, which was previously a
weak pointer to a SpirvShader object. If the corresponding shader module
is destroyed, and there is no (more) pipeline cache to hold a shared_ptr
reference to it, we'd access a deleted object.

The `pipelineLayout` member is safe-ish because we explicitly reference
count it in the vk::Pipeline class, since graphics pipelines also use it
to (re)compile routines at draw execution time.

The ComputeProgramKey was modified to use unique integer identifiers
instead of pointers to the shader and pipeline layout. This prevents a
false cache hit when these objects are destroyed and new ones get
allocated at the same address. Note that this means we lose the nice
property of constructing new cache entries only from cache key data,
but this is a better compromise than the previous buggy code.

Bug: b/197982536
Change-Id: Ie75bb0e8df21ad25c2a7fed29adbf086fab072e3
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/57168
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/Pipeline/ComputeProgram.hpp b/src/Pipeline/ComputeProgram.hpp
index 839f494..79a0bcb 100644
--- a/src/Pipeline/ComputeProgram.hpp
+++ b/src/Pipeline/ComputeProgram.hpp
@@ -46,7 +46,7 @@
                            int32_t subgroupCount)>
 {
 public:
-	ComputeProgram(vk::Device *device, SpirvShader const *spirvShader, vk::PipelineLayout const *pipelineLayout, const vk::DescriptorSet::Bindings &descriptorSets);
+	ComputeProgram(vk::Device *device, std::shared_ptr<SpirvShader> spirvShader, vk::PipelineLayout const *pipelineLayout, const vk::DescriptorSet::Bindings &descriptorSets);
 
 	virtual ~ComputeProgram();
 
@@ -81,8 +81,8 @@
 	};
 
 	vk::Device *const device;
-	SpirvShader const *const shader;
-	vk::PipelineLayout const *const pipelineLayout;
+	const std::shared_ptr<SpirvShader> shader;
+	const vk::PipelineLayout *const pipelineLayout;  // Reference held by vk::Pipeline
 	const vk::DescriptorSet::Bindings &descriptorSets;
 };