LocalSizeId for VK_KHR_maintenance4

This CL adds support in SPIR-V for spv::ExecutionModeLocalSizeId and
spv::OpExecutionModeId. This is required for VK_KHR_maintenance4
support.

Bug: b/204502926
Change-Id: I00113b9f0e649c49c2c81b68aedd8340ea003297
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/63294
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Commit-Queue: Alexis Hétu <sugoi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 446059d..d3fb589 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -99,6 +99,7 @@
 			break;
 
 		case spv::OpExecutionMode:
+		case spv::OpExecutionModeId:
 			ProcessExecutionMode(insn);
 			break;
 
@@ -396,6 +397,7 @@
 					executionModes.WorkgroupSizeX = object.constantValue[0];
 					executionModes.WorkgroupSizeY = object.constantValue[1];
 					executionModes.WorkgroupSizeZ = object.constantValue[2];
+					executionModes.useWorkgroupSizeId = false;
 				}
 			}
 			break;
@@ -1014,9 +1016,11 @@
 		executionModes.DepthUnchanged = true;
 		break;
 	case spv::ExecutionModeLocalSize:
+	case spv::ExecutionModeLocalSizeId:
 		executionModes.WorkgroupSizeX = insn.word(3);
 		executionModes.WorkgroupSizeY = insn.word(4);
 		executionModes.WorkgroupSizeZ = insn.word(5);
+		executionModes.useWorkgroupSizeId = (mode == spv::ExecutionModeLocalSizeId);
 		break;
 	case spv::ExecutionModeOriginUpperLeft:
 		// This is always the case for a Vulkan shader. Do nothing.
@@ -1026,6 +1030,21 @@
 	}
 }
 
+uint32_t SpirvShader::getWorkgroupSizeX() const
+{
+	return executionModes.useWorkgroupSizeId ? getObject(executionModes.WorkgroupSizeX).constantValue[0] : executionModes.WorkgroupSizeX.value();
+}
+
+uint32_t SpirvShader::getWorkgroupSizeY() const
+{
+	return executionModes.useWorkgroupSizeId ? getObject(executionModes.WorkgroupSizeY).constantValue[0] : executionModes.WorkgroupSizeY.value();
+}
+
+uint32_t SpirvShader::getWorkgroupSizeZ() const
+{
+	return executionModes.useWorkgroupSizeId ? getObject(executionModes.WorkgroupSizeZ).constantValue[0] : executionModes.WorkgroupSizeZ.value();
+}
+
 uint32_t SpirvShader::ComputeTypeSize(InsnIterator insn)
 {
 	// Types are always built from the bottom up (with the exception of forward ptrs, which
@@ -1806,6 +1825,7 @@
 	case spv::OpTypeSampledImage:
 	case spv::OpTypeSampler:
 	case spv::OpExecutionMode:
+	case spv::OpExecutionModeId:
 	case spv::OpMemoryModel:
 	case spv::OpFunction:
 	case spv::OpFunctionEnd: