gogpu/naga

Pure Go Shader Compiler — WGSL to SPIR-V, MSL, GLSL, HLSL, DXIL. Zero CGO.

Go

53

198 commits

updated Oct 17, 2026

See the code

README

naga

Pure Go Shader Compiler
WGSL to SPIR-V, MSL, GLSL, HLSL, and DXIL. Zero CGO.

CI codecov Go Reference Go Report Card License Latest Release Go Version Zero CGO Stars Discussions

Part of the GoGPU ecosystem


Overview

naga is a shader compiler written entirely in Go. It compiles WGSL (WebGPU Shading Language) to multiple backend formats without requiring CGO or external dependencies.

Key Features

CategoryCapabilities
InputFull WGSL parser (120+ tokens), 48 short type aliases (vec3f, mat4x4f...), abstract constructors
OutputsSPIR-V (checked with spirv-val in CI), MSL, GLSL, HLSL; DXIL — 172/237 IDxcValidator on the Rust naga corpus (experimental)
ComputeStorage buffers, workgroups, atomics, barriers, subgroup operations
Ray TracingRay query types, acceleration structures, 7 ray query builtins
CompatibilityTested against Rust naga's WGSL snapshot corpus (172 shaders, gfx-rs/wgpu 14328f49): every output is compared, and each known difference is recorded with its reason — see Rust Naga Compatibility
BuildZero CGO, single binary

Features

  • Pure Go — No CGO, no external dependencies
  • WGSL Frontend — Full lexer and parser (120+ tokens), 48 short type aliases (vec3f, mat4x4f, etc.), abstract constructors (vec3(1,2,3))
  • Rust Naga Compatibility — every IR, SPIR-V, MSL, GLSL and HLSL output is compared with Rust naga's on its 172-shader WGSL corpus; known differences are recorded per output with a reason. 28 own test shaders; 936 golden outputs
  • IR — Complete intermediate representation (expressions, statements, types)
  • Compute Shaders — Storage buffers, workgroup memory, @workgroup_size
  • Atomic Operations — atomicAdd, atomicSub, atomicMin, atomicMax, atomicCompareExchangeWeak
  • Barriers — workgroupBarrier, storageBarrier, textureBarrier
  • Type Inference — Automatic type resolution for all expressions, including let bindings
  • Type Deduplication — SPIR-V compliant unique type emission
  • Array Initialization — array(1, 2, 3) shorthand with inferred type and size
  • Texture Sampling — textureSample, textureLoad, textureStore, textureDimensions, textureGather, textureSampleCompare
  • Swizzle Operations — Full vector swizzle support (.xyz, .rgba, .xxyy, etc.)
  • Function Calls — OpFunctionCall support for modular WGSL shaders with helper functions
  • SPIR-V Backend — Vulkan-compatible bytecode generation: integer div/mod safety wrappers, image bounds checking (Restrict/ReadZeroSkipWrite), ray query helpers, force loop bounding, workgroup zero-init polyfill, NonUniform decorations, capability-aware instruction emission
  • MSL Backend — Metal Shading Language output for macOS/iOS, vertex pulling transform, external textures, override pipeline constants, function-scope workgroup declarations (no host setThreadgroupMemoryLength needed)
  • GLSL Backend — OpenGL Shading Language for OpenGL 3.3+, ES 3.0+, dead code elimination, ProcessOverrides, image bounds checking, version-aware layout(binding=N) emission (SupportsExplicitLocations for GL 4.2+/ES 3.1+), UniformInfo reflection for runtime binding fallback on older GL drivers
  • HLSL Backend — High-Level Shading Language for DirectX 11/12
  • DXIL Backend (experimental) — Direct DXIL generation from naga IR (172 of 237 entry points of the Rust naga test corpus pass IDxcValidator; 103 of 182 DXC roundtrip comparisons match exactly; gg production shaders: 45 of 50 entry points valid; visual: renders circles + text on D3D12). LLVM 3.7 bitcode with dx.op intrinsics, DXBC container. Vertex, fragment, compute, and mesh shaders (SM 6.0-6.5). CBV/SRV/UAV (read-only storage as SRV, read-write as UAV), atomics (i32/i64/f32 + image), barriers, ray query (35 intrinsics), wave/subgroup ops (13 intrinsics), texture sampling (8 variants), matrix scalarization, pack/unpack, helper functions. Optimization passes: DCE (mark-and-sweep), SROA (struct decomposition), mem2reg (SSA promotion), single-store local promotion, loadInput DCE (per-member backwards reachability), workgroup struct decomposition, function inlining (early-return wrapping), strength reduction (mul→shl, urem→and, sub→add), constant folding. Options.BindingMap for WGSL→DXIL (space, register) remap (wgpu root signature compatibility). Eliminates FXC/DXC dependency. dxil.Compile() API. ~50K LOC, 330+ unit tests. World's first Pure Go DXIL generator.
  • Type Conversions — Scalar constructors f32(x), u32(y), i32(z) with correct SPIR-V opcodes
  • Bitcast — bitcast<T>(expr) for reinterpreting bit patterns between types
  • Warnings — Unused variable detection with _ prefix exception
  • Validation — Type checking, semantic validation, function call argument type/count verification, @must_use enforcement, const_assert evaluation, @binding/@group pairing, array size validation, swizzle namespace enforcement, mandatory semicolons
  • CLI Tool — nagac command-line compiler

