@simulatte/webgpu 0.2.0
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/API_CONTRACT.md +172 -0
- package/COMPAT_SCOPE.md +32 -0
- package/README.md +138 -0
- package/assets/fawn-icon-main-256.png +0 -0
- package/assets/fawn-icon-main.svg +272 -0
- package/assets/package-surface-cube-snapshot.svg +81 -0
- package/bin/fawn-webgpu-bench.js +182 -0
- package/bin/fawn-webgpu-compare.js +96 -0
- package/binding.gyp +21 -0
- package/doe-build-metadata.schema.json +23 -0
- package/headless-webgpu-comparison.md +43 -0
- package/native/doe_napi.c +1922 -0
- package/package.json +55 -0
- package/prebuild-metadata.schema.json +58 -0
- package/prebuilds/darwin-arm64/doe_napi.node +0 -0
- package/prebuilds/darwin-arm64/libwebgpu_dawn.dylib +0 -0
- package/prebuilds/darwin-arm64/libwebgpu_doe.dylib +0 -0
- package/prebuilds/darwin-arm64/metadata.json +26 -0
- package/scripts/generate-readme-assets.js +270 -0
- package/scripts/install.js +36 -0
- package/scripts/prebuild.js +179 -0
- package/scripts/smoke-test.js +118 -0
- package/src/build_metadata.js +104 -0
- package/src/bun-ffi.js +1057 -0
- package/src/bun.js +2 -0
- package/src/index.js +580 -0
- package/src/node-runtime.js +2 -0
- package/src/node.js +2 -0
- package/src/package-entry.js +1 -0
- package/src/runtime_cli.js +202 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<!-- Generated by scripts/generate-readme-assets.js. Do not edit by hand. -->
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="640" viewBox="0 0 1200 640" role="img" aria-labelledby="title desc">
|
|
3
|
+
<title id="title">Package surface benchmark cube snapshot</title>
|
|
4
|
+
<desc id="desc">Two-card package surface snapshot for Node and Bun generated from bench/out/cube/latest/cube.summary.json.</desc>
|
|
5
|
+
<defs>
|
|
6
|
+
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
7
|
+
<stop offset="0%" stop-color="#050816"/>
|
|
8
|
+
<stop offset="100%" stop-color="#0f172a"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
<linearGradient id="panel-left" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
11
|
+
<stop offset="0%" stop-color="#ef444420"/>
|
|
12
|
+
<stop offset="60%" stop-color="#ef444426"/>
|
|
13
|
+
<stop offset="100%" stop-color="#7c3aed22"/>
|
|
14
|
+
</linearGradient>
|
|
15
|
+
<linearGradient id="panel-right" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
16
|
+
<stop offset="0%" stop-color="#7c3aed20"/>
|
|
17
|
+
<stop offset="60%" stop-color="#7c3aed24"/>
|
|
18
|
+
<stop offset="100%" stop-color="#2563eb22"/>
|
|
19
|
+
</linearGradient>
|
|
20
|
+
<style>
|
|
21
|
+
.title { font: 700 34px "Segoe UI", "Helvetica Neue", Arial, sans-serif; fill: #ffffff; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
22
|
+
.subtitle { font: 500 18px "Segoe UI", "Helvetica Neue", Arial, sans-serif; fill: #cbd5e1; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
23
|
+
.cardTitle { font: 700 26px "Segoe UI", "Helvetica Neue", Arial, sans-serif; fill: #ffffff; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
24
|
+
.cardMeta { font: 500 16px "Segoe UI", "Helvetica Neue", Arial, sans-serif; fill: #cbd5e1; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
25
|
+
.metricTitle { font: 700 18px "Segoe UI", "Helvetica Neue", Arial, sans-serif; fill: #ffffff; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
26
|
+
.metricBody { font: 500 15px SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; fill: #e2e8f0; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
27
|
+
.pillText { font: 700 13px "Segoe UI", "Helvetica Neue", Arial, sans-serif; fill: #f8fafc; letter-spacing: 0.5px; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
28
|
+
.foot { font: 500 14px "Segoe UI", "Helvetica Neue", Arial, sans-serif; fill: #cbd5e1; paint-order: stroke fill; stroke: #000000; stroke-width: 2px; stroke-linejoin: round; }
|
|
29
|
+
.panel { stroke-width: 4; }
|
|
30
|
+
.toneLeft { fill: url(#panel-left); stroke: #ef4444; }
|
|
31
|
+
.toneRight { fill: url(#panel-right); stroke: #2563eb; }
|
|
32
|
+
.metric { fill: #020617a8; stroke-width: 1.8; }
|
|
33
|
+
.metric.toneLeft { stroke: #ef4444; }
|
|
34
|
+
.metric.toneRight { stroke: #2563eb; }
|
|
35
|
+
</style>
|
|
36
|
+
</defs>
|
|
37
|
+
<rect width="1200" height="640" fill="url(#bg)"/>
|
|
38
|
+
<text x="72" y="72" class="title">@simulatte/webgpu package snapshot</text>
|
|
39
|
+
<text x="72" y="102" class="subtitle">Derived from bench/out/cube/latest/cube.summary.json | latest populated cell 2026-03-06T21:55:26.482Z</text>
|
|
40
|
+
<text x="72" y="128" class="subtitle">Package-surface evidence only. Backend-native strict claim lanes remain separate.</text>
|
|
41
|
+
|
|
42
|
+
<rect x="72" y="176" width="488" height="318" rx="24" class="panel toneLeft"/>
|
|
43
|
+
<text x="100" y="216" class="cardTitle">Node package lane</text>
|
|
44
|
+
<text x="100" y="244" class="cardMeta">Primary support | mac_apple_silicon</text>
|
|
45
|
+
<text x="100" y="266" class="cardMeta">latest populated cell 2026-03-06T21:40:32.181Z</text>
|
|
46
|
+
|
|
47
|
+
<rect x="90" y="300" width="452" height="82" rx="16" class="metric toneLeft"/>
|
|
48
|
+
<text x="114" y="331" class="metricTitle">Uploads</text>
|
|
49
|
+
<rect x="386" y="315" width="132" height="28" rx="14" fill="#16a34a" stroke="#86efac" stroke-width="1.5"/>
|
|
50
|
+
<text x="452" y="334" text-anchor="middle" class="pillText">CLAIMABLE</text>
|
|
51
|
+
<text x="114" y="357" class="metricBody">5 rows | claimable</text>
|
|
52
|
+
<text x="114" y="377" class="metricBody">median p50 delta +53.9%</text>
|
|
53
|
+
|
|
54
|
+
<rect x="90" y="396" width="452" height="82" rx="16" class="metric toneLeft"/>
|
|
55
|
+
<text x="114" y="427" class="metricTitle">Compute E2E</text>
|
|
56
|
+
<rect x="386" y="411" width="132" height="28" rx="14" fill="#d97706" stroke="#fbbf24" stroke-width="1.5"/>
|
|
57
|
+
<text x="452" y="430" text-anchor="middle" class="pillText">COMPARABLE</text>
|
|
58
|
+
<text x="114" y="453" class="metricBody">3 rows | comparable</text>
|
|
59
|
+
<text x="114" y="473" class="metricBody">median p50 delta +21.2%</text>
|
|
60
|
+
|
|
61
|
+
<rect x="640" y="176" width="488" height="318" rx="24" class="panel toneRight"/>
|
|
62
|
+
<text x="668" y="216" class="cardTitle">Bun package lane</text>
|
|
63
|
+
<text x="668" y="244" class="cardMeta">Prototype support | linux_x64</text>
|
|
64
|
+
<text x="668" y="266" class="cardMeta">latest populated cell 2026-03-06T21:55:26.482Z</text>
|
|
65
|
+
|
|
66
|
+
<rect x="658" y="300" width="452" height="82" rx="16" class="metric toneRight"/>
|
|
67
|
+
<text x="682" y="331" class="metricTitle">Compute E2E</text>
|
|
68
|
+
<rect x="954" y="315" width="132" height="28" rx="14" fill="#16a34a" stroke="#86efac" stroke-width="1.5"/>
|
|
69
|
+
<text x="1020" y="334" text-anchor="middle" class="pillText">CLAIMABLE</text>
|
|
70
|
+
<text x="682" y="357" class="metricBody">3 rows | claimable</text>
|
|
71
|
+
<text x="682" y="377" class="metricBody">median p50 delta +77.2%</text>
|
|
72
|
+
|
|
73
|
+
<rect x="658" y="396" width="452" height="82" rx="16" class="metric toneRight"/>
|
|
74
|
+
<text x="682" y="427" class="metricTitle">Uploads</text>
|
|
75
|
+
<rect x="954" y="411" width="132" height="28" rx="14" fill="#d97706" stroke="#fbbf24" stroke-width="1.5"/>
|
|
76
|
+
<text x="1020" y="430" text-anchor="middle" class="pillText">COMPARABLE</text>
|
|
77
|
+
<text x="682" y="453" class="metricBody">5 rows | comparable</text>
|
|
78
|
+
<text x="682" y="473" class="metricBody">median p50 delta +8.6%</text>
|
|
79
|
+
<text x="72" y="590" class="foot">Generated by nursery/webgpu/scripts/generate-readme-assets.js.</text>
|
|
80
|
+
<text x="72" y="612" class="foot">Static claim and comparability card from the package-surface cube. It is not a substitute for strict backend reports.</text>
|
|
81
|
+
</svg>
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { createDoeRuntime } from "../src/node-runtime.js";
|
|
4
|
+
|
|
5
|
+
function usage() {
|
|
6
|
+
console.log(`Usage:
|
|
7
|
+
fawn-webgpu-bench --commands PATH [options]
|
|
8
|
+
|
|
9
|
+
Options:
|
|
10
|
+
--commands PATH Command JSON input (required)
|
|
11
|
+
--quirks PATH Quirk JSON input
|
|
12
|
+
--vendor NAME Profile vendor
|
|
13
|
+
--api NAME Profile API
|
|
14
|
+
--family NAME Device family
|
|
15
|
+
--driver VERSION Driver string
|
|
16
|
+
--trace-jsonl PATH Trace NDJSON output path
|
|
17
|
+
--trace-meta PATH Trace meta JSON output path
|
|
18
|
+
--queue-wait-mode MODE process-events|wait-any
|
|
19
|
+
--queue-sync-mode MODE per-command|deferred
|
|
20
|
+
--upload-buffer-usage MODE copy-dst|copy-dst-copy-src
|
|
21
|
+
--upload-submit-every N Upload submission cadence
|
|
22
|
+
--doe-bin PATH doe-zig-runtime path override
|
|
23
|
+
--doe-lib PATH libwebgpu_doe path override
|
|
24
|
+
--extra-arg ARG Pass through additional arg to runtime (repeatable)
|
|
25
|
+
--json Emit full JSON result
|
|
26
|
+
--help Show this help
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseArgs(argv) {
|
|
31
|
+
const opts = { extraArgs: [] };
|
|
32
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
33
|
+
const arg = argv[i];
|
|
34
|
+
const next = argv[i + 1];
|
|
35
|
+
switch (arg) {
|
|
36
|
+
case "--help":
|
|
37
|
+
opts.help = true;
|
|
38
|
+
break;
|
|
39
|
+
case "--json":
|
|
40
|
+
opts.json = true;
|
|
41
|
+
break;
|
|
42
|
+
case "--commands":
|
|
43
|
+
opts.commandsPath = next;
|
|
44
|
+
i += 1;
|
|
45
|
+
break;
|
|
46
|
+
case "--quirks":
|
|
47
|
+
opts.quirksPath = next;
|
|
48
|
+
i += 1;
|
|
49
|
+
break;
|
|
50
|
+
case "--vendor":
|
|
51
|
+
opts.vendor = next;
|
|
52
|
+
i += 1;
|
|
53
|
+
break;
|
|
54
|
+
case "--api":
|
|
55
|
+
opts.api = next;
|
|
56
|
+
i += 1;
|
|
57
|
+
break;
|
|
58
|
+
case "--family":
|
|
59
|
+
opts.family = next;
|
|
60
|
+
i += 1;
|
|
61
|
+
break;
|
|
62
|
+
case "--driver":
|
|
63
|
+
opts.driver = next;
|
|
64
|
+
i += 1;
|
|
65
|
+
break;
|
|
66
|
+
case "--trace-jsonl":
|
|
67
|
+
opts.traceJsonlPath = next;
|
|
68
|
+
i += 1;
|
|
69
|
+
break;
|
|
70
|
+
case "--trace-meta":
|
|
71
|
+
opts.traceMetaPath = next;
|
|
72
|
+
i += 1;
|
|
73
|
+
break;
|
|
74
|
+
case "--queue-wait-mode":
|
|
75
|
+
opts.queueWaitMode = next;
|
|
76
|
+
i += 1;
|
|
77
|
+
break;
|
|
78
|
+
case "--queue-sync-mode":
|
|
79
|
+
opts.queueSyncMode = next;
|
|
80
|
+
i += 1;
|
|
81
|
+
break;
|
|
82
|
+
case "--upload-buffer-usage":
|
|
83
|
+
opts.uploadBufferUsage = next;
|
|
84
|
+
i += 1;
|
|
85
|
+
break;
|
|
86
|
+
case "--upload-submit-every":
|
|
87
|
+
opts.uploadSubmitEvery = Number.parseInt(next ?? "", 10);
|
|
88
|
+
i += 1;
|
|
89
|
+
break;
|
|
90
|
+
case "--doe-bin":
|
|
91
|
+
opts.binPath = next;
|
|
92
|
+
i += 1;
|
|
93
|
+
break;
|
|
94
|
+
case "--doe-lib":
|
|
95
|
+
opts.libPath = next;
|
|
96
|
+
i += 1;
|
|
97
|
+
break;
|
|
98
|
+
case "--extra-arg":
|
|
99
|
+
opts.extraArgs.push(next ?? "");
|
|
100
|
+
i += 1;
|
|
101
|
+
break;
|
|
102
|
+
default:
|
|
103
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return opts;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function toAbsolutePath(path) {
|
|
110
|
+
if (!path) return path;
|
|
111
|
+
return resolve(path);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function summarize(result) {
|
|
115
|
+
const lines = [
|
|
116
|
+
`ok: ${result.ok}`,
|
|
117
|
+
`exitCode: ${result.exitCode}`,
|
|
118
|
+
];
|
|
119
|
+
if (result.traceMetaPath) {
|
|
120
|
+
lines.push(`traceMetaPath: ${result.traceMetaPath}`);
|
|
121
|
+
}
|
|
122
|
+
if (result.traceJsonlPath) {
|
|
123
|
+
lines.push(`traceJsonlPath: ${result.traceJsonlPath}`);
|
|
124
|
+
}
|
|
125
|
+
if (result.traceMeta?.executionTotalNs != null) {
|
|
126
|
+
lines.push(`executionTotalNs: ${result.traceMeta.executionTotalNs}`);
|
|
127
|
+
}
|
|
128
|
+
if (result.traceMeta?.executionEncodeTotalNs != null) {
|
|
129
|
+
lines.push(`executionEncodeTotalNs: ${result.traceMeta.executionEncodeTotalNs}`);
|
|
130
|
+
}
|
|
131
|
+
if (result.traceMeta?.executionSubmitWaitTotalNs != null) {
|
|
132
|
+
lines.push(`executionSubmitWaitTotalNs: ${result.traceMeta.executionSubmitWaitTotalNs}`);
|
|
133
|
+
}
|
|
134
|
+
return lines.join("\n");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function main() {
|
|
138
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
139
|
+
if (opts.help) {
|
|
140
|
+
usage();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (!opts.commandsPath) {
|
|
144
|
+
usage();
|
|
145
|
+
throw new Error("--commands is required");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const runtime = createDoeRuntime({
|
|
149
|
+
binPath: toAbsolutePath(opts.binPath),
|
|
150
|
+
libPath: toAbsolutePath(opts.libPath),
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const result = runtime.runBench({
|
|
154
|
+
commandsPath: toAbsolutePath(opts.commandsPath),
|
|
155
|
+
quirksPath: toAbsolutePath(opts.quirksPath),
|
|
156
|
+
vendor: opts.vendor,
|
|
157
|
+
api: opts.api,
|
|
158
|
+
family: opts.family,
|
|
159
|
+
driver: opts.driver,
|
|
160
|
+
traceJsonlPath: toAbsolutePath(opts.traceJsonlPath),
|
|
161
|
+
traceMetaPath: toAbsolutePath(opts.traceMetaPath),
|
|
162
|
+
queueWaitMode: opts.queueWaitMode,
|
|
163
|
+
queueSyncMode: opts.queueSyncMode,
|
|
164
|
+
uploadBufferUsage: opts.uploadBufferUsage,
|
|
165
|
+
uploadSubmitEvery: opts.uploadSubmitEvery,
|
|
166
|
+
extraArgs: opts.extraArgs,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (opts.json) {
|
|
170
|
+
console.log(JSON.stringify(result, null, 2));
|
|
171
|
+
} else {
|
|
172
|
+
console.log(summarize(result));
|
|
173
|
+
}
|
|
174
|
+
process.exitCode = result.exitCode;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
main();
|
|
179
|
+
} catch (error) {
|
|
180
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
181
|
+
process.exitCode = 1;
|
|
182
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { runDawnVsDoeCompare } from "../src/node-runtime.js";
|
|
4
|
+
|
|
5
|
+
function usage() {
|
|
6
|
+
console.log(`Usage:
|
|
7
|
+
fawn-webgpu-compare --config PATH [options] [-- <extra compare args>]
|
|
8
|
+
|
|
9
|
+
Options:
|
|
10
|
+
--config PATH compare_dawn_vs_doe config JSON path (required unless passed in --extra-arg)
|
|
11
|
+
--out PATH output report path
|
|
12
|
+
--repo-root PATH Fawn repo root override
|
|
13
|
+
--compare-script PATH compare_dawn_vs_doe.py path override
|
|
14
|
+
--python BIN Python executable (default: python3)
|
|
15
|
+
--extra-arg ARG pass-through arg (repeatable)
|
|
16
|
+
--help show this help
|
|
17
|
+
`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseArgs(argv) {
|
|
21
|
+
const opts = { extraArgs: [] };
|
|
22
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
23
|
+
const arg = argv[i];
|
|
24
|
+
const next = argv[i + 1];
|
|
25
|
+
switch (arg) {
|
|
26
|
+
case "--help":
|
|
27
|
+
opts.help = true;
|
|
28
|
+
break;
|
|
29
|
+
case "--config":
|
|
30
|
+
opts.configPath = next;
|
|
31
|
+
i += 1;
|
|
32
|
+
break;
|
|
33
|
+
case "--out":
|
|
34
|
+
opts.outPath = next;
|
|
35
|
+
i += 1;
|
|
36
|
+
break;
|
|
37
|
+
case "--repo-root":
|
|
38
|
+
opts.repoRoot = next;
|
|
39
|
+
i += 1;
|
|
40
|
+
break;
|
|
41
|
+
case "--compare-script":
|
|
42
|
+
opts.compareScriptPath = next;
|
|
43
|
+
i += 1;
|
|
44
|
+
break;
|
|
45
|
+
case "--python":
|
|
46
|
+
opts.pythonBin = next;
|
|
47
|
+
i += 1;
|
|
48
|
+
break;
|
|
49
|
+
case "--extra-arg":
|
|
50
|
+
opts.extraArgs.push(next ?? "");
|
|
51
|
+
i += 1;
|
|
52
|
+
break;
|
|
53
|
+
case "--":
|
|
54
|
+
opts.extraArgs.push(...argv.slice(i + 1));
|
|
55
|
+
i = argv.length;
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return opts;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function toAbsolute(path) {
|
|
65
|
+
if (!path) return path;
|
|
66
|
+
return resolve(path);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function main() {
|
|
70
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
71
|
+
if (opts.help) {
|
|
72
|
+
usage();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const result = runDawnVsDoeCompare({
|
|
77
|
+
repoRoot: toAbsolute(opts.repoRoot),
|
|
78
|
+
compareScriptPath: toAbsolute(opts.compareScriptPath),
|
|
79
|
+
pythonBin: opts.pythonBin,
|
|
80
|
+
configPath: toAbsolute(opts.configPath),
|
|
81
|
+
outPath: toAbsolute(opts.outPath),
|
|
82
|
+
extraArgs: opts.extraArgs,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
86
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
87
|
+
process.exitCode = result.exitCode;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
main();
|
|
92
|
+
} catch (error) {
|
|
93
|
+
usage();
|
|
94
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
}
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "doe_napi",
|
|
5
|
+
"sources": ["native/doe_napi.c"],
|
|
6
|
+
"include_dirs": [],
|
|
7
|
+
"defines": ["NAPI_VERSION=8"],
|
|
8
|
+
"conditions": [
|
|
9
|
+
["OS=='mac'", {
|
|
10
|
+
"xcode_settings": {
|
|
11
|
+
"OTHER_CFLAGS": ["-std=c11"],
|
|
12
|
+
"MACOSX_DEPLOYMENT_TARGET": "13.0"
|
|
13
|
+
}
|
|
14
|
+
}],
|
|
15
|
+
["OS=='linux'", {
|
|
16
|
+
"cflags": ["-std=c11"]
|
|
17
|
+
}]
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "Doe Zig Build Metadata",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"schemaVersion",
|
|
7
|
+
"artifact",
|
|
8
|
+
"leanVerifiedBuild",
|
|
9
|
+
"proofArtifactSha256"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"schemaVersion": { "type": "integer", "const": 1 },
|
|
13
|
+
"artifact": { "type": "string", "const": "libwebgpu_doe" },
|
|
14
|
+
"leanVerifiedBuild": { "type": "boolean" },
|
|
15
|
+
"proofArtifactSha256": {
|
|
16
|
+
"anyOf": [
|
|
17
|
+
{ "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
18
|
+
{ "type": "null" }
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"additionalProperties": false
|
|
23
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# WebGPU Headless Runtime Comparison Matrix
|
|
2
|
+
|
|
3
|
+
This document outlines qualitative differences and target use-cases for headless WebGPU workloads in JavaScript environments. It is intentionally scoped as a comparison draft, not a claim report.
|
|
4
|
+
|
|
5
|
+
| Feature / Trait | **Fawn Doe** (`@simulatte/webgpu`) | **Node WebGPU** (`webgpu`) | **Bun WebGPU** (`bun-webgpu`) |
|
|
6
|
+
| :--- | :--- | :--- | :--- |
|
|
7
|
+
| **Underlying Engine** | `libwebgpu_doe` (Zig + Lean pipeline) | Google Dawn (C++) | Google Dawn (C++) |
|
|
8
|
+
| **Primary Focus** | Deterministic Compute, ML/AI, Verifiability | Browser Parity, Graphics | Browser Parity, Graphics |
|
|
9
|
+
| **Binary Footprint** | Smaller targeted runtime expected | Varies by build/distribution | Varies by build/distribution |
|
|
10
|
+
| **JS Binding Layer** | Node-API (N-API) / Bun FFI | Node-API (N-API) | Bun FFI (Fast Foreign Function) |
|
|
11
|
+
| **Security Model** | Explicit schema/gate discipline in Fawn pipeline | Runtime heuristics + Dawn validation | Runtime heuristics + Dawn validation |
|
|
12
|
+
| **Resource Allocation** | Arena-backed, predictable memory | General WebGPU async allocations | General WebGPU async allocations |
|
|
13
|
+
| **WebGPU Spec Compliance**| Compute-prioritized subset target | Broad Chromium-aligned coverage | Broad Chromium-aligned coverage |
|
|
14
|
+
| **WGSL Shader Support** | Runtime-specific compiler/tooling path | Tint | Tint |
|
|
15
|
+
| **Target Use Case** | LLM Inference Testing, Benchmarks, Contracts | E2E Graphics Testing, Headless bots | High-perf TS Server Compute |
|
|
16
|
+
|
|
17
|
+
## Architectural Takeaways for Fawn
|
|
18
|
+
|
|
19
|
+
1. Determinism and fail-fast contracts are the intended Doe value proposition for benchmarking workflows.
|
|
20
|
+
2. Bun FFI can reduce wrapper overhead versus heavier bridge layers, but end-to-end results must be measured per workload.
|
|
21
|
+
3. Distribution size and startup claims must be backed by measured artifacts before release claims.
|
|
22
|
+
|
|
23
|
+
## Ecosystem reference: official/community competitors and stats
|
|
24
|
+
|
|
25
|
+
Sorted by GitHub stars (snapshot taken: 2026-03-02).
|
|
26
|
+
This list is limited to real WebGPU runtime implementations (not types/tooling).
|
|
27
|
+
|
|
28
|
+
| Runtime surface | GitHub project | Maintainer signal | Stars |
|
|
29
|
+
| :--- | :--- | :--- | ---: |
|
|
30
|
+
| `webgpu` (npm) | `dawn-gpu/node-webgpu` | `dawn-gpu` (official Dawn upstream) | 73 |
|
|
31
|
+
| `bun-webgpu` (npm) | `kommander/bun-webgpu` | Community maintained | 29 |
|
|
32
|
+
|
|
33
|
+
Notes:
|
|
34
|
+
|
|
35
|
+
1. `@simulatte/webgpu` is still pre-publication, so no direct npm star baseline exists in this snapshot yet.
|
|
36
|
+
2. This section is for runtime head-to-head comparability only; stars are a popularity signal, not a quality or correctness signal.
|
|
37
|
+
3. For this repo’s “official” definition, maintainer/org governance is the gate.
|
|
38
|
+
|
|
39
|
+
## Scaffolding the Fawn NPM Package
|
|
40
|
+
|
|
41
|
+
- Doe is exposed through a native C ABI and can be bridged from JS via Bun FFI now.
|
|
42
|
+
- Node N-API support now exists in the canonical `@simulatte/webgpu` package.
|
|
43
|
+
- Browser API parity is not claimed by this draft package; the current focus is headless benchmarking workflows.
|