SpirvShader: Expose shader capabilities.

Some capabilities affect downstream behaviour in unexpected ways. For example: https://github.com/KhronosGroup/glslang/issues/1868

Bug: b/139207336
Change-Id: I43b4f1ab3558864bb6cb93c0cbf780d0dd2e3406
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35029
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index b0759c5..adfd1c3 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -486,7 +486,7 @@
 			bool robustBufferAccess)
 				: insns{insns}, inputs{MAX_INTERFACE_COMPONENTS},
 				  outputs{MAX_INTERFACE_COMPONENTS},
-				  codeSerialID(codeSerialID), modes{},
+				  codeSerialID(codeSerialID),
 				  robustBufferAccess(robustBufferAccess)
 	{
 		ASSERT(insns.size() > 0);
@@ -800,20 +800,18 @@
 				auto capability = static_cast<spv::Capability>(insn.word(1));
 				switch (capability)
 				{
-				case spv::CapabilityMatrix:
-				case spv::CapabilityShader:
-				case spv::CapabilityInputAttachment:
-				case spv::CapabilitySampled1D:
-				case spv::CapabilityImage1D:
-				case spv::CapabilitySampledBuffer:
-				case spv::CapabilityImageBuffer:
-				case spv::CapabilityImageQuery:
-				case spv::CapabilityDerivativeControl:
-				case spv::CapabilityMultiView:
-				case spv::CapabilityDeviceGroup:
-				case spv::CapabilityGroupNonUniform:
-					break;
-
+				case spv::CapabilityMatrix: capabilities.Matrix = true; break;
+				case spv::CapabilityShader: capabilities.Shader = true; break;
+				case spv::CapabilityInputAttachment: capabilities.InputAttachment = true; break;
+				case spv::CapabilitySampled1D: capabilities.Sampled1D = true; break;
+				case spv::CapabilityImage1D: capabilities.Image1D = true; break;
+				case spv::CapabilitySampledBuffer: capabilities.SampledBuffer = true; break;
+				case spv::CapabilityImageBuffer: capabilities.ImageBuffer = true; break;
+				case spv::CapabilityImageQuery: capabilities.ImageQuery = true; break;
+				case spv::CapabilityDerivativeControl: capabilities.DerivativeControl = true; break;
+				case spv::CapabilityGroupNonUniform: capabilities.GroupNonUniform = true; break;
+				case spv::CapabilityMultiView: capabilities.MultiView = true; break;
+				case spv::CapabilityDeviceGroup: capabilities.DeviceGroup = true; break;
 				default:
 					UNSUPPORTED("Unsupported capability %u", insn.word(1));
 				}
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 2d06679..44e252e 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -723,6 +723,27 @@
 			return modes;
 		}
 
+		struct Capabilities
+		{
+			bool Matrix : 1;
+			bool Shader : 1;
+			bool InputAttachment : 1;
+			bool Sampled1D : 1;
+			bool Image1D : 1;
+			bool SampledBuffer : 1;
+			bool ImageBuffer : 1;
+			bool ImageQuery : 1;
+			bool DerivativeControl : 1;
+			bool GroupNonUniform : 1;
+			bool MultiView : 1;
+			bool DeviceGroup : 1;
+		};
+
+		Capabilities const &getUsedCapabilities() const
+		{
+			return capabilities;
+		}
+
 		enum AttribType : unsigned char
 		{
 			ATTRIBTYPE_FLOAT,
@@ -873,7 +894,8 @@
 
 	private:
 		const uint32_t codeSerialID;
-		Modes modes;
+		Modes modes = {};
+		Capabilities capabilities = {};
 		HandleMap<Type> types;
 		HandleMap<Object> defs;
 		HandleMap<Function> functions;