Skip to content

Commit 97fe275

Browse files
authored
feat: naga v0.14.0 — Essential 15 reference shaders, major WGSL coverage expansion
* fix(spirv): let semantics, ImageQuery capability, matrix multiply, deferred stores - parser: letStmt() returns ConstDecl (named expression), not VarDecl - spirv: add CapabilityImageQuery (50) for textureDimensions - spirv: matrix multiply ops (mat*vec, vec*mat, mat*mat, mat*scalar) - spirv: deferred complex stores for var x = func() - 0.5 pattern - tests: function call in let, ImageQuery, full MSDF text shader - hlsl: fix test for dead code elimination after let fix * fix(spirv): Mul result type for scalar*vector, MatrixStride decoration - ir/resolve: resolveBinaryType for Multiply now returns correct result type (vec4 for scalar*vec4, not scalar). Matches WGSL spec. - spirv/backend: add ColMajor + MatrixStride decorations for matrix members in uniform blocks (required by Vulkan SPIR-V validation). - tests: add spirv-val validation via Vulkan SDK in MSDF shader test. * test(spirv): add spirv-val validation, SDF render shader test - validateWithVulkanSDK: run spirv-val/spirv-dis from Vulkan SDK - TestCompileSDFRenderShader: full SDF shape shader (both pass spirv-val) - TestCompileMSDFTextShader: now validated by spirv-val * fix(wgsl): emit let bindings at declaration point for SSA dominance let bindings (ConstDecl) were lazily emitted at first use site by the SPIR-V backend. When a let binding was first used inside an if/else branch, the SPIR-V ID was defined in that branch block and could not be used in the other branch — violating SSA dominance rules. Fix: add StmtEmit at the let declaration point in lowerLocalConst, forcing the expression to be emitted before any control flow. Also adds 5 new shader compilation tests with spirv-val validation covering gogpu and gg shaders (positionedQuad, texturedQuad, stencilFill, cover, blit). * fix(wgsl,spirv): module constants, switch termination, select/divide vector promotion Four fixes for complex shader compilation: 1. Module-level const: lowerConstant now evaluates literal initializers and registers them in IR, enabling switch cases with named constants (e.g., case BLEND_NORMAL in blend shader). 2. Switch termination: blockEndsWithTerminator now handles StmtSwitch, and emitSwitch adds OpUnreachable in unreachable merge blocks when all cases return. 3. OpSelect vector promotion: when condition is scalar bool but operands are vectors, splat condition to matching bool vector via OpCompositeConstruct (WGSL broadcasts, SPIR-V does not). 4. OpFDiv vector/scalar: added promoteScalarToVector for divide operations where one operand is vector and other is scalar, splatting the scalar. Tested with gg blend shader (29 blend modes, HSL, switch, select, step). * fix(spirv): vector/scalar promotion for add, subtract, modulo Extends the scalar-to-vector splatting from divide to add, subtract, and modulo operations. WGSL allows vec3 + scalar (broadcasts), but SPIR-V OpFAdd/OpFSub/OpFMod require matching operand types. * fix(spirv,wgsl): type resolution for scalar-vec ops, select float-to-bool, arrayed textures, image store - Fix binary type resolution: scalar op vec returns vec type (not scalar) - Fix OpSelect with float condition: convert to bool via OpFOrdNotEqual - Fix getSampledImageType to resolve actual image type from expression - Add array index handling for texture_2d_array sampling (SPIR-V vec3 coord) - Add StmtImageStore (OpImageWrite) for textureStore() in compute shaders - Add isTextureArrayed check in WGSL lowerer for arrayed texture sampling - Add tests for full gg production shaders: blend (424 lines), strip, composite - All 12 shader tests pass spirv-val validation * fix(spirv): derive sampled type from storage format for storage texture OpTypeImage Storage textures with uint/sint formats (e.g. rgba8uint) require the sampled type to match the format (u32/i32), not hardcoded f32. * fix(spirv): atomicStore/Load, workgroup layout, storage decorations, production shader tests - Add atomicStore/atomicLoad WGSL lowering and SPIR-V emission - AtomicStore uses Release semantics, AtomicLoad uses Acquire semantics - Use emitPointerExpression for atomic pointer operands (not auto-load) - Resolve AtomicType to ScalarType for constant emission - Exclude workgroup variables from SPIR-V 1.3 entry point interfaces - Emit workgroup array types without ArrayStride decoration - Add NonReadable/NonWritable decorations for storage images - Resolve ExprAtomicResult type by searching function body - Add flatten, coarse, fine production shader compilation tests (all spirv-val VALID) * fix(wgsl,spirv): loop continuing blocks, duplicate Block decoration - Parse loop { ... continuing { ... } } syntax in WGSL parser - Deduplicate Block decoration when multiple variables share a struct type - Add boids (loop+continuing, runtime arrays) and collatz (while, function calls) reference shader tests * fix(spirv,wgsl): uniform struct wrapping, vector type conversion, trailing semicolons - Wrap non-struct Uniform variables in OpTypeStruct (VUID-StandaloneSpirv-Uniform-06807) - Add AccessChain through wrapper struct when loading wrapped uniform values - Add matrix ColMajor/MatrixStride decorations for wrapper struct members - Handle vec2<i32>(vec2<f32>) as type conversion (ExprAs) instead of composition - Parse optional trailing semicolons after struct declarations - Export TypeResInner for cross-package use - Add cube, hello_triangle, hello_compute reference shader tests * fix(wgsl): float literals without trailing digit, increment/decrement, vector type inference - Lex '1.' as float literal (WGSL allows trailing-dot floats like 1., -3.) - Parse i++ and i-- as compound assignment (desugar to i += 1 / i -= 1) - Infer vec2/vec3/vec4 scalar type from arguments when template params omitted - Add MSAA line, uniform values (skipped), cube, hello_triangle, hello_compute tests * test(spirv): add hello_workgroups, render_to_texture reference shader tests - render_to_texture passes spirv-val (local arrays, vertex-less rendering) - hello_workgroups skipped (requires abstract integer literal handling) * fix(wgsl,spirv): const constructors, transpose, depth textures, angle bracket splitting - Add composite constant lowering (vec3/vec4 constructors in module constants) - Add unary negation support in constant expressions - Add MathTranspose with native OpTranspose SPIR-V opcode - Add matrix type caching to prevent duplicate OpTypeMatrix declarations - Add texture_depth_2d_array as non-parameterized type - Add textureSampleCompare/textureSampleCompareLevel lowering - Fix textureDimensions to accept 1 argument (texture only) - Fix >> token splitting for nested template closing (ptr<function, vec3<f32>>) * fix(wgsl): struct constructors, pointer deref LHS, compound assignment - Struct constructor syntax: StructName(field1, field2) creates ExprCompose - Pointer dereference on assignment LHS: *ptr = val extracts inner pointer - Compound assignment: remove explicit ExprLoad, use auto-load from SPIR-V backend * feat(wgsl,spirv): short type aliases, switch parsing, discard, modf, call tree traversal - Add 48 WGSL predeclared short type aliases (vec3f, mat4x4f, etc.) - Fix switch/default parsing: default as case selector, trailing commas, optional colon - Implement _ discard identifier in assignments and let bindings - Implement modf().fract/whole and frexp().fract/exp member access - Extend findCallResultInTree to handle 12 expression types (swizzle, access, compose, etc.) - Refactor token.go String() to map-based lookup with full coverage Essential 15 reference shaders: 8/15 pass (was 7/14) * feat(wgsl,spirv): abstract constructors, bitcast, math functions, texture gather, pointer access Parser: - Abstract type constructors without template params (vec3(...), array(...)) - bitcast<T>(expr) template syntax with BitcastExpr AST node - Float literal f/h suffix without decimal point (1f, 1h) Lowerer: - Constant expression evaluator for switch case selectors - dot4I8Packed/dot4U8Packed math builtins - textureGather, textureGatherCompare, textureSampleBaseClampToEdge - evalGatherComponent for compile-time component validation SPIR-V backend: - 25 new math functions: bit manipulation, pack/unpack, quantizeF16, dot product packed - OpImageGather/OpImageDrefGather emission with component index - Pointer access chains on function arguments (ExprLoad, ExprFunctionArgument) - SPV_KHR_integer_dot_product extension support - findCallResultInTree extended to 12+ expression types Essential 15 reference shaders: 10/15 pass (was 8/15) * feat(wgsl,spirv): Essential 15 reference shaders — 15/15 pass Complete WGSL language coverage for all Essential 15 Rust naga reference shaders: Parser: - Abstract constructors for all types (vec/mat/array without <T>) - binding_array<T, N> type syntax Lowerer: - BitcastExpr handling (ExprAs with CastBitcast) - Global variable type inference from initializer - textureGather depth overloads (3-4 args, no component) - Constant expression evaluator for switch case selectors - BindingArrayType resolution and opaque resource detection IR: - BindingArrayType for descriptor array types SPIR-V: - BindingArrayType emission (OpTypeArray/OpTypeRuntimeArray) - Access chain indexing into binding arrays - Identity conversion early return (bool(bool())) - Inline type handling in pointer access chains Essential 15: 15/15 pass (was 10/15) * test(spirv): Essential 15 + 2 bonus reference shader regression tests Embedded 17 Rust naga reference WGSL shaders as regression tests: - 15 Essential shaders covering core WGSL features - 2 bonus shaders (skybox, water) for advanced coverage - Full pipeline: lex → parse → lower → SPIR-V compile - SPIR-V magic number and size validation - Shader sources embedded as string literals (CI-ready, no external deps) * docs: add ARCHITECTURE.md, update CHANGELOG and README for v0.14.0
1 parent 8ed2b77 commit 97fe275

