https://github.com/gogpu/naga
Pure Go Shader Compiler — WGSL to SPIR-V, MSL, GLSL, HLSL, DXIL. Zero CGO.
https://github.com/gogpu/naga
compiler directx dxil glsl go golang gpu graphics hlsl metal msl opengl pure-go shader spirv vulkan webgpu wgsl
Last synced: about 1 month ago
JSON representation
Pure Go Shader Compiler — WGSL to SPIR-V, MSL, GLSL, HLSL, DXIL. Zero CGO.
- Host: GitHub
- URL: https://github.com/gogpu/naga
- Owner: gogpu
- License: mit
- Created: 2025-12-05T15:25:01.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-04-29T16:14:45.000Z (about 1 month ago)
- Last Synced: 2026-04-29T18:15:26.035Z (about 1 month ago)
- Topics: compiler, directx, dxil, glsl, go, golang, gpu, graphics, hlsl, metal, msl, opengl, pure-go, shader, spirv, vulkan, webgpu, wgsl
- Language: Go
- Size: 3.39 MB
- Stars: 33
- Watchers: 0
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
- Roadmap: ROADMAP.md
Awesome Lists containing this project
README
naga
Pure Go Shader Compiler
WGSL to SPIR-V, MSL, GLSL, HLSL, and DXIL. Zero CGO.
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 — 100% validation; DXIL — 94.7% IDxcValidator (experimental) |
| **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 72/72** — 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 72/72** — 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 (**72/72 exact Rust naga parity**)
- **DXIL Backend** (experimental) — Direct DXIL generation from naga IR (**161/170 IDxcValidator validation, 94.7%**; **105/208 DXC golden parity, diff=0**; **gg production: 58/59 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(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
```bash
go get github.com/gogpu/naga
```
**Requirements:** Go 1.25+
---
## Usage
### As Library
```go
package main
import (
"fmt"
"log"
"github.com/gogpu/naga"
)
func main() {
source := `
@vertex
fn main(@builtin(vertex_index) idx: u32) -> @builtin(position) vec4 {
return vec4(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
```go
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
```bash
# 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
```bash
# 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/in/ # 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
```go
// 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
```go
// 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/ ~192K 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, 161/170 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`, `vec3`, `vec4` (and short aliases: `vec2f`, `vec3i`, `vec4u`, etc.)
- Matrices: `mat2x2` ... `mat4x4` (and short aliases: `mat2x2f`, `mat4x4f`, etc.)
- Arrays: `array`, `array` (runtime-sized, storage buffers)
- Structs: `struct { ... }` (with constructor syntax: `StructName(field1, field2)`)
- Atomics: `atomic`, `atomic`
- Textures: `texture_2d`, `texture_3d`, `texture_cube`, `texture_depth_2d_array`
- Samplers: `sampler`, `sampler_comparison`
- Binding arrays: `binding_array`
- Ray tracing: `acceleration_structure`, `ray_query`
- Abstract constructors: `vec3(1,2,3)`, `mat2x2(...)`, `array(...)` (without explicit template parameters)
- Type aliases: `alias FVec3 = vec3;`
### 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 buffer
- `var` — Read-only storage buffer
- `var` — Read-write storage buffer
- `var` — 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](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 | ✅ **72/72 Rust parity** | DirectX 11/12 |
| DXIL | **161/170 IDxcValidator (94.7%)** | DirectX 12 (SM 6.0-6.5, experimental) |
See [ROADMAP.md](ROADMAP.md) for detailed development plans.
---
## References
- [WGSL Specification](https://www.w3.org/TR/WGSL/)
- [SPIR-V Specification](https://registry.khronos.org/SPIR-V/)
- [naga (Rust)](https://github.com/gfx-rs/naga) — Original implementation
### Rust Naga Compatibility
naga is tested against **all 144 reference WGSL shaders** from the [Rust naga](https://github.com/gfx-rs/naga) test suite — **100% compatibility** across all five layers: **IR 144/144**, **SPIR-V 87/87**, **MSL 91/91**, **GLSL 68/68**, **HLSL 72/72** exact output match. Total: 164 test shaders with 994 golden outputs.
---
## Ecosystem
**naga** is the shader compiler for the [GoGPU](https://github.com/gogpu) ecosystem.
| Project | Description |
|---------|-------------|
| [gogpu/gogpu](https://github.com/gogpu/gogpu) | GPU framework with windowing and input |
| [gogpu/wgpu](https://github.com/gogpu/wgpu) | Pure Go WebGPU implementation |
| **gogpu/naga** | **Shader compiler (this repo)** |
| [gogpu/gg](https://github.com/gogpu/gg) | 2D graphics library |
| [gogpu/ui](https://github.com/gogpu/ui) | GUI toolkit (22 widgets, M3/Fluent/Cupertino) |
---
## Documentation
- **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** — Compiler architecture, pipeline, IR design
- **[ROADMAP.md](ROADMAP.md)** — Development milestones
- **[CHANGELOG.md](CHANGELOG.md)** — Release notes
- **[pkg.go.dev](https://pkg.go.dev/github.com/gogpu/naga)** — API reference
---
## 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](LICENSE) for details.
---
naga — Shaders in Pure Go