Crate spirv_cross2

source ·
Expand description

Safe and sound Rust bindings to SPIRV-Cross.

All backends exposed by the SPIRV-Cross C API are fully supported, including

The API provided is roughly similar to the SPIRV-Cross Compiler C++ API, with some inspiration from naga. A best effort has been made to ensure that these bindings are sound, and that mutations occur strictly within Rust’s borrow rules.

§Context

The entry point to the library is SpirvCrossContext, which owns all foreign allocations. Hence, structs wrapping SPIRV-Cross objects have a lifetime parameter that refers to the lifetime of the context.

Compiler instances can share a context, in which case the context must outlive all associated objects, or it can take ownership of a context and have a 'static lifetime, in which case the context becomes internally ref-counted and will be dropped when the last child resource is dropped.

§Strings

Methods on Compiler return and accept ContextStr instead of a normal string type. A ContextStr may or may not be owned by the context, or may come from Rust. Rust string types can be coerced automatically to ContextStr as an input, and ContextStr can easily be copied to a Rust string type.

If a returned ContextStr is owned by the context and is immutable, it will share the lifetime of the context. Some functions return short lived strings which are owned by the compiler instance, rather than the context.

The underlying string data could possibly be modified by set_ functions, thus they only have a lifetime corresponding to the lifetime of the immutable borrow of the Compiler that produced them. References to these short-lived strings can not be alive before calling a mutating function.

§Handles

All reflected SPIR-V IDs are returned as Handle<T>, where the u32 ID part can be retrieved with Handle::id. Handles are tagged with the pointer of the compiler instance they came from, and are required to ensure safety such that reflection queries aren’t made between different SPIR-V modules.

Any function that takes or returns SPIR-V handles in the SPIRV-Cross API has been wrapped to accept Handle<T> in this crate.

Handles can be unsafely forged with Compiler::create_handle, but there are very few if any situations where this would be needed.

§Usage

Here is an example of using the API to do some reflection and compile to GLSL.

Note the 'static lifetime of the artifact, as the context is owned by the compiler.

use spirv_cross2::compile::{CompilableTarget, CompiledArtifact};
use spirv_cross2::{Module, SpirvCrossContext, SpirvCrossError};
use spirv_cross2::compile::glsl::GlslVersion;
use spirv_cross2::reflect::{DecorationValue, ResourceType};
use spirv_cross2::spirv;
use spirv_cross2::targets::Glsl;

fn compile_spirv(words: &[u32]) -> Result<CompiledArtifact<'static, Glsl>, SpirvCrossError> {
    let module = Module::from_words(words);
    let context = SpirvCrossContext::new()?;

    let mut compiler = context.into_compiler::<Glsl>(module)?;

    let resources = compiler.shader_resources()?;

    for resource in resources.resources_for_type(ResourceType::SampledImage)? {
        let Some(DecorationValue::Literal(set)) =
                compiler.decoration(resource.id,  spirv::Decoration::DescriptorSet)? else {
            continue;
        };
        let Some(DecorationValue::Literal(binding)) =
            compiler.decoration(resource.id,  spirv::Decoration::Binding)? else {
            continue;
        };

        println!("Image {} at set = {}, binding = {}", resource.name, set, binding);

        // Modify the decoration to prepare it for GLSL.
        compiler.set_decoration(resource.id, spirv::Decoration::DescriptorSet,
                DecorationValue::unset())?;

        // Some arbitrary remapping if we want.
        compiler.set_decoration(resource.id, spirv::Decoration::Binding,
            Some(set * 16 + binding))?;
    }

    let mut options = Glsl::options();
    options.version = GlslVersion::Glsl300Es;

    compiler.compile(&options)
}

Modules§

  • Compilation of SPIR-V to a textual format.
  • Handles to SPIR-V IDs from reflection.
  • SPIR-V reflection helpers and types.
  • SPIR-V types and definitions.
  • Compiler output targets.

Structs§

  • An instance of a SPIRV-Cross compiler.
  • An immutable wrapper around a valid UTF-8 string whose memory contents may or may not be originating from a SpirvCrossContext context.
  • A SPIR-V Module represented as SPIR-V words.
  • The SPIRV-Cross context. All memory allocations originating from this context will have the same lifetime as the context.

Enums§

Traits§

  • Helper trait to detach objects with lifetimes attached to a compiler or context.