naga

package module
v0.15.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 31, 2026 License: MIT Imports: 4 Imported by: 4

README

naga

Pure Go Shader Compiler
WGSL to SPIR-V, MSL, GLSL, and HLSL. 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

Category Capabilities
Input Full WGSL parser (120+ tokens), 48 short type aliases (vec3f, mat4x4f...), abstract constructors
Outputs SPIR-V, MSL, GLSL, HLSL
Compute Storage buffers, workgroups, atomics, barriers, subgroup operations
Ray Tracing Ray query types, acceleration structures, 7 ray query builtins
Compatibility 144/144 (100%) reference shaders compile. Five-layer exact match: IR 144/144, SPIR-V 87/87, MSL 91/91, GLSL 68/68, HLSL 58/58 — complete Rust naga parity on all backends
Build Zero 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 — 144/144 (100%) reference shaders compile. Five-layer exact match: IR 144/144, SPIR-V 87/87, MSL 91/91, GLSL 68/68, HLSL 58/58 — complete Rust naga parity on all backends. 164 snapshot tests with 994 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 (87/87 exact Rust naga parity): 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 (91/91 exact Rust naga parity), vertex pulling transform, external textures, override pipeline constants
  • GLSL Backend — OpenGL Shading Language for OpenGL 3.3+, ES 3.0+ (68/68 exact Rust naga parity), dead code elimination, ProcessOverrides, image bounds checking
  • HLSL Backend — High-Level Shading Language for DirectX 11/12 (58/58 exact Rust naga parity)
  • 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 and semantic validation
  • 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

# 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)
hlslCode, _, _ := hlsl.Compile(module, hlsl.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/                              ~90K 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
├── 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.

Backend Status Target Platform
SPIR-V ✅ 87/87 Rust parity Vulkan
MSL ✅ 91/91 Rust parity Metal (macOS/iOS)
GLSL ✅ 68/68 Rust parity OpenGL 3.3+, ES 3.0+
HLSL ✅ 58/58 Rust parity DirectX 11/12

See ROADMAP.md for detailed development plans.


References

Rust Naga Compatibility

naga is tested against all 144 reference WGSL shaders from the Rust naga test suite — 100% compatibility across all five layers: IR 144/144, SPIR-V 87/87, MSL 91/91, GLSL 68/68, HLSL 58/58 exact output match. Total: 164 test shaders with 994 golden outputs.


Ecosystem

naga is the shader compiler for the GoGPU ecosystem.

Project Description
gogpu/gogpu GPU framework with windowing and input
gogpu/wgpu Pure Go WebGPU implementation
gogpu/naga Shader compiler (this repo)
gogpu/gg 2D graphics library
gogpu/ui GUI toolkit (planned)

Documentation


Contributing

We welcome contributions! Areas where help is needed:

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

License

MIT License — see LICENSE for details.


naga — Shaders in Pure Go

Documentation

Overview

Package naga provides a Pure Go shader compiler.

naga compiles WGSL (WebGPU Shading Language) source code to multiple output formats:

  • SPIR-V — Binary format for Vulkan
  • MSL — Metal Shading Language for macOS/iOS
  • GLSL — OpenGL Shading Language for OpenGL 3.3+, ES 3.0+
  • HLSL — High Level Shading Language for DirectX

The package provides a simple, high-level API for shader compilation as well as lower-level access to individual compilation stages.

Example usage (SPIR-V):

source := `
@vertex
fn main(@builtin(vertex_index) idx: u32) -> @builtin(position) vec4<f32> {
    return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}
`
spirv, err := naga.Compile(source)
if err != nil {
    log.Fatal(err)
}

For MSL output, use the msl package:

module, _ := naga.Lower(ast)
mslCode, info, err := msl.Compile(module, msl.DefaultOptions())

For GLSL output, use the glsl package:

module, _ := naga.Lower(ast)
glslCode, info, err := glsl.Compile(module, glsl.DefaultOptions())

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Compile

func Compile(source string) ([]byte, error)

Compile compiles WGSL source code to SPIR-V binary using default options.

This is the simplest way to compile a shader. For more control, use CompileWithOptions or the individual Parse/Lower/Generate functions.

func CompileWithOptions

func CompileWithOptions(source string, opts CompileOptions) ([]byte, error)

CompileWithOptions compiles WGSL source code to SPIR-V binary with custom options.

The compilation pipeline is:

  1. Parse WGSL source to AST
  2. Lower AST to IR (intermediate representation)
  3. Validate IR (if enabled)
  4. Generate SPIR-V binary

func GenerateSPIRV

func GenerateSPIRV(module *ir.Module, opts spirv.Options) ([]byte, error)

GenerateSPIRV generates SPIR-V binary from IR module.

This is the final stage of compilation. The output is a binary blob that can be directly consumed by Vulkan or other SPIR-V consumers.

func Lower

func Lower(ast *wgsl.Module) (*ir.Module, error)

Lower converts WGSL AST to IR (Intermediate Representation).

The IR is a lower-level representation that includes type information, resolved identifiers, and a simpler structure suitable for code generation.

func LowerWithSource added in v0.4.0

func LowerWithSource(ast *wgsl.Module, source string) (*ir.Module, error)

LowerWithSource converts WGSL AST to IR, keeping source for error messages.

When source is provided, errors will include line:column information and can show source context using ErrorList.FormatAll().

func Parse

func Parse(source string) (*wgsl.Module, error)

Parse parses WGSL source code to AST (Abstract Syntax Tree).

This is the first stage of compilation. The AST represents the syntactic structure of the shader but does not include semantic information like types.

func Validate

func Validate(module *ir.Module) ([]ir.ValidationError, error)

Validate validates an IR module for correctness.

Validation checks include:

  • Type consistency
  • Reference validity (all handles point to valid objects)
  • Control flow validity (structured control flow rules)
  • Binding uniqueness (no duplicate @group/@binding)

Returns a slice of validation errors. If the slice is empty, validation passed.

Types

type CompileOptions

type CompileOptions struct {
	// SPIRVVersion is the target SPIR-V version (default: 1.3)
	SPIRVVersion spirv.Version

	// Debug enables debug info in output (OpName, OpLine, etc.)
	Debug bool

	// Validate enables IR validation before code generation
	Validate bool
}

CompileOptions configures shader compilation.

func DefaultOptions

func DefaultOptions() CompileOptions

DefaultOptions returns sensible default options.

Directories

Path Synopsis
cmd
nagac command
Command nagac is the naga shader compiler CLI.
Command nagac is the naga shader compiler CLI.
spvdis command
spvdis - SPIR-V disassembler Generates valid .spvasm text format
spvdis - SPIR-V disassembler Generates valid .spvasm text format
texture_compile command
Package glsl provides a GLSL (OpenGL Shading Language) backend for naga.
Package glsl provides a GLSL (OpenGL Shading Language) backend for naga.
Package hlsl provides HLSL (High-Level Shading Language) code generation from the naga intermediate representation.
Package hlsl provides HLSL (High-Level Shading Language) code generation from the naga intermediate representation.
Package ir defines the intermediate representation for naga.
Package ir defines the intermediate representation for naga.
Package msl implements Metal Shading Language (MSL) code generation for naga.
Package msl implements Metal Shading Language (MSL) code generation for naga.
Package spirv provides SPIR-V code generation from naga IR.
Package spirv provides SPIR-V code generation from naga IR.
Package wgsl provides WGSL (WebGPU Shading Language) parsing.
Package wgsl provides WGSL (WebGPU Shading Language) parsing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL