nagami-rs 2026.7.2 → 2026.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -36,6 +36,7 @@ Nagami lowers WGSL into [Naga IR](https://github.com/gfx-rs/wgpu/tree/trunk/naga
36
36
  - Float precision trimming - cap decimal places or significant figures, per type (lossy, opt-in)
37
37
  - Preamble support - external declarations excluded from output
38
38
  - Library modules - shader fragments without entry points preserved
39
+ - Name map - original -> final identifier mapping for hosts that address shaders by source names
39
40
 
40
41
  Runs passes in fixed-point sweeps until the output stops shrinking. Typically converges in 3 sweeps.
41
42
 
@@ -44,7 +45,7 @@ Runs passes in fixed-point sweeps until the output stops shrinking. Typically co
44
45
  Install with cargo:
45
46
 
46
47
  ```sh
47
- cargo install nagami --features cli
48
+ cargo install nagami
48
49
  ```
49
50
 
50
51
  Example usage:
@@ -52,10 +53,13 @@ Example usage:
52
53
  ```sh
53
54
  nagami shader.wgsl -o shader.min.wgsl # minify (max profile by default)
54
55
  nagami shader.wgsl --in-place --stats # in-place, print savings
55
- nagami shader.wgsl -o out.wgsl -p baseline # lighter touch, no mangle
56
+ nagami shader.wgsl -o out.wgsl -p baseline # DCE + folding only
56
57
  cat shader.wgsl | nagami - > out.wgsl # stdin -> stdout
57
58
  nagami shader.wgsl --check # exit 1 if not minified
58
59
  nagami shader.wgsl --preamble env.wgsl -o out.wgsl # external declarations
60
+ nagami shader.wgsl -o out.wgsl --name-map map.json # original -> final identifier map
61
+ nagami shader.wgsl --format json # one JSON document on stdout
62
+ nagami shader.wgsl -o out.wgsl --strict-fallback # fail instead of shipping a text-only bailout
59
63
  nagami shader.wgsl --decimal-places 6 -o out.wgsl # lossy: cap fractional digits
60
64
  nagami shader.wgsl --sig-figs 4 -o out.wgsl # lossy: cap significant figures
61
65
  ```
@@ -70,16 +74,16 @@ Three optimization profiles control which IR passes run. Generator-level optimiz
70
74
  | Constant folding | ✓ | ✓ | ✓ |
71
75
  | Dead parameter elimination | ✓ | ✓ | ✓ |
72
76
  | Emit merge | ✓ | ✓ | ✓ |
73
- | Rename (preserve names) | ✓ | ✓ | ✓ |
77
+ | Identifier renaming (globals, functions, params, locals) | ✓ | ✓ | ✓ |
74
78
  | Function inlining | - | ✓ (24 nodes / 3 call sites) | ✓ (48 nodes / 6 call sites) |
75
79
  | Load dedup + dead stores | - | ✓ | ✓ |
76
80
  | Variable coalescing | - | ✓ | ✓ |
77
81
  | Struct-build coalescing | - | ✓ | ✓ |
78
- | Vector-constant hoisting | - | ✓ | ✓ |
82
+ | Vector-constant hoisting | - | - | ✓ |
79
83
  | Common subexpression elim | - | - | ✓ |
80
- | Identifier mangling | - | - | ✓ |
84
+ | Mangling (struct types/members, constants, overrides) | - | - | ✓ |
81
85
 
82
- Passes run in fixed-point sweeps (up to 16) until the output stops shrinking. `baseline` is fast and safe; `aggressive` adds the full IR pipeline without mangling; `max` enables CSE and raises inlining limits for maximum compression.
86
+ The `baseline` is fast and safe; `aggressive` adds the full IR pipeline without mangling; `max` raises inlining limits and enables CSE and vector-constant hoisting (both only while mangling is on) for maximum compression. `--no-mangle` disables mangling in any profile.
83
87
 
84
88
  ## Preamble
85
89
 
@@ -102,14 +106,14 @@ Preamble names are automatically preserved from renaming so that member access e
102
106
  Install with cargo:
103
107
 
104
108
  ```sh
105
- cargo add nagami
109
+ cargo add nagami --no-default-features
106
110
  ```
107
111
 
108
112
  Run with default config:
109
113
 
110
114
  ```rust
111
115
  let output = nagami::run(src, &nagami::config::Config::default())?;
112
- println!("{}", output.source); // smol shader
116
+ println!("{}", output.source);
113
117
  ```
114
118
 
115
119
  With a preamble (external declarations excluded from output):
@@ -134,10 +138,15 @@ Browser / bundler:
134
138
 
135
139
  ```js
136
140
  import init, { run } from 'nagami-rs';
137
- await init(); // load the WASM module once
138
- const { source, report } = run(shader);
139
- console.log(source); // minified WGSL
140
- console.log(report); // optimization report
141
+ await init(); // load the WASM module once
142
+ const { source, report, nameMap } = run(shader);
143
+ console.log(source); // minified WGSL
144
+ console.log(report); // optimization report; report.bailout holds naga's
145
+ // error when the output is text-compacted only
146
+ console.log(nameMap); // original -> final names for bindings, functions,
147
+ // overrides, entry points, struct members; null when
148
+ // the shipped text is not the generator's output
149
+ // (bailout, emitter fallback, input already smaller)
141
150
  ```
142
151
 
143
152
  With config (all fields optional):
@@ -145,7 +154,7 @@ With config (all fields optional):
145
154
  ```js
146
155
  const { source, report } = run(shader, {
147
156
  profile: 'max', // "baseline" | "aggressive" | "max" (default)
148
- mangle: true, // rename identifiers (default: on for "max")
157
+ mangle: true, // also rename struct types/members, constants, overrides (default: on for "max")
149
158
  preserveSymbols: ['main'], // names to keep untouched
150
159
  beautify: false, // compact output (default: false)
151
160
  indent: 2, // spaces per level when beautify is true
@@ -153,20 +162,20 @@ const { source, report } = run(shader, {
153
162
  // also accepts { decimalPlaces: 6 }, { significantFigures: 4 },
154
163
  // or per-type: { f32: 6, f64: { significantFigures: 12 } }
155
164
  maxInlineNodeCount: 48, // inlining budget per function
156
- maxInlineCallSites: 6, // inlining budget per call site
165
+ maxInlineCallSites: 6, // max call sites a function may have and still inline
157
166
  preamble: preambleSrc, // external decls prepended for parsing, stripped from output
158
167
  validateEachPass: false, // re-validate WGSL after every pass
159
168
  });
160
169
  ```
161
170
 
162
- Node.js (synchronous init):
171
+ Node.js 20.6+ (synchronous init):
163
172
 
164
173
  ```js
165
174
  import { readFileSync } from 'node:fs';
166
175
  import { initSync, run } from 'nagami-rs';
167
176
  const wasm = readFileSync(new URL('nagami_bg.wasm', import.meta.resolve('nagami-rs')));
168
177
  initSync({ module: wasm });
169
- const { source, report } = run(shader); // or with config as above
178
+ const { source, report } = run(shader);
170
179
  ```
171
180
 
172
181
  ## License
package/nagami.d.ts CHANGED
@@ -46,12 +46,29 @@ export interface Report {
46
46
  outputBytes: number;
47
47
  converged: boolean;
48
48
  sweeps: number;
49
+ /** naga's error when the output is the input lexically compacted only. */
50
+ bailout: string | null;
49
51
  passReports: PassReport[];
50
52
  }
51
53
 
54
+ export interface StructRename {
55
+ name: string;
56
+ members: Record<string, string>;
57
+ }
58
+
59
+ export interface NameMap {
60
+ entryPoints: Record<string, string>;
61
+ globals: Record<string, string>;
62
+ functions: Record<string, string>;
63
+ constants: Record<string, string>;
64
+ overrides: Record<string, string>;
65
+ structs: Record<string, StructRename>;
66
+ }
67
+
52
68
  export interface Output {
53
69
  source: string;
54
70
  report: Report;
71
+ nameMap: NameMap | null;
55
72
  }
56
73
 
57
74
  export function run(source: string, config?: Config): Output;
@@ -60,12 +77,9 @@ export function version(): string;
60
77
 
61
78
 
62
79
  /**
63
- * Route Rust panic info to `console.error` at module instantiation:
64
- * under `panic = "abort"` the hook still runs first, so browsers get
65
- * the panic text and file:line instead of an opaque
66
- * `RuntimeError: unreachable executed`. Hand-rolled because the
67
- * `console_error_panic_hook` crate adds only a JS stack trace of
68
- * mangled wasm frame indices.
80
+ * Panic text to `console.error`: under `panic = "abort"` the hook still runs
81
+ * first, so browsers see the message instead of `RuntimeError: unreachable`.
82
+ * Hand-rolled; `console_error_panic_hook` adds only mangled wasm frames.
69
83
  */
70
84
  export function install_panic_hook(): void;
71
85
 
package/nagami.js CHANGED
@@ -1,25 +1,19 @@
1
1
  /* @ts-self-types="./nagami.d.ts" */
2
2
 
3
3
  /**
4
- * Route Rust panic info to `console.error` at module instantiation:
5
- * under `panic = "abort"` the hook still runs first, so browsers get
6
- * the panic text and file:line instead of an opaque
7
- * `RuntimeError: unreachable executed`. Hand-rolled because the
8
- * `console_error_panic_hook` crate adds only a JS stack trace of
9
- * mangled wasm frame indices.
4
+ * Panic text to `console.error`: under `panic = "abort"` the hook still runs
5
+ * first, so browsers see the message instead of `RuntimeError: unreachable`.
6
+ * Hand-rolled; `console_error_panic_hook` adds only mangled wasm frames.
10
7
  */
11
8
  export function install_panic_hook() {
12
9
  wasm.install_panic_hook();
13
10
  }
14
11
 
15
12
  /**
16
- * Minify a WGSL source string. Returns a JS object matching the
17
- * TypeScript `Output` interface declared below.
18
- *
19
- * # Errors
20
- *
21
- * Propagates any [`crate::error::Error`] from the pipeline as a
22
- * [`JsError`] carrying the rendered message.
13
+ * Minify `source` into the parsed [`crate::json`] document (TS `Output`).
14
+ * Errors are thrown JS `Error`s; a `JSON.parse` rejection (unreachable, the
15
+ * renderer emits valid JSON) propagates as its own `SyntaxError`, which keeps
16
+ * `JsValue`'s `Debug` glue out of the bundle.
23
17
  * @param {string} source
24
18
  * @param {any} config
25
19
  * @returns {any}
@@ -43,7 +37,7 @@ export function run(source, config) {
43
37
  }
44
38
 
45
39
  /**
46
- * Return the `CARGO_PKG_VERSION` baked into the wasm bundle.
40
+ * Crate version baked into the bundle.
47
41
  * @returns {string}
48
42
  */
49
43
  export function version() {
@@ -104,7 +98,7 @@ function __wbg_get_imports() {
104
98
  __wbg___wbindgen_throw_bb96b2010945f0bc: function(arg0, arg1) {
105
99
  throw new Error(getStringFromWasm0(arg0, arg1));
106
100
  },
107
- __wbg_error_7f1e71fe68e5559e: function(arg0, arg1) {
101
+ __wbg_error_82407668d9111acb: function(arg0, arg1) {
108
102
  console.error(getStringFromWasm0(arg0, arg1));
109
103
  },
110
104
  __wbg_get_971a0c45d172643f: function() { return handleError(function (arg0, arg1) {
@@ -123,28 +117,11 @@ function __wbg_get_imports() {
123
117
  const ret = getObject(arg0).length;
124
118
  return ret;
125
119
  },
126
- __wbg_new_116be93542d39019: function() {
127
- const ret = new Array();
120
+ __wbg_parse_1cc93481b0865939: function() { return handleError(function (arg0, arg1) {
121
+ const ret = JSON.parse(getStringFromWasm0(arg0, arg1));
128
122
  return addHeapObject(ret);
129
- },
130
- __wbg_new_ebe3e0f6837f0879: function() {
131
- const ret = new Object();
132
- return addHeapObject(ret);
133
- },
134
- __wbg_push_adb0107829f02d75: function(arg0, arg1) {
135
- const ret = getObject(arg0).push(getObject(arg1));
136
- return ret;
137
- },
138
- __wbg_set_8155bb79a948541b: function() { return handleError(function (arg0, arg1, arg2) {
139
- const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
140
- return ret;
141
123
  }, arguments); },
142
- __wbindgen_cast_0000000000000001: function(arg0) {
143
- // Cast intrinsic for `F64 -> Externref`.
144
- const ret = arg0;
145
- return addHeapObject(ret);
146
- },
147
- __wbindgen_cast_0000000000000002: function(arg0, arg1) {
124
+ __wbindgen_cast_0000000000000001: function(arg0, arg1) {
148
125
  // Cast intrinsic for `Ref(String) -> Externref`.
149
126
  const ret = getStringFromWasm0(arg0, arg1);
150
127
  return addHeapObject(ret);
package/nagami_bg.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "nagami-rs",
3
3
  "type": "module",
4
4
  "description": "Shrinks WGSL shaders via Naga IR optimization passes",
5
- "version": "2026.7.2",
5
+ "version": "2026.9.1",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",