Search code examples
vulkanspir-v

Which types in SPIR-V are not allowed to be type aliases?


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?


Solution

  • 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.