Installation

go get github.com/gogpu/naga

Requirements: Go 1.25+


Usage

As Library

package main

import (
    "fmt"
    "log"

    "github.com/gogpu/naga"
)

func main() {
    source := `
@vertex
fn main(@builtin(vertex_index) idx: u32) -> @builtin(position) vec4<f32> {
    return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
`
    // Simple compilation
    spirv, err := naga.Compile(source)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Generated %d bytes of SPIR-V\n", len(spirv))
}

With Options

opts := naga.CompileOptions{
    SPIRVVersion: spirv.Version1_3,
    Debug:        true,   // Include debug names
    Validate:     true,   // Enable IR validation
}
spirv, err := naga.CompileWithOptions(source, opts)

CLI Tool

# Install
go install github.com/gogpu/naga/cmd/nagac@latest

# Compile shader
nagac shader.wgsl -o shader.spv

# With debug info
nagac -debug shader.wgsl -o shader.spv

# Show version
nagac -version

Development Tools

# SPIR-V disassembler (debugging shader compilation)
go install github.com/gogpu/naga/cmd/spvdis@latest
spvdis shader.spv

# DXIL validator — Pure Go wrapper around Microsoft IDxcValidator (Windows)
# First Pure Go integration with dxil.dll, zero CGO. Runs a three-layer
# defensive pre-check (DXBC structural + LLVM bitcode metadata walker)
# before handing blobs to IDxcValidator::Validate.
go install github.com/gogpu/naga/cmd/dxilval@latest
dxilval shader.dxil                       # validate a single container
dxilval --wgsl shader.wgsl                # compile through naga, then validate
dxilval --corpus snapshot/testdata/rust/in/wgsl/  # walk a directory, typed-error summary

# Texture shader compile tool (testing)
go install github.com/gogpu/naga/cmd/texture_compile@latest
texture_compile shader.wgsl

Multiple Backends

// Parse and lower WGSL to IR (shared across all backends)
ast, _ := naga.Parse(source)
module, _ := naga.Lower(ast)

// Generate SPIR-V (Vulkan)
spirvBytes, _ := naga.GenerateSPIRV(module, spirv.Options{})

// Generate MSL (Metal)
mslCode, _, _ := msl.Compile(module, msl.DefaultOptions())

// Generate GLSL (OpenGL)
glslCode, _, _ := glsl.Compile(module, glsl.DefaultOptions())

// Generate HLSL (DirectX 11/12)
hlslCode, _, _ := hlsl.Compile(module, hlsl.DefaultOptions())

// Generate DXIL (DirectX 12, SM 6.0 — experimental)
dxilBytes, _ := dxil.Compile(module, dxil.DefaultOptions())

Individual Stages

// Parse WGSL to AST
ast, err := naga.Parse(source)

// Lower AST to IR
module, err := naga.Lower(ast)

// Validate IR
errors, err := naga.Validate(module)

// Generate SPIR-V
spirvOpts := spirv.Options{Version: spirv.Version1_3, Debug: true}
spirvBytes, err := naga.GenerateSPIRV(module, spirvOpts)

Architecture

