Currently have made a spirv parser/assembler library. The api is not versatile to make sure of minimal allocation.
There's a WordBuffer
class containing functions like AddOpVariable
and AddOpTypeInteger
with parameters. Each parameters is then put into a stack allocated array and pushed to the buffer.
SPIR-V are composed of 32bit integer words (not exactly byte code). Types have to be declared and are either 2 or 3 words depending the type declared. There's an implicit index given to these instruction which can be used by other instruction.
Example below
; Magic: 0x07230203 (SPIR-V)
; Version: 0x00010000 (Version: 1.0.0)
; Generator: 0x00080001 (Khronos Glslang Reference Front End; 1)
; Bound: 63
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main" %31 %33 %42 %57
OpExecutionMode %4 OriginLowerLeft
. . .
; All types, variables, and constants
%2 = OpTypeVoid
%3 = OpTypeFunction %2 ; void ()
%6 = OpTypeFloat 32 ; 32-bit float
%7 = OpTypeVector %6 4 ; vec4
%8 = OpTypePointer Function %7 ; function-local vec4*
%10 = OpConstant %6 1
%11 = OpConstant %6 2
. . .
Where %6 = OpTypeFloat 32
is the 6th instruction declared in the buffer that implicitely has an Id. It is used right after with %7 = OpTypeVector %6 4
.
OpTypeFloat is a 2 word instruction, one word for OpTypeFloat
and the other for the value 32
declaring a 32bit float type.
OpTypeVector is a 3 word instruction, one word for OpTypeVector
, one for the index of the type %6
and the last one for the number of components 4
which results in a float4
/vec4
type.
Mixins would be defined as a SPIR-V byte code containing partial informations.
Let's define MixinA
containing the OpTypeFloat instruction and MixinB
containing the OpTypeVector instruction referencing the OpTypeFloat instruction.
In MixinA
, OpTypeFloat would be the first instruction with an implicit Id, it would be disassembled as %1 = OpTypeFloat 32
.
In MixinB
, the same would happen with OpTypeVector, it would also reference the OpTypeFloat present in MixinA
and everything would be disassembled as %1 = OpTypeVector %1
.
The index clash is the core issue we're facing with mixing spir-v raw byte code.
Each mixin object will have an additional parameter giving an offset to the current mixin.