Open-Source Wikis

/

wgpu

/

Crates

/

naga

gfx-rs/wgpu

naga

Active contributors: Andy Leiserson, teoxoy, Jim Blandy, Inner Daemons

naga (naga/) is the shader translator that powers wgpu. It reads WGSL, GLSL, or SPIR-V; builds an internal IR; validates the IR against the WGSL specification's static rules; and writes back out to SPIR-V, MSL, HLSL, GLSL, WGSL, or GraphViz DOT. It is #![no_std] and #![forbid(unsafe_code)].

Purpose

  • Be the shader-translation surface for wgpu-core (and indirectly the entire wgpu ecosystem).
  • Validate WGSL programs against the spec, with consistent error messages that the WGSL frontend uses to provide source-location diagnostics.
  • Convert between every shading language wgpu cares about, so that wgpu can accept user shaders in any supported source language and produce shaders in whatever language the active backend needs.
  • Stay independent enough that it can be used standalone (via naga-cli) or by other Rust projects that want shader translation.

Sub-pages

  • Frontends — WGSL, GLSL, SPIR-V parsers.
  • IR — the Naga IR data model.
  • Processing passes — constant evaluator, type inference, namers, layouter, indexer.
  • Validationnaga::valid and Capabilities.
  • Backends — SPIR-V, MSL, HLSL, GLSL, WGSL, DOT writers.

Directory layout

naga/
├── Cargo.toml
├── README.md
├── CHANGELOG.md             naga-specific changelog (separate from wgpu's)
├── build.rs
├── fuzz/                    cargo-fuzz targets
├── hlsl-snapshots/          helper crate
├── xtask/                   `cargo xtask validate <backend>`
├── src/
│   ├── lib.rs               crate root: re-exports + glue types
│   ├── arena.rs             Arena<T>, Handle<T>, UniqueArena<T>
│   ├── span.rs              SourceLocation, Span, WithSpan
│   ├── error.rs
│   ├── non_max_u32.rs       NonZero-based handle helper
│   ├── racy_lock.rs
│   ├── ir/                  the IR data model
│   ├── front/               wgsl/, glsl/, spv/
│   ├── back/                spv/, msl/, hlsl/, glsl/, wgsl/, dot/
│   ├── valid/               validator
│   ├── proc/                processing passes
│   ├── compact/             dead-code elimination
│   ├── common/              shared helpers
│   ├── keywords/            per-language keyword sets
│   └── diagnostic_filter.rs
├── tests/                   snapshot, error, validation tests
└── ...

Key abstractions

Type File Purpose
Module naga/src/ir/mod.rs Top-level shader IR. Owns arenas of types, constants, expressions, functions, entry points.
Arena<T> naga/src/arena.rs Index-based container; items addressed by Handle<T>.
Handle<T> naga/src/arena.rs NonZeroU32 index. Copy + Eq + Hash. No lifetime.
Span naga/src/span.rs Source-position for IR items.
Validator naga/src/valid/mod.rs Validates a Module, producing ModuleInfo.
ModuleInfo naga/src/valid/mod.rs Per-expression type info, used by backends.
Capabilities naga/src/valid/mod.rs Bitflags gating optional language features.
BoundsCheckPolicies naga/src/proc/mod.rs Per-target out-of-bounds policy.

How it works

graph LR
    Source[Source text or SPIR-V binary] --> Front
    Front[Frontend<br/>front/wgsl, glsl, spv] --> Mod[Module]
    Mod --> Compact[compact<br/>optional]
    Compact --> Mod
    Mod --> Valid[Validator]
    Valid --> Info[ModuleInfo]
    Info --> Back[Backend<br/>back/spv, msl, hlsl, glsl, wgsl, dot]
    Back --> Out[Target source / binary]

The same Module flows through the whole pipeline. Frontends are responsible for converting source-level constructs into IR; processing passes (naga/src/proc/) prepare and analyze the IR; the validator checks it; backends emit text or bytes.

The README's small example shows the validator/backend invocation pattern explicitly:

let module = naga::front::wgsl::parse_str(wgsl)?;
let info = naga::valid::Validator::new(
    naga::valid::ValidationFlags::all(),
    naga::valid::Capabilities::all(),
).validate(&module)?;
naga::back::glsl::Writer::new(...).write()?;

Test infrastructure

Naga's tests are extensive and rely on snapshot files:

  • naga/tests/in/ — input shaders in WGSL, GLSL, SPIR-V.
  • naga/tests/out/ — expected outputs in every backend's language.
  • naga/tests/naga/ — the integration test harnesses (snapshot.rs, wgsl_errors.rs, validation.rs, spirv_capabilities.rs, example_wgsl.rs).

The "butterfly" pattern (WGSL → all backends, GLSL/SPIR-V → WGSL) is documented in docs/testing.md. After regenerating snapshots, run cargo xtask validate <backend> from naga/ to validate outputs against external compilers.

Capabilities and configuration

The validator is parameterized by ValidationFlags and Capabilities. Every WGSL feature beyond the spec's baseline (subgroup ops, float16/64, mesh-shader-shaped entry points, ray queries, ...) is gated by a Capabilities bit. The active set is computed from the device's Features by wgpu-naga-bridge.

Integration points

  • Above: wgpu-naga-bridge is the canonical caller. The published naga crate is also used by naga-cli and (in some cases) by user code that wants offline shader translation.
  • Below: bit-set, hashbrown, indexmap, petgraph, rspirv, spirv, pp-rs (GLSL preprocessor), codespan-reporting (error formatting), unicode-ident. No platform-graphics dependencies.

Entry points for modification

  • A new IR variant — see ir. Touches every frontend and backend.
  • A new validation rule — see validation.
  • A new constant evaluator opnaga/src/proc/constant_evaluator.rs. AGENTS.md has notes on the borrow-checker patterns to use.
  • A frontend or backend feature — see the dedicated sub-pages.

Cross-references

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

naga – wgpu wiki | Factory