naga/                              ~323K LOC total
├── wgsl/              # WGSL frontend (~19.5K LOC)
│   ├── token.go       # Token types (120+)
│   ├── lexer.go       # Tokenizer
│   ├── ast.go         # AST types
│   ├── parser.go      # Recursive descent parser
│   └── lower.go       # AST → IR converter
├── ir/                # Intermediate representation (~6.5K LOC)
│   ├── ir.go          # Core types (Module, Type, Function)
│   ├── expression.go  # 30+ expression kinds
│   ├── statement.go   # 20+ statement kinds
│   ├── validate.go    # IR validation
│   ├── resolve.go     # Type inference
│   └── registry.go    # Type deduplication
├── spirv/             # SPIR-V backend (~10.8K LOC)
│   ├── spirv.go       # SPIR-V constants and opcodes
│   ├── block.go       # Block ownership model (Rust naga pattern)
│   ├── writer.go      # Binary module builder
│   ├── backend.go     # IR → SPIR-V translator
│   └── ray_query.go   # Ray query helper functions
├── msl/               # MSL backend (~14.2K LOC)
│   ├── backend.go     # Public API, Options, Compile()
│   ├── writer.go      # MSL code writer
│   ├── types.go       # Type generation
│   ├── expressions.go # Expression codegen
│   ├── statements.go  # Statement codegen
│   ├── functions.go   # Entry points and functions
│   └── keywords.go    # MSL/C++ reserved words
├── glsl/              # GLSL backend (~7.8K LOC)
│   ├── backend.go     # Public API, version targeting
│   ├── writer.go      # GLSL code writer
│   ├── types.go       # Type generation
│   ├── expressions.go # Expression codegen
│   ├── statements.go  # Statement codegen
│   └── keywords.go    # Reserved word escaping
├── hlsl/              # HLSL backend (~13.6K LOC)
│   ├── backend.go     # Public API, Options, Compile()
│   ├── writer.go      # HLSL code writer
│   ├── types.go       # Type generation
│   ├── expressions.go # Expression codegen
│   ├── statements.go  # Statement codegen
│   ├── storage.go     # Buffer/atomic operations
│   ├── functions.go   # Entry points with semantics
│   └── keywords.go    # HLSL reserved words
├── dxil/              # DXIL backend (~50K LOC, 172/237 IDxcValidator)
│   ├── dxil.go        # Public API: Compile(), DefaultOptions()
│   └── internal/      # All implementation internal
│       ├── bitcode/   # LLVM 3.7 bit-level writer
│       ├── module/    # DXIL module + bitcode serialization
│       ├── container/ # DXBC container (ISG1/OSG1/PSG1/PSV0/SFI0/HASH)
│       └── emit/      # naga IR → DXIL lowering (all shader stages)
├── naga.go            # Public API
└── cmd/
    ├── nagac/         # CLI compiler
    ├── spvdis/        # SPIR-V disassembler
    └── texture_compile/ # Texture shader testing

Supported WGSL Features

Types

  • Scalars: f16, f32, f64, i32, u32, i64, u64, bool
  • Vectors: vec2<T>, vec3<T>, vec4<T> (and short aliases: vec2f, vec3i, vec4u, etc.)
  • Matrices: mat2x2<f32> ... mat4x4<f32> (and short aliases: mat2x2f, mat4x4f, etc.)
  • Arrays: array<T, N>, array<T> (runtime-sized, storage buffers)
  • Structs: struct { ... } (with constructor syntax: StructName(field1, field2))
  • Atomics: atomic<u32>, atomic<i32>
  • Textures: texture_2d<f32>, texture_3d<f32>, texture_cube<f32>, texture_depth_2d_array
  • Samplers: sampler, sampler_comparison
  • Binding arrays: binding_array<T, N>
  • Ray tracing: acceleration_structure, ray_query
  • Abstract constructors: vec3(1,2,3), mat2x2(...), array(...) (without explicit template parameters)
  • Type aliases: alias FVec3 = vec3<f32>;

Shader Stages

  • @vertex — Vertex shaders with @builtin(position) output
  • @fragment — Fragment shaders with @location(N) outputs
  • @compute — Compute shaders with @workgroup_size(X, Y, Z)

Bindings

  • @builtin(position), @builtin(vertex_index), @builtin(instance_index)
  • @builtin(global_invocation_id) — Compute shader invocation ID
  • @location(N) — Vertex attributes and fragment outputs
  • @group(G) @binding(B) — Resource bindings

Address Spaces

  • var<uniform> — Uniform buffer
  • var<storage, read> — Read-only storage buffer
  • var<storage, read_write> — Read-write storage buffer
  • var<workgroup> — Workgroup shared memory

Statements

  • Variable declarations: var, let, const
  • Override declarations: @id(N) override name: type = default;
  • Compile-time assertions: const_assert expr;
  • Control flow: if, else, for, while, loop, switch, case, default
  • Loop control: break, continue, break if (continuing blocks)
  • Functions: return, discard
  • Assignment: =, +=, -=, *=, /=

