Skip to content

Extending GL_EXT_spirv_intrinsics #331

@rdb

Description

@rdb

GL_EXT_spirv_intrinsics maps GLSL function declarations to SPIR-V instructions, but a spirv_instruction prototype must be fixed-arity, and its arguments are limited to 32-bit int/bool/float literals or by-id objects. Two classes of instruction therefore can't be defined in a header today:

  • instructions with a variable-length operand tail, and
  • instructions taking literal-string operands.

An example of such an instruction that is established today is debugPrintfEXT, which cannot currently be expressed using GL_EXT_spirv_intrinsics. As discussed in KhronosGroup/glslang#2679, I would like to add this ability, extending the usefulness of this extension to both existing and potentially new use cases.

Based on the fact that GL_EXT_spirv_intrinsics is established and (de facto) no longer in Draft, I understand I should propose new extensions. I could fold it into a single extension but the functionality cleanly separates along these two orthogonal axes:

Variadic tail support (GL_EXT_spirv_intrinsics_variadic)

This would permit a spirv_instruction-qualified function declaration to end in a trailing ..., which allows 0..n arguments to be passed in. Default encoding is by id, matching the default. For completeness, spirv_literal ... could be made valid which would encode the whole tail as literal operands (a la OpVectorShuffle):

// OpVectorShuffle (literal tail)
spirv_instruction(id = 79)
vec4 shuffle(vec4 a, vec4 b, spirv_literal ...);

String support (GL_EXT_spirv_intrinsics_string)

This would add a new spirv_string pseudo-type, which can only occur in a spirv_instruction-qualified function declaration. It would also allow literal strings to be passed to variadic arguments. They would normally be encoded as an OpString id.

An open question is the combination spirv_literal spirv_string. Current NonSemantic extensions take an OpString by id, but literal string operands are well-established in SPIR-V, such as in OpEntryPoint, where the characters are encoded in successive uint32_t arguments until a null byte is encountered. As far as I know there is no current use case for this, as I'm not aware of any such instruction that can appear in a function body, but it does kind of fall naturally out of the specification so I would be willing to add it for completeness' sake.

Using spirv_by_reference spirv_string would not be allowed since no pointers to string literals can be constructed.

The combination of these extensions allows fully and cleanly capturing GL_EXT_debug_printf:

#extension GL_EXT_spirv_intrinsics : enable
#extension GL_EXT_spirv_intrinsics_variadic : enable
#extension GL_EXT_spirv_intrinsics_string : enable

spirv_instruction(extensions = ["SPV_KHR_non_semantic_info"],
                  set = "NonSemantic.DebugPrintf", id = 1)
void debugPrintfEXT(spirv_string format, ...);

I have no prior experience drafting extensions, so I would like some feedback on whether I'm going in the right direction before proceeding with working out the exact grammar and drafting the extension text.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions