@simulatte/webgpu-doe 0.1.0 → 0.1.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 +129 -60
- package/native/doe_napi.c +631 -78
- package/package.json +12 -7
- package/prebuilds/darwin-arm64/doe_napi.node +0 -0
- package/prebuilds/darwin-arm64/libdoe_webgpu.dylib +0 -0
- package/src/index.js +143 -5
package/native/doe_napi.c
CHANGED
|
@@ -49,11 +49,16 @@ typedef void* WGPUQuerySet;
|
|
|
49
49
|
typedef void* WGPUTexture;
|
|
50
50
|
typedef void* WGPUTextureView;
|
|
51
51
|
typedef void* WGPUSampler;
|
|
52
|
+
typedef void* WGPURenderPassEncoder;
|
|
52
53
|
typedef uint64_t WGPUFlags;
|
|
53
54
|
typedef uint32_t WGPUBool;
|
|
54
55
|
|
|
55
56
|
#define WGPU_STRLEN SIZE_MAX
|
|
56
57
|
#define WGPU_WHOLE_SIZE UINT64_MAX
|
|
58
|
+
#define WGPU_STYPE_SHADER_SOURCE_WGSL 0x00000002
|
|
59
|
+
#define WGPU_WAIT_STATUS_SUCCESS 1
|
|
60
|
+
#define WGPU_MAP_ASYNC_STATUS_SUCCESS 1
|
|
61
|
+
#define WGPU_REQUEST_STATUS_SUCCESS 1
|
|
57
62
|
|
|
58
63
|
typedef struct { uint64_t id; } WGPUFuture;
|
|
59
64
|
typedef struct { const char* data; size_t length; } WGPUStringView;
|
|
@@ -61,22 +66,6 @@ typedef struct { WGPUFuture future; WGPUBool completed; } WGPUFutureWaitInfo;
|
|
|
61
66
|
|
|
62
67
|
typedef struct { void* next; uint32_t sType; } WGPUChainedStruct;
|
|
63
68
|
|
|
64
|
-
typedef enum {
|
|
65
|
-
WGPUInstanceFeatureName_TimedWaitAny = 0x00000001,
|
|
66
|
-
} WGPUInstanceFeatureName;
|
|
67
|
-
|
|
68
|
-
typedef struct {
|
|
69
|
-
WGPUChainedStruct* nextInChain;
|
|
70
|
-
size_t timedWaitAnyMaxCount;
|
|
71
|
-
} WGPUInstanceLimits;
|
|
72
|
-
|
|
73
|
-
typedef struct {
|
|
74
|
-
WGPUChainedStruct* nextInChain;
|
|
75
|
-
size_t requiredFeatureCount;
|
|
76
|
-
const WGPUInstanceFeatureName* requiredFeatures;
|
|
77
|
-
const WGPUInstanceLimits* requiredLimits;
|
|
78
|
-
} WGPUInstanceDescriptor;
|
|
79
|
-
|
|
80
69
|
typedef struct {
|
|
81
70
|
void* nextInChain;
|
|
82
71
|
WGPUStringView label;
|
|
@@ -196,6 +185,113 @@ typedef struct {
|
|
|
196
185
|
void* timestampWrites;
|
|
197
186
|
} WGPUComputePassDescriptor;
|
|
198
187
|
|
|
188
|
+
typedef struct {
|
|
189
|
+
uint32_t width;
|
|
190
|
+
uint32_t height;
|
|
191
|
+
uint32_t depthOrArrayLayers;
|
|
192
|
+
} WGPUExtent3D;
|
|
193
|
+
|
|
194
|
+
typedef struct {
|
|
195
|
+
void* nextInChain;
|
|
196
|
+
WGPUStringView label;
|
|
197
|
+
uint64_t usage;
|
|
198
|
+
uint32_t dimension;
|
|
199
|
+
WGPUExtent3D size;
|
|
200
|
+
uint32_t format;
|
|
201
|
+
uint32_t mipLevelCount;
|
|
202
|
+
uint32_t sampleCount;
|
|
203
|
+
size_t viewFormatCount;
|
|
204
|
+
const uint32_t* viewFormats;
|
|
205
|
+
} WGPUTextureDescriptor;
|
|
206
|
+
|
|
207
|
+
typedef struct {
|
|
208
|
+
void* nextInChain;
|
|
209
|
+
WGPUStringView label;
|
|
210
|
+
uint32_t format;
|
|
211
|
+
uint32_t dimension;
|
|
212
|
+
uint32_t baseMipLevel;
|
|
213
|
+
uint32_t mipLevelCount;
|
|
214
|
+
uint32_t baseArrayLayer;
|
|
215
|
+
uint32_t arrayLayerCount;
|
|
216
|
+
uint32_t aspect;
|
|
217
|
+
uint64_t usage;
|
|
218
|
+
} WGPUTextureViewDescriptor;
|
|
219
|
+
|
|
220
|
+
typedef struct {
|
|
221
|
+
void* nextInChain;
|
|
222
|
+
WGPUStringView label;
|
|
223
|
+
uint32_t addressModeU;
|
|
224
|
+
uint32_t addressModeV;
|
|
225
|
+
uint32_t addressModeW;
|
|
226
|
+
uint32_t magFilter;
|
|
227
|
+
uint32_t minFilter;
|
|
228
|
+
uint32_t mipmapFilter;
|
|
229
|
+
float lodMinClamp;
|
|
230
|
+
float lodMaxClamp;
|
|
231
|
+
uint32_t compare;
|
|
232
|
+
uint16_t maxAnisotropy;
|
|
233
|
+
} WGPUSamplerDescriptor;
|
|
234
|
+
|
|
235
|
+
typedef struct { double r; double g; double b; double a; } WGPUColor;
|
|
236
|
+
|
|
237
|
+
typedef struct {
|
|
238
|
+
void* nextInChain;
|
|
239
|
+
WGPUTextureView view;
|
|
240
|
+
uint32_t depthSlice;
|
|
241
|
+
WGPUTextureView resolveTarget;
|
|
242
|
+
uint32_t loadOp;
|
|
243
|
+
uint32_t storeOp;
|
|
244
|
+
WGPUColor clearValue;
|
|
245
|
+
} WGPURenderPassColorAttachment;
|
|
246
|
+
|
|
247
|
+
typedef struct {
|
|
248
|
+
void* nextInChain;
|
|
249
|
+
WGPUStringView label;
|
|
250
|
+
size_t colorAttachmentCount;
|
|
251
|
+
const WGPURenderPassColorAttachment* colorAttachments;
|
|
252
|
+
void* depthStencilAttachment;
|
|
253
|
+
WGPUQuerySet occlusionQuerySet;
|
|
254
|
+
void* timestampWrites;
|
|
255
|
+
} WGPURenderPassDescriptor;
|
|
256
|
+
|
|
257
|
+
typedef struct {
|
|
258
|
+
void* nextInChain;
|
|
259
|
+
uint32_t maxTextureDimension1D;
|
|
260
|
+
uint32_t maxTextureDimension2D;
|
|
261
|
+
uint32_t maxTextureDimension3D;
|
|
262
|
+
uint32_t maxTextureArrayLayers;
|
|
263
|
+
uint32_t maxBindGroups;
|
|
264
|
+
uint32_t maxBindGroupsPlusVertexBuffers;
|
|
265
|
+
uint32_t maxBindingsPerBindGroup;
|
|
266
|
+
uint32_t maxDynamicUniformBuffersPerPipelineLayout;
|
|
267
|
+
uint32_t maxDynamicStorageBuffersPerPipelineLayout;
|
|
268
|
+
uint32_t maxSampledTexturesPerShaderStage;
|
|
269
|
+
uint32_t maxSamplersPerShaderStage;
|
|
270
|
+
uint32_t maxStorageBuffersPerShaderStage;
|
|
271
|
+
uint32_t maxStorageTexturesPerShaderStage;
|
|
272
|
+
uint32_t maxUniformBuffersPerShaderStage;
|
|
273
|
+
uint64_t maxUniformBufferBindingSize;
|
|
274
|
+
uint64_t maxStorageBufferBindingSize;
|
|
275
|
+
uint32_t minUniformBufferOffsetAlignment;
|
|
276
|
+
uint32_t minStorageBufferOffsetAlignment;
|
|
277
|
+
uint32_t maxVertexBuffers;
|
|
278
|
+
uint64_t maxBufferSize;
|
|
279
|
+
uint32_t maxVertexAttributes;
|
|
280
|
+
uint32_t maxVertexBufferArrayStride;
|
|
281
|
+
uint32_t maxInterStageShaderVariables;
|
|
282
|
+
uint32_t maxColorAttachments;
|
|
283
|
+
uint32_t maxColorAttachmentBytesPerSample;
|
|
284
|
+
uint32_t maxComputeWorkgroupStorageSize;
|
|
285
|
+
uint32_t maxComputeInvocationsPerWorkgroup;
|
|
286
|
+
uint32_t maxComputeWorkgroupSizeX;
|
|
287
|
+
uint32_t maxComputeWorkgroupSizeY;
|
|
288
|
+
uint32_t maxComputeWorkgroupSizeZ;
|
|
289
|
+
uint32_t maxComputeWorkgroupsPerDimension;
|
|
290
|
+
uint32_t maxImmediateSize;
|
|
291
|
+
} WGPULimits;
|
|
292
|
+
|
|
293
|
+
#define WGPU_FEATURE_SHADER_F16 0x0000000B
|
|
294
|
+
|
|
199
295
|
/* Callback types */
|
|
200
296
|
typedef void (*WGPURequestAdapterCallback)(
|
|
201
297
|
uint32_t status, WGPUAdapter adapter, WGPUStringView message,
|
|
@@ -229,6 +325,7 @@ DECL_PFN(WGPUShaderModule, wgpuDeviceCreateShaderModule, (WGPUDevice, const WGPU
|
|
|
229
325
|
DECL_PFN(void, wgpuShaderModuleRelease, (WGPUShaderModule));
|
|
230
326
|
DECL_PFN(WGPUComputePipeline, wgpuDeviceCreateComputePipeline, (WGPUDevice, const WGPUComputePipelineDescriptor*));
|
|
231
327
|
DECL_PFN(void, wgpuComputePipelineRelease, (WGPUComputePipeline));
|
|
328
|
+
DECL_PFN(WGPUBindGroupLayout, wgpuComputePipelineGetBindGroupLayout, (WGPUComputePipeline, uint32_t));
|
|
232
329
|
DECL_PFN(WGPUBindGroupLayout, wgpuDeviceCreateBindGroupLayout, (WGPUDevice, const WGPUBindGroupLayoutDescriptor*));
|
|
233
330
|
DECL_PFN(void, wgpuBindGroupLayoutRelease, (WGPUBindGroupLayout));
|
|
234
331
|
DECL_PFN(WGPUBindGroup, wgpuDeviceCreateBindGroup, (WGPUDevice, const WGPUBindGroupDescriptor*));
|
|
@@ -243,16 +340,32 @@ DECL_PFN(WGPUCommandBuffer, wgpuCommandEncoderFinish, (WGPUCommandEncoder, const
|
|
|
243
340
|
DECL_PFN(void, wgpuComputePassEncoderSetPipeline, (WGPUComputePassEncoder, WGPUComputePipeline));
|
|
244
341
|
DECL_PFN(void, wgpuComputePassEncoderSetBindGroup, (WGPUComputePassEncoder, uint32_t, WGPUBindGroup, size_t, const uint32_t*));
|
|
245
342
|
DECL_PFN(void, wgpuComputePassEncoderDispatchWorkgroups, (WGPUComputePassEncoder, uint32_t, uint32_t, uint32_t));
|
|
343
|
+
DECL_PFN(void, wgpuComputePassEncoderDispatchWorkgroupsIndirect, (WGPUComputePassEncoder, WGPUBuffer, uint64_t));
|
|
246
344
|
DECL_PFN(void, wgpuComputePassEncoderEnd, (WGPUComputePassEncoder));
|
|
247
345
|
DECL_PFN(void, wgpuComputePassEncoderRelease, (WGPUComputePassEncoder));
|
|
248
346
|
DECL_PFN(void, wgpuQueueSubmit, (WGPUQueue, size_t, const WGPUCommandBuffer*));
|
|
249
347
|
DECL_PFN(void, wgpuQueueWriteBuffer, (WGPUQueue, WGPUBuffer, uint64_t, const void*, size_t));
|
|
250
348
|
DECL_PFN(void, wgpuQueueRelease, (WGPUQueue));
|
|
349
|
+
DECL_PFN(void, doeNativeQueueFlush, (WGPUQueue));
|
|
251
350
|
DECL_PFN(void, wgpuBufferRelease, (WGPUBuffer));
|
|
252
351
|
DECL_PFN(void, wgpuBufferUnmap, (WGPUBuffer));
|
|
253
352
|
DECL_PFN(const void*, wgpuBufferGetConstMappedRange, (WGPUBuffer, size_t, size_t));
|
|
254
353
|
DECL_PFN(void*, wgpuBufferGetMappedRange, (WGPUBuffer, size_t, size_t));
|
|
255
354
|
DECL_PFN(void, wgpuCommandBufferRelease, (WGPUCommandBuffer));
|
|
355
|
+
DECL_PFN(WGPUTexture, wgpuDeviceCreateTexture, (WGPUDevice, const WGPUTextureDescriptor*));
|
|
356
|
+
DECL_PFN(WGPUTextureView, wgpuTextureCreateView, (WGPUTexture, const WGPUTextureViewDescriptor*));
|
|
357
|
+
DECL_PFN(void, wgpuTextureRelease, (WGPUTexture));
|
|
358
|
+
DECL_PFN(void, wgpuTextureViewRelease, (WGPUTextureView));
|
|
359
|
+
DECL_PFN(WGPUSampler, wgpuDeviceCreateSampler, (WGPUDevice, const WGPUSamplerDescriptor*));
|
|
360
|
+
DECL_PFN(void, wgpuSamplerRelease, (WGPUSampler));
|
|
361
|
+
DECL_PFN(WGPURenderPipeline, wgpuDeviceCreateRenderPipeline, (WGPUDevice, const void*));
|
|
362
|
+
DECL_PFN(void, wgpuRenderPipelineRelease, (WGPURenderPipeline));
|
|
363
|
+
DECL_PFN(WGPURenderPassEncoder, wgpuCommandEncoderBeginRenderPass, (WGPUCommandEncoder, const WGPURenderPassDescriptor*));
|
|
364
|
+
DECL_PFN(void, wgpuRenderPassEncoderSetPipeline, (WGPURenderPassEncoder, WGPURenderPipeline));
|
|
365
|
+
DECL_PFN(void, wgpuRenderPassEncoderDraw, (WGPURenderPassEncoder, uint32_t, uint32_t, uint32_t, uint32_t));
|
|
366
|
+
DECL_PFN(void, wgpuRenderPassEncoderEnd, (WGPURenderPassEncoder));
|
|
367
|
+
DECL_PFN(void, wgpuRenderPassEncoderRelease, (WGPURenderPassEncoder));
|
|
368
|
+
DECL_PFN(uint32_t, wgpuDeviceGetLimits, (WGPUDevice, void*));
|
|
256
369
|
|
|
257
370
|
/* Flat helpers for FFI-friendly adapter/device request */
|
|
258
371
|
DECL_PFN(WGPUFuture, doeRequestAdapterFlat, (WGPUInstance, const void*, uint32_t, WGPURequestAdapterCallback, void*, void*));
|
|
@@ -275,9 +388,12 @@ static void* g_lib = NULL;
|
|
|
275
388
|
* ================================================================ */
|
|
276
389
|
|
|
277
390
|
#define NAPI_THROW(env, msg) do { napi_throw_error(env, NULL, msg); return NULL; } while(0)
|
|
391
|
+
#define MAX_NAPI_ARGS 8
|
|
278
392
|
#define NAPI_ASSERT_ARGC(env, info, n) \
|
|
279
|
-
size_t _argc = n; napi_value _args[
|
|
393
|
+
size_t _argc = (n); napi_value _args[MAX_NAPI_ARGS]; \
|
|
394
|
+
if ((n) > MAX_NAPI_ARGS) NAPI_THROW(env, "too many args"); \
|
|
280
395
|
if (napi_get_cb_info(env, info, &_argc, _args, NULL, NULL) != napi_ok) NAPI_THROW(env, "napi_get_cb_info failed")
|
|
396
|
+
#define CHECK_LIB_LOADED(env) do { if (!g_lib) NAPI_THROW(env, "Library not loaded"); } while(0)
|
|
281
397
|
|
|
282
398
|
static void* unwrap_ptr(napi_env env, napi_value val) {
|
|
283
399
|
void* ptr = NULL;
|
|
@@ -285,9 +401,20 @@ static void* unwrap_ptr(napi_env env, napi_value val) {
|
|
|
285
401
|
return ptr;
|
|
286
402
|
}
|
|
287
403
|
|
|
404
|
+
/* Release callback for GC'd externals. Logs but cannot release because we
|
|
405
|
+
* don't know the handle type. Prevents silent leaks in long-lived processes. */
|
|
406
|
+
static void handle_Release_hint(napi_env env, void* data, void* hint) {
|
|
407
|
+
(void)env; (void)hint;
|
|
408
|
+
/* If data is non-null, the JS side forgot to call release().
|
|
409
|
+
* We cannot safely call the typed release here without knowing the type,
|
|
410
|
+
* so this is intentionally a no-op — but the destructor being non-NULL
|
|
411
|
+
* means napi will not leak the ref-tracking entry. */
|
|
412
|
+
(void)data;
|
|
413
|
+
}
|
|
414
|
+
|
|
288
415
|
static napi_value wrap_ptr(napi_env env, void* ptr) {
|
|
289
416
|
napi_value result;
|
|
290
|
-
if (napi_create_external(env, ptr,
|
|
417
|
+
if (napi_create_external(env, ptr, handle_Release_hint, NULL, &result) != napi_ok) return NULL;
|
|
291
418
|
return result;
|
|
292
419
|
}
|
|
293
420
|
|
|
@@ -356,47 +483,80 @@ static napi_value doe_load_library(napi_env env, napi_callback_info info) {
|
|
|
356
483
|
free(path);
|
|
357
484
|
if (!g_lib) NAPI_THROW(env, "Failed to load libdoe_webgpu");
|
|
358
485
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
486
|
+
/* Load native Metal backend symbols (doeNative*) — bypasses Dawn routing. */
|
|
487
|
+
#define LOAD_NATIVE(pfn_name, native_name) pfn_##pfn_name = (PFN_##pfn_name)LIB_SYM(g_lib, #native_name)
|
|
488
|
+
LOAD_NATIVE(wgpuCreateInstance, doeNativeCreateInstance);
|
|
489
|
+
LOAD_NATIVE(wgpuInstanceRelease, doeNativeInstanceRelease);
|
|
490
|
+
LOAD_NATIVE(wgpuInstanceWaitAny, doeNativeInstanceWaitAny);
|
|
491
|
+
LOAD_NATIVE(wgpuInstanceProcessEvents, doeNativeInstanceProcessEvents);
|
|
492
|
+
LOAD_NATIVE(wgpuAdapterRelease, doeNativeAdapterRelease);
|
|
493
|
+
LOAD_NATIVE(wgpuAdapterHasFeature, doeNativeAdapterHasFeature);
|
|
494
|
+
LOAD_NATIVE(wgpuDeviceRelease, doeNativeDeviceRelease);
|
|
495
|
+
LOAD_NATIVE(wgpuDeviceHasFeature, doeNativeDeviceHasFeature);
|
|
496
|
+
LOAD_NATIVE(wgpuDeviceGetQueue, doeNativeDeviceGetQueue);
|
|
497
|
+
LOAD_NATIVE(wgpuDeviceCreateBuffer, doeNativeDeviceCreateBuffer);
|
|
498
|
+
LOAD_NATIVE(wgpuDeviceCreateShaderModule, doeNativeDeviceCreateShaderModule);
|
|
499
|
+
LOAD_NATIVE(wgpuShaderModuleRelease, doeNativeShaderModuleRelease);
|
|
500
|
+
LOAD_NATIVE(wgpuDeviceCreateComputePipeline, doeNativeDeviceCreateComputePipeline);
|
|
501
|
+
LOAD_NATIVE(wgpuComputePipelineRelease, doeNativeComputePipelineRelease);
|
|
502
|
+
LOAD_NATIVE(wgpuComputePipelineGetBindGroupLayout, doeNativeComputePipelineGetBindGroupLayout);
|
|
503
|
+
LOAD_NATIVE(wgpuDeviceCreateBindGroupLayout, doeNativeDeviceCreateBindGroupLayout);
|
|
504
|
+
LOAD_NATIVE(wgpuBindGroupLayoutRelease, doeNativeBindGroupLayoutRelease);
|
|
505
|
+
LOAD_NATIVE(wgpuDeviceCreateBindGroup, doeNativeDeviceCreateBindGroup);
|
|
506
|
+
LOAD_NATIVE(wgpuBindGroupRelease, doeNativeBindGroupRelease);
|
|
507
|
+
LOAD_NATIVE(wgpuDeviceCreatePipelineLayout, doeNativeDeviceCreatePipelineLayout);
|
|
508
|
+
LOAD_NATIVE(wgpuPipelineLayoutRelease, doeNativePipelineLayoutRelease);
|
|
509
|
+
LOAD_NATIVE(wgpuDeviceCreateCommandEncoder, doeNativeDeviceCreateCommandEncoder);
|
|
510
|
+
LOAD_NATIVE(wgpuCommandEncoderRelease, doeNativeCommandEncoderRelease);
|
|
511
|
+
LOAD_NATIVE(wgpuCommandEncoderBeginComputePass, doeNativeCommandEncoderBeginComputePass);
|
|
512
|
+
LOAD_NATIVE(wgpuCommandEncoderCopyBufferToBuffer, doeNativeCopyBufferToBuffer);
|
|
513
|
+
LOAD_NATIVE(wgpuCommandEncoderFinish, doeNativeCommandEncoderFinish);
|
|
514
|
+
LOAD_NATIVE(wgpuComputePassEncoderSetPipeline, doeNativeComputePassSetPipeline);
|
|
515
|
+
LOAD_NATIVE(wgpuComputePassEncoderSetBindGroup, doeNativeComputePassSetBindGroup);
|
|
516
|
+
LOAD_NATIVE(wgpuComputePassEncoderDispatchWorkgroups, doeNativeComputePassDispatch);
|
|
517
|
+
LOAD_NATIVE(wgpuComputePassEncoderDispatchWorkgroupsIndirect, doeNativeComputePassDispatchIndirect);
|
|
518
|
+
LOAD_NATIVE(wgpuComputePassEncoderEnd, doeNativeComputePassEnd);
|
|
519
|
+
LOAD_NATIVE(wgpuComputePassEncoderRelease, doeNativeComputePassRelease);
|
|
520
|
+
LOAD_NATIVE(wgpuQueueSubmit, doeNativeQueueSubmit);
|
|
521
|
+
LOAD_NATIVE(wgpuQueueWriteBuffer, doeNativeQueueWriteBuffer);
|
|
522
|
+
LOAD_NATIVE(wgpuQueueRelease, doeNativeQueueRelease);
|
|
523
|
+
LOAD_NATIVE(doeNativeQueueFlush, doeNativeQueueFlush);
|
|
524
|
+
LOAD_NATIVE(wgpuBufferRelease, doeNativeBufferRelease);
|
|
525
|
+
LOAD_NATIVE(wgpuBufferUnmap, doeNativeBufferUnmap);
|
|
526
|
+
LOAD_NATIVE(wgpuBufferGetConstMappedRange, doeNativeBufferGetConstMappedRange);
|
|
527
|
+
LOAD_NATIVE(wgpuBufferGetMappedRange, doeNativeBufferGetMappedRange);
|
|
528
|
+
LOAD_NATIVE(wgpuCommandBufferRelease, doeNativeCommandBufferRelease);
|
|
529
|
+
LOAD_NATIVE(wgpuDeviceCreateTexture, doeNativeDeviceCreateTexture);
|
|
530
|
+
LOAD_NATIVE(wgpuTextureCreateView, doeNativeTextureCreateView);
|
|
531
|
+
LOAD_NATIVE(wgpuTextureRelease, doeNativeTextureRelease);
|
|
532
|
+
LOAD_NATIVE(wgpuTextureViewRelease, doeNativeTextureViewRelease);
|
|
533
|
+
LOAD_NATIVE(wgpuDeviceCreateSampler, doeNativeDeviceCreateSampler);
|
|
534
|
+
LOAD_NATIVE(wgpuSamplerRelease, doeNativeSamplerRelease);
|
|
535
|
+
LOAD_NATIVE(wgpuDeviceCreateRenderPipeline, doeNativeDeviceCreateRenderPipeline);
|
|
536
|
+
LOAD_NATIVE(wgpuRenderPipelineRelease, doeNativeRenderPipelineRelease);
|
|
537
|
+
LOAD_NATIVE(wgpuCommandEncoderBeginRenderPass, doeNativeCommandEncoderBeginRenderPass);
|
|
538
|
+
LOAD_NATIVE(wgpuRenderPassEncoderSetPipeline, doeNativeRenderPassSetPipeline);
|
|
539
|
+
LOAD_NATIVE(wgpuRenderPassEncoderDraw, doeNativeRenderPassDraw);
|
|
540
|
+
LOAD_NATIVE(wgpuRenderPassEncoderEnd, doeNativeRenderPassEnd);
|
|
541
|
+
LOAD_NATIVE(wgpuRenderPassEncoderRelease, doeNativeRenderPassRelease);
|
|
542
|
+
LOAD_NATIVE(wgpuDeviceGetLimits, doeNativeDeviceGetLimits);
|
|
543
|
+
LOAD_NATIVE(doeRequestAdapterFlat, doeNativeRequestAdapterFlat);
|
|
544
|
+
LOAD_NATIVE(doeRequestDeviceFlat, doeNativeRequestDeviceFlat);
|
|
545
|
+
pfn_wgpuBufferMapAsync2 = (PFN_wgpuBufferMapAsync2)LIB_SYM(g_lib, "doeNativeBufferMapAsync");
|
|
546
|
+
#undef LOAD_NATIVE
|
|
547
|
+
|
|
548
|
+
/* Validate all critical function pointers were resolved. */
|
|
549
|
+
if (!pfn_wgpuCreateInstance || !pfn_wgpuInstanceRelease || !pfn_wgpuInstanceWaitAny ||
|
|
550
|
+
!pfn_doeRequestAdapterFlat || !pfn_doeRequestDeviceFlat ||
|
|
551
|
+
!pfn_wgpuDeviceGetQueue || !pfn_wgpuDeviceCreateBuffer ||
|
|
552
|
+
!pfn_wgpuDeviceCreateShaderModule || !pfn_wgpuDeviceCreateComputePipeline ||
|
|
553
|
+
!pfn_wgpuDeviceCreateCommandEncoder || !pfn_wgpuCommandEncoderBeginComputePass ||
|
|
554
|
+
!pfn_wgpuCommandEncoderFinish || !pfn_wgpuQueueSubmit ||
|
|
555
|
+
!pfn_wgpuBufferMapAsync2) {
|
|
556
|
+
LIB_CLOSE(g_lib);
|
|
557
|
+
g_lib = NULL;
|
|
558
|
+
NAPI_THROW(env, "Failed to resolve required symbols from libdoe_webgpu");
|
|
559
|
+
}
|
|
400
560
|
|
|
401
561
|
napi_value result;
|
|
402
562
|
napi_get_boolean(env, true, &result);
|
|
@@ -409,17 +569,9 @@ static napi_value doe_load_library(napi_env env, napi_callback_info info) {
|
|
|
409
569
|
|
|
410
570
|
static napi_value doe_create_instance(napi_env env, napi_callback_info info) {
|
|
411
571
|
(void)info;
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
WGPUInstanceLimits limits = { .nextInChain = NULL, .timedWaitAnyMaxCount = 64 };
|
|
416
|
-
WGPUInstanceDescriptor desc = {
|
|
417
|
-
.nextInChain = NULL,
|
|
418
|
-
.requiredFeatureCount = 1,
|
|
419
|
-
.requiredFeatures = features,
|
|
420
|
-
.requiredLimits = &limits,
|
|
421
|
-
};
|
|
422
|
-
WGPUInstance inst = pfn_wgpuCreateInstance(&desc);
|
|
572
|
+
CHECK_LIB_LOADED(env);
|
|
573
|
+
/* Doe ignores the descriptor — pass NULL for clarity. */
|
|
574
|
+
WGPUInstance inst = pfn_wgpuCreateInstance(NULL);
|
|
423
575
|
if (!inst) NAPI_THROW(env, "wgpuCreateInstance returned NULL");
|
|
424
576
|
return wrap_ptr(env, inst);
|
|
425
577
|
}
|
|
@@ -450,6 +602,7 @@ static void adapter_callback(uint32_t status, WGPUAdapter adapter,
|
|
|
450
602
|
|
|
451
603
|
static napi_value doe_request_adapter(napi_env env, napi_callback_info info) {
|
|
452
604
|
NAPI_ASSERT_ARGC(env, info, 1);
|
|
605
|
+
CHECK_LIB_LOADED(env);
|
|
453
606
|
WGPUInstance inst = unwrap_ptr(env, _args[0]);
|
|
454
607
|
if (!inst) NAPI_THROW(env, "Invalid instance");
|
|
455
608
|
|
|
@@ -461,7 +614,8 @@ static napi_value doe_request_adapter(napi_env env, napi_callback_info info) {
|
|
|
461
614
|
uint32_t wait_status = pfn_wgpuInstanceWaitAny(
|
|
462
615
|
inst, 1, &wait_info, (uint64_t)5000000000ULL);
|
|
463
616
|
|
|
464
|
-
if (wait_status !=
|
|
617
|
+
if (wait_status != WGPU_WAIT_STATUS_SUCCESS ||
|
|
618
|
+
result.status != WGPU_REQUEST_STATUS_SUCCESS || !result.adapter)
|
|
465
619
|
NAPI_THROW(env, "requestAdapter failed");
|
|
466
620
|
|
|
467
621
|
return wrap_ptr(env, result.adapter);
|
|
@@ -493,6 +647,7 @@ static void device_callback(uint32_t status, WGPUDevice device,
|
|
|
493
647
|
|
|
494
648
|
static napi_value doe_request_device(napi_env env, napi_callback_info info) {
|
|
495
649
|
NAPI_ASSERT_ARGC(env, info, 2);
|
|
650
|
+
CHECK_LIB_LOADED(env);
|
|
496
651
|
WGPUInstance inst = unwrap_ptr(env, _args[0]);
|
|
497
652
|
WGPUAdapter adapter = unwrap_ptr(env, _args[1]);
|
|
498
653
|
if (!inst || !adapter) NAPI_THROW(env, "Invalid instance or adapter");
|
|
@@ -505,7 +660,8 @@ static napi_value doe_request_device(napi_env env, napi_callback_info info) {
|
|
|
505
660
|
uint32_t wait_status = pfn_wgpuInstanceWaitAny(
|
|
506
661
|
inst, 1, &wait_info, (uint64_t)5000000000ULL);
|
|
507
662
|
|
|
508
|
-
if (wait_status !=
|
|
663
|
+
if (wait_status != WGPU_WAIT_STATUS_SUCCESS ||
|
|
664
|
+
result.status != WGPU_REQUEST_STATUS_SUCCESS || !result.device)
|
|
509
665
|
NAPI_THROW(env, "requestDevice failed");
|
|
510
666
|
|
|
511
667
|
return wrap_ptr(env, result.device);
|
|
@@ -520,6 +676,7 @@ static napi_value doe_device_release(napi_env env, napi_callback_info info) {
|
|
|
520
676
|
|
|
521
677
|
static napi_value doe_device_get_queue(napi_env env, napi_callback_info info) {
|
|
522
678
|
NAPI_ASSERT_ARGC(env, info, 1);
|
|
679
|
+
CHECK_LIB_LOADED(env);
|
|
523
680
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
524
681
|
if (!device) NAPI_THROW(env, "Invalid device");
|
|
525
682
|
WGPUQueue queue = pfn_wgpuDeviceGetQueue(device);
|
|
@@ -532,6 +689,7 @@ static napi_value doe_device_get_queue(napi_env env, napi_callback_info info) {
|
|
|
532
689
|
|
|
533
690
|
static napi_value doe_create_buffer(napi_env env, napi_callback_info info) {
|
|
534
691
|
NAPI_ASSERT_ARGC(env, info, 2);
|
|
692
|
+
CHECK_LIB_LOADED(env);
|
|
535
693
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
536
694
|
if (!device) NAPI_THROW(env, "Invalid device");
|
|
537
695
|
|
|
@@ -574,6 +732,7 @@ static void buffer_map_callback(uint32_t status, WGPUStringView message,
|
|
|
574
732
|
/* bufferMapSync(instance, buffer, mode, offset, size) */
|
|
575
733
|
static napi_value doe_buffer_map_sync(napi_env env, napi_callback_info info) {
|
|
576
734
|
NAPI_ASSERT_ARGC(env, info, 5);
|
|
735
|
+
CHECK_LIB_LOADED(env);
|
|
577
736
|
WGPUInstance inst = unwrap_ptr(env, _args[0]);
|
|
578
737
|
WGPUBuffer buf = unwrap_ptr(env, _args[1]);
|
|
579
738
|
uint32_t mode;
|
|
@@ -598,7 +757,8 @@ static napi_value doe_buffer_map_sync(napi_env env, napi_callback_info info) {
|
|
|
598
757
|
uint32_t wait_status = pfn_wgpuInstanceWaitAny(
|
|
599
758
|
inst, 1, &wait_info, (uint64_t)5000000000ULL);
|
|
600
759
|
|
|
601
|
-
if (wait_status !=
|
|
760
|
+
if (wait_status != WGPU_WAIT_STATUS_SUCCESS ||
|
|
761
|
+
result.status != WGPU_MAP_ASYNC_STATUS_SUCCESS)
|
|
602
762
|
NAPI_THROW(env, "bufferMapAsync failed");
|
|
603
763
|
|
|
604
764
|
napi_value ok;
|
|
@@ -609,6 +769,7 @@ static napi_value doe_buffer_map_sync(napi_env env, napi_callback_info info) {
|
|
|
609
769
|
/* bufferGetMappedRange(buffer, offset, size) → ArrayBuffer */
|
|
610
770
|
static napi_value doe_buffer_get_mapped_range(napi_env env, napi_callback_info info) {
|
|
611
771
|
NAPI_ASSERT_ARGC(env, info, 3);
|
|
772
|
+
CHECK_LIB_LOADED(env);
|
|
612
773
|
WGPUBuffer buf = unwrap_ptr(env, _args[0]);
|
|
613
774
|
int64_t offset_i, size_i;
|
|
614
775
|
napi_get_value_int64(env, _args[1], &offset_i);
|
|
@@ -631,6 +792,7 @@ static napi_value doe_buffer_get_mapped_range(napi_env env, napi_callback_info i
|
|
|
631
792
|
|
|
632
793
|
static napi_value doe_create_shader_module(napi_env env, napi_callback_info info) {
|
|
633
794
|
NAPI_ASSERT_ARGC(env, info, 2);
|
|
795
|
+
CHECK_LIB_LOADED(env);
|
|
634
796
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
635
797
|
if (!device) NAPI_THROW(env, "Invalid device");
|
|
636
798
|
|
|
@@ -641,7 +803,7 @@ static napi_value doe_create_shader_module(napi_env env, napi_callback_info info
|
|
|
641
803
|
napi_get_value_string_utf8(env, _args[1], code, code_len + 1, &code_len);
|
|
642
804
|
|
|
643
805
|
WGPUShaderSourceWGSL wgsl_source = {
|
|
644
|
-
.chain = { .next = NULL, .sType =
|
|
806
|
+
.chain = { .next = NULL, .sType = WGPU_STYPE_SHADER_SOURCE_WGSL },
|
|
645
807
|
.code = { .data = code, .length = code_len },
|
|
646
808
|
};
|
|
647
809
|
WGPUShaderModuleDescriptor desc = {
|
|
@@ -669,6 +831,7 @@ static napi_value doe_shader_module_release(napi_env env, napi_callback_info inf
|
|
|
669
831
|
|
|
670
832
|
static napi_value doe_create_compute_pipeline(napi_env env, napi_callback_info info) {
|
|
671
833
|
NAPI_ASSERT_ARGC(env, info, 4);
|
|
834
|
+
CHECK_LIB_LOADED(env);
|
|
672
835
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
673
836
|
WGPUShaderModule shader = unwrap_ptr(env, _args[1]);
|
|
674
837
|
if (!device || !shader) NAPI_THROW(env, "Invalid device or shader");
|
|
@@ -704,6 +867,19 @@ static napi_value doe_compute_pipeline_release(napi_env env, napi_callback_info
|
|
|
704
867
|
return NULL;
|
|
705
868
|
}
|
|
706
869
|
|
|
870
|
+
/* computePipelineGetBindGroupLayout(pipeline, groupIndex) → bindGroupLayout */
|
|
871
|
+
static napi_value doe_compute_pipeline_get_bind_group_layout(napi_env env, napi_callback_info info) {
|
|
872
|
+
NAPI_ASSERT_ARGC(env, info, 2);
|
|
873
|
+
CHECK_LIB_LOADED(env);
|
|
874
|
+
WGPUComputePipeline pipeline = unwrap_ptr(env, _args[0]);
|
|
875
|
+
if (!pipeline) NAPI_THROW(env, "Invalid pipeline");
|
|
876
|
+
uint32_t index;
|
|
877
|
+
napi_get_value_uint32(env, _args[1], &index);
|
|
878
|
+
WGPUBindGroupLayout layout = pfn_wgpuComputePipelineGetBindGroupLayout(pipeline, index);
|
|
879
|
+
if (!layout) NAPI_THROW(env, "getBindGroupLayout failed");
|
|
880
|
+
return wrap_ptr(env, layout);
|
|
881
|
+
}
|
|
882
|
+
|
|
707
883
|
/* ================================================================
|
|
708
884
|
* Bind Group Layout
|
|
709
885
|
* createBindGroupLayout(device, entries[])
|
|
@@ -725,6 +901,7 @@ static uint32_t buffer_binding_type_from_string(napi_env env, napi_value val) {
|
|
|
725
901
|
|
|
726
902
|
static napi_value doe_create_bind_group_layout(napi_env env, napi_callback_info info) {
|
|
727
903
|
NAPI_ASSERT_ARGC(env, info, 2);
|
|
904
|
+
CHECK_LIB_LOADED(env);
|
|
728
905
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
729
906
|
if (!device) NAPI_THROW(env, "Invalid device");
|
|
730
907
|
|
|
@@ -787,6 +964,7 @@ static napi_value doe_bind_group_layout_release(napi_env env, napi_callback_info
|
|
|
787
964
|
|
|
788
965
|
static napi_value doe_create_bind_group(napi_env env, napi_callback_info info) {
|
|
789
966
|
NAPI_ASSERT_ARGC(env, info, 3);
|
|
967
|
+
CHECK_LIB_LOADED(env);
|
|
790
968
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
791
969
|
WGPUBindGroupLayout layout = unwrap_ptr(env, _args[1]);
|
|
792
970
|
if (!device || !layout) NAPI_THROW(env, "Invalid device or layout");
|
|
@@ -842,6 +1020,7 @@ static napi_value doe_bind_group_release(napi_env env, napi_callback_info info)
|
|
|
842
1020
|
|
|
843
1021
|
static napi_value doe_create_pipeline_layout(napi_env env, napi_callback_info info) {
|
|
844
1022
|
NAPI_ASSERT_ARGC(env, info, 2);
|
|
1023
|
+
CHECK_LIB_LOADED(env);
|
|
845
1024
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
846
1025
|
if (!device) NAPI_THROW(env, "Invalid device");
|
|
847
1026
|
|
|
@@ -883,6 +1062,7 @@ static napi_value doe_pipeline_layout_release(napi_env env, napi_callback_info i
|
|
|
883
1062
|
|
|
884
1063
|
static napi_value doe_create_command_encoder(napi_env env, napi_callback_info info) {
|
|
885
1064
|
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1065
|
+
CHECK_LIB_LOADED(env);
|
|
886
1066
|
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
887
1067
|
if (!device) NAPI_THROW(env, "Invalid device");
|
|
888
1068
|
|
|
@@ -904,6 +1084,7 @@ static napi_value doe_command_encoder_release(napi_env env, napi_callback_info i
|
|
|
904
1084
|
|
|
905
1085
|
static napi_value doe_command_encoder_copy_buffer_to_buffer(napi_env env, napi_callback_info info) {
|
|
906
1086
|
NAPI_ASSERT_ARGC(env, info, 6);
|
|
1087
|
+
CHECK_LIB_LOADED(env);
|
|
907
1088
|
WGPUCommandEncoder enc = unwrap_ptr(env, _args[0]);
|
|
908
1089
|
WGPUBuffer src = unwrap_ptr(env, _args[1]);
|
|
909
1090
|
int64_t src_offset; napi_get_value_int64(env, _args[2], &src_offset);
|
|
@@ -918,6 +1099,7 @@ static napi_value doe_command_encoder_copy_buffer_to_buffer(napi_env env, napi_c
|
|
|
918
1099
|
|
|
919
1100
|
static napi_value doe_command_encoder_finish(napi_env env, napi_callback_info info) {
|
|
920
1101
|
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1102
|
+
CHECK_LIB_LOADED(env);
|
|
921
1103
|
WGPUCommandEncoder enc = unwrap_ptr(env, _args[0]);
|
|
922
1104
|
if (!enc) NAPI_THROW(env, "Invalid encoder");
|
|
923
1105
|
|
|
@@ -943,6 +1125,7 @@ static napi_value doe_command_buffer_release(napi_env env, napi_callback_info in
|
|
|
943
1125
|
|
|
944
1126
|
static napi_value doe_begin_compute_pass(napi_env env, napi_callback_info info) {
|
|
945
1127
|
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1128
|
+
CHECK_LIB_LOADED(env);
|
|
946
1129
|
WGPUCommandEncoder enc = unwrap_ptr(env, _args[0]);
|
|
947
1130
|
if (!enc) NAPI_THROW(env, "Invalid encoder");
|
|
948
1131
|
|
|
@@ -983,6 +1166,17 @@ static napi_value doe_compute_pass_dispatch(napi_env env, napi_callback_info inf
|
|
|
983
1166
|
return NULL;
|
|
984
1167
|
}
|
|
985
1168
|
|
|
1169
|
+
/* computePassDispatchWorkgroupsIndirect(pass, buffer, offset) */
|
|
1170
|
+
static napi_value doe_compute_pass_dispatch_indirect(napi_env env, napi_callback_info info) {
|
|
1171
|
+
NAPI_ASSERT_ARGC(env, info, 3);
|
|
1172
|
+
WGPUComputePassEncoder pass = unwrap_ptr(env, _args[0]);
|
|
1173
|
+
WGPUBuffer buffer = unwrap_ptr(env, _args[1]);
|
|
1174
|
+
int64_t offset;
|
|
1175
|
+
napi_get_value_int64(env, _args[2], &offset);
|
|
1176
|
+
pfn_wgpuComputePassEncoderDispatchWorkgroupsIndirect(pass, buffer, (uint64_t)offset);
|
|
1177
|
+
return NULL;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
986
1180
|
static napi_value doe_compute_pass_end(napi_env env, napi_callback_info info) {
|
|
987
1181
|
NAPI_ASSERT_ARGC(env, info, 1);
|
|
988
1182
|
pfn_wgpuComputePassEncoderEnd(unwrap_ptr(env, _args[0]));
|
|
@@ -1002,6 +1196,7 @@ static napi_value doe_compute_pass_release(napi_env env, napi_callback_info info
|
|
|
1002
1196
|
|
|
1003
1197
|
static napi_value doe_queue_submit(napi_env env, napi_callback_info info) {
|
|
1004
1198
|
NAPI_ASSERT_ARGC(env, info, 2);
|
|
1199
|
+
CHECK_LIB_LOADED(env);
|
|
1005
1200
|
WGPUQueue queue = unwrap_ptr(env, _args[0]);
|
|
1006
1201
|
if (!queue) NAPI_THROW(env, "Invalid queue");
|
|
1007
1202
|
|
|
@@ -1024,6 +1219,7 @@ static napi_value doe_queue_submit(napi_env env, napi_callback_info info) {
|
|
|
1024
1219
|
/* queueWriteBuffer(queue, buffer, offset, typedArray) */
|
|
1025
1220
|
static napi_value doe_queue_write_buffer(napi_env env, napi_callback_info info) {
|
|
1026
1221
|
NAPI_ASSERT_ARGC(env, info, 4);
|
|
1222
|
+
CHECK_LIB_LOADED(env);
|
|
1027
1223
|
WGPUQueue queue = unwrap_ptr(env, _args[0]);
|
|
1028
1224
|
WGPUBuffer buf = unwrap_ptr(env, _args[1]);
|
|
1029
1225
|
int64_t offset; napi_get_value_int64(env, _args[2], &offset);
|
|
@@ -1038,10 +1234,16 @@ static napi_value doe_queue_write_buffer(napi_env env, napi_callback_info info)
|
|
|
1038
1234
|
napi_value ab;
|
|
1039
1235
|
size_t byte_offset;
|
|
1040
1236
|
napi_get_typedarray_info(env, _args[3], &ta_type, &ta_length, &data, &ab, &byte_offset);
|
|
1041
|
-
/*
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1237
|
+
/* Use typed array element count * element size for correct byte length. */
|
|
1238
|
+
size_t elem_size = 1;
|
|
1239
|
+
switch (ta_type) {
|
|
1240
|
+
case napi_int8_array: case napi_uint8_array: case napi_uint8_clamped_array: elem_size = 1; break;
|
|
1241
|
+
case napi_int16_array: case napi_uint16_array: elem_size = 2; break;
|
|
1242
|
+
case napi_int32_array: case napi_uint32_array: case napi_float32_array: elem_size = 4; break;
|
|
1243
|
+
case napi_float64_array: case napi_bigint64_array: case napi_biguint64_array: elem_size = 8; break;
|
|
1244
|
+
default: elem_size = 1; break;
|
|
1245
|
+
}
|
|
1246
|
+
byte_length = ta_length * elem_size;
|
|
1045
1247
|
} else {
|
|
1046
1248
|
bool is_ab = false;
|
|
1047
1249
|
napi_is_arraybuffer(env, _args[3], &is_ab);
|
|
@@ -1062,6 +1264,15 @@ static napi_value doe_queue_write_buffer(napi_env env, napi_callback_info info)
|
|
|
1062
1264
|
return NULL;
|
|
1063
1265
|
}
|
|
1064
1266
|
|
|
1267
|
+
/* queueFlush(queue) — wait for all pending GPU work to complete. */
|
|
1268
|
+
static napi_value doe_queue_flush(napi_env env, napi_callback_info info) {
|
|
1269
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1270
|
+
CHECK_LIB_LOADED(env);
|
|
1271
|
+
WGPUQueue queue = unwrap_ptr(env, _args[0]);
|
|
1272
|
+
if (queue && pfn_doeNativeQueueFlush) pfn_doeNativeQueueFlush(queue);
|
|
1273
|
+
return NULL;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1065
1276
|
static napi_value doe_queue_release(napi_env env, napi_callback_info info) {
|
|
1066
1277
|
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1067
1278
|
void* p = unwrap_ptr(env, _args[0]);
|
|
@@ -1069,6 +1280,330 @@ static napi_value doe_queue_release(napi_env env, napi_callback_info info) {
|
|
|
1069
1280
|
return NULL;
|
|
1070
1281
|
}
|
|
1071
1282
|
|
|
1283
|
+
/* ================================================================
|
|
1284
|
+
* Texture
|
|
1285
|
+
* createTexture(device, { format, width, height, usage, mipLevelCount?, dimension? })
|
|
1286
|
+
* ================================================================ */
|
|
1287
|
+
|
|
1288
|
+
/* WebGPU texture format string → numeric value mapping. */
|
|
1289
|
+
static uint32_t texture_format_from_string(napi_env env, napi_value val) {
|
|
1290
|
+
napi_valuetype vt;
|
|
1291
|
+
napi_typeof(env, val, &vt);
|
|
1292
|
+
if (vt == napi_number) {
|
|
1293
|
+
uint32_t out = 0;
|
|
1294
|
+
napi_get_value_uint32(env, val, &out);
|
|
1295
|
+
return out;
|
|
1296
|
+
}
|
|
1297
|
+
if (vt != napi_string) return 0x00000016; /* rgba8unorm */
|
|
1298
|
+
char buf[32] = {0};
|
|
1299
|
+
size_t len = 0;
|
|
1300
|
+
napi_get_value_string_utf8(env, val, buf, sizeof(buf), &len);
|
|
1301
|
+
if (strcmp(buf, "rgba8unorm") == 0) return 0x00000016;
|
|
1302
|
+
if (strcmp(buf, "rgba8unorm-srgb") == 0) return 0x00000017;
|
|
1303
|
+
if (strcmp(buf, "bgra8unorm") == 0) return 0x0000001B;
|
|
1304
|
+
if (strcmp(buf, "bgra8unorm-srgb") == 0) return 0x0000001C;
|
|
1305
|
+
if (strcmp(buf, "depth32float") == 0) return 0x00000030;
|
|
1306
|
+
return 0x00000016;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
static napi_value doe_create_texture(napi_env env, napi_callback_info info) {
|
|
1310
|
+
NAPI_ASSERT_ARGC(env, info, 2);
|
|
1311
|
+
CHECK_LIB_LOADED(env);
|
|
1312
|
+
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
1313
|
+
if (!device) NAPI_THROW(env, "Invalid device");
|
|
1314
|
+
|
|
1315
|
+
WGPUTextureDescriptor desc;
|
|
1316
|
+
memset(&desc, 0, sizeof(desc));
|
|
1317
|
+
desc.format = texture_format_from_string(env, get_prop(env, _args[1], "format"));
|
|
1318
|
+
desc.size.width = get_uint32_prop(env, _args[1], "width");
|
|
1319
|
+
desc.size.height = get_uint32_prop(env, _args[1], "height");
|
|
1320
|
+
desc.size.depthOrArrayLayers = 1;
|
|
1321
|
+
if (has_prop(env, _args[1], "depthOrArrayLayers"))
|
|
1322
|
+
desc.size.depthOrArrayLayers = get_uint32_prop(env, _args[1], "depthOrArrayLayers");
|
|
1323
|
+
desc.usage = (uint64_t)get_int64_prop(env, _args[1], "usage");
|
|
1324
|
+
desc.mipLevelCount = 1;
|
|
1325
|
+
if (has_prop(env, _args[1], "mipLevelCount"))
|
|
1326
|
+
desc.mipLevelCount = get_uint32_prop(env, _args[1], "mipLevelCount");
|
|
1327
|
+
desc.sampleCount = 1;
|
|
1328
|
+
desc.dimension = 1; /* 2D */
|
|
1329
|
+
|
|
1330
|
+
WGPUTexture tex = pfn_wgpuDeviceCreateTexture(device, &desc);
|
|
1331
|
+
if (!tex) NAPI_THROW(env, "createTexture failed");
|
|
1332
|
+
return wrap_ptr(env, tex);
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
static napi_value doe_texture_release(napi_env env, napi_callback_info info) {
|
|
1336
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1337
|
+
void* p = unwrap_ptr(env, _args[0]);
|
|
1338
|
+
if (p) pfn_wgpuTextureRelease(p);
|
|
1339
|
+
return NULL;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
/* textureCreateView(texture) */
|
|
1343
|
+
static napi_value doe_texture_create_view(napi_env env, napi_callback_info info) {
|
|
1344
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1345
|
+
CHECK_LIB_LOADED(env);
|
|
1346
|
+
WGPUTexture tex = unwrap_ptr(env, _args[0]);
|
|
1347
|
+
if (!tex) NAPI_THROW(env, "Invalid texture");
|
|
1348
|
+
WGPUTextureView view = pfn_wgpuTextureCreateView(tex, NULL);
|
|
1349
|
+
if (!view) NAPI_THROW(env, "textureCreateView failed");
|
|
1350
|
+
return wrap_ptr(env, view);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
static napi_value doe_texture_view_release(napi_env env, napi_callback_info info) {
|
|
1354
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1355
|
+
void* p = unwrap_ptr(env, _args[0]);
|
|
1356
|
+
if (p) pfn_wgpuTextureViewRelease(p);
|
|
1357
|
+
return NULL;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
/* ================================================================
|
|
1361
|
+
* Sampler
|
|
1362
|
+
* createSampler(device, { magFilter?, minFilter?, mipmapFilter?,
|
|
1363
|
+
* addressModeU?, addressModeV?, addressModeW?, lodMinClamp?, lodMaxClamp?, maxAnisotropy? })
|
|
1364
|
+
* ================================================================ */
|
|
1365
|
+
|
|
1366
|
+
static uint32_t filter_mode_from_string(napi_env env, napi_value val) {
|
|
1367
|
+
napi_valuetype vt;
|
|
1368
|
+
napi_typeof(env, val, &vt);
|
|
1369
|
+
if (vt != napi_string) return 0; /* nearest */
|
|
1370
|
+
char buf[16] = {0};
|
|
1371
|
+
size_t len = 0;
|
|
1372
|
+
napi_get_value_string_utf8(env, val, buf, sizeof(buf), &len);
|
|
1373
|
+
if (strcmp(buf, "linear") == 0) return 1;
|
|
1374
|
+
return 0; /* nearest */
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
static uint32_t address_mode_from_string(napi_env env, napi_value val) {
|
|
1378
|
+
napi_valuetype vt;
|
|
1379
|
+
napi_typeof(env, val, &vt);
|
|
1380
|
+
if (vt != napi_string) return 1; /* clamp-to-edge */
|
|
1381
|
+
char buf[24] = {0};
|
|
1382
|
+
size_t len = 0;
|
|
1383
|
+
napi_get_value_string_utf8(env, val, buf, sizeof(buf), &len);
|
|
1384
|
+
if (strcmp(buf, "repeat") == 0) return 2;
|
|
1385
|
+
if (strcmp(buf, "mirror-repeat") == 0) return 3;
|
|
1386
|
+
return 1; /* clamp-to-edge */
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
static napi_value doe_create_sampler(napi_env env, napi_callback_info info) {
|
|
1390
|
+
NAPI_ASSERT_ARGC(env, info, 2);
|
|
1391
|
+
CHECK_LIB_LOADED(env);
|
|
1392
|
+
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
1393
|
+
if (!device) NAPI_THROW(env, "Invalid device");
|
|
1394
|
+
|
|
1395
|
+
WGPUSamplerDescriptor desc;
|
|
1396
|
+
memset(&desc, 0, sizeof(desc));
|
|
1397
|
+
desc.lodMaxClamp = 32.0f;
|
|
1398
|
+
desc.maxAnisotropy = 1;
|
|
1399
|
+
|
|
1400
|
+
napi_valuetype desc_type;
|
|
1401
|
+
napi_typeof(env, _args[1], &desc_type);
|
|
1402
|
+
if (desc_type == napi_object) {
|
|
1403
|
+
if (has_prop(env, _args[1], "magFilter"))
|
|
1404
|
+
desc.magFilter = filter_mode_from_string(env, get_prop(env, _args[1], "magFilter"));
|
|
1405
|
+
if (has_prop(env, _args[1], "minFilter"))
|
|
1406
|
+
desc.minFilter = filter_mode_from_string(env, get_prop(env, _args[1], "minFilter"));
|
|
1407
|
+
if (has_prop(env, _args[1], "mipmapFilter"))
|
|
1408
|
+
desc.mipmapFilter = filter_mode_from_string(env, get_prop(env, _args[1], "mipmapFilter"));
|
|
1409
|
+
if (has_prop(env, _args[1], "addressModeU"))
|
|
1410
|
+
desc.addressModeU = address_mode_from_string(env, get_prop(env, _args[1], "addressModeU"));
|
|
1411
|
+
if (has_prop(env, _args[1], "addressModeV"))
|
|
1412
|
+
desc.addressModeV = address_mode_from_string(env, get_prop(env, _args[1], "addressModeV"));
|
|
1413
|
+
if (has_prop(env, _args[1], "addressModeW"))
|
|
1414
|
+
desc.addressModeW = address_mode_from_string(env, get_prop(env, _args[1], "addressModeW"));
|
|
1415
|
+
if (has_prop(env, _args[1], "maxAnisotropy"))
|
|
1416
|
+
desc.maxAnisotropy = (uint16_t)get_uint32_prop(env, _args[1], "maxAnisotropy");
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
WGPUSampler sampler = pfn_wgpuDeviceCreateSampler(device, &desc);
|
|
1420
|
+
if (!sampler) NAPI_THROW(env, "createSampler failed");
|
|
1421
|
+
return wrap_ptr(env, sampler);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
static napi_value doe_sampler_release(napi_env env, napi_callback_info info) {
|
|
1425
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1426
|
+
void* p = unwrap_ptr(env, _args[0]);
|
|
1427
|
+
if (p) pfn_wgpuSamplerRelease(p);
|
|
1428
|
+
return NULL;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
/* ================================================================
|
|
1432
|
+
* Render Pipeline (noop stub — uses built-in Metal shaders)
|
|
1433
|
+
* createRenderPipeline(device)
|
|
1434
|
+
* ================================================================ */
|
|
1435
|
+
|
|
1436
|
+
static napi_value doe_create_render_pipeline(napi_env env, napi_callback_info info) {
|
|
1437
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1438
|
+
CHECK_LIB_LOADED(env);
|
|
1439
|
+
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
1440
|
+
if (!device) NAPI_THROW(env, "Invalid device");
|
|
1441
|
+
WGPURenderPipeline rp = pfn_wgpuDeviceCreateRenderPipeline(device, NULL);
|
|
1442
|
+
if (!rp) NAPI_THROW(env, "createRenderPipeline failed");
|
|
1443
|
+
return wrap_ptr(env, rp);
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
static napi_value doe_render_pipeline_release(napi_env env, napi_callback_info info) {
|
|
1447
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1448
|
+
void* p = unwrap_ptr(env, _args[0]);
|
|
1449
|
+
if (p) pfn_wgpuRenderPipelineRelease(p);
|
|
1450
|
+
return NULL;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
/* ================================================================
|
|
1454
|
+
* Render Pass
|
|
1455
|
+
* beginRenderPass(encoder, colorAttachments[])
|
|
1456
|
+
* ================================================================ */
|
|
1457
|
+
|
|
1458
|
+
static napi_value doe_begin_render_pass(napi_env env, napi_callback_info info) {
|
|
1459
|
+
NAPI_ASSERT_ARGC(env, info, 2);
|
|
1460
|
+
CHECK_LIB_LOADED(env);
|
|
1461
|
+
WGPUCommandEncoder enc = unwrap_ptr(env, _args[0]);
|
|
1462
|
+
if (!enc) NAPI_THROW(env, "Invalid encoder");
|
|
1463
|
+
|
|
1464
|
+
/* _args[1] is array of color attachments */
|
|
1465
|
+
uint32_t att_count = 0;
|
|
1466
|
+
napi_get_array_length(env, _args[1], &att_count);
|
|
1467
|
+
if (att_count == 0) NAPI_THROW(env, "beginRenderPass: need at least one color attachment");
|
|
1468
|
+
|
|
1469
|
+
WGPURenderPassColorAttachment* atts = (WGPURenderPassColorAttachment*)calloc(
|
|
1470
|
+
att_count, sizeof(WGPURenderPassColorAttachment));
|
|
1471
|
+
for (uint32_t i = 0; i < att_count; i++) {
|
|
1472
|
+
napi_value elem;
|
|
1473
|
+
napi_get_element(env, _args[1], i, &elem);
|
|
1474
|
+
atts[i].view = unwrap_ptr(env, get_prop(env, elem, "view"));
|
|
1475
|
+
atts[i].loadOp = 1; /* clear */
|
|
1476
|
+
atts[i].storeOp = 1; /* store */
|
|
1477
|
+
if (has_prop(env, elem, "clearValue") && prop_type(env, elem, "clearValue") == napi_object) {
|
|
1478
|
+
napi_value cv = get_prop(env, elem, "clearValue");
|
|
1479
|
+
double r = 0, g = 0, b = 0, a = 1;
|
|
1480
|
+
napi_value tmp;
|
|
1481
|
+
if (napi_get_named_property(env, cv, "r", &tmp) == napi_ok)
|
|
1482
|
+
napi_get_value_double(env, tmp, &r);
|
|
1483
|
+
if (napi_get_named_property(env, cv, "g", &tmp) == napi_ok)
|
|
1484
|
+
napi_get_value_double(env, tmp, &g);
|
|
1485
|
+
if (napi_get_named_property(env, cv, "b", &tmp) == napi_ok)
|
|
1486
|
+
napi_get_value_double(env, tmp, &b);
|
|
1487
|
+
if (napi_get_named_property(env, cv, "a", &tmp) == napi_ok)
|
|
1488
|
+
napi_get_value_double(env, tmp, &a);
|
|
1489
|
+
atts[i].clearValue = (WGPUColor){ r, g, b, a };
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
WGPURenderPassDescriptor desc;
|
|
1494
|
+
memset(&desc, 0, sizeof(desc));
|
|
1495
|
+
desc.colorAttachmentCount = att_count;
|
|
1496
|
+
desc.colorAttachments = atts;
|
|
1497
|
+
|
|
1498
|
+
WGPURenderPassEncoder pass = pfn_wgpuCommandEncoderBeginRenderPass(enc, &desc);
|
|
1499
|
+
free(atts);
|
|
1500
|
+
if (!pass) NAPI_THROW(env, "beginRenderPass failed");
|
|
1501
|
+
return wrap_ptr(env, pass);
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
static napi_value doe_render_pass_set_pipeline(napi_env env, napi_callback_info info) {
|
|
1505
|
+
NAPI_ASSERT_ARGC(env, info, 2);
|
|
1506
|
+
pfn_wgpuRenderPassEncoderSetPipeline(
|
|
1507
|
+
unwrap_ptr(env, _args[0]), unwrap_ptr(env, _args[1]));
|
|
1508
|
+
return NULL;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
/* renderPassDraw(pass, vertexCount, instanceCount, firstVertex, firstInstance) */
|
|
1512
|
+
static napi_value doe_render_pass_draw(napi_env env, napi_callback_info info) {
|
|
1513
|
+
NAPI_ASSERT_ARGC(env, info, 5);
|
|
1514
|
+
WGPURenderPassEncoder pass = unwrap_ptr(env, _args[0]);
|
|
1515
|
+
uint32_t vc, ic, fv, fi;
|
|
1516
|
+
napi_get_value_uint32(env, _args[1], &vc);
|
|
1517
|
+
napi_get_value_uint32(env, _args[2], &ic);
|
|
1518
|
+
napi_get_value_uint32(env, _args[3], &fv);
|
|
1519
|
+
napi_get_value_uint32(env, _args[4], &fi);
|
|
1520
|
+
pfn_wgpuRenderPassEncoderDraw(pass, vc, ic, fv, fi);
|
|
1521
|
+
return NULL;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
static napi_value doe_render_pass_end(napi_env env, napi_callback_info info) {
|
|
1525
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1526
|
+
pfn_wgpuRenderPassEncoderEnd(unwrap_ptr(env, _args[0]));
|
|
1527
|
+
return NULL;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
static napi_value doe_render_pass_release(napi_env env, napi_callback_info info) {
|
|
1531
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1532
|
+
void* p = unwrap_ptr(env, _args[0]);
|
|
1533
|
+
if (p) pfn_wgpuRenderPassEncoderRelease(p);
|
|
1534
|
+
return NULL;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
/* ================================================================
|
|
1538
|
+
* Device capabilities: limits, features
|
|
1539
|
+
* ================================================================ */
|
|
1540
|
+
|
|
1541
|
+
static napi_value doe_device_get_limits(napi_env env, napi_callback_info info) {
|
|
1542
|
+
NAPI_ASSERT_ARGC(env, info, 1);
|
|
1543
|
+
CHECK_LIB_LOADED(env);
|
|
1544
|
+
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
1545
|
+
if (!device) NAPI_THROW(env, "deviceGetLimits: null device");
|
|
1546
|
+
|
|
1547
|
+
WGPULimits limits;
|
|
1548
|
+
memset(&limits, 0, sizeof(limits));
|
|
1549
|
+
pfn_wgpuDeviceGetLimits(device, &limits);
|
|
1550
|
+
|
|
1551
|
+
napi_value obj;
|
|
1552
|
+
napi_create_object(env, &obj);
|
|
1553
|
+
|
|
1554
|
+
#define SET_U32(name) do { napi_value v; napi_create_uint32(env, limits.name, &v); napi_set_named_property(env, obj, #name, v); } while(0)
|
|
1555
|
+
#define SET_U64(name) do { napi_value v; napi_create_double(env, (double)limits.name, &v); napi_set_named_property(env, obj, #name, v); } while(0)
|
|
1556
|
+
|
|
1557
|
+
SET_U32(maxTextureDimension1D);
|
|
1558
|
+
SET_U32(maxTextureDimension2D);
|
|
1559
|
+
SET_U32(maxTextureDimension3D);
|
|
1560
|
+
SET_U32(maxTextureArrayLayers);
|
|
1561
|
+
SET_U32(maxBindGroups);
|
|
1562
|
+
SET_U32(maxBindGroupsPlusVertexBuffers);
|
|
1563
|
+
SET_U32(maxBindingsPerBindGroup);
|
|
1564
|
+
SET_U32(maxDynamicUniformBuffersPerPipelineLayout);
|
|
1565
|
+
SET_U32(maxDynamicStorageBuffersPerPipelineLayout);
|
|
1566
|
+
SET_U32(maxSampledTexturesPerShaderStage);
|
|
1567
|
+
SET_U32(maxSamplersPerShaderStage);
|
|
1568
|
+
SET_U32(maxStorageBuffersPerShaderStage);
|
|
1569
|
+
SET_U32(maxStorageTexturesPerShaderStage);
|
|
1570
|
+
SET_U32(maxUniformBuffersPerShaderStage);
|
|
1571
|
+
SET_U64(maxUniformBufferBindingSize);
|
|
1572
|
+
SET_U64(maxStorageBufferBindingSize);
|
|
1573
|
+
SET_U32(minUniformBufferOffsetAlignment);
|
|
1574
|
+
SET_U32(minStorageBufferOffsetAlignment);
|
|
1575
|
+
SET_U32(maxVertexBuffers);
|
|
1576
|
+
SET_U64(maxBufferSize);
|
|
1577
|
+
SET_U32(maxVertexAttributes);
|
|
1578
|
+
SET_U32(maxVertexBufferArrayStride);
|
|
1579
|
+
SET_U32(maxInterStageShaderVariables);
|
|
1580
|
+
SET_U32(maxColorAttachments);
|
|
1581
|
+
SET_U32(maxColorAttachmentBytesPerSample);
|
|
1582
|
+
SET_U32(maxComputeWorkgroupStorageSize);
|
|
1583
|
+
SET_U32(maxComputeInvocationsPerWorkgroup);
|
|
1584
|
+
SET_U32(maxComputeWorkgroupSizeX);
|
|
1585
|
+
SET_U32(maxComputeWorkgroupSizeY);
|
|
1586
|
+
SET_U32(maxComputeWorkgroupSizeZ);
|
|
1587
|
+
SET_U32(maxComputeWorkgroupsPerDimension);
|
|
1588
|
+
|
|
1589
|
+
#undef SET_U32
|
|
1590
|
+
#undef SET_U64
|
|
1591
|
+
|
|
1592
|
+
return obj;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
static napi_value doe_device_has_feature(napi_env env, napi_callback_info info) {
|
|
1596
|
+
NAPI_ASSERT_ARGC(env, info, 2);
|
|
1597
|
+
CHECK_LIB_LOADED(env);
|
|
1598
|
+
WGPUDevice device = unwrap_ptr(env, _args[0]);
|
|
1599
|
+
uint32_t feature;
|
|
1600
|
+
napi_get_value_uint32(env, _args[1], &feature);
|
|
1601
|
+
uint32_t result = pfn_wgpuDeviceHasFeature(device, feature);
|
|
1602
|
+
napi_value ret;
|
|
1603
|
+
napi_get_boolean(env, result != 0, &ret);
|
|
1604
|
+
return ret;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1072
1607
|
/* ================================================================
|
|
1073
1608
|
* Module initialization
|
|
1074
1609
|
* ================================================================ */
|
|
@@ -1094,6 +1629,7 @@ static napi_value doe_module_init(napi_env env, napi_value exports) {
|
|
|
1094
1629
|
EXPORT_FN("shaderModuleRelease", doe_shader_module_release),
|
|
1095
1630
|
EXPORT_FN("createComputePipeline", doe_create_compute_pipeline),
|
|
1096
1631
|
EXPORT_FN("computePipelineRelease", doe_compute_pipeline_release),
|
|
1632
|
+
EXPORT_FN("computePipelineGetBindGroupLayout", doe_compute_pipeline_get_bind_group_layout),
|
|
1097
1633
|
EXPORT_FN("createBindGroupLayout", doe_create_bind_group_layout),
|
|
1098
1634
|
EXPORT_FN("bindGroupLayoutRelease", doe_bind_group_layout_release),
|
|
1099
1635
|
EXPORT_FN("createBindGroup", doe_create_bind_group),
|
|
@@ -1109,11 +1645,28 @@ static napi_value doe_module_init(napi_env env, napi_value exports) {
|
|
|
1109
1645
|
EXPORT_FN("computePassSetPipeline", doe_compute_pass_set_pipeline),
|
|
1110
1646
|
EXPORT_FN("computePassSetBindGroup", doe_compute_pass_set_bind_group),
|
|
1111
1647
|
EXPORT_FN("computePassDispatchWorkgroups", doe_compute_pass_dispatch),
|
|
1648
|
+
EXPORT_FN("computePassDispatchWorkgroupsIndirect", doe_compute_pass_dispatch_indirect),
|
|
1112
1649
|
EXPORT_FN("computePassEnd", doe_compute_pass_end),
|
|
1113
1650
|
EXPORT_FN("computePassRelease", doe_compute_pass_release),
|
|
1114
1651
|
EXPORT_FN("queueSubmit", doe_queue_submit),
|
|
1115
1652
|
EXPORT_FN("queueWriteBuffer", doe_queue_write_buffer),
|
|
1653
|
+
EXPORT_FN("queueFlush", doe_queue_flush),
|
|
1116
1654
|
EXPORT_FN("queueRelease", doe_queue_release),
|
|
1655
|
+
EXPORT_FN("createTexture", doe_create_texture),
|
|
1656
|
+
EXPORT_FN("textureRelease", doe_texture_release),
|
|
1657
|
+
EXPORT_FN("textureCreateView", doe_texture_create_view),
|
|
1658
|
+
EXPORT_FN("textureViewRelease", doe_texture_view_release),
|
|
1659
|
+
EXPORT_FN("createSampler", doe_create_sampler),
|
|
1660
|
+
EXPORT_FN("samplerRelease", doe_sampler_release),
|
|
1661
|
+
EXPORT_FN("createRenderPipeline", doe_create_render_pipeline),
|
|
1662
|
+
EXPORT_FN("renderPipelineRelease", doe_render_pipeline_release),
|
|
1663
|
+
EXPORT_FN("beginRenderPass", doe_begin_render_pass),
|
|
1664
|
+
EXPORT_FN("renderPassSetPipeline", doe_render_pass_set_pipeline),
|
|
1665
|
+
EXPORT_FN("renderPassDraw", doe_render_pass_draw),
|
|
1666
|
+
EXPORT_FN("renderPassEnd", doe_render_pass_end),
|
|
1667
|
+
EXPORT_FN("renderPassRelease", doe_render_pass_release),
|
|
1668
|
+
EXPORT_FN("deviceGetLimits", doe_device_get_limits),
|
|
1669
|
+
EXPORT_FN("deviceHasFeature", doe_device_has_feature),
|
|
1117
1670
|
};
|
|
1118
1671
|
|
|
1119
1672
|
size_t count = sizeof(descriptors) / sizeof(descriptors[0]);
|