Migrate ComputeProgram to using Coroutines

This is a smallest-change migration:
• The yield type is a dummy int. Nothing currently yields.
• There's no handling of coroutine resumes.

Bug: b/131672705
Change-Id: I238b1fa65c62ded7148816d87000103245373e33
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30849
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/ComputeProgram.cpp b/src/Pipeline/ComputeProgram.cpp
index 6daaa3a..361cbb1 100644
--- a/src/Pipeline/ComputeProgram.cpp
+++ b/src/Pipeline/ComputeProgram.cpp
@@ -198,14 +198,11 @@
 	}
 
 	void ComputeProgram::run(
-		Routine *routine, SpirvShader const *shader,
 		vk::DescriptorSet::Bindings const &descriptorSets,
 		vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets,
 		PushConstantStorage const &pushConstants,
 		uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
 	{
-		auto runWorkgroup = (void(*)(void*, int, int, int, int, int))(routine->getEntry());
-
 		auto &modes = shader->getModes();
 
 		auto invocationsPerSubgroup = SIMD::Width;
@@ -242,7 +239,7 @@
 			{
 				for (uint32_t groupX = 0; groupX < groupCountX; groupX++)
 				{
-					runWorkgroup(&data, groupX, groupY, groupZ, 0, subgroupsPerWorkgroup);
+					(*this)(&data, groupX, groupY, groupZ, 0, subgroupsPerWorkgroup);
 				}
 			}
 		}
diff --git a/src/Pipeline/ComputeProgram.hpp b/src/Pipeline/ComputeProgram.hpp
index 493d89b..b2a3785 100644
--- a/src/Pipeline/ComputeProgram.hpp
+++ b/src/Pipeline/ComputeProgram.hpp
@@ -17,7 +17,7 @@
 
 #include "SpirvShader.hpp"
 
-#include "Reactor/Reactor.hpp"
+#include "Reactor/Coroutine.hpp"
 #include "Device/Context.hpp"
 #include "Vulkan/VkDescriptorSet.hpp"
 
@@ -37,13 +37,13 @@
 	struct Constants;
 
 	// ComputeProgram builds a SPIR-V compute shader.
-	class ComputeProgram : public Function<Void(
-			Pointer<Byte> data,
-			Int workgroupX,
-			Int workgroupY,
-			Int workgroupZ,
-			Int firstSubgroup,
-			Int subgroupCount)>
+	class ComputeProgram : public Coroutine<int(
+			void* data,
+			int32_t workgroupX,
+			int32_t workgroupY,
+			int32_t workgroupZ,
+			int32_t firstSubgroup,
+			int32_t subgroupCount)>
 	{
 	public:
 		ComputeProgram(SpirvShader const *spirvShader, vk::PipelineLayout const *pipelineLayout, const vk::DescriptorSet::Bindings &descriptorSets);
@@ -54,9 +54,7 @@
 		void generate();
 
 		// run executes the compute shader routine for all workgroups.
-		// TODO(bclayton): This probably does not belong here. Consider moving.
-		static void run(
-			Routine *routine, SpirvShader const *shader,
+		void run(
 			vk::DescriptorSet::Bindings const &descriptorSetBindings,
 			vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets,
 			PushConstantStorage const &pushConstants,
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 3d0a4ac..d0cd19e 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -533,6 +533,7 @@
 void ComputePipeline::destroyPipeline(const VkAllocationCallbacks* pAllocator)
 {
 	delete shader;
+	delete program;
 }
 
 size_t ComputePipeline::ComputeRequiredAllocationSize(const VkComputePipelineCreateInfo* pCreateInfo)
@@ -553,12 +554,9 @@
 	// FIXME(b/119409619): use allocator.
 	shader = new sw::SpirvShader(code, nullptr, 0);
 	vk::DescriptorSet::Bindings descriptorSets;  // FIXME(b/129523279): Delay code generation until invoke time.
-	sw::ComputeProgram program(shader, layout, descriptorSets);
-
-	program.generate();
-
-	// TODO(bclayton): Cache program
-	routine = program("ComputeRoutine");
+	program = new sw::ComputeProgram(shader, layout, descriptorSets);
+	program->generate();
+	program->finalize();
 }
 
 void ComputePipeline::run(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ,
@@ -566,9 +564,8 @@
 	vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets,
 	sw::PushConstantStorage const &pushConstants)
 {
-	ASSERT_OR_RETURN(routine != nullptr);
-	sw::ComputeProgram::run(
-		routine, shader,
+	ASSERT_OR_RETURN(program != nullptr);
+	program->run(
 		descriptorSets, descriptorDynamicOffsets, pushConstants,
 		groupCountX, groupCountY, groupCountZ);
 }
diff --git a/src/Vulkan/VkPipeline.hpp b/src/Vulkan/VkPipeline.hpp
index bf6092a..d14a547 100644
--- a/src/Vulkan/VkPipeline.hpp
+++ b/src/Vulkan/VkPipeline.hpp
@@ -19,7 +19,11 @@
 #include "Vulkan/VkDescriptorSet.hpp"
 #include "Device/Renderer.hpp"
 
-namespace sw { class SpirvShader; }
+namespace sw
+{
+	class ComputeProgram;
+	class SpirvShader;
+}
 
 namespace vk
 {
@@ -113,7 +117,7 @@
 
 protected:
 	sw::SpirvShader *shader = nullptr;
-	rr::Routine *routine = nullptr;
+	sw::ComputeProgram *program = nullptr;
 };
 
 static inline Pipeline* Cast(VkPipeline object)