File tree

17 files changed

+7426
-268
lines changed

17 files changed

+7426
-268
lines changed

CHANGELOG.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,88 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.14.0] - 2026-02-21
9+
10+
Major WGSL language coverage expansion: 15/15 Essential reference shaders from Rust naga test suite now compile to valid SPIR-V.
11+
12+
### Added
13+
14+
#### WGSL Parser
15+
- Abstract type constructors without template parameters (`vec3(1,2,3)`, `mat2x2(...)`, `array(...)`)
16+
- `bitcast<T>(expr)` template syntax with dedicated AST node
17+
- `binding_array<T, N>` type syntax
18+
- Float literal suffixes without decimal point (`1f`, `1h`)
19+
- Switch statement: `default` as case selector, trailing commas, optional colon
20+
- Increment/decrement statements (`i++`, `i--`)
21+
22+
#### WGSL Lowerer
23+
- 48 predeclared short type aliases (`vec3f`, `mat4x4f`, `vec2i`, etc.)
24+
- Struct constructor syntax (`StructName(field1, field2)`)
25+
- Pointer dereference on assignment LHS (`*ptr = value`)
26+
- `_` discard identifier in assignments and let bindings
27+
- `modf().fract`/`.whole` and `frexp().fract`/`.exp` member access on builtin results
28+
- `bitcast` expression lowering
29+
- Constant expression evaluator for switch case selectors
30+
- `dot4I8Packed` / `dot4U8Packed` packed dot product builtins
31+
- `textureGather`, `textureGatherCompare`, `textureSampleBaseClampToEdge`
32+
- `texture_depth_2d_array` as non-parameterized type
33+
- `textureSampleCompare` / `textureSampleCompareLevel`
34+
- Global variable type inference from initializer
35+
- `BindingArrayType` for descriptor array types
36+
37+
#### SPIR-V Backend
38+
- `OpTranspose` (native SPIR-V opcode 84) with matrix type swap
39+
- Matrix type caching (prevents duplicate OpTypeMatrix)
40+
- 25 new math functions: bit manipulation (countOneBits, reverseBits, extractBits, insertBits, firstLeadingBit, firstTrailingBit, countLeadingZeros, countTrailingZeros), pack/unpack (4x8snorm, 4x8unorm, 2x16snorm, 2x16unorm, 2x16float), quantizeToF16
41+
- `OpSDotKHR` / `OpUDotKHR` with SPV_KHR_integer_dot_product extension
42+
- `OpImageGather` / `OpImageDrefGather` with component index
43+
- `OpBitCount`, `OpBitReverse`, `OpBitFieldInsert`, `OpBitFieldSExtract`, `OpBitFieldUExtract`
44+
- Pointer access chains on function arguments
45+
- `findCallResultInTree` extended to 12+ expression types
46+
- `BindingArrayType` emission (OpTypeArray/OpTypeRuntimeArray)
47+
- Identity conversion early return
48+
49+
#### IR
50+
- `BindingArrayType` struct for descriptor array types
51+
52+
#### Testing
53+
- **17 reference shader regression tests** — 15 Essential + 2 bonus (skybox, water) from Rust naga test suite, embedded as string literals for CI compatibility
54+
- SPIR-V validation via `spirv-val` in CI
55+
56+
### Fixed
57+
58+
#### WGSL Frontend
59+
- Compound assignment (`+=`, `-=`) on local variables — removed explicit ExprLoad
60+
- `textureDimensions` accepting 1 argument (texture only)
61+
- `>>` token splitting for nested template closing (`ptr<function, vec3<f32>>`)
62+
- Const with constructor expressions (`const light = vec3<f32>(1,2,3)`)
63+
- Unary negation in constant expressions (`const X = -0.1`)
64+
- `let` bindings emitted at declaration point for SSA dominance correctness
65+
- Float literals without trailing digit (`1.` now parsed correctly)
66+
- Module-level constants with constructor initializers
67+
- Switch statement termination analysis for exhaustive matching
68+
- Trailing semicolons after closing braces no longer cause parse errors
69+
- Vector type inference from constructor arguments
70+
71+
#### SPIR-V Backend
72+
- `OpIMul` result type for scalar*vector promotion (was using scalar type instead of vector)
73+
- `MatrixStride` decoration for uniform matrix members
74+
- `let` variable semantics — emit `OpLoad` for `let` bindings (value semantics, not reference)
75+
- `OpCapability ImageQuery` emitted when using `textureDimensions`/`textureNumLevels`
76+
- Matrix multiply (`OpMatrixTimesVector`, `OpVectorTimesMatrix`, `OpMatrixTimesMatrix`) type handling
77+
- Deferred `OpStore` for variables initialized from complex expressions
78+
- Vector/scalar type promotion for `add`, `subtract`, `modulo` binary operations
79+
- `select()` builtin: float-to-bool condition conversion
80+
- Arrayed texture coordinate handling (array index as separate component)
81+
- `OpImageWrite` operand ordering for storage textures
82+
- Sampled type derived from storage format for `OpTypeImage` (was defaulting to float)
83+
- `atomicStore` / `atomicLoad` — correct SPIR-V opcode emission
84+
- Workgroup variable layout decorations (Offset, ArrayStride)
85+
- `OpDecorate Block` deduplication — no longer emits duplicate decorations
86+
- Loop `continuing` block codegen — correct back-edge and merge block structure
87+
- Uniform struct wrapping — storage/uniform buffer structs get correct member decorations
88+
- Vector type conversion in composite constructors
89+
890
## [0.13.1] - 2026-02-17
991