Built-in Functions (100+)

  • Math: abs, min, max, clamp, saturate, sign, fma, modf, frexp, ldexp, quantizeToF16
  • Trigonometric: sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanh
  • Angle: radians, degrees
  • Exponential: exp, exp2, log, log2, pow, sqrt, inverseSqrt
  • Decomposition: ceil, floor, round, fract, trunc
  • Geometric: dot, cross, length, distance, normalize, faceForward, reflect, refract, outerProduct
  • Interpolation: mix, step, smoothstep
  • Matrix: transpose, determinant, inverse
  • Relational: all, any, isnan, isinf
  • Bit: countTrailingZeros, countLeadingZeros, countOneBits, reverseBits, extractBits, insertBits, firstTrailingBit, firstLeadingBit
  • Packing: pack4x8snorm, pack4x8unorm, pack2x16snorm, pack2x16unorm, pack2x16float, pack4xI8, pack4xU8, pack4xI8Clamp, pack4xU8Clamp, unpack4x8snorm, unpack4x8unorm, unpack2x16snorm, unpack2x16unorm, unpack2x16float, unpack4xI8, unpack4xU8
  • Selection: select
  • Derivatives: dpdx, dpdy, fwidth, dpdxCoarse, dpdyCoarse, fwidthCoarse, dpdxFine, dpdyFine, fwidthFine
  • Atomic: atomicAdd, atomicSub, atomicMin, atomicMax, atomicAnd, atomicOr, atomicXor, atomicExchange, atomicCompareExchangeWeak
  • Barriers: workgroupBarrier, storageBarrier, textureBarrier, subgroupBarrier
  • Subgroup: subgroupBallot, subgroupAll, subgroupAny, subgroupAdd/Mul/Min/Max/And/Or/Xor, subgroupBroadcast/First, subgroupShuffle/XOR/Up/Down, quadSwap/Broadcast
  • Ray Query: rayQueryInitialize, rayQueryProceed, rayQueryGetCommittedIntersection, rayQueryGetCandidateIntersection, rayQueryTerminate
  • Uniform Load: workgroupUniformLoad
  • Array: arrayLength

Status

Current Version: See CHANGELOG.md for release history.

BackendStatusTarget Platform
SPIR-V✅ Stable, spirv-val in CIVulkan
MSL✅ StableMetal (macOS/iOS)
GLSL✅ Stable, version-aware bindingOpenGL 3.3+, ES 3.0+
HLSL✅ StableDirectX 11/12
DXIL172/237 IDxcValidator (Rust naga corpus), 103/182 DXC goldenDirectX 12 (SM 6.0-6.5, experimental)

See ROADMAP.md for detailed development plans.

Test Coverage

~60% overall (62K tracked lines). 12/18 packages at ≥80%. Enterprise-quality tests with output verification, edge cases, regression protection, and hand-crafted IR for specialized paths.

PackageCoverage
internal/textutil, dxil/module100%
internal/backend96.6%
dxil/passes (dce/mem2reg/sroa)83-93%
ir, glsl, wgsl/parser, dxil/bitcode/container/viewid80-84%
spirv76.5%
hlsl70.6%
internal/registry75.2%
wgsl/lower65.3%
msl64.2%

Architecture

All backends follow the DXIL internal package pattern — implementation in internal/codegen/, thin public API with real types (not aliases). Zero panics in error paths.


References

Rust Naga Compatibility

naga is tested against the WGSL snapshot corpus of Rust naga: 172 shaders with their test parameters and reference outputs, vendored from gfx-rs/wgpu at commit 14328f49 (snapshot/testdata/rust/, with a manifest of every file). Every output Rust's snapshot driver writes — IR, SPIR-V, MSL, GLSL, HLSL — is compared with ours. An output that does not match is a test failure unless it is recorded in snapshot/rust_deviations_test.go with its reason and a fingerprint of the difference; most records name the upstream commits not ported yet, and some are bugs being fixed. SPIR-V is still compared by instruction counts rather than exactly. Shaders using features we do not support yet (cooperative matrices, debugPrintf, 16-bit integers, ray tracing pipelines) are listed with their expected error. In addition, 28 own test shaders and 936 golden outputs guard against unintended changes.


Ecosystem

naga is the shader compiler for the GoGPU ecosystem.

ProjectDescription
gogpu/gogpuGPU framework with windowing and input
gogpu/wgpuPure Go WebGPU implementation
gogpu/nagaShader compiler (this repo)
gogpu/gg2D graphics library
gogpu/uiGUI toolkit (22 widgets, M3/Fluent/Cupertino)

Documentation


Contributing

We welcome contributions! Areas where help is needed:

  • Additional WGSL features
  • Test cases from real shaders
  • Backend optimizations
  • Documentation improvements

Star History

Star History Chart

License

MIT License — see LICENSE for details.


naga — Shaders in Pure Go

compiler
directx
dxil
glsl
go
golang
gpu
graphics
hlsl
metal
msl
opengl
pure-go
shader
spirv
vulkan
webgpu
wgsl

gogpu/naga

Pure Go Shader Compiler — WGSL to SPIR-V, MSL, GLSL, HLSL, DXIL. Zero CGO.

