Pure Go Shader Compiler — WGSL to SPIR-V, MSL, GLSL, HLSL, DXIL. Zero CGO.
Go
53
198 commits
updated Oct 17, 2026
Pure Go Shader Compiler
WGSL to SPIR-V, MSL, GLSL, HLSL, and DXIL. Zero CGO.
Part of the GoGPU ecosystem
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.
| Category | Capabilities |
|---|---|
| Input | Full WGSL parser (120+ tokens), 48 short type aliases (vec3f, mat4x4f...), abstract constructors |
| Outputs | SPIR-V (checked with spirv-val in CI), MSL, GLSL, HLSL; DXIL — 172/237 IDxcValidator on the Rust naga corpus (experimental) |
| Compute | Storage buffers, workgroups, atomics, barriers, subgroup operations |
| Ray Tracing | Ray query types, acceleration structures, 7 ray query builtins |
| Compatibility | Tested 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 |
| Build | Zero CGO, single binary |
vec3f, mat4x4f, etc.), abstract constructors (vec3(1,2,3))@workgroup_sizelet bindingsarray(1, 2, 3) shorthand with inferred type and size.xyz, .rgba, .xxyy, etc.)OpFunctionCall support for modular WGSL shaders with helper functionssetThreadgroupMemoryLength needed)layout(binding=N) emission (SupportsExplicitLocations for GL 4.2+/ES 3.1+), UniformInfo reflection for runtime binding fallback on older GL driversOptions.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.f32(x), u32(y), i32(z) with correct SPIR-V opcodesbitcast<T>(expr) for reinterpreting bit patterns between types_ prefix exception@must_use enforcement, const_assert evaluation, @binding/@group pairing, array size validation, swizzle namespace enforcement, mandatory semicolonsnagac command-line compilergo get github.com/gogpu/naga
Requirements: Go 1.25+
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))
}
opts := naga.CompileOptions{
SPIRVVersion: spirv.Version1_3,
Debug: true, // Include debug names
Validate: true, // Enable IR validation
}
spirv, err := naga.CompileWithOptions(source, opts)
# 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
# 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
// 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())
// 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)
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
f16, f32, f64, i32, u32, i64, u64, boolvec2<T>, vec3<T>, vec4<T> (and short aliases: vec2f, vec3i, vec4u, etc.)mat2x2<f32> ... mat4x4<f32> (and short aliases: mat2x2f, mat4x4f, etc.)array<T, N>, array<T> (runtime-sized, storage buffers)struct { ... } (with constructor syntax: StructName(field1, field2))atomic<u32>, atomic<i32>texture_2d<f32>, texture_3d<f32>, texture_cube<f32>, texture_depth_2d_arraysampler, sampler_comparisonbinding_array<T, N>acceleration_structure, ray_queryvec3(1,2,3), mat2x2(...), array(...) (without explicit template parameters)alias FVec3 = vec3<f32>;@vertex — Vertex shaders with @builtin(position) output@fragment — Fragment shaders with @location(N) outputs@compute — Compute shaders with @workgroup_size(X, Y, Z)@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 bindingsvar<uniform> — Uniform buffervar<storage, read> — Read-only storage buffervar<storage, read_write> — Read-write storage buffervar<workgroup> — Workgroup shared memoryvar, let, const@id(N) override name: type = default;const_assert expr;if, else, for, while, loop, switch, case, defaultbreak, continue, break if (continuing blocks)return, discard=, +=, -=, *=, /=abs, min, max, clamp, saturate, sign, fma, modf, frexp, ldexp, quantizeToF16sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanhradians, degreesexp, exp2, log, log2, pow, sqrt, inverseSqrtceil, floor, round, fract, truncdot, cross, length, distance, normalize, faceForward, reflect, refract, outerProductmix, step, smoothsteptranspose, determinant, inverseall, any, isnan, isinfcountTrailingZeros, countLeadingZeros, countOneBits, reverseBits, extractBits, insertBits, firstTrailingBit, firstLeadingBitpack4x8snorm, pack4x8unorm, pack2x16snorm, pack2x16unorm, pack2x16float, pack4xI8, pack4xU8, pack4xI8Clamp, pack4xU8Clamp, unpack4x8snorm, unpack4x8unorm, unpack2x16snorm, unpack2x16unorm, unpack2x16float, unpack4xI8, unpack4xU8selectdpdx, dpdy, fwidth, dpdxCoarse, dpdyCoarse, fwidthCoarse, dpdxFine, dpdyFine, fwidthFineatomicAdd, atomicSub, atomicMin, atomicMax, atomicAnd, atomicOr, atomicXor, atomicExchange, atomicCompareExchangeWeakworkgroupBarrier, storageBarrier, textureBarrier, subgroupBarriersubgroupBallot, subgroupAll, subgroupAny, subgroupAdd/Mul/Min/Max/And/Or/Xor, subgroupBroadcast/First, subgroupShuffle/XOR/Up/Down, quadSwap/BroadcastrayQueryInitialize, rayQueryProceed, rayQueryGetCommittedIntersection, rayQueryGetCandidateIntersection, rayQueryTerminateworkgroupUniformLoadarrayLengthCurrent Version: See CHANGELOG.md for release history.
| Backend | Status | Target Platform |
|---|---|---|
| SPIR-V | ✅ Stable, spirv-val in CI | Vulkan |
| MSL | ✅ Stable | Metal (macOS/iOS) |
| GLSL | ✅ Stable, version-aware binding | OpenGL 3.3+, ES 3.0+ |
| HLSL | ✅ Stable | DirectX 11/12 |
| DXIL | 172/237 IDxcValidator (Rust naga corpus), 103/182 DXC golden | DirectX 12 (SM 6.0-6.5, experimental) |
See ROADMAP.md for detailed development plans.
~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.
| Package | Coverage |
|---|---|
| internal/textutil, dxil/module | 100% |
| internal/backend | 96.6% |
| dxil/passes (dce/mem2reg/sroa) | 83-93% |
| ir, glsl, wgsl/parser, dxil/bitcode/container/viewid | 80-84% |
| spirv | 76.5% |
| hlsl | 70.6% |
| internal/registry | 75.2% |
| wgsl/lower | 65.3% |
| msl | 64.2% |
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.
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.
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 (22 widgets, M3/Fluent/Cupertino) |
We welcome contributions! Areas where help is needed:
MIT License — see LICENSE for details.
naga — Shaders in Pure Go
341 followers · starred Dec 2025
64 followers · starred Dec 2025
Pure Go Shader Compiler — WGSL to SPIR-V, MSL, GLSL, HLSL, DXIL. Zero CGO.
Go
53
198 commits
updated Oct 17, 2026
Pure Go Shader Compiler
WGSL to SPIR-V, MSL, GLSL, HLSL, and DXIL. Zero CGO.
Part of the GoGPU ecosystem
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.
| Category | Capabilities |
|---|---|
| Input | Full WGSL parser (120+ tokens), 48 short type aliases (vec3f, mat4x4f...), abstract constructors |
| Outputs | SPIR-V (checked with spirv-val in CI), MSL, GLSL, HLSL; DXIL — 172/237 IDxcValidator on the Rust naga corpus (experimental) |
| Compute | Storage buffers, workgroups, atomics, barriers, subgroup operations |
| Ray Tracing | Ray query types, acceleration structures, 7 ray query builtins |
| Compatibility | Tested 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 |
| Build | Zero CGO, single binary |
vec3f, mat4x4f, etc.), abstract constructors (vec3(1,2,3))@workgroup_sizelet bindingsarray(1, 2, 3) shorthand with inferred type and size.xyz, .rgba, .xxyy, etc.)OpFunctionCall support for modular WGSL shaders with helper functionssetThreadgroupMemoryLength needed)layout(binding=N) emission (SupportsExplicitLocations for GL 4.2+/ES 3.1+), UniformInfo reflection for runtime binding fallback on older GL driversOptions.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.f32(x), u32(y), i32(z) with correct SPIR-V opcodesbitcast<T>(expr) for reinterpreting bit patterns between types_ prefix exception@must_use enforcement, const_assert evaluation, @binding/@group pairing, array size validation, swizzle namespace enforcement, mandatory semicolonsnagac command-line compilergo get github.com/gogpu/naga
Requirements: Go 1.25+
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))
}
opts := naga.CompileOptions{
SPIRVVersion: spirv.Version1_3,
Debug: true, // Include debug names
Validate: true, // Enable IR validation
}
spirv, err := naga.CompileWithOptions(source, opts)
# 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
# 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
// 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())
// 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)
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
f16, f32, f64, i32, u32, i64, u64, boolvec2<T>, vec3<T>, vec4<T> (and short aliases: vec2f, vec3i, vec4u, etc.)mat2x2<f32> ... mat4x4<f32> (and short aliases: mat2x2f, mat4x4f, etc.)array<T, N>, array<T> (runtime-sized, storage buffers)struct { ... } (with constructor syntax: StructName(field1, field2))atomic<u32>, atomic<i32>texture_2d<f32>, texture_3d<f32>, texture_cube<f32>, texture_depth_2d_arraysampler, sampler_comparisonbinding_array<T, N>acceleration_structure, ray_queryvec3(1,2,3), mat2x2(...), array(...) (without explicit template parameters)alias FVec3 = vec3<f32>;@vertex — Vertex shaders with @builtin(position) output@fragment — Fragment shaders with @location(N) outputs@compute — Compute shaders with @workgroup_size(X, Y, Z)@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 bindingsvar<uniform> — Uniform buffervar<storage, read> — Read-only storage buffervar<storage, read_write> — Read-write storage buffervar<workgroup> — Workgroup shared memoryvar, let, const@id(N) override name: type = default;const_assert expr;if, else, for, while, loop, switch, case, defaultbreak, continue, break if (continuing blocks)return, discard=, +=, -=, *=, /=abs, min, max, clamp, saturate, sign, fma, modf, frexp, ldexp, quantizeToF16sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanhradians, degreesexp, exp2, log, log2, pow, sqrt, inverseSqrtceil, floor, round, fract, truncdot, cross, length, distance, normalize, faceForward, reflect, refract, outerProductmix, step, smoothsteptranspose, determinant, inverseall, any, isnan, isinfcountTrailingZeros, countLeadingZeros, countOneBits, reverseBits, extractBits, insertBits, firstTrailingBit, firstLeadingBitpack4x8snorm, pack4x8unorm, pack2x16snorm, pack2x16unorm, pack2x16float, pack4xI8, pack4xU8, pack4xI8Clamp, pack4xU8Clamp, unpack4x8snorm, unpack4x8unorm, unpack2x16snorm, unpack2x16unorm, unpack2x16float, unpack4xI8, unpack4xU8selectdpdx, dpdy, fwidth, dpdxCoarse, dpdyCoarse, fwidthCoarse, dpdxFine, dpdyFine, fwidthFineatomicAdd, atomicSub, atomicMin, atomicMax, atomicAnd, atomicOr, atomicXor, atomicExchange, atomicCompareExchangeWeakworkgroupBarrier, storageBarrier, textureBarrier, subgroupBarriersubgroupBallot, subgroupAll, subgroupAny, subgroupAdd/Mul/Min/Max/And/Or/Xor, subgroupBroadcast/First, subgroupShuffle/XOR/Up/Down, quadSwap/BroadcastrayQueryInitialize, rayQueryProceed, rayQueryGetCommittedIntersection, rayQueryGetCandidateIntersection, rayQueryTerminateworkgroupUniformLoadarrayLengthCurrent Version: See CHANGELOG.md for release history.
| Backend | Status | Target Platform |
|---|---|---|
| SPIR-V | ✅ Stable, spirv-val in CI | Vulkan |
| MSL | ✅ Stable | Metal (macOS/iOS) |
| GLSL | ✅ Stable, version-aware binding | OpenGL 3.3+, ES 3.0+ |
| HLSL | ✅ Stable | DirectX 11/12 |
| DXIL | 172/237 IDxcValidator (Rust naga corpus), 103/182 DXC golden | DirectX 12 (SM 6.0-6.5, experimental) |
See ROADMAP.md for detailed development plans.
~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.
| Package | Coverage |
|---|---|
| internal/textutil, dxil/module | 100% |
| internal/backend | 96.6% |
| dxil/passes (dce/mem2reg/sroa) | 83-93% |
| ir, glsl, wgsl/parser, dxil/bitcode/container/viewid | 80-84% |
| spirv | 76.5% |
| hlsl | 70.6% |
| internal/registry | 75.2% |
| wgsl/lower | 65.3% |
| msl | 64.2% |
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.
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.
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 (22 widgets, M3/Fluent/Cupertino) |
We welcome contributions! Areas where help is needed:
MIT License — see LICENSE for details.
naga — Shaders in Pure Go
341 followers · starred Dec 2025
64 followers · starred Dec 2025