Skip to main content

Module spirv

Module spirv 

Source
Expand description

A minimal SPIR-V binary emitter: enough to write one compute shader by hand, and nothing more.

§Why hand-emit SPIR-V

The beachhead had to answer a question the roadmap asks explicitly: can ferrox’s shaders be built without a C++ toolchain at build time? There are three ways to get SPIR-V into a Rust binary and only one of them says yes without qualification:

  1. glslangValidator / glslc in build.rs. This is what llama.cpp’s Vulkan backend does (it builds a vulkan-shaders-gen C++ program at configure time). It makes a C++ toolchain a build prerequisite for every ferrox user who enables the feature, on every platform, forever. ferrox-cuda deliberately refused the equivalent (cudarc in dynamic-loading mode, no nvcc) and this crate refuses it for the same reason.
  2. Commit a pre-built .spv blob. No build dependency, but the repo then carries an opaque binary that no reviewer can read and that silently drifts from whatever source it was generated from. This codebase’s whole test culture is against that.
  3. Emit the words from Rust. The shader is ordinary reviewable Rust, there is no build step at all, and the emitter is small enough to hold in your head. That is this file.

The cost is stated honestly in the verdict: option 3 does not scale to a hundred kernels. It scales to one, which is exactly the size of a GO/NO-GO.

§What this is not

Not an SSA builder, not a validator, not a type deduplicator. It writes words in the order it is told to, into the five sections SPIR-V’s logical layout requires. Getting the layout or the types wrong produces an invalid module, and the crate’s answer to that is to run spirv-val over the emitted words in a test whenever the tool is on PATH (see q8_0_matvec’s tests).

Structs§

Builder
Accumulates SPIR-V words per section and hands out result ids.

Enums§

Section
Where an instruction goes in SPIR-V’s required logical layout.

Constants§

ADDRESSING_LOGICAL
BUILTIN_GLOBAL_INVOCATION_ID
CAP_SHADER
DEC_ARRAY_STRIDE
DEC_BINDING
DEC_BLOCK
DEC_BUFFER_BLOCK
DEC_BUILTIN
DEC_DESCRIPTOR_SET
DEC_OFFSET
EXEC_MODEL_GL_COMPUTE
EXEC_MODE_LOCAL_SIZE
GENERATOR
Generator magic. 0 is “unregistered”; tools accept it.
MAGIC
SPIR-V magic number (first word of every module).
MEMORY_MODEL_GLSL450
NONE
OP_ACCESS_CHAIN
OP_BITCAST
OP_BITWISE_AND
OP_BITWISE_OR
OP_BITWISE_XOR
OP_BRANCH
OP_BRANCH_CONDITIONAL
OP_CAPABILITY
OP_COMPOSITE_EXTRACT
OP_CONSTANT
OP_CONVERT_S_TO_F
OP_CONVERT_U_TO_F
OP_DECORATE
OP_ENTRY_POINT
OP_EXECUTION_MODE
OP_FUNCTION
OP_FUNCTION_END
OP_F_ADD
OP_F_MUL
OP_F_NEGATE
OP_I_ADD
OP_I_EQUAL
OP_I_MUL
OP_I_NOT_EQUAL
OP_I_SUB
OP_LABEL
OP_LOAD
OP_LOOP_MERGE
OP_MEMBER_DECORATE
OP_MEMBER_NAME
OP_MEMORY_MODEL
OP_NAME
OP_RETURN
OP_SELECT
OP_SELECTION_MERGE
OP_SHIFT_LEFT_LOGICAL
OP_SHIFT_RIGHT_LOGICAL
OP_STORE
OP_TYPE_BOOL
OP_TYPE_FLOAT
OP_TYPE_FUNCTION
OP_TYPE_INT
OP_TYPE_POINTER
OP_TYPE_RUNTIME_ARRAY
OP_TYPE_STRUCT
OP_TYPE_VECTOR
OP_TYPE_VOID
OP_U_LESS_THAN
OP_VARIABLE
SC_FUNCTION
SC_INPUT
SC_PUSH_CONSTANT
SC_UNIFORM
VERSION_1_0
Target SPIR-V version, encoded 0 | major<<16 | minor<<8 | 0.

Functions§

encode_string
SPIR-V literal string: UTF-8, NUL-terminated, zero-padded to a whole number of little-endian words.
to_bytes
The emitted words as the little-endian byte stream a .spv file holds, for handing to an external validator.