Separate analysis info from SPIR-V execution modes

Fixes: b/177839655
Change-Id: I1186ee62fe34ea0a06904c4907c710853b2f8dd2
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/56270
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/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index de940fa..a3e96b9 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -142,7 +142,7 @@
 
 	state.occlusionEnabled = occlusionEnabled;
 
-	bool fragmentContainsKill = (fragmentShader && fragmentShader->getModes().ContainsKill);
+	bool fragmentContainsKill = (fragmentShader && fragmentShader->getAnalysis().ContainsKill);
 	for(int i = 0; i < RENDERTARGETS; i++)
 	{
 		state.colorWriteMask |= pipelineState.colorWriteActive(i, attachments) << (4 * i);
@@ -177,7 +177,7 @@
 
 	if(state.enableMultiSampling && fragmentShader)
 	{
-		state.centroid = fragmentShader->getModes().NeedsCentroid;
+		state.centroid = fragmentShader->getAnalysis().NeedsCentroid;
 	}
 
 	state.frontFace = pipelineState.getFrontFace();
diff --git a/src/Pipeline/ComputeProgram.cpp b/src/Pipeline/ComputeProgram.cpp
index 1016663..43926f4 100644
--- a/src/Pipeline/ComputeProgram.cpp
+++ b/src/Pipeline/ComputeProgram.cpp
@@ -214,10 +214,10 @@
     uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
     uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
 {
-	auto &modes = shader->getModes();
+	auto &executionModes = shader->getExecutionModes();
 
 	auto invocationsPerSubgroup = SIMD::Width;
-	auto invocationsPerWorkgroup = modes.WorkgroupSizeX * modes.WorkgroupSizeY * modes.WorkgroupSizeZ;
+	auto invocationsPerWorkgroup = executionModes.WorkgroupSizeX * executionModes.WorkgroupSizeY * executionModes.WorkgroupSizeZ;
 	auto subgroupsPerWorkgroup = (invocationsPerWorkgroup + invocationsPerSubgroup - 1) / invocationsPerSubgroup;
 
 	Data data;
@@ -227,9 +227,9 @@
 	data.numWorkgroups[Y] = groupCountY;
 	data.numWorkgroups[Z] = groupCountZ;
 	data.numWorkgroups[3] = 0;
-	data.workgroupSize[X] = modes.WorkgroupSizeX;
-	data.workgroupSize[Y] = modes.WorkgroupSizeY;
-	data.workgroupSize[Z] = modes.WorkgroupSizeZ;
+	data.workgroupSize[X] = executionModes.WorkgroupSizeX;
+	data.workgroupSize[Y] = executionModes.WorkgroupSizeY;
+	data.workgroupSize[Z] = executionModes.WorkgroupSizeZ;
 	data.workgroupSize[3] = 0;
 	data.invocationsPerSubgroup = invocationsPerSubgroup;
 	data.invocationsPerWorkgroup = invocationsPerWorkgroup;
@@ -266,7 +266,7 @@
 				using Coroutine = std::unique_ptr<rr::Stream<SpirvShader::YieldResult>>;
 				std::queue<Coroutine> coroutines;
 
-				if(modes.ContainsControlBarriers)
+				if(shader->getAnalysis().ContainsControlBarriers)
 				{
 					// Make a function call per subgroup so each subgroup
 					// can yield, bringing all subgroups to the barrier
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index 705ccf5..3c6d136 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -220,7 +220,7 @@
 
 	clampColor(c);
 
-	if(spirvShader->getModes().ContainsKill)
+	if(spirvShader->getAnalysis().ContainsKill)
 	{
 		for(unsigned int q : samples)
 		{
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 069544d..019477b 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -33,7 +33,7 @@
     , routine(pipelineLayout)
     , descriptorSets(descriptorSets)
     , shaderContainsInterpolation(spirvShader && spirvShader->getUsedCapabilities().InterpolationFunction)
-    , shaderContainsSampleQualifier(spirvShader && spirvShader->getModes().ContainsSampleQualifier)
+    , shaderContainsSampleQualifier(spirvShader && spirvShader->getAnalysis().ContainsSampleQualifier)
     , perSampleShading((state.sampleShadingEnabled && (state.minSampleShading * state.multiSampleCount > 1.0f)) ||
                        shaderContainsSampleQualifier || shaderContainsInterpolation)  // TODO(b/194714095)
     , invocationCount(perSampleShading ? state.multiSampleCount : 1)
@@ -81,7 +81,7 @@
 
 void PixelRoutine::quad(Pointer<Byte> cBuffer[RENDERTARGETS], Pointer<Byte> &zBuffer, Pointer<Byte> &sBuffer, Int cMask[4], Int &x, Int &y)
 {
-	const bool earlyFragmentTests = !spirvShader || spirvShader->getModes().EarlyFragmentTests;
+	const bool earlyFragmentTests = !spirvShader || spirvShader->getExecutionModes().EarlyFragmentTests;
 
 	Int zMask[4];  // Depth mask
 	Int sMask[4];  // Stencil mask
@@ -295,7 +295,7 @@
 
 			Bool alphaPass = alphaTest(cMask, samples);
 
-			if((spirvShader && spirvShader->getModes().ContainsKill) || state.alphaToCoverage)
+			if((spirvShader && spirvShader->getAnalysis().ContainsKill) || state.alphaToCoverage)
 			{
 				for(unsigned int q : samples)
 				{
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 3d330b8..37ccbb3 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -118,7 +118,7 @@
 					descriptorDecorations[targetId].InputAttachmentIndex = value;
 					break;
 				case spv::DecorationSample:
-					modes.ContainsSampleQualifier = true;
+					analysis.ContainsSampleQualifier = true;
 					break;
 				default:
 					// Only handling descriptor decorations here.
@@ -127,7 +127,7 @@
 
 				if(decoration == spv::DecorationCentroid)
 				{
-					modes.NeedsCentroid = true;
+					analysis.NeedsCentroid = true;
 				}
 			}
 			break;
@@ -147,7 +147,7 @@
 
 				if(decoration == spv::DecorationCentroid)
 				{
-					modes.NeedsCentroid = true;
+					analysis.NeedsCentroid = true;
 				}
 			}
 			break;
@@ -234,7 +234,7 @@
 
 				if(opcode == spv::OpKill)
 				{
-					modes.ContainsKill = true;
+					analysis.ContainsKill = true;
 				}
 			}
 			break;
@@ -376,9 +376,9 @@
 					// The object decorated with WorkgroupSize must be declared
 					// as a three-component vector of 32-bit integers.
 					ASSERT(getType(object).componentCount == 3);
-					modes.WorkgroupSizeX = object.constantValue[0];
-					modes.WorkgroupSizeY = object.constantValue[1];
-					modes.WorkgroupSizeZ = object.constantValue[2];
+					executionModes.WorkgroupSizeX = object.constantValue[0];
+					executionModes.WorkgroupSizeY = object.constantValue[1];
+					executionModes.WorkgroupSizeZ = object.constantValue[2];
 				}
 			}
 			break;
@@ -739,7 +739,7 @@
 			break;
 
 		case spv::OpControlBarrier:
-			modes.ContainsControlBarriers = true;
+			analysis.ContainsControlBarriers = true;
 			break;
 
 		case spv::OpExtension:
@@ -943,27 +943,27 @@
 	switch(mode)
 	{
 	case spv::ExecutionModeEarlyFragmentTests:
-		modes.EarlyFragmentTests = true;
+		executionModes.EarlyFragmentTests = true;
 		break;
 	case spv::ExecutionModeDepthReplacing:
-		modes.DepthReplacing = true;
+		executionModes.DepthReplacing = true;
 		break;
 	case spv::ExecutionModeDepthGreater:
 		// TODO(b/177915067): Can be used to optimize depth test, currently unused.
-		modes.DepthGreater = true;
+		executionModes.DepthGreater = true;
 		break;
 	case spv::ExecutionModeDepthLess:
 		// TODO(b/177915067): Can be used to optimize depth test, currently unused.
-		modes.DepthLess = true;
+		executionModes.DepthLess = true;
 		break;
 	case spv::ExecutionModeDepthUnchanged:
 		// TODO(b/177915067): Can be used to optimize depth test, currently unused.
-		modes.DepthUnchanged = true;
+		executionModes.DepthUnchanged = true;
 		break;
 	case spv::ExecutionModeLocalSize:
-		modes.WorkgroupSizeX = insn.word(3);
-		modes.WorkgroupSizeY = insn.word(4);
-		modes.WorkgroupSizeZ = insn.word(5);
+		executionModes.WorkgroupSizeX = insn.word(3);
+		executionModes.WorkgroupSizeY = insn.word(4);
+		executionModes.WorkgroupSizeZ = insn.word(5);
 		break;
 	case spv::ExecutionModeOriginUpperLeft:
 		// This is always the case for a Vulkan shader. Do nothing.
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index d08925f..62b885b 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -573,7 +573,7 @@
 
 	~SpirvShader();
 
-	struct Modes
+	struct ExecutionModes
 	{
 		bool EarlyFragmentTests : 1;
 		bool DepthReplacing : 1;
@@ -581,22 +581,28 @@
 		bool DepthLess : 1;
 		bool DepthUnchanged : 1;
 
-		// TODO(b/177839655): These are not SPIR-V execution modes.
-		// Move to an Analysis structure.
-		bool ContainsKill : 1;
-		bool ContainsControlBarriers : 1;
-		bool NeedsCentroid : 1;
-		bool ContainsSampleQualifier : 1;
-
 		// Compute workgroup dimensions
 		int WorkgroupSizeX = 1;
 		int WorkgroupSizeY = 1;
 		int WorkgroupSizeZ = 1;
 	};
 
-	Modes const &getModes() const
+	const ExecutionModes &getExecutionModes() const
 	{
-		return modes;
+		return executionModes;
+	}
+
+	struct Analysis
+	{
+		bool ContainsKill : 1;
+		bool ContainsControlBarriers : 1;
+		bool NeedsCentroid : 1;
+		bool ContainsSampleQualifier : 1;
+	};
+
+	const Analysis &getAnalysis() const
+	{
+		return analysis;
 	}
 
 	struct Capabilities
@@ -630,7 +636,7 @@
 		bool StencilExportEXT : 1;
 	};
 
-	Capabilities const &getUsedCapabilities() const
+	const Capabilities &getUsedCapabilities() const
 	{
 		return capabilities;
 	}
@@ -830,7 +836,8 @@
 
 private:
 	const uint32_t codeSerialID;
-	Modes modes = {};
+	ExecutionModes executionModes = {};
+	Analysis analysis = {};
 	Capabilities capabilities = {};
 	HandleMap<Type> types;
 	HandleMap<Object> defs;