Open-Source Wikis

/

wgpu

/

Crates

/

Naga backends

gfx-rs/wgpu

Naga backends

Backends consume a validated Module (plus its ModuleInfo) and emit text or bytes in a target shading language. They live under naga/src/back/.

Layout

naga/src/back/
├── mod.rs                  shared types (FunctionCtx, etc.) (~14 KB)
├── continue_forward.rs     `continue` and forward-jump rewriting helper (~13 KB)
├── pipeline_constants.rs   pipeline-constant override substitution (~42 KB)
├── spv/                    SPIR-V binary writer
├── msl/                    Metal Shading Language writer
├── hlsl/                   HLSL writer (Shader Model 5.0+)
├── glsl/                   GLSL writer (GLSL 330+, GLSL ES 300+)
├── wgsl/                   WGSL writer
└── dot/                    GraphViz DOT writer

Status

Backend Status Notes
SPIR-V (spv-out) Primary Used by Vulkan.
MSL (msl-out) Primary Used by Metal.
HLSL (hlsl-out) Primary Used by DX12. Shader Model 5.0+.
GLSL (glsl-out) Secondary Used by GLES. GLSL 330+ / ES 300+.
WGSL (wgsl-out) Secondary Round-trips. Used for snapshot tests of GLSL/SPIR-V → WGSL.
DOT (dot-out) Secondary GraphViz dump for debugging.

SPIR-V backend (spv/)

naga/src/back/spv/:

  • writer.rs (~163 KB) — SpvWriter implementation.
  • block.rs (~183 KB) — control-flow emission.
  • Plus instructions.rs, image.rs, helpers.rs, etc.

Builds SPIR-V via spirv and rspirv. Emits OpCapability declarations matching the IR's use of features (Float64, RayQueryKHR, ...). The spirv_capabilities test asserts the right ones come out.

The SPIR-V backend uses pipeline_constants.rs to substitute pipeline-override constants at the IR level before emission, so the resulting SPIR-V module is fully concrete.

Metal backend (msl/)

naga/src/back/msl/:

  • writer.rs (~349 KB) — the largest source file in the repo.
  • Plus support for argument buffers, raytracing intrinsics, mesh-shader entry points.

Emits MSL source text, which Metal compiles via MTLDevice::newLibraryWithSource:. The Metal backend handles a lot of fiddly details around argument-buffer encoding, autorelease behavior of intermediate types, and MSL's specific syntax for things like atomics and barycentric coordinates.

HLSL backend (hlsl/)

naga/src/back/hlsl/:

  • writer.rs (~214 KB).
  • Targets Shader Model 5.0+, i.e. DirectX 11 and DirectX 12.
  • Output is passed to DXC (preferred), static-DXC, or FXC by the DX12 HAL backend.

HLSL has tricky shape-conversion rules; the backend goes to some lengths to emit correct cbuffer layouts, structured buffer member orderings, and root-signature-friendly bindings. The naga/hlsl-snapshots/ helper crate participates in HLSL-specific snapshot tests.

GLSL backend (glsl/)

naga/src/back/glsl/:

  • writer.rs (~198 KB).
  • Targets GLSL 330+ and GLSL ES 300+.
  • Used by wgpu-hal/src/gles/ and by anyone who wants WGSL → GLSL conversion.

GLSL is the trickiest target because of the GLES feature ladder: storage buffers, compute shaders, and some sampling modes were added across GLES 3.0/3.1/3.2. The backend takes a Version parameter that gates emission.

WGSL backend (wgsl/)

naga/src/back/wgsl/ writes WGSL. Useful for:

  • Round-trip testing — parse SPIR-V/GLSL, lower to IR, write WGSL, ensure semantics are preserved.
  • Tooling that wants a canonical form (deno_webgpu and others may use this).

DOT backend (dot/)

GraphViz output. Use naga --flow-dir <dir> shader.spv to dump the SPIR-V control-flow graph as .dot files. Useful for understanding what the SPIR-V structurizer sees.

Pipeline constants

naga/src/back/pipeline_constants.rs performs override substitution: WGSL's @override constants and SPIR-V's specialization constants are replaced with concrete values before code emission. This happens once per pipeline, not once per shader module — wgpu-core calls it when constructing a RenderPipeline/ComputePipeline.

Bounds checks at the backend level

Backends respect BoundsCheckPolicies (from naga::proc). They emit either:

  • a min(idx, len-1) style clamp,
  • a guarded read that returns zero on out-of-bounds,
  • or no check at all (Unchecked),

depending on the policy and address space.

Modifying a backend

Common patterns:

  • A new IR variant emitted differently — add the case to each backend's writer. Pay attention to the differences in target-language semantics (HLSL doesn't have mat3x4, MSL has different array-of-array rules, GLSL has version-dependent atomics, etc.).
  • A new emission for an existing variant — usually a single-file change in the affected backend's writer.rs.
  • A new pipeline-constant casenaga/src/back/pipeline_constants.rs is centralized.
  • A new bounds-check policy — extend BoundsCheckPolicy, then add the emission for each backend.

Always run cd naga && cargo xtask validate <backend> after regenerating snapshots so the output is checked by the actual external compiler.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Naga backends – wgpu wiki | Factory