Non-structure types (scalars, vectors, arrays, etc.) with the same operand parameterization cannot be type aliases. For non-structures, two type
<id>
s match if-and-only-if the types match.
What exactly does this mean?
#version 400
void main()
{
uint a = 4;
uint b = 5;
}
Compiling this shader with glslang results in
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 12
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main"
OpSource GLSL 400
OpName %main "main"
OpName %a "a"
OpName %b "b"
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%_ptr_Function_uint = OpTypePointer Function %uint
%uint_4 = OpConstant %uint 4
%uint_5 = OpConstant %uint 5
%main = OpFunction %void None %3
%5 = OpLabel
%a = OpVariable %_ptr_Function_uint Function
%b = OpVariable %_ptr_Function_uint Function
OpStore %a %uint_4
OpStore %b %uint_5
OpReturn
OpFunctionEnd
Here %uint = OpTypeInt 32 0
is used several times and %_ptr_Function_uint
is also used two times.
Where does this rule even apply?
My guess is that that validation rule is unfortunately worded and refers to this (2.8. Types and Variables of SPIR-V specification):
Two different type
<id>
s form, by definition, two different types. It is valid to declare multiple aggregate type<id>
s having the same opcode and operands. This is to allow multiple instances of aggregate types with the same structure to be decorated differently. (Different decorations are not required; two different aggregate type<id>
s are allowed to have identical declarations and decorations, and will still be two different types.) Non-aggregate types are different: It is invalid to declare multiple type<id>
s for the same scalar, vector, or matrix type. That is, non-aggregate type declarations must all have different opcodes or operands. (Note that non-aggregate types cannot be decorated in ways that affect their type.)
But there are differences. E.g. "non-aggregate"(i.e. non-structure + non-array) vs "non-structure".
So, what it means is you cannot do things like:
OpTypeInt id=1 bits=32 sign=0 // OK
OpTypeInt id=1 bits=32 sign=1 // ERROR -- redefined result id
OpTypeInt id=2 bits=32 sign=0 // ERROR -- uint32 already defined as id 1
OpTypeInt id=3 bits=32 sign=1 // OK
I don't see this rule violated in your human-readable SPIR-V example.