Crate inline_spirv

source ·
Expand description

§inline-spirv

The first string is always your shader path or the source code, depending on the macro you use. Other following parameters give you finer control over the compilation process.

§Source Language

inline-spirv currently support three source languages:

  • spvasm: The shader source is in SPIR-V assembly (always there);
  • glsl: The shader source is in GLSL (enabled by default);
  • hlsl: The shader source is in HLSL (enabled by default);
  • wgsl: The shader source is in WGSL.

The experimental WGSL support for WebGPU is available when wgsl feature is enabled, but currently you have to compile with a nightly toolchain. Limited by the naga backend, most of the extra parameters won’t be effective and only the first entry point is generated in SPIR-V.

§Shader Stages

The following shader stages are supported:

  • vert: Vertex shader;
  • tesc: Tessellation control shader (Hull shader);
  • tese: Tessellation evaluation shader (Domain shader);
  • geom: Geometry shader;
  • frag: Fragment shader (Pixel shader);
  • comp: Compute shader;
  • mesh: (Mesh shading) Mesh shader;
  • task: (Mesh shading) Task shader;
  • rgen: (Raytracing) ray-generation shader;
  • rint: (Raytracing) intersection shader;
  • rahit: (Raytracing) any-hit shader;
  • rchit: (Raytracing) closest-hit shader;
  • rmiss: (Raytracing) miss shader;
  • rcall: (Raytracing) callable shader;

§Specify Entry Function

By default the compiler seeks for an entry point function named main. You can also explicitly specify the entry function name:

include_spirv!("path/to/shader.hlsl", hlsl, vert, entry="very_main");

§Optimization Preference

To decide how much you want the SPIR-V to be optimized:

  • min_size: Optimize for the minimal output size;
  • max_perf: Optimize for the best performance;
  • no_debug: Strip off all the debug information (don’t do this if you want to reflect the SPIR-V and get variable names).

§Include External Source

You can use #include "x.h" to include a file relative to the shader source file (you cannot use this in inline source); or you can use #include <x.h> to include a file relative to any of your provided include directories (searched in order). To specify a include directory:

include_spirv!("path/to/shader.glsl", vert,
    I "path/to/shader-headers/",
    I "path/to/also-shader-headers/");

§Include SPIR-V Binary

You may also want to inline precompiled SPIR-V binaries if you already have your pipeline set up. To do so, you can use include_spirv_bytes!:

include_spirv!("path/to/shader.spv");

Note that all compile arguments are ignored in this case, since there is no compilation.

§Compiler Definition

You can also define macro substitutions:

include_spirv!("path/to/shader.glsl", vert,
    D USE_LIGHTMAP,
    D LIGHTMAP_COUNT="2");

You can request a specific version of target environment:

  • vulkan1_0 for Vulkan 1.0 (default, supports SPIR-V 1.0);
  • vulkan1_1 for Vulkan 1.1 (supports SPIR-V 1.3);
  • vulkan1_2 for Vulkan 1.2 (supports SPIR-V 1.5).
  • opengl4_5 for OpenGL 4.5 core profile.
  • webgpu for WebGPU.

Of course once you started to use macro is basically means that you are getting so dynamic that this little crate might not be enough. Then it might be a good time to build your own shader compilation pipeline!

§Descriptor Auto-binding

If you are just off your work being tooooo tired to specify the descriptor binding points yourself, you can switch on auto_bind:

inline_spirv!(r#"
    #version 450 core
    uniform sampler2D limap;
    uniform sampler2D emit_map;
    void main() {}
"#, glsl, frag, auto_bind);

However, if you don’t have any automated reflection tool to get the actual binding points, it’s not recommended to use this.

§Flip-Y for WebGPU

If you intend to compile WGSL for a WebGPU backend, naga by default inverts the Y-axis due to the discrepancy in NDC (Normalized Device Coordinates) between WebGPU and Vulkan. If such correction is undesired, you can opt out with no_y_flip.

§Tips

The macro can be verbose especially you have a bunch of #includes, so please be aware of that you can alias and define a more customized macro for yourself:

use inline_spirv::include_spirv as include_spirv_raw;

macro_rules! include_spirv {
    ($path:expr, $stage:ident) => {
        include_spirv_raw!(
            $path,
            $stage, hlsl,
            entry="my_entry_pt",
            D VERBOSE_DEFINITION,
            D ANOTHER_VERBOSE_DEFINITION="verbose definition substitution",
            I "long/path/to/include/directory",
        )
    }
}

// ...
let vert: &[u32] = include_spirv!("examples/demo/assets/demo.hlsl", vert);

Macros§

  • Compile external shader source and embed the SPIR-V binary word sequence. Returns a &'static [u32].
  • Compile inline shader source and embed the SPIR-V binary word sequence. Returns a &'static [u32].