Go

53

198 commits

updated Oct 17, 2026

See the code

README

naga

Pure Go Shader Compiler
WGSL to SPIR-V, MSL, GLSL, HLSL, and DXIL. Zero CGO.

CI codecov Go Reference Go Report Card License Latest Release Go Version Zero CGO Stars Discussions

Part of the GoGPU ecosystem


Overview

naga is a shader compiler written entirely in Go. It compiles WGSL (WebGPU Shading Language) to multiple backend formats without requiring CGO or external dependencies.

Key Features

CategoryCapabilities
InputFull WGSL parser (120+ tokens), 48 short type aliases (vec3f, mat4x4f...), abstract constructors
OutputsSPIR-V (checked with spirv-val in CI), MSL, GLSL, HLSL; DXIL — 172/237 IDxcValidator on the Rust naga corpus (experimental)
ComputeStorage buffers, workgroups, atomics, barriers, subgroup operations
Ray TracingRay query types, acceleration structures, 7 ray query builtins
CompatibilityTested against Rust naga's WGSL snapshot corpus (172 shaders, gfx-rs/wgpu 14328f49): every output is compared, and each known difference is recorded with its reason — see Rust Naga Compatibility
BuildZero CGO, single binary

Features

  • Pure Go — No CGO, no external dependencies
  • WGSL Frontend — Full lexer and parser (120+ tokens), 48 short type aliases (vec3f, mat4x4f, etc.), abstract constructors (vec3(1,2,3))
  • Rust Naga Compatibility — every IR, SPIR-V, MSL, GLSL and HLSL output is compared with Rust naga's on its 172-shader WGSL corpus; known differences are recorded per output with a reason. 28 own test shaders; 936 golden outputs
  • IR — Complete intermediate representation (expressions, statements, types)
  • Compute Shaders — Storage buffers, workgroup memory, @workgroup_size
  • Atomic Operations — atomicAdd, atomicSub, atomicMin, atomicMax, atomicCompareExchangeWeak
  • Barriers — workgroupBarrier, storageBarrier, textureBarrier
  • Type Inference — Automatic type resolution for all expressions, including let bindings
  • Type Deduplication — SPIR-V compliant unique type emission
  • Array Initialization — array(1, 2, 3) shorthand with inferred type and size
  • Texture Sampling — textureSample, textureLoad, textureStore, textureDimensions, textureGather, textureSampleCompare
  • Swizzle Operations — Full vector swizzle support (.xyz, .rgba, .xxyy, etc.)
  • Function Calls — OpFunctionCall support for modular WGSL shaders with helper functions
  • SPIR-V Backend — Vulkan-compatible bytecode generation: integer div/mod safety wrappers, image bounds checking (Restrict/ReadZeroSkipWrite), ray query helpers, force loop bounding, workgroup zero-init polyfill, NonUniform decorations, capability-aware instruction emission
  • MSL Backend — Metal Shading Language output for macOS/iOS, vertex pulling transform, external textures, override pipeline constants, function-scope workgroup declarations (no host setThreadgroupMemoryLength needed)
  • GLSL Backend — OpenGL Shading Language for OpenGL 3.3+, ES 3.0+, dead code elimination, ProcessOverrides, image bounds checking, version-aware layout(binding=N) emission (SupportsExplicitLocations for GL 4.2+/ES 3.1+), UniformInfo reflection for runtime binding fallback on older GL drivers
  • HLSL Backend — High-Level Shading Language for DirectX 11/12
  • DXIL Backend (experimental) — Direct DXIL generation from naga IR (172 of 237 entry points of the Rust naga test corpus pass IDxcValidator; 103 of 182 DXC roundtrip comparisons match exactly; gg production shaders: 45 of 50 entry points valid; visual: renders circles + text on D3D12). LLVM 3.7 bitcode with dx.op intrinsics, DXBC container. Vertex, fragment, compute, and mesh shaders (SM 6.0-6.5). CBV/SRV/UAV (read-only storage as SRV, read-write as UAV), atomics (i32/i64/f32 + image), barriers, ray query (35 intrinsics), wave/subgroup ops (13 intrinsics), texture sampling (8 variants), matrix scalarization, pack/unpack, helper functions. Optimization passes: DCE (mark-and-sweep), SROA (struct decomposition), mem2reg (SSA promotion), single-store local promotion, loadInput DCE (per-member backwards reachability), workgroup struct decomposition, function inlining (early-return wrapping), strength reduction (mul→shl, urem→and, sub→add), constant folding. Options.BindingMap for WGSL→DXIL (space, register) remap (wgpu root signature compatibility). Eliminates FXC/DXC dependency. dxil.Compile() API. ~50K LOC, 330+ unit tests. World's first Pure Go DXIL generator.
  • Type Conversions — Scalar constructors f32(x), u32(y), i32(z) with correct SPIR-V opcodes
  • Bitcast — bitcast<T>(expr) for reinterpreting bit patterns between types
  • Warnings — Unused variable detection with _ prefix exception
  • Validation — Type checking, semantic validation, function call argument type/count verification, @must_use enforcement, const_assert evaluation, @binding/@group pairing, array size validation, swizzle namespace enforcement, mandatory semicolons
  • CLI Tool — nagac command-line compiler