1092
SPIR-V OpArrayLength fix, comprehensive benchmarks, and compiler allocation optimization (−32%).
@@ -726,6 +808,7 @@ First stable release. Complete WGSL to SPIR-V compilation pipeline (~10K LOC).
726808
---
727809

728810
[Unreleased]: https://github.com/gogpu/naga/compare/v0.13.1...HEAD
811+
[0.14.0]: https://github.com/gogpu/naga/compare/v0.13.1...v0.14.0
729812
[0.13.1]: https://github.com/gogpu/naga/compare/v0.13.0...v0.13.1
730813
[0.13.0]: https://github.com/gogpu/naga/compare/v0.12.1...v0.13.0
731814
[0.12.1]: https://github.com/gogpu/naga/compare/v0.12.0...v0.12.1

README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,32 +34,35 @@
3434

3535
| Category | Capabilities |
3636
|----------|--------------|
37-
| **Input** | Full WGSL parser (120+ tokens) |
37+
| **Input** | Full WGSL parser (120+ tokens), 48 short type aliases (`vec3f`, `mat4x4f`...), abstract constructors |
3838
| **Outputs** | SPIR-V, MSL, GLSL, HLSL |
3939
| **Compute** | Storage buffers, workgroups, atomics, barriers |
40+
| **Compatibility** | 15/15 Essential reference shaders from Rust naga test suite |
4041
| **Build** | Zero CGO, single binary |
4142

