@simulatte/webgpu-doe 0.1.2 → 0.1.3

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/src/index.js DELETED
@@ -1,495 +0,0 @@
1
- import { createRequire } from 'node:module';
2
- import { existsSync } from 'node:fs';
3
- import { resolve, dirname } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
-
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const require = createRequire(import.meta.url);
8
-
9
- const addon = loadAddon();
10
- const DOE_LIB_PATH = resolveDoeLibraryPath();
11
- let libraryLoaded = false;
12
-
13
- function loadAddon() {
14
- const prebuildPath = resolve(__dirname, '..', 'prebuilds', `${process.platform}-${process.arch}`, 'doe_napi.node');
15
- try {
16
- return require(prebuildPath);
17
- } catch {
18
- try {
19
- return require('../build/Release/doe_napi.node');
20
- } catch {
21
- try {
22
- return require('../build/Debug/doe_napi.node');
23
- } catch {
24
- return null;
25
- }
26
- }
27
- }
28
- }
29
-
30
- function resolveDoeLibraryPath() {
31
- const ext = process.platform === 'darwin' ? 'dylib'
32
- : process.platform === 'win32' ? 'dll' : 'so';
33
-
34
- const candidates = [
35
- process.env.DOE_WEBGPU_LIB,
36
- resolve(__dirname, '..', 'prebuilds', `${process.platform}-${process.arch}`, `libdoe_webgpu.${ext}`),
37
- resolve(__dirname, '..', '..', '..', 'zig', 'zig-out', 'lib', `libdoe_webgpu.${ext}`),
38
- resolve(process.cwd(), 'zig', 'zig-out', 'lib', `libdoe_webgpu.${ext}`),
39
- ];
40
-
41
- for (const candidate of candidates) {
42
- if (candidate && existsSync(candidate)) return candidate;
43
- }
44
- return null;
45
- }
46
-
47
- function ensureLibrary() {
48
- if (libraryLoaded) return;
49
- if (!addon) {
50
- throw new Error(
51
- '@simulatte/webgpu-doe: Native addon not found. Run `npm run build` or `npx node-gyp rebuild`.'
52
- );
53
- }
54
- if (!DOE_LIB_PATH) {
55
- throw new Error(
56
- '@simulatte/webgpu-doe: libdoe_webgpu not found. Build it with `cd fawn/zig && zig build dropin` or set DOE_WEBGPU_LIB.'
57
- );
58
- }
59
- addon.loadLibrary(DOE_LIB_PATH);
60
- libraryLoaded = true;
61
- }
62
-
63
- // WebGPU enum constants (standard values).
64
- export const globals = {
65
- GPUBufferUsage: {
66
- MAP_READ: 0x0001,
67
- MAP_WRITE: 0x0002,
68
- COPY_SRC: 0x0004,
69
- COPY_DST: 0x0008,
70
- INDEX: 0x0010,
71
- VERTEX: 0x0020,
72
- UNIFORM: 0x0040,
73
- STORAGE: 0x0080,
74
- INDIRECT: 0x0100,
75
- QUERY_RESOLVE: 0x0200,
76
- },
77
- GPUShaderStage: {
78
- VERTEX: 0x1,
79
- FRAGMENT: 0x2,
80
- COMPUTE: 0x4,
81
- },
82
- GPUMapMode: {
83
- READ: 0x0001,
84
- WRITE: 0x0002,
85
- },
86
- GPUTextureUsage: {
87
- COPY_SRC: 0x01,
88
- COPY_DST: 0x02,
89
- TEXTURE_BINDING: 0x04,
90
- STORAGE_BINDING: 0x08,
91
- RENDER_ATTACHMENT: 0x10,
92
- },
93
- };
94
-
95
- class DoeGPUBuffer {
96
- constructor(native, instance, size, usage, queue) {
97
- this._native = native;
98
- this._instance = instance;
99
- this._queue = queue;
100
- this.size = size;
101
- this.usage = usage;
102
- }
103
-
104
- async mapAsync(mode, offset = 0, size = this.size) {
105
- if (this._queue) addon.queueFlush(this._queue);
106
- addon.bufferMapSync(this._instance, this._native, mode, offset, size);
107
- }
108
-
109
- getMappedRange(offset = 0, size = this.size) {
110
- return addon.bufferGetMappedRange(this._native, offset, size);
111
- }
112
-
113
- unmap() {
114
- addon.bufferUnmap(this._native);
115
- }
116
-
117
- destroy() {
118
- addon.bufferRelease(this._native);
119
- this._native = null;
120
- }
121
- }
122
-
123
- class DoeGPUComputePassEncoder {
124
- constructor(native) { this._native = native; }
125
-
126
- setPipeline(pipeline) {
127
- addon.computePassSetPipeline(this._native, pipeline._native);
128
- }
129
-
130
- setBindGroup(index, bindGroup) {
131
- addon.computePassSetBindGroup(this._native, index, bindGroup._native);
132
- }
133
-
134
- dispatchWorkgroups(x, y = 1, z = 1) {
135
- addon.computePassDispatchWorkgroups(this._native, x, y, z);
136
- }
137
-
138
- dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset = 0) {
139
- addon.computePassDispatchWorkgroupsIndirect(this._native, indirectBuffer._native, indirectOffset);
140
- }
141
-
142
- end() {
143
- addon.computePassEnd(this._native);
144
- }
145
- }
146
-
147
- class DoeGPUCommandEncoder {
148
- constructor(native) { this._native = native; }
149
-
150
- beginComputePass(descriptor) {
151
- const pass = addon.beginComputePass(this._native);
152
- return new DoeGPUComputePassEncoder(pass);
153
- }
154
-
155
- beginRenderPass(descriptor) {
156
- const colorAttachments = (descriptor.colorAttachments || []).map((a) => ({
157
- view: a.view._native,
158
- clearValue: a.clearValue || { r: 0, g: 0, b: 0, a: 1 },
159
- }));
160
- const pass = addon.beginRenderPass(this._native, colorAttachments);
161
- return new DoeGPURenderPassEncoder(pass);
162
- }
163
-
164
- copyBufferToBuffer(src, srcOffset, dst, dstOffset, size) {
165
- addon.commandEncoderCopyBufferToBuffer(
166
- this._native, src._native, srcOffset, dst._native, dstOffset, size);
167
- }
168
-
169
- finish() {
170
- const cmd = addon.commandEncoderFinish(this._native);
171
- return { _native: cmd };
172
- }
173
- }
174
-
175
- class DoeGPUQueue {
176
- constructor(native) { this._native = native; }
177
-
178
- submit(commandBuffers) {
179
- const natives = commandBuffers.map((c) => c._native);
180
- addon.queueSubmit(this._native, natives);
181
- }
182
-
183
- writeBuffer(buffer, bufferOffset, data, dataOffset = 0, size) {
184
- let view = data;
185
- if (dataOffset > 0 || size !== undefined) {
186
- const byteOffset = data.byteOffset + dataOffset * (data.BYTES_PER_ELEMENT || 1);
187
- const byteLength = size !== undefined
188
- ? size * (data.BYTES_PER_ELEMENT || 1)
189
- : data.byteLength - dataOffset * (data.BYTES_PER_ELEMENT || 1);
190
- view = new Uint8Array(data.buffer, byteOffset, byteLength);
191
- }
192
- addon.queueWriteBuffer(this._native, buffer._native, bufferOffset, view);
193
- }
194
-
195
- async onSubmittedWorkDone() {
196
- addon.queueFlush(this._native);
197
- }
198
- }
199
-
200
- class DoeGPURenderPassEncoder {
201
- constructor(native) { this._native = native; }
202
-
203
- setPipeline(pipeline) {
204
- addon.renderPassSetPipeline(this._native, pipeline._native);
205
- }
206
-
207
- draw(vertexCount, instanceCount = 1, firstVertex = 0, firstInstance = 0) {
208
- addon.renderPassDraw(this._native, vertexCount, instanceCount, firstVertex, firstInstance);
209
- }
210
-
211
- end() {
212
- addon.renderPassEnd(this._native);
213
- }
214
- }
215
-
216
- class DoeGPUTexture {
217
- constructor(native) { this._native = native; }
218
-
219
- createView(descriptor) {
220
- const view = addon.textureCreateView(this._native);
221
- return new DoeGPUTextureView(view);
222
- }
223
-
224
- destroy() {
225
- addon.textureRelease(this._native);
226
- this._native = null;
227
- }
228
- }
229
-
230
- class DoeGPUTextureView {
231
- constructor(native) { this._native = native; }
232
- }
233
-
234
- class DoeGPUSampler {
235
- constructor(native) { this._native = native; }
236
- }
237
-
238
- class DoeGPURenderPipeline {
239
- constructor(native) { this._native = native; }
240
- }
241
-
242
- class DoeGPUShaderModule {
243
- constructor(native) { this._native = native; }
244
- }
245
-
246
- class DoeGPUComputePipeline {
247
- constructor(native) { this._native = native; }
248
-
249
- getBindGroupLayout(index) {
250
- const layout = addon.computePipelineGetBindGroupLayout(this._native, index);
251
- return new DoeGPUBindGroupLayout(layout);
252
- }
253
- }
254
-
255
- class DoeGPUBindGroupLayout {
256
- constructor(native) { this._native = native; }
257
- }
258
-
259
- class DoeGPUBindGroup {
260
- constructor(native) { this._native = native; }
261
- }
262
-
263
- class DoeGPUPipelineLayout {
264
- constructor(native) { this._native = native; }
265
- }
266
-
267
- // Metal defaults for Apple Silicon — matches doe_device_caps.zig METAL_LIMITS.
268
- const DOE_LIMITS = Object.freeze({
269
- maxTextureDimension1D: 16384,
270
- maxTextureDimension2D: 16384,
271
- maxTextureDimension3D: 2048,
272
- maxTextureArrayLayers: 2048,
273
- maxBindGroups: 4,
274
- maxBindGroupsPlusVertexBuffers: 24,
275
- maxBindingsPerBindGroup: 1000,
276
- maxDynamicUniformBuffersPerPipelineLayout: 8,
277
- maxDynamicStorageBuffersPerPipelineLayout: 4,
278
- maxSampledTexturesPerShaderStage: 16,
279
- maxSamplersPerShaderStage: 16,
280
- maxStorageBuffersPerShaderStage: 8,
281
- maxStorageTexturesPerShaderStage: 4,
282
- maxUniformBuffersPerShaderStage: 12,
283
- maxUniformBufferBindingSize: 65536,
284
- maxStorageBufferBindingSize: 134217728,
285
- minUniformBufferOffsetAlignment: 256,
286
- minStorageBufferOffsetAlignment: 32,
287
- maxVertexBuffers: 8,
288
- maxBufferSize: 268435456,
289
- maxVertexAttributes: 16,
290
- maxVertexBufferArrayStride: 2048,
291
- maxInterStageShaderVariables: 16,
292
- maxColorAttachments: 8,
293
- maxColorAttachmentBytesPerSample: 32,
294
- maxComputeWorkgroupStorageSize: 32768,
295
- maxComputeInvocationsPerWorkgroup: 1024,
296
- maxComputeWorkgroupSizeX: 1024,
297
- maxComputeWorkgroupSizeY: 1024,
298
- maxComputeWorkgroupSizeZ: 64,
299
- maxComputeWorkgroupsPerDimension: 65535,
300
- });
301
-
302
- const DOE_FEATURES = Object.freeze(new Set(['shader-f16']));
303
-
304
- class DoeGPUDevice {
305
- constructor(native, instance) {
306
- this._native = native;
307
- this._instance = instance;
308
- const q = addon.deviceGetQueue(native);
309
- this.queue = new DoeGPUQueue(q);
310
- this.limits = DOE_LIMITS;
311
- this.features = DOE_FEATURES;
312
- }
313
-
314
- createBuffer(descriptor) {
315
- const buf = addon.createBuffer(this._native, descriptor);
316
- return new DoeGPUBuffer(buf, this._instance, descriptor.size, descriptor.usage, this.queue._native);
317
- }
318
-
319
- createShaderModule(descriptor) {
320
- const code = descriptor.code || descriptor.source;
321
- if (!code) throw new Error('createShaderModule: descriptor.code is required');
322
- const mod = addon.createShaderModule(this._native, code);
323
- return new DoeGPUShaderModule(mod);
324
- }
325
-
326
- createComputePipeline(descriptor) {
327
- const shader = descriptor.compute?.module;
328
- const entryPoint = descriptor.compute?.entryPoint || 'main';
329
- const layout = descriptor.layout === 'auto' ? null : descriptor.layout;
330
- const native = addon.createComputePipeline(
331
- this._native, shader._native, entryPoint,
332
- layout?._native ?? null);
333
- return new DoeGPUComputePipeline(native);
334
- }
335
-
336
- async createComputePipelineAsync(descriptor) {
337
- return this.createComputePipeline(descriptor);
338
- }
339
-
340
- createBindGroupLayout(descriptor) {
341
- const entries = (descriptor.entries || []).map((e) => ({
342
- binding: e.binding,
343
- visibility: e.visibility,
344
- buffer: e.buffer ? {
345
- type: e.buffer.type || 'uniform',
346
- hasDynamicOffset: e.buffer.hasDynamicOffset || false,
347
- minBindingSize: e.buffer.minBindingSize || 0,
348
- } : undefined,
349
- storageTexture: e.storageTexture,
350
- }));
351
- const native = addon.createBindGroupLayout(this._native, entries);
352
- return new DoeGPUBindGroupLayout(native);
353
- }
354
-
355
- createBindGroup(descriptor) {
356
- const entries = (descriptor.entries || []).map((e) => {
357
- const entry = {
358
- binding: e.binding,
359
- buffer: e.resource?.buffer?._native ?? e.resource?._native ?? null,
360
- offset: e.resource?.offset ?? 0,
361
- };
362
- if (e.resource?.size !== undefined) entry.size = e.resource.size;
363
- return entry;
364
- });
365
- const native = addon.createBindGroup(
366
- this._native, descriptor.layout._native, entries);
367
- return new DoeGPUBindGroup(native);
368
- }
369
-
370
- createPipelineLayout(descriptor) {
371
- const layouts = (descriptor.bindGroupLayouts || []).map((l) => l._native);
372
- const native = addon.createPipelineLayout(this._native, layouts);
373
- return new DoeGPUPipelineLayout(native);
374
- }
375
-
376
- createTexture(descriptor) {
377
- const native = addon.createTexture(this._native, {
378
- format: descriptor.format || 'rgba8unorm',
379
- width: descriptor.size?.[0] ?? descriptor.size?.width ?? descriptor.size ?? 1,
380
- height: descriptor.size?.[1] ?? descriptor.size?.height ?? 1,
381
- depthOrArrayLayers: descriptor.size?.[2] ?? descriptor.size?.depthOrArrayLayers ?? 1,
382
- usage: descriptor.usage || 0,
383
- mipLevelCount: descriptor.mipLevelCount || 1,
384
- });
385
- return new DoeGPUTexture(native);
386
- }
387
-
388
- createSampler(descriptor = {}) {
389
- const native = addon.createSampler(this._native, descriptor);
390
- return new DoeGPUSampler(native);
391
- }
392
-
393
- createRenderPipeline(descriptor) {
394
- const native = addon.createRenderPipeline(this._native);
395
- return new DoeGPURenderPipeline(native);
396
- }
397
-
398
- createCommandEncoder(descriptor) {
399
- const native = addon.createCommandEncoder(this._native);
400
- return new DoeGPUCommandEncoder(native);
401
- }
402
-
403
- destroy() {
404
- addon.deviceRelease(this._native);
405
- this._native = null;
406
- }
407
- }
408
-
409
- class DoeGPUAdapter {
410
- constructor(native, instance) {
411
- this._native = native;
412
- this._instance = instance;
413
- this.features = DOE_FEATURES;
414
- this.limits = DOE_LIMITS;
415
- }
416
-
417
- async requestDevice(descriptor) {
418
- const device = addon.requestDevice(this._instance, this._native);
419
- return new DoeGPUDevice(device, this._instance);
420
- }
421
-
422
- destroy() {
423
- addon.adapterRelease(this._native);
424
- this._native = null;
425
- }
426
- }
427
-
428
- class DoeGPU {
429
- constructor(instance) {
430
- this._instance = instance;
431
- }
432
-
433
- async requestAdapter(options) {
434
- const adapter = addon.requestAdapter(this._instance);
435
- return new DoeGPUAdapter(adapter, this._instance);
436
- }
437
- }
438
-
439
- export function create(createArgs = null) {
440
- ensureLibrary();
441
- const instance = addon.createInstance();
442
- return new DoeGPU(instance);
443
- }
444
-
445
- export function setupGlobals(target = globalThis, createArgs = null) {
446
- for (const [name, value] of Object.entries(globals)) {
447
- if (target[name] === undefined) {
448
- Object.defineProperty(target, name, {
449
- value,
450
- writable: true,
451
- configurable: true,
452
- enumerable: false,
453
- });
454
- }
455
- }
456
- const gpu = create(createArgs);
457
- if (typeof target.navigator === 'undefined') {
458
- Object.defineProperty(target, 'navigator', {
459
- value: { gpu },
460
- writable: true,
461
- configurable: true,
462
- enumerable: false,
463
- });
464
- } else if (!target.navigator.gpu) {
465
- Object.defineProperty(target.navigator, 'gpu', {
466
- value: gpu,
467
- writable: true,
468
- configurable: true,
469
- enumerable: false,
470
- });
471
- }
472
- return gpu;
473
- }
474
-
475
- export async function requestAdapter(adapterOptions = undefined, createArgs = null) {
476
- const gpu = create(createArgs);
477
- return gpu.requestAdapter(adapterOptions);
478
- }
479
-
480
- export async function requestDevice(options = {}) {
481
- const createArgs = options?.createArgs ?? null;
482
- const adapter = await requestAdapter(options?.adapterOptions, createArgs);
483
- return adapter.requestDevice(options?.deviceDescriptor);
484
- }
485
-
486
- export function providerInfo() {
487
- return {
488
- module: '@simulatte/webgpu-doe',
489
- loaded: !!addon && !!DOE_LIB_PATH,
490
- loadError: !addon ? 'native addon not found' : !DOE_LIB_PATH ? 'libdoe_webgpu not found' : '',
491
- defaultCreateArgs: [],
492
- doeNative: true,
493
- doeLibraryPath: DOE_LIB_PATH ?? '',
494
- };
495
- }