Installation

go get github.com/gogpu/naga

Requirements: Go 1.25+


Usage

As Library

package main

import (
    "fmt"
    "log"

    "github.com/gogpu/naga"
)

func main() {
    source := `
@vertex
fn main(@builtin(vertex_index) idx: u32) -> @builtin(position) vec4<f32> {
    return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
`
    // Simple compilation
    spirv, err := naga.Compile(source)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Generated %d bytes of SPIR-V\n", len(spirv))
}

With Options

opts := naga.CompileOptions{
    SPIRVVersion: spirv.Version1_3,
    Debug:        true,   // Include debug names
    Validate:     true,   // Enable IR validation
}
spirv, err := naga.CompileWithOptions(source, opts)

CLI Tool

# Install
go install github.com/gogpu/naga/cmd/nagac@latest

# Compile shader
nagac shader.wgsl -o shader.spv

# With debug info
nagac -debug shader.wgsl -o shader.spv

# Show version
nagac -version

Development Tools

# SPIR-V disassembler (debugging shader compilation)
go install github.com/gogpu/naga/cmd/spvdis@latest
spvdis shader.spv

# DXIL validator — Pure Go wrapper around Microsoft IDxcValidator (Windows)
# First Pure Go integration with dxil.dll, zero CGO. Runs a three-layer
# defensive pre-check (DXBC structural + LLVM bitcode metadata walker)
# before handing blobs to IDxcValidator::Validate.
go install github.com/gogpu/naga/cmd/dxilval@latest
dxilval shader.dxil                       # validate a single container
dxilval --wgsl shader.wgsl                # compile through naga, then validate
dxilval --corpus snapshot/testdata/rust/in/wgsl/  # walk a directory, typed-error summary

# Texture shader compile tool (testing)
go install github.com/gogpu/naga/cmd/texture_compile@latest
texture_compile shader.wgsl

Multiple Backends

// Parse and lower WGSL to IR (shared across all backends)
ast, _ := naga.Parse(source)
module, _ := naga.Lower(ast)

// Generate SPIR-V (Vulkan)
spirvBytes, _ := naga.GenerateSPIRV(module, spirv.Options{})

// Generate MSL (Metal)
mslCode, _, _ := msl.Compile(module, msl.DefaultOptions())

// Generate GLSL (OpenGL)
glslCode, _, _ := glsl.Compile(module, glsl.DefaultOptions())

// Generate HLSL (DirectX 11/12)
hlslCode, _, _ := hlsl.Compile(module, hlsl.DefaultOptions())

// Generate DXIL (DirectX 12, SM 6.0 — experimental)
dxilBytes, _ := dxil.Compile(module, dxil.DefaultOptions())

Individual Stages

// Parse WGSL to AST
ast, err := naga.Parse(source)

// Lower AST to IR
module, err := naga.Lower(ast)

// Validate IR
errors, err := naga.Validate(module)

// Generate SPIR-V
spirvOpts := spirv.Options{Version: spirv.Version1_3, Debug: true}
spirvBytes, err := naga.GenerateSPIRV(module, spirvOpts)

Architecture

