[0017] - Target Extension Types for Inline SPIR-V and Decorated Types
Status | Design In Progress |
---|---|
Author |
Introduction
In this proposal, we define the spirv.Type
and spirv.DecoratedType
target extension types for the SPIR-V backend.
Motivation
We would like to implement SpirvType
and SpirvOpaqueType
from Inline
SPIR-V (HLSL proposal 0011)
in the SPIR-V backend. These allow users to create arbitrary OpType
instructions, and use them like any other HLSL type. Using these types, a
vendor creating a new extension can expose it to users by creating a header
file without needing to modify the compiler.
Additionally, we need a way to represent types with SPIR-V decorations in LLVM IR.
Proposed solution
SpirvType
To represent vk::SpirvType
and vk::SpirvOpaqueType
in LLVM IR, we will add
three new target extension types:
Type | HasZeroInit | CanBeGlobal | CanBeLocal |
---|---|---|---|
spirv.Type | false | true | true |
spirv.IntegralConstant | false | false | false |
spirv.Literal | false | false | false |
IntegralConstant
and Literal
are used to encode arguments to Type
, and
may not be used outside that context. They are necessary because target
extension types must have all type arguments precede all integer arguments,
whereas SPIR-V type instructions may have an arbitrary number of type,
immediate literal, and constant id operands in any order.
spirv.Type
target("spirv.Type", operands..., opcode, size, alignment)
opcode
is an integer literal representing the opcode of the OpType
instruction to be generated. size
and alignment
are integer literals
representing the number of bytes a single value of the type occupies and the
power of two that the value will be aligned to in memory. An opaque type can be
represented by setting size
and alignment
to zero. operands
represents a
list of type arguments encoding the operands of the OpType
instruction. Each
operand must be one of:
- A type argument, which will be lowered to the id of the lowered SPIR-V type
- A
spirv.IntegralConstant
, which will be lowered to the id of anOpConstant
instruction - A
spirv.Literal
, which will be lowered to an immediate literal value
spirv.IntegralConstant
target("spirv.IntegralConstant", integral_type, value...)
integral_type
is the type argument for the OpConstant
instruction to be
generated, and value
is its literal integer value. To represent a value larger
than a single 32-bit word, multiple 32-bit words may be passed as arguments. As
stated in the
SPIR-V Specification,
they should be in little-endian order.
spirv.Literal
target("spirv.Literal", value...)
value
is the literal integer value to be generated. To represent a value
larger than a single 32-bit word, multiple 32-bit words may be passed as
arguments, in little-endian order.
Example
Here’s an example of using these types to represent an array of images:
%type_2d_image = type target("spirv.Image", float, 1, 2, 0, 0, 1, 0)
%integral_constant_28 = type target("spirv.IntegralConstant", i32, 28)
%integral_constant_4 = type target("spirv.IntegralConstant", i32, 4)
%ArrayTex2D = type target("spirv.Type", %type_2d_image, %integral_constant_4, 28)
Type decorations
In order to represent types with the vk::ext_decorate
, vk::ext_decorate_id
,
and vk::ext_decorate_string
annotations, we will use the
int_spv_assign_decoration
intrinsic.