4243
---
4344

4445
## Features
4546

4647
- **Pure Go** — No CGO, no external dependencies
47-
- **WGSL Frontend** — Full lexer and parser (120+ tokens)
48+
- **WGSL Frontend** — Full lexer and parser (120+ tokens), 48 short type aliases (`vec3f`, `mat4x4f`, etc.), abstract constructors (`vec3(1,2,3)`)
49+
- **Rust Naga Compatibility** — 15/15 Essential reference shaders from the Rust naga test suite compile to valid SPIR-V, with 17 regression tests
4850
- **IR** — Complete intermediate representation (expressions, statements, types)
4951
- **Compute Shaders** — Storage buffers, workgroup memory, `@workgroup_size`
5052
- **Atomic Operations** — atomicAdd, atomicSub, atomicMin, atomicMax, atomicCompareExchangeWeak
5153
- **Barriers** — workgroupBarrier, storageBarrier, textureBarrier
5254
- **Type Inference** — Automatic type resolution for all expressions, including `let` bindings
5355
- **Type Deduplication** — SPIR-V compliant unique type emission
5456
- **Array Initialization**`array(1, 2, 3)` shorthand with inferred type and size
55-
- **Texture Sampling** — textureSample, textureLoad, textureStore, textureDimensions
57+
- **Texture Sampling** — textureSample, textureLoad, textureStore, textureDimensions, textureGather, textureSampleCompare
5658
- **Swizzle Operations** — Full vector swizzle support (`.xyz`, `.rgba`, `.xxyy`, etc.)
5759
- **Function Calls**`OpFunctionCall` support for modular WGSL shaders with helper functions
5860
- **SPIR-V Backend** — Vulkan-compatible bytecode generation with correct type handling
5961
- **MSL Backend** — Metal Shading Language output for macOS/iOS
6062
- **GLSL Backend** — OpenGL Shading Language for OpenGL 3.3+, ES 3.0+
6163
- **HLSL Backend** — High-Level Shading Language for DirectX 11/12
6264
- **Type Conversions** — Scalar constructors `f32(x)`, `u32(y)`, `i32(z)` with correct SPIR-V opcodes
65+
- **Bitcast**`bitcast<T>(expr)` for reinterpreting bit patterns between types
6366
- **Warnings** — Unused variable detection with `_` prefix exception
6467
- **Validation** — Type checking and semantic validation
6568
- **CLI Tool**`nagac` command-line compiler
@@ -240,13 +243,15 @@ naga/
240243