naga/                              ~323K LOC total
├── wgsl/              # WGSL frontend (~19.5K LOC)
│   ├── token.go       # Token types (120+)
│   ├── lexer.go       # Tokenizer
│   ├── ast.go         # AST types
│   ├── parser.go      # Recursive descent parser
│   └── lower.go       # AST → IR converter
├── ir/                # Intermediate representation (~6.5K LOC)
│   ├── ir.go          # Core types (Module, Type, Function)
│   ├── expression.go  # 30+ expression kinds
│   ├── statement.go   # 20+ statement kinds
│   ├── validate.go    # IR validation
│   ├── resolve.go     # Type inference
│   └── registry.go    # Type deduplication
├── spirv/             # SPIR-V backend (~10.8K LOC)
│   ├── spirv.go       # SPIR-V constants and opcodes
│   ├── block.go       # Block ownership model (Rust naga pattern)
│   ├── writer.go      # Binary module builder
│   ├── backend.go     # IR → SPIR-V translator
│   └── ray_query.go   # Ray query helper functions
├── msl/               # MSL backend (~14.2K LOC)
│   ├── backend.go     # Public API, Options, Compile()
│   ├── writer.go      # MSL code writer
│   ├── types.go       # Type generation
│   ├── expressions.go # Expression codegen
│   ├── statements.go  # Statement codegen
│   ├── functions.go   # Entry points and functions
│   └── keywords.go    # MSL/C++ reserved words
├── glsl/              # GLSL backend (~7.8K LOC)
│   ├── backend.go     # Public API, version targeting
│   ├── writer.go      # GLSL code writer
│   ├── types.go       # Type generation
│   ├── expressions.go # Expression codegen
│   ├── statements.go  # Statement codegen
│   └── keywords.go    # Reserved word escaping
├── hlsl/              # HLSL backend (~13.6K LOC)
│   ├── backend.go     # Public API, Options, Compile()
│   ├── writer.go      # HLSL code writer
│   ├── types.go       # Type generation
│   ├── expressions.go # Expression codegen
│   ├── statements.go  # Statement codegen
│   ├── storage.go     # Buffer/atomic operations
│   ├── functions.go   # Entry points with semantics
│   └── keywords.go    # HLSL reserved words
├── dxil/              # DXIL backend (~50K LOC, 172/237 IDxcValidator)
│   ├── dxil.go        # Public API: Compile(), DefaultOptions()
│   └── internal/      # All implementation internal
│       ├── bitcode/   # LLVM 3.7 bit-level writer
│       ├── module/    # DXIL module + bitcode serialization
│       ├── container/ # DXBC container (ISG1/OSG1/PSG1/PSV0/SFI0/HASH)
│       └── emit/      # naga IR → DXIL lowering (all shader stages)
├── naga.go            # Public API
└── cmd/
    ├── nagac/         # CLI compiler
    ├── spvdis/        # SPIR-V disassembler
    └── texture_compile/ # Texture shader testing

Supported WGSL Features

Types

  • Scalars: f16, f32, f64, i32, u32, i64, u64, bool
  • Vectors: vec2<T>, vec3<T>, vec4<T> (and short aliases: vec2f, vec3i, vec4u, etc.)
  • Matrices: mat2x2<f32> ... mat4x4<f32> (and short aliases: mat2x2f, mat4x4f, etc.)
  • Arrays: array<T, N>, array<T> (runtime-sized, storage buffers)
  • Structs: struct { ... } (with constructor syntax: StructName(field1, field2))
  • Atomics: atomic<u32>, atomic<i32>
  • Textures: texture_2d<f32>, texture_3d<f32>, texture_cube<f32>, texture_depth_2d_array
  • Samplers: sampler, sampler_comparison
  • Binding arrays: binding_array<T, N>
  • Ray tracing: acceleration_structure, ray_query
  • Abstract constructors: vec3(1,2,3), mat2x2(...), array(...) (without explicit template parameters)
  • Type aliases: alias FVec3 = vec3<f32>;

Shader Stages

  • @vertex — Vertex shaders with @builtin(position) output
  • @fragment — Fragment shaders with @location(N) outputs
  • @compute — Compute shaders with @workgroup_size(X, Y, Z)

Bindings

  • @builtin(position), @builtin(vertex_index), @builtin(instance_index)
  • @builtin(global_invocation_id) — Compute shader invocation ID
  • @location(N) — Vertex attributes and fragment outputs
  • @group(G) @binding(B) — Resource bindings

Address Spaces

  • var<uniform> — Uniform buffer
  • var<storage, read> — Read-only storage buffer
  • var<storage, read_write> — Read-write storage buffer
  • var<workgroup> — Workgroup shared memory

Statements

  • Variable declarations: var, let, const
  • Override declarations: @id(N) override name: type = default;
  • Compile-time assertions: const_assert expr;
  • Control flow: if, else, for, while, loop, switch, case, default
  • Loop control: break, continue, break if (continuing blocks)
  • Functions: return, discard
  • Assignment: =, +=, -=, *=, /=

