Rust implementation of SPIR-V module processing functionalities. It aims to provide:
- APIs for processing SPIR-V modules
 - Command line tools building on top of the APIs for common processing tasks
 
rspirv defines a common SPIR-V data representation (DR) as the medium for various purposes. rspirv also provides a builder to build the DR interactively and a parser to parse a given SPIR-V binary module into its DR. A higher level structured representation is currently under developing.
SPIR-V is a common intermediate language for representing graphics shaders and compute kernels for multiple Khronos APIs, such as Vulkan, OpenGL, and OpenCL.
SPIRV-Tools is the Khronos Group's official C++ implementation of SPIR-V binary parser, assembler, disassembler, optimizer, and validator. rspirv is not a Rust language binding for that project; it is a complete rewrite using Rust.
The current implementation supports SPIR-V 1.5 (Revision 4).
Multiple crates are published from this project:
| Name | Crate | Docs | 
|---|---|---|
| rspirv | ||
| spirv | 
In total rspirv APIs contains:
- The SPIR-V header (all SPIR-V structs, enums, and constants)
 - The whole SPIR-V grammar (instruction layouts and their operands)
 - A data representation of SPIR-V modules and its loader and builder
 - SPIR-V binary module decoding and parsing functionalities
 
The Khronos SPIR-V JSON grammar is leveraged to generate parts
of the source code using rspirv-autogen.
Please see the links to docs.rs for detailed documentation.
I plan to implement several functionalities:
- SPIR-V data representation (DR)
 - SPIR-V module builder
 - SPIR-V module assembler
 - SPIR-V binary module parser
 - SPIR-V binary module disassembler
 - HLSL/GLSL to SPIR-V frontend (maybe)
 - SPIR-V DR to LLVM IR transformation (maybe)
 
The DR doesn't handle OpLine and OpNoLine well right now.
The SPIR-V binary module parser is feature complete.
This project uses associated constants, which became available in the stable channel since 1.20. So to compile with a compiler from the stable channel, please make sure that the version is >= 1.20.
Building a SPIR-V module, assembling it, parsing it, and then disassembling it:
use rspirv::binary::Assemble;
use rspirv::binary::Disassemble;
fn main() {
    // Building
    let mut b = rspirv::dr::Builder::new();
    b.set_version(1, 0);
    b.capability(spirv::Capability::Shader);
    b.memory_model(spirv::AddressingModel::Logical, spirv::MemoryModel::GLSL450);
    let void = b.type_void();
    let voidf = b.type_function(void, vec![]);
    let fun = b
        .begin_function(
            void,
            None,
            spirv::FunctionControl::DONT_INLINE | spirv::FunctionControl::CONST,
            voidf,
        )
        .unwrap();
    b.begin_basic_block(None).unwrap();
    b.ret().unwrap();
    b.end_function().unwrap();
    b.entry_point(spirv::ExecutionModel::Vertex, fun, "foo", vec![]);
    let module = b.module();
    // Assembling
    let code = module.assemble();
    assert!(code.len() > 20); // Module header contains 5 words
    assert_eq!(spirv::MAGIC_NUMBER, code[0]);
    // Parsing
    let mut loader = rspirv::dr::Loader::new();
    rspirv::binary::parse_words(&code, &mut loader).unwrap();
    let module = loader.module();
    // Disassembling
    assert_eq!(
        module.disassemble(),
        "; SPIR-V\n\
         ; Version: 1.0\n\
         ; Generator: rspirv\n\
         ; Bound: 5\n\
         OpCapability Shader\n\
         OpMemoryModel Logical GLSL450\n\
         OpEntryPoint Vertex %3 \"foo\"\n\
         %1 = OpTypeVoid\n\
         %2 = OpTypeFunction %1\n\
         %3 = OpFunction  %1  DontInline|Const %2\n\
         %4 = OpLabel\n\
         OpReturn\n\
         OpFunctionEnd"
    );
}There are multiple crates inside this repo:
autogen/: Crate to generate various Rust code snippets used in the modules inspirv/andrspirv/, from SPIR-V's JSON grammar. If you are not modifyingspirv/orrspirv/, you don't need to care about this directory.spirv/: Thespirvcrate.rspirv/: The corerspirvcrate.dis/: A binary SPIR-V disassembler based on therspirvcrate.spirv-blobs: SPIR-V blobs provided by the user for testing.
git clone https://github.com/gfx-rs/rspirv.git /path/to/rspirvIf you just want to compile and use the spirv crate:
cd /path/to/rspirv/spirv
cargo buildIf you just want to compile and use the rspirv crate:
cd /path/to/rspirv/rspirv
cargo buildIf you want to refresh the spirv or rspirv crate with new code
snippets generated from SPIR-V's JSON grammar:
cd /path/to/rspirv
# Clone the SPIRV-Headers repo
git submodule update --init
cargo run -p rspirv-autogenRunning cargo test would scan spirv-blobs folder and its subfolders
(with symlinks followed) for any SPIR-V binary blobs. The test will try to
load them, disassemble them, and then compose back from the internal
representations, ensuring the smooth round-trip.
This project is licensed under the Apache License, Version 2.0 (LICENSE or http://www.apache.org/licenses/LICENSE-2.0). Please see CONTRIBUTING before contributing.
This project is initialized Lei Zhang (@antiagainst) and currently developed by the gfx-rs Translators team.