241244
### Types
242245
- Scalars: `f16`, `f32`, `i32`, `u32`, `bool`
243-
- Vectors: `vec2<T>`, `vec3<T>`, `vec4<T>`
244-
- Matrices: `mat2x2<f32>` ... `mat4x4<f32>`
246+
- Vectors: `vec2<T>`, `vec3<T>`, `vec4<T>` (and short aliases: `vec2f`, `vec3i`, `vec4u`, etc.)
247+
- Matrices: `mat2x2<f32>` ... `mat4x4<f32>` (and short aliases: `mat2x2f`, `mat4x4f`, etc.)
245248
- Arrays: `array<T, N>`, `array<T>` (runtime-sized, storage buffers)
246-
- Structs: `struct { ... }`
249+
- Structs: `struct { ... }` (with constructor syntax: `StructName(field1, field2)`)
247250
- Atomics: `atomic<u32>`, `atomic<i32>`
248-
- Textures: `texture_2d<f32>`, `texture_3d<f32>`, `texture_cube<f32>`
251+
- Textures: `texture_2d<f32>`, `texture_3d<f32>`, `texture_cube<f32>`, `texture_depth_2d_array`
249252
- Samplers: `sampler`, `sampler_comparison`
253+
- Binding arrays: `binding_array<T, N>`
254+
- Abstract constructors: `vec3(1,2,3)`, `mat2x2(...)`, `array(...)` (without explicit template parameters)
250255

251256
### Shader Stages
252257
- `@vertex` — Vertex shaders with `@builtin(position)` output
@@ -313,6 +318,10 @@ See [ROADMAP.md](ROADMAP.md) for detailed development plans.
313318
- [SPIR-V Specification](https://registry.khronos.org/SPIR-V/)
314319
- [naga (Rust)](https://github.com/gfx-rs/naga) — Original implementation
315320

321+
### Rust Naga Compatibility
322+
323+
naga is tested against reference shaders from the [Rust naga](https://github.com/gfx-rs/naga) test suite. All 15 Essential reference shaders compile to valid SPIR-V, with 17 regression tests embedded in the CI pipeline to prevent regressions.
324+
316325
---
317326

318327
## Ecosystem
@@ -331,6 +340,7 @@ See [ROADMAP.md](ROADMAP.md) for detailed development plans.
331340

332341
## Documentation
333342

343+
- **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** — Compiler architecture, pipeline, IR design
334344
- **[ROADMAP.md](ROADMAP.md)** — Development milestones
335345
- **[CHANGELOG.md](CHANGELOG.md)** — Release notes
336346
- **[pkg.go.dev](https://pkg.go.dev/github.com/gogpu/naga)** — API reference

0 commit comments

Comments
 (0)