Built-in Functions (100+)

  • Math: abs, min, max, clamp, saturate, sign, fma, modf, frexp, ldexp, quantizeToF16
  • Trigonometric: sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanh
  • Angle: radians, degrees
  • Exponential: exp, exp2, log, log2, pow, sqrt, inverseSqrt
  • Decomposition: ceil, floor, round, fract, trunc
  • Geometric: dot, cross, length, distance, normalize, faceForward, reflect, refract, outerProduct
  • Interpolation: mix, step, smoothstep
  • Matrix: transpose, determinant, inverse
  • Relational: all, any, isnan, isinf
  • Bit: countTrailingZeros, countLeadingZeros, countOneBits, reverseBits, extractBits, insertBits, firstTrailingBit, firstLeadingBit
  • Packing: pack4x8snorm, pack4x8unorm, pack2x16snorm, pack2x16unorm, pack2x16float, pack4xI8, pack4xU8, pack4xI8Clamp, pack4xU8Clamp, unpack4x8snorm, unpack4x8unorm, unpack2x16snorm, unpack2x16unorm, unpack2x16float, unpack4xI8, unpack4xU8
  • Selection: select
  • Derivatives: dpdx, dpdy, fwidth, dpdxCoarse, dpdyCoarse, fwidthCoarse, dpdxFine, dpdyFine, fwidthFine
  • Atomic: atomicAdd, atomicSub, atomicMin, atomicMax, atomicAnd, atomicOr, atomicXor, atomicExchange, atomicCompareExchangeWeak
  • Barriers: workgroupBarrier, storageBarrier, textureBarrier, subgroupBarrier
  • Subgroup: subgroupBallot, subgroupAll, subgroupAny, subgroupAdd/Mul/Min/Max/And/Or/Xor, subgroupBroadcast/First, subgroupShuffle/XOR/Up/Down, quadSwap/Broadcast
  • Ray Query: rayQueryInitialize, rayQueryProceed, rayQueryGetCommittedIntersection, rayQueryGetCandidateIntersection, rayQueryTerminate
  • Uniform Load: workgroupUniformLoad
  • Array: arrayLength

Status

Current Version: See CHANGELOG.md for release history.

BackendStatusTarget Platform
SPIR-V✅ Stable, spirv-val in CIVulkan
MSL✅ StableMetal (macOS/iOS)
GLSL✅ Stable, version-aware bindingOpenGL 3.3+, ES 3.0+
HLSL✅ StableDirectX 11/12
DXIL172/237 IDxcValidator (Rust naga corpus), 103/182 DXC goldenDirectX 12 (SM 6.0-6.5, experimental)

See ROADMAP.md for detailed development plans.

Test Coverage

~60% overall (62K tracked lines). 12/18 packages at ≥80%. Enterprise-quality tests with output verification, edge cases, regression protection, and hand-crafted IR for specialized paths.

PackageCoverage
internal/textutil, dxil/module100%
internal/backend96.6%
dxil/passes (dce/mem2reg/sroa)83-93%
ir, glsl, wgsl/parser, dxil/bitcode/container/viewid80-84%
spirv76.5%
hlsl70.6%
internal/registry75.2%
wgsl/lower65.3%
msl64.2%

Architecture

All backends follow the DXIL internal package pattern — implementation in internal/codegen/, thin public API with real types (not aliases). Zero panics in error paths.


References

Rust Naga Compatibility

naga is tested against the WGSL snapshot corpus of Rust naga: 172 shaders with their test parameters and reference outputs, vendored from gfx-rs/wgpu at commit 14328f49 (snapshot/testdata/rust/, with a manifest of every file). Every output Rust's snapshot driver writes — IR, SPIR-V, MSL, GLSL, HLSL — is compared with ours. An output that does not match is a test failure unless it is recorded in snapshot/rust_deviations_test.go with its reason and a fingerprint of the difference; most records name the upstream commits not ported yet, and some are bugs being fixed. SPIR-V is still compared by instruction counts rather than exactly. Shaders using features we do not support yet (cooperative matrices, debugPrintf, 16-bit integers, ray tracing pipelines) are listed with their expected error. In addition, 28 own test shaders and 936 golden outputs guard against unintended changes.


Ecosystem

naga is the shader compiler for the GoGPU ecosystem.

ProjectDescription
gogpu/gogpuGPU framework with windowing and input
gogpu/wgpuPure Go WebGPU implementation
gogpu/nagaShader compiler (this repo)
gogpu/gg2D graphics library
gogpu/uiGUI toolkit (22 widgets, M3/Fluent/Cupertino)

Documentation


Contributing

We welcome contributions! Areas where help is needed:

  • Additional WGSL features
  • Test cases from real shaders
  • Backend optimizations
  • Documentation improvements

Star History

Star History Chart

License

MIT License — see LICENSE for details.


naga — Shaders in Pure Go

compiler
directx
dxil
glsl
go
golang
gpu
graphics
hlsl
metal
msl
opengl
pure-go
shader
spirv
vulkan
webgpu
wgsl

Project health

Latest release

v0.20.0 · Oct 17, 2026

Releases this year

59

Significant stargazers

Robin

341 followers · starred Dec 2025

Will Faught

64 followers · starred Dec 2025