GLSL spirv_instruction Syntax for SPIR-V IDs

The spirv_instruction qualifier enables developers to invoke specific SPIR-V opcodes directly within GLSL through the GL_EXT_spirv_intrinsics extension. By binding custom GLSL function prototypes to core SPIR-V instructions or extended instruction sets via numerical IDs, developers can emit exact SPIR-V instructions without writing external assembly or relying on standard compiler intrinsic mappings.

Prerequisites and Enabling the Extension

To use spirv_instruction, the GL_EXT_spirv_intrinsics extension must first be declared and required at the top of the GLSL shader:

#version 450
#extension GL_EXT_spirv_intrinsics : require

Core SPIR-V Instruction Syntax

To invoke a core SPIR-V instruction, prepend the spirv_instruction attribute directly to a function declaration, using the id argument assigned to the numeric opcode defined in the SPIR-V specification.

spirv_instruction(id = <opcode_number>)
<return_type> <function_name>(<parameters>);
  • id: The decimal or hexadecimal numerical opcode corresponding to the SPIR-V instruction (e.g., 12 for OpNop, 128 for OpIAdd).
  • <return_type>: Maps directly to the instruction's Result <id> Type. If the SPIR-V instruction does not return a value (has no Result <id>), the return type must be void.
  • <parameters>: Map directly to the instruction's input operands in the exact sequence expected by the SPIR-V specification.

Example: Core Instruction Mapping

The core instruction OpIAdd has the SPIR-V opcode 128. In SPIR-V, it takes a result type, a result ID, and two operand IDs. In GLSL, it is declared as:

spirv_instruction(id = 128)
int spirv_iadd(int a, int b);

When spirv_iadd(x, y) is invoked in code, the compiler emits an OpIAdd instruction consuming x and y and producing an integer result.

Extended Instruction Set Syntax

SPIR-V instructions that belong to extended instruction sets (such as GLSL.std.450 or NonSemantic.DebugPrintf) require identifying both the instruction set name and the specific instruction ID within that set. This is done by adding the set string argument inside spirv_instruction:

spirv_instruction(set = "<set_name>", id = <instruction_number>)
<return_type> <function_name>(<parameters>);
  • set: A string literal representing the extended instruction set name as imported by OpExtInstImport.
  • id: The integer identifier of the instruction within that specific extended instruction set.

Example: Extended Instruction Mapping

Instruction number 4 in the GLSL.std.450 extended set is Exp (exponential). This instruction is bound using:

spirv_instruction(set = "GLSL.std.450", id = 4)
float spirv_ext_exp(float x);

When invoked, the compiler automatically handles the OpExtInstImport "GLSL.std.450" header and emits an OpExtInst targeting instruction ID 4.

Passing Constants and Literals

Certain SPIR-V instructions require literal values or capabilities rather than variable operand IDs. Literals can be defined using standard GLSL constant expressions or specialized constant intrinsic attributes where required:

spirv_instruction(id = 61 /* OpLoad */)
vec4 spirv_load(inout vec4 pointer);

The arguments provided to functions decorated with spirv_instruction correspond positionally to the operands required by the target SPIR-V opcode.