blob: b467d15b1a3154527a3116de238f4daa6238e87b [file] [log] [blame]
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001/**
2 * @license
3 * Copyright 2019 The Emscripten Authors
4 * SPDX-License-Identifier: MIT
5 */
6
7/*
Kai Ninomiya11784002024-07-03 19:46:03 +00008 * Dawn's fork of Emscripten's WebGPU bindings. This will be contributed back to
9 * Emscripten after reaching approximately webgpu.h "1.0".
Kai Ninomiyaace5a582024-07-02 20:52:25 +000010 *
Kai Ninomiya11784002024-07-03 19:46:03 +000011 * IMPORTANT: See //src/emdawnwebgpu/README.md for info on how to use this.
Kai Ninomiyaace5a582024-07-02 20:52:25 +000012 */
13
14{{{
Kai Ninomiya11784002024-07-03 19:46:03 +000015 if (USE_WEBGPU || !__HAVE_EMDAWNWEBGPU_STRUCT_INFO || !__HAVE_EMDAWNWEBGPU_ENUM_TABLES || !__HAVE_EMDAWNWEBGPU_SIG_INFO) {
16 throw new Error("To use Dawn's library_webgpu.js, disable -sUSE_WEBGPU and first include Dawn's library_webgpu_struct_info.js and library_webgpu_enum_tables.js (before library_webgpu.js)");
17 }
18
Kai Ninomiyaace5a582024-07-02 20:52:25 +000019 // Helper functions for code generation
20 globalThis.gpu = {
Kai Ninomiyaace5a582024-07-02 20:52:25 +000021 convertSentinelToUndefined: function(name) {
22 return `if (${name} == -1) ${name} = undefined;`;
23 },
24
25 makeGetBool: function(struct, offset) {
26 return `!!(${makeGetValue(struct, offset, 'u32')})`;
27 },
28 makeGetU32: function(struct, offset) {
29 return makeGetValue(struct, offset, 'u32');
30 },
31 makeGetU64: function(struct, offset) {
32 var l = makeGetValue(struct, offset, 'u32');
33 var h = makeGetValue(`(${struct} + 4)`, offset, 'u32')
34 return `${h} * 0x100000000 + ${l}`
35 },
36 makeCheck: function(str) {
37 if (!ASSERTIONS) return '';
38 return `assert(${str});`;
39 },
40 makeCheckDefined: function(name) {
41 return this.makeCheck(`typeof ${name} != "undefined"`);
42 },
43 makeCheckDescriptor: function(descriptor) {
44 // Assert descriptor is non-null, then that its nextInChain is null.
45 // For descriptors that aren't the first in the chain (e.g
Lokbondo Kungb339ed42024-09-06 02:49:19 +000046 // ShaderSourceSPIRV), there is no .nextInChain pointer, but
Kai Ninomiyaace5a582024-07-02 20:52:25 +000047 // instead a ChainedStruct object: .chain. So we need to check if
48 // .chain.nextInChain is null. As long as nextInChain and chain are always
49 // the first member in the struct, descriptor.nextInChain and
50 // descriptor.chain.nextInChain should have the same offset (0) to the
51 // descriptor pointer and we can check it to be null.
52 var OffsetOfNextInChainMember = 0;
53 return this.makeCheck(descriptor) + this.makeCheck(makeGetValue(descriptor, OffsetOfNextInChainMember, '*') + ' === 0');
54 },
55
56 // Compile-time table for enum integer values used with templating.
57 // Must be in sync with webgpu.h.
58 // TODO: Generate this to keep it in sync with webgpu.h
59 COPY_STRIDE_UNDEFINED: 0xFFFFFFFF,
60 LIMIT_U32_UNDEFINED: 0xFFFFFFFF,
61 MIP_LEVEL_COUNT_UNDEFINED: 0xFFFFFFFF,
62 ARRAY_LAYER_COUNT_UNDEFINED: 0xFFFFFFFF,
Kai Ninomiya11784002024-07-03 19:46:03 +000063 ...WEBGPU_ENUM_CONSTANT_TABLES,
Kai Ninomiyaace5a582024-07-02 20:52:25 +000064 };
65 null;
66}}}
67
68var LibraryWebGPU = {
Kai Ninomiyaace5a582024-07-02 20:52:25 +000069 $WebGPU__deps: ['$stackSave', '$stackRestore', '$stringToUTF8OnStack'],
70 $WebGPU: {
Loko Kung424cda22024-08-17 01:29:10 +000071
72 // Object management is consolidated into a single table that doesn't care
73 // about object type, and is keyed on the pointer address to a refcount.
74 // Note that most objects are directly stored in the table with the
75 // exception of Buffers which are stored within a wrapper. The wrapper is
76 // currently necessary to handle mapping and unmapping of the Buffer.
77 _table: [],
78 _tableGet: (ptr) => {
79 if (!ptr) return undefined;
80 return WebGPU._table[ptr];
81 },
82 _tableInsert: (ptr, value) => {
83 WebGPU._table[ptr] = value;
84 },
85
Loko Kung859fb302024-08-17 01:44:58 +000086 // Future to promise management, and temporary list allocated up-front for
87 // WaitAny implementation on the promises. Note that all FutureIDs
88 // (uint64_t) are passed either as a low and high value or by pointer
89 // because they need to be passed back and forth between JS and C++, and JS
90 // is currently unable to pass a value to a C++ function as a uint64_t.
91 // This might be possible with -sWASM_BIGINT, but I was unable to get that
92 // to work properly at the time of writing.
93 _futures: [],
94 _futureInsert: (futureIdL, futureIdH, promise) => {
95#if ASYNCIFY
96 var futureId = futureIdH * 0x100000000 + futureIdL;
97 WebGPU._futures[futureId] =
Lokbondo Kung9ff15362024-08-22 20:56:54 +000098 new Promise((resolve) => promise.finally(() => resolve(futureId)));
Loko Kung859fb302024-08-17 01:44:58 +000099#endif
100 },
101 _waitAnyPromisesList: [],
102
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000103 errorCallback: (callback, type, message, userdata) => {
104 var sp = stackSave();
105 var messagePtr = stringToUTF8OnStack(message);
106 {{{ makeDynCall('vipp', 'callback') }}}(type, messagePtr, userdata);
107 stackRestore(sp);
108 },
109
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000110 makeColor: (ptr) => {
111 return {
112 "r": {{{ makeGetValue('ptr', 0, 'double') }}},
113 "g": {{{ makeGetValue('ptr', 8, 'double') }}},
114 "b": {{{ makeGetValue('ptr', 16, 'double') }}},
115 "a": {{{ makeGetValue('ptr', 24, 'double') }}},
116 };
117 },
118
119 makeExtent3D: (ptr) => {
120 return {
121 "width": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUExtent3D.width) }}},
122 "height": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUExtent3D.height) }}},
123 "depthOrArrayLayers": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUExtent3D.depthOrArrayLayers) }}},
124 };
125 },
126
127 makeOrigin3D: (ptr) => {
128 return {
129 "x": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUOrigin3D.x) }}},
130 "y": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUOrigin3D.y) }}},
131 "z": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUOrigin3D.z) }}},
132 };
133 },
134
135 makeImageCopyTexture: (ptr) => {
Kai Ninomiya11784002024-07-03 19:46:03 +0000136 {{{ gpu.makeCheck('ptr') }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000137 return {
Loko Kung424cda22024-08-17 01:29:10 +0000138 "texture": WebGPU._tableGet(
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000139 {{{ makeGetValue('ptr', C_STRUCTS.WGPUImageCopyTexture.texture, '*') }}}),
140 "mipLevel": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUImageCopyTexture.mipLevel) }}},
141 "origin": WebGPU.makeOrigin3D(ptr + {{{ C_STRUCTS.WGPUImageCopyTexture.origin }}}),
142 "aspect": WebGPU.TextureAspect[{{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUImageCopyTexture.aspect) }}}],
143 };
144 },
145
146 makeTextureDataLayout: (ptr) => {
147 {{{ gpu.makeCheckDescriptor('ptr') }}}
148 var bytesPerRow = {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUTextureDataLayout.bytesPerRow) }}};
149 var rowsPerImage = {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUTextureDataLayout.rowsPerImage) }}};
150 return {
151 "offset": {{{ gpu.makeGetU64('ptr', C_STRUCTS.WGPUTextureDataLayout.offset) }}},
152 "bytesPerRow": bytesPerRow === {{{ gpu.COPY_STRIDE_UNDEFINED }}} ? undefined : bytesPerRow,
153 "rowsPerImage": rowsPerImage === {{{ gpu.COPY_STRIDE_UNDEFINED }}} ? undefined : rowsPerImage,
154 };
155 },
156
157 makeImageCopyBuffer: (ptr) => {
Kai Ninomiya11784002024-07-03 19:46:03 +0000158 {{{ gpu.makeCheck('ptr') }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000159 var layoutPtr = ptr + {{{ C_STRUCTS.WGPUImageCopyBuffer.layout }}};
160 var bufferCopyView = WebGPU.makeTextureDataLayout(layoutPtr);
Loko Kung424cda22024-08-17 01:29:10 +0000161 bufferCopyView["buffer"] = WebGPU._tableGet(
Kai Ninomiya622c78d2024-09-05 23:05:52 +0000162 {{{ makeGetValue('ptr', C_STRUCTS.WGPUImageCopyBuffer.buffer, '*') }}}).object;
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000163 return bufferCopyView;
164 },
165
166 makePipelineConstants: (constantCount, constantsPtr) => {
167 if (!constantCount) return;
168 var constants = {};
169 for (var i = 0; i < constantCount; ++i) {
170 var entryPtr = constantsPtr + {{{ C_STRUCTS.WGPUConstantEntry.__size__ }}} * i;
171 var key = UTF8ToString({{{ makeGetValue('entryPtr', C_STRUCTS.WGPUConstantEntry.key, '*') }}});
172 constants[key] = {{{ makeGetValue('entryPtr', C_STRUCTS.WGPUConstantEntry.value, 'double') }}};
173 }
174 return constants;
175 },
176
177 makePipelineLayout: (layoutPtr) => {
178 if (!layoutPtr) return 'auto';
Loko Kung424cda22024-08-17 01:29:10 +0000179 return WebGPU._tableGet(layoutPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000180 },
181
182 makeProgrammableStageDescriptor: (ptr) => {
183 if (!ptr) return undefined;
184 {{{ gpu.makeCheckDescriptor('ptr') }}}
185 var desc = {
Loko Kung424cda22024-08-17 01:29:10 +0000186 "module": WebGPU._tableGet(
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000187 {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.module, '*') }}}),
188 "constants": WebGPU.makePipelineConstants(
189 {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.constantCount) }}},
190 {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.constants, '*') }}}),
191 };
192 var entryPointPtr = {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.entryPoint, '*') }}};
193 if (entryPointPtr) desc["entryPoint"] = UTF8ToString(entryPointPtr);
194 return desc;
195 },
196
Kai Ninomiya11784002024-07-03 19:46:03 +0000197 makeComputePipelineDesc: (descriptor) => {
198 {{{ gpu.makeCheckDescriptor('descriptor') }}}
199
200 var desc = {
201 "label": undefined,
202 "layout": WebGPU.makePipelineLayout(
203 {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePipelineDescriptor.layout, '*') }}}),
204 "compute": WebGPU.makeProgrammableStageDescriptor(
205 descriptor + {{{ C_STRUCTS.WGPUComputePipelineDescriptor.compute }}}),
206 };
207 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePipelineDescriptor.label, '*') }}};
208 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
209 return desc;
210 },
211
212 makeRenderPipelineDesc: (descriptor) => {
213 {{{ gpu.makeCheckDescriptor('descriptor') }}}
Kai Ninomiya11784002024-07-03 19:46:03 +0000214
Kai Ninomiyaa46bbf92024-09-05 23:02:32 +0000215 function makePrimitiveState(psPtr) {
216 if (!psPtr) return undefined;
217 {{{ gpu.makeCheckDescriptor('psPtr') }}}
Kai Ninomiya11784002024-07-03 19:46:03 +0000218 return {
219 "topology": WebGPU.PrimitiveTopology[
Kai Ninomiyaa46bbf92024-09-05 23:02:32 +0000220 {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.topology) }}}],
Kai Ninomiya11784002024-07-03 19:46:03 +0000221 "stripIndexFormat": WebGPU.IndexFormat[
Kai Ninomiyaa46bbf92024-09-05 23:02:32 +0000222 {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.stripIndexFormat) }}}],
Kai Ninomiya11784002024-07-03 19:46:03 +0000223 "frontFace": WebGPU.FrontFace[
Kai Ninomiyaa46bbf92024-09-05 23:02:32 +0000224 {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.frontFace) }}}],
Kai Ninomiya11784002024-07-03 19:46:03 +0000225 "cullMode": WebGPU.CullMode[
Kai Ninomiyaa46bbf92024-09-05 23:02:32 +0000226 {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.cullMode) }}}],
227 "unclippedDepth":
228 {{{ gpu.makeGetBool('psPtr', C_STRUCTS.WGPUPrimitiveState.unclippedDepth) }}},
Kai Ninomiya11784002024-07-03 19:46:03 +0000229 };
230 }
231
232 function makeBlendComponent(bdPtr) {
233 if (!bdPtr) return undefined;
234 return {
235 "operation": WebGPU.BlendOperation[
236 {{{ gpu.makeGetU32('bdPtr', C_STRUCTS.WGPUBlendComponent.operation) }}}],
237 "srcFactor": WebGPU.BlendFactor[
238 {{{ gpu.makeGetU32('bdPtr', C_STRUCTS.WGPUBlendComponent.srcFactor) }}}],
239 "dstFactor": WebGPU.BlendFactor[
240 {{{ gpu.makeGetU32('bdPtr', C_STRUCTS.WGPUBlendComponent.dstFactor) }}}],
241 };
242 }
243
244 function makeBlendState(bsPtr) {
245 if (!bsPtr) return undefined;
246 return {
247 "alpha": makeBlendComponent(bsPtr + {{{ C_STRUCTS.WGPUBlendState.alpha }}}),
248 "color": makeBlendComponent(bsPtr + {{{ C_STRUCTS.WGPUBlendState.color }}}),
249 };
250 }
251
252 function makeColorState(csPtr) {
253 {{{ gpu.makeCheckDescriptor('csPtr') }}}
254 var formatInt = {{{ gpu.makeGetU32('csPtr', C_STRUCTS.WGPUColorTargetState.format) }}};
255 return formatInt === {{{ gpu.TextureFormat.Undefined }}} ? undefined : {
256 "format": WebGPU.TextureFormat[formatInt],
257 "blend": makeBlendState({{{ makeGetValue('csPtr', C_STRUCTS.WGPUColorTargetState.blend, '*') }}}),
258 "writeMask": {{{ gpu.makeGetU32('csPtr', C_STRUCTS.WGPUColorTargetState.writeMask) }}},
259 };
260 }
261
262 function makeColorStates(count, csArrayPtr) {
263 var states = [];
264 for (var i = 0; i < count; ++i) {
265 states.push(makeColorState(csArrayPtr + {{{ C_STRUCTS.WGPUColorTargetState.__size__ }}} * i));
266 }
267 return states;
268 }
269
270 function makeStencilStateFace(ssfPtr) {
271 {{{ gpu.makeCheck('ssfPtr') }}}
272 return {
273 "compare": WebGPU.CompareFunction[
274 {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.compare) }}}],
275 "failOp": WebGPU.StencilOperation[
276 {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.failOp) }}}],
277 "depthFailOp": WebGPU.StencilOperation[
278 {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.depthFailOp) }}}],
279 "passOp": WebGPU.StencilOperation[
280 {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.passOp) }}}],
281 };
282 }
283
284 function makeDepthStencilState(dssPtr) {
285 if (!dssPtr) return undefined;
286
287 {{{ gpu.makeCheck('dssPtr') }}}
288 return {
289 "format": WebGPU.TextureFormat[
290 {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.format) }}}],
291 "depthWriteEnabled": {{{ gpu.makeGetBool('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthWriteEnabled) }}},
292 "depthCompare": WebGPU.CompareFunction[
293 {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthCompare) }}}],
294 "stencilFront": makeStencilStateFace(dssPtr + {{{ C_STRUCTS.WGPUDepthStencilState.stencilFront }}}),
295 "stencilBack": makeStencilStateFace(dssPtr + {{{ C_STRUCTS.WGPUDepthStencilState.stencilBack }}}),
296 "stencilReadMask": {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.stencilReadMask) }}},
297 "stencilWriteMask": {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.stencilWriteMask) }}},
298 "depthBias": {{{ makeGetValue('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthBias, 'i32') }}},
299 "depthBiasSlopeScale": {{{ makeGetValue('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthBiasSlopeScale, 'float') }}},
300 "depthBiasClamp": {{{ makeGetValue('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthBiasClamp, 'float') }}},
301 };
302 }
303
304 function makeVertexAttribute(vaPtr) {
305 {{{ gpu.makeCheck('vaPtr') }}}
306 return {
307 "format": WebGPU.VertexFormat[
308 {{{ gpu.makeGetU32('vaPtr', C_STRUCTS.WGPUVertexAttribute.format) }}}],
309 "offset": {{{ gpu.makeGetU64('vaPtr', C_STRUCTS.WGPUVertexAttribute.offset) }}},
310 "shaderLocation": {{{ gpu.makeGetU32('vaPtr', C_STRUCTS.WGPUVertexAttribute.shaderLocation) }}},
311 };
312 }
313
314 function makeVertexAttributes(count, vaArrayPtr) {
315 var vas = [];
316 for (var i = 0; i < count; ++i) {
317 vas.push(makeVertexAttribute(vaArrayPtr + i * {{{ C_STRUCTS.WGPUVertexAttribute.__size__ }}}));
318 }
319 return vas;
320 }
321
322 function makeVertexBuffer(vbPtr) {
323 if (!vbPtr) return undefined;
324 var stepModeInt = {{{ gpu.makeGetU32('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.stepMode) }}};
325 return stepModeInt === {{{ gpu.VertexStepMode.VertexBufferNotUsed }}} ? null : {
326 "arrayStride": {{{ gpu.makeGetU64('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.arrayStride) }}},
327 "stepMode": WebGPU.VertexStepMode[stepModeInt],
328 "attributes": makeVertexAttributes(
329 {{{ gpu.makeGetU32('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.attributeCount) }}},
330 {{{ makeGetValue('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.attributes, '*') }}}),
331 };
332 }
333
334 function makeVertexBuffers(count, vbArrayPtr) {
335 if (!count) return undefined;
336
337 var vbs = [];
338 for (var i = 0; i < count; ++i) {
339 vbs.push(makeVertexBuffer(vbArrayPtr + i * {{{ C_STRUCTS.WGPUVertexBufferLayout.__size__ }}}));
340 }
341 return vbs;
342 }
343
344 function makeVertexState(viPtr) {
345 if (!viPtr) return undefined;
346 {{{ gpu.makeCheckDescriptor('viPtr') }}}
347 var desc = {
Loko Kung424cda22024-08-17 01:29:10 +0000348 "module": WebGPU._tableGet(
Kai Ninomiya11784002024-07-03 19:46:03 +0000349 {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.module, '*') }}}),
350 "constants": WebGPU.makePipelineConstants(
351 {{{ gpu.makeGetU32('viPtr', C_STRUCTS.WGPUVertexState.constantCount) }}},
352 {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.constants, '*') }}}),
353 "buffers": makeVertexBuffers(
354 {{{ gpu.makeGetU32('viPtr', C_STRUCTS.WGPUVertexState.bufferCount) }}},
355 {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.buffers, '*') }}}),
356 };
357 var entryPointPtr = {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.entryPoint, '*') }}};
358 if (entryPointPtr) desc["entryPoint"] = UTF8ToString(entryPointPtr);
359 return desc;
360 }
361
362 function makeMultisampleState(msPtr) {
363 if (!msPtr) return undefined;
364 {{{ gpu.makeCheckDescriptor('msPtr') }}}
365 return {
366 "count": {{{ gpu.makeGetU32('msPtr', C_STRUCTS.WGPUMultisampleState.count) }}},
367 "mask": {{{ gpu.makeGetU32('msPtr', C_STRUCTS.WGPUMultisampleState.mask) }}},
368 "alphaToCoverageEnabled": {{{ gpu.makeGetBool('msPtr', C_STRUCTS.WGPUMultisampleState.alphaToCoverageEnabled) }}},
369 };
370 }
371
372 function makeFragmentState(fsPtr) {
373 if (!fsPtr) return undefined;
374 {{{ gpu.makeCheckDescriptor('fsPtr') }}}
375 var desc = {
Loko Kung424cda22024-08-17 01:29:10 +0000376 "module": WebGPU._tableGet(
Kai Ninomiya11784002024-07-03 19:46:03 +0000377 {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.module, '*') }}}),
378 "constants": WebGPU.makePipelineConstants(
379 {{{ gpu.makeGetU32('fsPtr', C_STRUCTS.WGPUFragmentState.constantCount) }}},
380 {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.constants, '*') }}}),
381 "targets": makeColorStates(
382 {{{ gpu.makeGetU32('fsPtr', C_STRUCTS.WGPUFragmentState.targetCount) }}},
383 {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.targets, '*') }}}),
384 };
385 var entryPointPtr = {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.entryPoint, '*') }}};
386 if (entryPointPtr) desc["entryPoint"] = UTF8ToString(entryPointPtr);
387 return desc;
388 }
389
390 var desc = {
391 "label": undefined,
392 "layout": WebGPU.makePipelineLayout(
393 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.layout, '*') }}}),
394 "vertex": makeVertexState(
395 descriptor + {{{ C_STRUCTS.WGPURenderPipelineDescriptor.vertex }}}),
396 "primitive": makePrimitiveState(
397 descriptor + {{{ C_STRUCTS.WGPURenderPipelineDescriptor.primitive }}}),
398 "depthStencil": makeDepthStencilState(
399 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.depthStencil, '*') }}}),
400 "multisample": makeMultisampleState(
401 descriptor + {{{ C_STRUCTS.WGPURenderPipelineDescriptor.multisample }}}),
402 "fragment": makeFragmentState(
403 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.fragment, '*') }}}),
404 };
405 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.label, '*') }}};
406 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
407 return desc;
408 },
409
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000410 fillLimitStruct: (limits, supportedLimitsOutPtr) => {
411 var limitsOutPtr = supportedLimitsOutPtr + {{{ C_STRUCTS.WGPUSupportedLimits.limits }}};
412
413 function setLimitValueU32(name, limitOffset) {
414 var limitValue = limits[name];
415 {{{ makeSetValue('limitsOutPtr', 'limitOffset', 'limitValue', 'i32') }}};
416 }
417 function setLimitValueU64(name, limitOffset) {
418 var limitValue = limits[name];
419 {{{ makeSetValue('limitsOutPtr', 'limitOffset', 'limitValue', 'i64') }}};
420 }
Kai Ninomiya11784002024-07-03 19:46:03 +0000421
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000422 setLimitValueU32('maxTextureDimension1D', {{{ C_STRUCTS.WGPULimits.maxTextureDimension1D }}});
423 setLimitValueU32('maxTextureDimension2D', {{{ C_STRUCTS.WGPULimits.maxTextureDimension2D }}});
424 setLimitValueU32('maxTextureDimension3D', {{{ C_STRUCTS.WGPULimits.maxTextureDimension3D }}});
425 setLimitValueU32('maxTextureArrayLayers', {{{ C_STRUCTS.WGPULimits.maxTextureArrayLayers }}});
426 setLimitValueU32('maxBindGroups', {{{ C_STRUCTS.WGPULimits.maxBindGroups }}});
427 setLimitValueU32('maxBindGroupsPlusVertexBuffers', {{{ C_STRUCTS.WGPULimits.maxBindGroupsPlusVertexBuffers }}});
428 setLimitValueU32('maxBindingsPerBindGroup', {{{ C_STRUCTS.WGPULimits.maxBindingsPerBindGroup }}});
429 setLimitValueU32('maxDynamicUniformBuffersPerPipelineLayout', {{{ C_STRUCTS.WGPULimits.maxDynamicUniformBuffersPerPipelineLayout }}});
430 setLimitValueU32('maxDynamicStorageBuffersPerPipelineLayout', {{{ C_STRUCTS.WGPULimits.maxDynamicStorageBuffersPerPipelineLayout }}});
431 setLimitValueU32('maxSampledTexturesPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxSampledTexturesPerShaderStage }}});
432 setLimitValueU32('maxSamplersPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxSamplersPerShaderStage }}});
433 setLimitValueU32('maxStorageBuffersPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxStorageBuffersPerShaderStage }}});
434 setLimitValueU32('maxStorageTexturesPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxStorageTexturesPerShaderStage }}});
435 setLimitValueU32('maxUniformBuffersPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxUniformBuffersPerShaderStage }}});
436 setLimitValueU32('minUniformBufferOffsetAlignment', {{{ C_STRUCTS.WGPULimits.minUniformBufferOffsetAlignment }}});
437 setLimitValueU32('minStorageBufferOffsetAlignment', {{{ C_STRUCTS.WGPULimits.minStorageBufferOffsetAlignment }}});
Kai Ninomiya11784002024-07-03 19:46:03 +0000438
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000439 setLimitValueU64('maxUniformBufferBindingSize', {{{ C_STRUCTS.WGPULimits.maxUniformBufferBindingSize }}});
440 setLimitValueU64('maxStorageBufferBindingSize', {{{ C_STRUCTS.WGPULimits.maxStorageBufferBindingSize }}});
Kai Ninomiya11784002024-07-03 19:46:03 +0000441
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000442 setLimitValueU32('maxVertexBuffers', {{{ C_STRUCTS.WGPULimits.maxVertexBuffers }}});
Loko Kungc1a2d1d2024-07-25 23:20:31 +0000443 setLimitValueU64('maxBufferSize', {{{ C_STRUCTS.WGPULimits.maxBufferSize }}});
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000444 setLimitValueU32('maxVertexAttributes', {{{ C_STRUCTS.WGPULimits.maxVertexAttributes }}});
445 setLimitValueU32('maxVertexBufferArrayStride', {{{ C_STRUCTS.WGPULimits.maxVertexBufferArrayStride }}});
446 setLimitValueU32('maxInterStageShaderComponents', {{{ C_STRUCTS.WGPULimits.maxInterStageShaderComponents }}});
447 setLimitValueU32('maxInterStageShaderVariables', {{{ C_STRUCTS.WGPULimits.maxInterStageShaderVariables }}});
448 setLimitValueU32('maxColorAttachments', {{{ C_STRUCTS.WGPULimits.maxColorAttachments }}});
449 setLimitValueU32('maxColorAttachmentBytesPerSample', {{{ C_STRUCTS.WGPULimits.maxColorAttachmentBytesPerSample }}});
450 setLimitValueU32('maxComputeWorkgroupStorageSize', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupStorageSize }}});
451 setLimitValueU32('maxComputeInvocationsPerWorkgroup', {{{ C_STRUCTS.WGPULimits.maxComputeInvocationsPerWorkgroup }}});
452 setLimitValueU32('maxComputeWorkgroupSizeX', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeX }}});
453 setLimitValueU32('maxComputeWorkgroupSizeY', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeY }}});
454 setLimitValueU32('maxComputeWorkgroupSizeZ', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeZ }}});
455 setLimitValueU32('maxComputeWorkgroupsPerDimension', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupsPerDimension }}});
456 },
457
Kai Ninomiya11784002024-07-03 19:46:03 +0000458 // Maps from enum string back to enum number, for callbacks.
459 {{{ WEBGPU_STRING_TO_INT_TABLES }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000460
Kai Ninomiya11784002024-07-03 19:46:03 +0000461 // Maps from enum number to enum string.
462 {{{ WEBGPU_INT_TO_STRING_TABLES }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000463 },
464
Loko Kung424cda22024-08-17 01:29:10 +0000465 // ----------------------------------------------------------------------------
Lokbondo Kungbc3246b2024-08-20 19:12:29 +0000466 // Definitions for standalone JS emwgpu functions (callable from webgpu.cpp and
467 // library_html5_html.js)
Loko Kung424cda22024-08-17 01:29:10 +0000468 // ----------------------------------------------------------------------------
469
470 emwgpuDelete: (id) => {
471 delete WebGPU._table[id];
472 },
473
Lokbondo Kungbc3246b2024-08-20 19:12:29 +0000474 // Extra helper that allow for directly inserting Devices (and their
475 // corresponding Queue) that is called from the HTML5 library since there
476 // isn't access to the C++ in webgpu.cpp there.
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000477 emwgpuTableInsertDevice__deps: ['emwgpuCreateDevice', 'emwgpuCreateQueue', 'wgpuCreateInstance'],
Lokbondo Kungbc3246b2024-08-20 19:12:29 +0000478 emwgpuTableInsertDevice: (device) => {
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000479 var instancePtr = _wgpuCreateInstance();
Lokbondo Kungbc3246b2024-08-20 19:12:29 +0000480 var queuePtr = _emwgpuCreateQueue();
481 WebGPU._tableInsert(queuePtr, device.queue);
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000482 var devicePtr = _emwgpuCreateDevice(instancePtr, queuePtr);
Lokbondo Kungbc3246b2024-08-20 19:12:29 +0000483 WebGPU._tableInsert(devicePtr, device);
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000484 return { instancePtr, devicePtr };
Lokbondo Kungbc3246b2024-08-20 19:12:29 +0000485 },
486
Loko Kung859fb302024-08-17 01:44:58 +0000487#if ASYNCIFY
488 // Returns a FutureID that was resolved, or kNullFutureId if timed out.
489 emwgpuWaitAny__async: true,
490 emwgpuWaitAny: (futurePtr, futureCount, timeoutNSPtr) => {
491 var promises = WebGPU._waitAnyPromisesList;
492 if (timeoutNSPtr) {
493 var timeoutMS = {{{ gpu.makeGetU64('timeoutNSPtr', 0) }}} / 1000000;
494 promises.length = futureCount + 1;
495 promise[futureCount] = new Promise((resolve) => setTimeout(resolve, timeoutMS, 0));
496 } else {
497 promises.length = futureCount;
498 }
499
500 for (var i = 0; i < futureCount; ++i) {
501 // If any of the FutureIDs are not tracked, it means it must be done.
502 var futureId = {{{ gpu.makeGetU64('(futurePtr + i * 8)', 0) }}};
503 if (!(futureId in WebGPU._futures)) {
504 return futureId;
505 }
506 promises[i] = WebGPU._futures[futureId];
507 }
508
509 var result = Asyncify.handleAsync(async () => {
510 return await Promise.race(promises);
511 });
512
513 // Clean up internal futures state.
514 delete WebGPU._futures[result];
515 WebGPU._waitAnyPromisesList.length = 0;
516 return result;
517 },
518#endif
519
Loko Kung424cda22024-08-17 01:29:10 +0000520 // --------------------------------------------------------------------------
521 // WebGPU function definitions, with methods organized by "class".
522 //
523 // Also note that the full set of functions declared in webgpu.h are only
524 // partially implemeted here. The remaining ones are implemented via
525 // webgpu.cpp.
526 // --------------------------------------------------------------------------
527
Loko Kung5a9506d2024-08-17 01:44:45 +0000528 // --------------------------------------------------------------------------
Loko Kung424cda22024-08-17 01:29:10 +0000529 // Standalone (non-method) functions
Loko Kung5a9506d2024-08-17 01:44:45 +0000530 // --------------------------------------------------------------------------
531
532 wgpuAdapterPropertiesFreeMembers: (value) => {
533 // wgpuAdapterGetProperties doesn't currently allocate anything.
534 },
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000535
536 wgpuGetInstanceFeatures: (featuresPtr) => {
537 abort('TODO: wgpuGetInstanceFeatures unimplemented');
538 return 0;
539 },
540
541 wgpuGetProcAddress: (device, procName) => {
542 abort('TODO(#11526): wgpuGetProcAddress unimplemented');
543 return 0;
544 },
545
Loko Kung5a9506d2024-08-17 01:44:45 +0000546 // --------------------------------------------------------------------------
547 // Methods of Adapter
548 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000549
Loko Kung5a9506d2024-08-17 01:44:45 +0000550 wgpuAdapterEnumerateFeatures: (adapterPtr, featuresOutPtr) => {
551 var adapter = WebGPU._tableGet(adapterPtr);
552 if (featuresOutPtr !== 0) {
553 var offset = 0;
554 adapter.features.forEach(feature => {
555 var featureEnumValue = WebGPU.FeatureNameString2Enum[feature];
556 {{{ makeSetValue('featuresOutPtr', 'offset', 'featureEnumValue', 'i32') }}};
557 offset += 4;
558 });
559 }
560 return adapter.features.size;
561 },
562
563 wgpuAdapterGetInfo__deps: ['$stringToNewUTF8'],
564 wgpuAdapterGetInfo: (adapterPtr, info) => {
565 var adapter = WebGPU._tableGet(adapterPtr);
566 {{{ gpu.makeCheckDescriptor('info') }}}
567
568 var vendorPtr = stringToNewUTF8(adapter.info.vendor);
569 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.vendor, 'vendorPtr', '*') }}};
570 var architecturePtr = stringToNewUTF8(adapter.info.architecture);
571 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.architecture, 'architecturePtr', '*') }}};
572 var devicePtr = stringToNewUTF8(adapter.info.device);
573 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.device, 'devicePtr', '*') }}};
574 var descriptionPtr = stringToNewUTF8(adapter.info.description);
575 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.description, 'descriptionPtr', '*') }}};
576 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.backendType, gpu.BackendType.WebGPU, 'i32') }}};
577 var adapterType = adapter.isFallbackAdapter ? {{{ gpu.AdapterType.CPU }}} : {{{ gpu.AdapterType.Unknown }}};
578 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.adapterType, 'adapterType', 'i32') }}};
579 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.vendorID, '0', 'i32') }}};
580 {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.deviceID, '0', 'i32') }}};
581 },
582
583 wgpuAdapterGetLimits: (adapterPtr, limitsOutPtr) => {
584 var adapter = WebGPU._tableGet(adapterPtr);
585 WebGPU.fillLimitStruct(adapter.limits, limitsOutPtr);
586 return 1;
587 },
588
589 wgpuAdapterGetProperties__deps: ['$warnOnce'],
590 wgpuAdapterGetProperties: (adapterPtr, properties) => {
591 warnOnce('wgpuAdapterGetProperties is deprecated, use wgpuAdapterGetInfo instead');
592
593 {{{ gpu.makeCheckDescriptor('properties') }}}
594 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.vendorID, '0', 'i32') }}};
595 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.vendorName, '0', 'i32') }}};
596 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.architecture, '0', 'i32') }}};
597 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.deviceID, '0', 'i32') }}};
598 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.name, '0', 'i32') }}};
599 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.driverDescription, '0', 'i32') }}};
600 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.adapterType, gpu.AdapterType.Unknown, 'i32') }}};
601 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.backendType, gpu.BackendType.WebGPU, 'i32') }}};
602 {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.compatibilityMode, '0', 'i32') }}};
603 },
604
605 wgpuAdapterHasFeature: (adapterPtr, featureEnumValue) => {
606 var adapter = WebGPU._tableGet(adapterPtr);
607 return adapter.features.has(WebGPU.FeatureName[featureEnumValue]);
608 },
609
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000610 emwgpuAdapterRequestDevice__i53abi: false,
Kai Ninomiya622c78d2024-09-05 23:05:52 +0000611 emwgpuAdapterRequestDevice__deps: ['$withStackSave', '$callUserCallback', '$stringToUTF8OnStack', 'emwgpuCreateQueue', 'emwgpuOnDeviceLostCompleted', 'emwgpuOnRequestDeviceCompleted', 'emwgpuOnUncapturedError'],
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000612 emwgpuAdapterRequestDevice: (
613 adapterPtr,
614 futureIdL, futureIdH,
615 deviceLostFutureIdL, deviceLostFutureIdH,
616 devicePtr, queuePtr, descriptor
617 ) => {
Loko Kung5a9506d2024-08-17 01:44:45 +0000618 var adapter = WebGPU._tableGet(adapterPtr);
619
620 var desc = {};
621 if (descriptor) {
622 {{{ gpu.makeCheckDescriptor('descriptor') }}}
623 var requiredFeatureCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUDeviceDescriptor.requiredFeatureCount) }}};
624 if (requiredFeatureCount) {
625 var requiredFeaturesPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.requiredFeatures, '*') }}};
626 desc["requiredFeatures"] = Array.from({{{ makeHEAPView('32', 'requiredFeaturesPtr', `requiredFeaturesPtr + requiredFeatureCount * ${POINTER_SIZE}`) }}},
627 (feature) => WebGPU.FeatureName[feature]);
628 }
629 var requiredLimitsPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.requiredLimits, '*') }}};
630 if (requiredLimitsPtr) {
631 {{{ gpu.makeCheckDescriptor('requiredLimitsPtr') }}}
632 var limitsPtr = requiredLimitsPtr + {{{ C_STRUCTS.WGPURequiredLimits.limits }}};
633 var requiredLimits = {};
634 function setLimitU32IfDefined(name, limitOffset) {
635 var ptr = limitsPtr + limitOffset;
636 var value = {{{ gpu.makeGetU32('ptr', 0) }}};
637 if (value != {{{ gpu.LIMIT_U32_UNDEFINED }}}) {
638 requiredLimits[name] = value;
639 }
640 }
641 function setLimitU64IfDefined(name, limitOffset) {
642 var ptr = limitsPtr + limitOffset;
643 // Handle WGPU_LIMIT_U64_UNDEFINED.
644 var limitPart1 = {{{ gpu.makeGetU32('ptr', 0) }}};
645 var limitPart2 = {{{ gpu.makeGetU32('ptr', 4) }}};
646 if (limitPart1 != 0xFFFFFFFF || limitPart2 != 0xFFFFFFFF) {
647 requiredLimits[name] = {{{ gpu.makeGetU64('ptr', 0) }}}
648 }
649 }
650
651 setLimitU32IfDefined("maxTextureDimension1D", {{{ C_STRUCTS.WGPULimits.maxTextureDimension1D }}});
652 setLimitU32IfDefined("maxTextureDimension2D", {{{ C_STRUCTS.WGPULimits.maxTextureDimension2D }}});
653 setLimitU32IfDefined("maxTextureDimension3D", {{{ C_STRUCTS.WGPULimits.maxTextureDimension3D }}});
654 setLimitU32IfDefined("maxTextureArrayLayers", {{{ C_STRUCTS.WGPULimits.maxTextureArrayLayers }}});
655 setLimitU32IfDefined("maxBindGroups", {{{ C_STRUCTS.WGPULimits.maxBindGroups }}});
656 setLimitU32IfDefined('maxBindGroupsPlusVertexBuffers', {{{ C_STRUCTS.WGPULimits.maxBindGroupsPlusVertexBuffers }}});
657 setLimitU32IfDefined("maxDynamicUniformBuffersPerPipelineLayout", {{{ C_STRUCTS.WGPULimits.maxDynamicUniformBuffersPerPipelineLayout }}});
658 setLimitU32IfDefined("maxDynamicStorageBuffersPerPipelineLayout", {{{ C_STRUCTS.WGPULimits.maxDynamicStorageBuffersPerPipelineLayout }}});
659 setLimitU32IfDefined("maxSampledTexturesPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxSampledTexturesPerShaderStage }}});
660 setLimitU32IfDefined("maxSamplersPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxSamplersPerShaderStage }}});
661 setLimitU32IfDefined("maxStorageBuffersPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxStorageBuffersPerShaderStage }}});
662 setLimitU32IfDefined("maxStorageTexturesPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxStorageTexturesPerShaderStage }}});
663 setLimitU32IfDefined("maxUniformBuffersPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxUniformBuffersPerShaderStage }}});
664 setLimitU32IfDefined("minUniformBufferOffsetAlignment", {{{ C_STRUCTS.WGPULimits.minUniformBufferOffsetAlignment }}});
665 setLimitU32IfDefined("minStorageBufferOffsetAlignment", {{{ C_STRUCTS.WGPULimits.minStorageBufferOffsetAlignment }}});
666 setLimitU64IfDefined("maxUniformBufferBindingSize", {{{ C_STRUCTS.WGPULimits.maxUniformBufferBindingSize }}});
667 setLimitU64IfDefined("maxStorageBufferBindingSize", {{{ C_STRUCTS.WGPULimits.maxStorageBufferBindingSize }}});
668 setLimitU32IfDefined("maxVertexBuffers", {{{ C_STRUCTS.WGPULimits.maxVertexBuffers }}});
669 setLimitU64IfDefined("maxBufferSize", {{{ C_STRUCTS.WGPULimits.maxBufferSize }}});
670 setLimitU32IfDefined("maxVertexAttributes", {{{ C_STRUCTS.WGPULimits.maxVertexAttributes }}});
671 setLimitU32IfDefined("maxVertexBufferArrayStride", {{{ C_STRUCTS.WGPULimits.maxVertexBufferArrayStride }}});
672 setLimitU32IfDefined("maxInterStageShaderComponents", {{{ C_STRUCTS.WGPULimits.maxInterStageShaderComponents }}});
673 setLimitU32IfDefined("maxInterStageShaderVariables", {{{ C_STRUCTS.WGPULimits.maxInterStageShaderVariables }}});
674 setLimitU32IfDefined("maxColorAttachments", {{{ C_STRUCTS.WGPULimits.maxColorAttachments }}});
675 setLimitU32IfDefined("maxColorAttachmentBytesPerSample", {{{ C_STRUCTS.WGPULimits.maxColorAttachmentBytesPerSample }}});
676 setLimitU32IfDefined("maxComputeWorkgroupStorageSize", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupStorageSize }}});
677 setLimitU32IfDefined("maxComputeInvocationsPerWorkgroup", {{{ C_STRUCTS.WGPULimits.maxComputeInvocationsPerWorkgroup }}});
678 setLimitU32IfDefined("maxComputeWorkgroupSizeX", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeX }}});
679 setLimitU32IfDefined("maxComputeWorkgroupSizeY", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeY }}});
680 setLimitU32IfDefined("maxComputeWorkgroupSizeZ", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeZ }}});
681 setLimitU32IfDefined("maxComputeWorkgroupsPerDimension", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupsPerDimension }}});
682 desc["requiredLimits"] = requiredLimits;
683 }
684
685 var defaultQueuePtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.defaultQueue, '*') }}};
686 if (defaultQueuePtr) {
687 var defaultQueueDesc = {};
688 var labelPtr = {{{ makeGetValue('defaultQueuePtr', C_STRUCTS.WGPUQueueDescriptor.label, '*') }}};
689 if (labelPtr) defaultQueueDesc["label"] = UTF8ToString(labelPtr);
690 desc["defaultQueue"] = defaultQueueDesc;
691 }
692
Loko Kung5a9506d2024-08-17 01:44:45 +0000693 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.label, '*') }}};
694 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
695 }
696
697 {{{ runtimeKeepalivePush() }}}
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000698 var hasDeviceLostFutureId = !!deviceLostFutureIdH || !!deviceLostFutureIdL;
699 WebGPU._futureInsert(futureIdL, futureIdH, adapter.requestDevice(desc).then((device) => {
Loko Kung5a9506d2024-08-17 01:44:45 +0000700 {{{ runtimeKeepalivePop() }}}
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000701 WebGPU._tableInsert(queuePtr, device.queue);
702 WebGPU._tableInsert(devicePtr, device);
Loko Kung5a9506d2024-08-17 01:44:45 +0000703
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000704 // Set up device lost promise resolution.
705 if (hasDeviceLostFutureId) {
Kai Ninomiyae7ad6c42024-09-06 10:14:22 +0000706 {{{ runtimeKeepalivePush() }}}
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000707 WebGPU._futureInsert(deviceLostFutureIdL, deviceLostFutureIdH, device.lost.then((info) => {
Kai Ninomiyae7ad6c42024-09-06 10:14:22 +0000708 {{{ runtimeKeepalivePop() }}}
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000709 // Unset the uncaptured error handler.
710 device.onuncapturederror = (ev) => {};
711 withStackSave(() => {
712 var messagePtr = stringToUTF8OnStack(info.message);
713 _emwgpuOnDeviceLostCompleted(deviceLostFutureIdL, deviceLostFutureIdH, WebGPU.Int_DeviceLostReason[info.reason], messagePtr);
Loko Kung5a9506d2024-08-17 01:44:45 +0000714 });
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000715 }));
716 }
717
718 // Set up uncaptured error handlers.
719#if ASSERTIONS
720 assert(typeof GPUValidationError != 'undefined');
721 assert(typeof GPUOutOfMemoryError != 'undefined');
722 assert(typeof GPUInternalError != 'undefined');
723#endif
724 device.onuncapturederror = (ev) => {
725 var type = {{{ gpu.ErrorType.Unknown }}};;
726 if (ev.error instanceof GPUValidationError) type = {{{ gpu.ErrorType.Validation }}};
727 else if (ev.error instanceof GPUOutOfMemoryError) type = {{{ gpu.ErrorType.OutOfMemory }}};
728 else if (ev.error instanceof GPUInternalError) type = {{{ gpu.ErrorType.Internal }}};
729 withStackSave(() => {
730 var messagePtr = stringToUTF8OnStack(ev.error.message);
731 _emwgpuOnUncapturedError(devicePtr, type, messagePtr);
732 });
733 };
734
735 _emwgpuOnRequestDeviceCompleted(futureIdL, futureIdH, {{{ gpu.RequestDeviceStatus.Success }}}, devicePtr, 0);
736 }, (ex) => {
Loko Kung5a9506d2024-08-17 01:44:45 +0000737 {{{ runtimeKeepalivePop() }}}
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000738 withStackSave(() => {
Loko Kung5a9506d2024-08-17 01:44:45 +0000739 var messagePtr = stringToUTF8OnStack(ex.message);
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000740 _emwgpuOnRequestDeviceCompleted(futureIdL, futureIdH, {{{ gpu.RequestDeviceStatus.Error }}}, devicePtr, messagePtr);
Kai Ninomiya622c78d2024-09-05 23:05:52 +0000741 if (hasDeviceLostFutureId) {
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000742 _emwgpuOnDeviceLostCompleted(deviceLostFutureIdL, deviceLostFutureIdH, {{{ gpu.DeviceLostReason.FailedCreation }}}, messagePtr);
743 }
Loko Kung5a9506d2024-08-17 01:44:45 +0000744 });
Lokbondo Kunga8fbe982024-08-30 04:46:53 +0000745 }));
Loko Kung5a9506d2024-08-17 01:44:45 +0000746 },
747
748 // --------------------------------------------------------------------------
749 // Methods of BindGroup
750 // --------------------------------------------------------------------------
751
752 wgpuBindGroupSetLabel: (bindGroupPtr, labelPtr) => {
753 var bindGroup = WebGPU._tableGet(bindGroupPtr);
754 bindGroup.label = UTF8ToString(labelPtr);
755 },
756
757 // --------------------------------------------------------------------------
758 // Methods of BindGroupLayout
759 // --------------------------------------------------------------------------
760
761 wgpuBindGroupLayoutSetLabel: (bindGroupLayoutPtr, labelPtr) => {
762 var bindGroupLayout = WebGPU._tableGet(bindGroupLayoutPtr);
763 bindGroupLayout.label = UTF8ToString(labelPtr);
764 },
765
766 // --------------------------------------------------------------------------
767 // Methods of Buffer
768 // --------------------------------------------------------------------------
769
770 wgpuBufferDestroy: (bufferPtr) => {
771 var bufferWrapper = WebGPU._tableGet(bufferPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000772 {{{ gpu.makeCheckDefined('bufferWrapper') }}}
773 if (bufferWrapper.onUnmap) {
774 for (var i = 0; i < bufferWrapper.onUnmap.length; ++i) {
775 bufferWrapper.onUnmap[i]();
776 }
777 bufferWrapper.onUnmap = undefined;
778 }
779
Loko Kung424cda22024-08-17 01:29:10 +0000780 bufferWrapper.object.destroy();
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000781 },
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000782
Loko Kung5a9506d2024-08-17 01:44:45 +0000783 // In webgpu.h offset and size are passed in as size_t.
784 // And library_webgpu assumes that size_t is always 32bit in emscripten.
785 wgpuBufferGetConstMappedRange__deps: ['$warnOnce', 'memalign', 'free'],
786 wgpuBufferGetConstMappedRange: (bufferPtr, offset, size) => {
787 var bufferWrapper = WebGPU._tableGet(bufferPtr);
788 {{{ gpu.makeCheckDefined('bufferWrapper') }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000789
Loko Kung5a9506d2024-08-17 01:44:45 +0000790 if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE');
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000791
Loko Kung5a9506d2024-08-17 01:44:45 +0000792 {{{ gpu.convertSentinelToUndefined('size') }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000793
Loko Kung5a9506d2024-08-17 01:44:45 +0000794 var mapped;
795 try {
796 mapped = bufferWrapper.object.getMappedRange(offset, size);
797 } catch (ex) {
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000798#if ASSERTIONS
Loko Kung5a9506d2024-08-17 01:44:45 +0000799 err(`wgpuBufferGetConstMappedRange(${offset}, ${size}) failed: ${ex}`);
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000800#endif
Loko Kung5a9506d2024-08-17 01:44:45 +0000801 // TODO(kainino0x): Somehow inject a validation error?
802 return 0;
803 }
804 var data = _memalign(16, mapped.byteLength);
805 HEAPU8.set(new Uint8Array(mapped), data);
806 bufferWrapper.onUnmap.push(() => _free(data));
807 return data;
808 },
809
810 wgpuBufferGetMapState: (bufferPtr) => {
811 var buffer = WebGPU._tableGet(bufferPtr).object;
812 return WebGPU.Int_BufferMapState[buffer.mapState];
813 },
814
815 // In webgpu.h offset and size are passed in as size_t.
816 // And library_webgpu assumes that size_t is always 32bit in emscripten.
817 wgpuBufferGetMappedRange__deps: ['$warnOnce', 'memalign', 'free'],
818 wgpuBufferGetMappedRange: (bufferPtr, offset, size) => {
819 var bufferWrapper = WebGPU._tableGet(bufferPtr);
820 {{{ gpu.makeCheckDefined('bufferWrapper') }}}
821
822 if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE');
823
824 {{{ gpu.convertSentinelToUndefined('size') }}}
825
826 if (bufferWrapper.mapMode !== {{{ gpu.MapMode.Write }}}) {
827#if ASSERTIONS
828 abort("GetMappedRange called, but buffer not mapped for writing");
829#endif
830 // TODO(kainino0x): Somehow inject a validation error?
831 return 0;
832 }
833
834 var mapped;
835 try {
836 mapped = bufferWrapper.object.getMappedRange(offset, size);
837 } catch (ex) {
838#if ASSERTIONS
839 err(`wgpuBufferGetMappedRange(${offset}, ${size}) failed: ${ex}`);
840#endif
841 // TODO(kainino0x): Somehow inject a validation error?
842 return 0;
843 }
844
845 var data = _memalign(16, mapped.byteLength);
846 HEAPU8.fill(0, data, mapped.byteLength);
847 bufferWrapper.onUnmap.push(() => {
848 new Uint8Array(mapped).set(HEAPU8.subarray(data, data + mapped.byteLength));
849 _free(data);
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000850 });
Loko Kung5a9506d2024-08-17 01:44:45 +0000851 return data;
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000852 },
853
Loko Kung5a9506d2024-08-17 01:44:45 +0000854 wgpuBufferGetSize: (bufferPtr) => {
855 var buffer = WebGPU._tableGet(bufferPtr).object;
856 // 64-bit
857 return buffer.size;
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000858 },
859
Loko Kung5a9506d2024-08-17 01:44:45 +0000860 wgpuBufferGetUsage: (bufferPtr) => {
861 var buffer = WebGPU._tableGet(bufferPtr).object;
862 return buffer.usage;
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000863 },
864
Loko Kung5a9506d2024-08-17 01:44:45 +0000865 // In webgpu.h offset and size are passed in as size_t.
866 // And library_webgpu assumes that size_t is always 32bit in emscripten.
867 wgpuBufferMapAsync__deps: ['$callUserCallback'],
868 wgpuBufferMapAsync: (bufferPtr, mode, offset, size, callback, userdata) => {
869 var bufferWrapper = WebGPU._tableGet(bufferPtr);
870 {{{ gpu.makeCheckDefined('bufferWrapper') }}}
871 bufferWrapper.mapMode = mode;
872 bufferWrapper.onUnmap = [];
873 var buffer = bufferWrapper.object;
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000874
Loko Kung5a9506d2024-08-17 01:44:45 +0000875 {{{ gpu.convertSentinelToUndefined('size') }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000876
Loko Kung5a9506d2024-08-17 01:44:45 +0000877 // `callback` takes (WGPUBufferMapAsyncStatus status, void * userdata)
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000878
879 {{{ runtimeKeepalivePush() }}}
Loko Kung5a9506d2024-08-17 01:44:45 +0000880 buffer.mapAsync(mode, offset, size).then(() => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000881 {{{ runtimeKeepalivePop() }}}
882 callUserCallback(() => {
Loko Kung5a9506d2024-08-17 01:44:45 +0000883 {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.BufferMapAsyncStatus.Success }}}, userdata);
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000884 });
885 }, () => {
886 {{{ runtimeKeepalivePop() }}}
887 callUserCallback(() => {
Loko Kung5a9506d2024-08-17 01:44:45 +0000888 // TODO(kainino0x): Figure out how to pick other error status values.
889 {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.BufferMapAsyncStatus.ValidationError }}}, userdata);
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000890 });
891 });
892 },
893
Loko Kung5a9506d2024-08-17 01:44:45 +0000894 wgpuBufferSetLabel: (bufferPtr, labelPtr) => {
895 var buffer = WebGPU._tableGet(bufferPtr).object;
896 buffer.label = UTF8ToString(labelPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000897 },
898
Loko Kung5a9506d2024-08-17 01:44:45 +0000899 wgpuBufferUnmap: (bufferPtr) => {
900 var bufferWrapper = WebGPU._tableGet(bufferPtr);
901 {{{ gpu.makeCheckDefined('bufferWrapper') }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000902
Loko Kung5a9506d2024-08-17 01:44:45 +0000903 if (!bufferWrapper.onUnmap) {
904 // Already unmapped
905 return;
906 }
907
908 for (var i = 0; i < bufferWrapper.onUnmap.length; ++i) {
909 bufferWrapper.onUnmap[i]();
910 }
911 bufferWrapper.onUnmap = undefined;
912
913 bufferWrapper.object.unmap();
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000914 },
915
Loko Kung5a9506d2024-08-17 01:44:45 +0000916 // --------------------------------------------------------------------------
917 // Methods of CommandBuffer
918 // --------------------------------------------------------------------------
919
920 wgpuCommandBufferSetLabel: (commandBufferPtr, labelPtr) => {
921 var commandBuffer = WebGPU._tableGet(commandBufferPtr);
922 commandBuffer.label = UTF8ToString(labelPtr);
923 },
924
925 // --------------------------------------------------------------------------
926 // Methods of CommandEncoder
927 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000928
Loko Kung424cda22024-08-17 01:29:10 +0000929 wgpuCommandEncoderBeginComputePass__deps: ['emwgpuCreateComputePassEncoder'],
Loko Kung5a9506d2024-08-17 01:44:45 +0000930 wgpuCommandEncoderBeginComputePass: (encoderPtr, descriptor) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000931 var desc;
932
933 function makeComputePassTimestampWrites(twPtr) {
934 if (twPtr === 0) return undefined;
935
936 return {
Loko Kung424cda22024-08-17 01:29:10 +0000937 "querySet": WebGPU._tableGet(
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000938 {{{ makeGetValue('twPtr', C_STRUCTS.WGPUComputePassTimestampWrites.querySet, '*') }}}),
939 "beginningOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPUComputePassTimestampWrites.beginningOfPassWriteIndex) }}},
940 "endOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPUComputePassTimestampWrites.endOfPassWriteIndex) }}},
941 };
942 }
943
944 if (descriptor) {
945 {{{ gpu.makeCheckDescriptor('descriptor') }}}
946 desc = {
947 "label": undefined,
948 "timestampWrites": makeComputePassTimestampWrites(
949 {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePassDescriptor.timestampWrites, '*') }}}),
950 };
951 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePassDescriptor.label, '*') }}};
952 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
953
954 }
Loko Kung5a9506d2024-08-17 01:44:45 +0000955 var commandEncoder = WebGPU._tableGet(encoderPtr);
Loko Kung424cda22024-08-17 01:29:10 +0000956 var ptr = _emwgpuCreateComputePassEncoder();
957 WebGPU._tableInsert(ptr, commandEncoder.beginComputePass(desc));
958 return ptr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000959 },
960
Loko Kung424cda22024-08-17 01:29:10 +0000961 wgpuCommandEncoderBeginRenderPass__deps: ['emwgpuCreateRenderPassEncoder'],
Loko Kung5a9506d2024-08-17 01:44:45 +0000962 wgpuCommandEncoderBeginRenderPass: (encoderPtr, descriptor) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000963 {{{ gpu.makeCheck('descriptor') }}}
964
965 function makeColorAttachment(caPtr) {
966 var viewPtr = {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.view) }}};
967 if (viewPtr === 0) {
968 // view could be undefined.
969 return undefined;
970 }
971
972 var depthSlice = {{{ makeGetValue('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.depthSlice, 'i32') }}};
973 {{{ gpu.convertSentinelToUndefined('depthSlice') }}}
974
975 var loadOpInt = {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.loadOp) }}};
976 #if ASSERTIONS
977 assert(loadOpInt !== {{{ gpu.LoadOp.Undefined }}});
978 #endif
979
980 var storeOpInt = {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.storeOp) }}};
981 #if ASSERTIONS
982 assert(storeOpInt !== {{{ gpu.StoreOp.Undefined }}});
983 #endif
984
985 var clearValue = WebGPU.makeColor(caPtr + {{{ C_STRUCTS.WGPURenderPassColorAttachment.clearValue }}});
986
987 return {
Loko Kung424cda22024-08-17 01:29:10 +0000988 "view": WebGPU._tableGet(viewPtr),
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000989 "depthSlice": depthSlice,
Loko Kung424cda22024-08-17 01:29:10 +0000990 "resolveTarget": WebGPU._tableGet(
Kai Ninomiyaace5a582024-07-02 20:52:25 +0000991 {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.resolveTarget) }}}),
992 "clearValue": clearValue,
993 "loadOp": WebGPU.LoadOp[loadOpInt],
994 "storeOp": WebGPU.StoreOp[storeOpInt],
995 };
996 }
997
998 function makeColorAttachments(count, caPtr) {
999 var attachments = [];
1000 for (var i = 0; i < count; ++i) {
1001 attachments.push(makeColorAttachment(caPtr + {{{ C_STRUCTS.WGPURenderPassColorAttachment.__size__ }}} * i));
1002 }
1003 return attachments;
1004 }
1005
1006 function makeDepthStencilAttachment(dsaPtr) {
1007 if (dsaPtr === 0) return undefined;
1008
1009 return {
Loko Kung424cda22024-08-17 01:29:10 +00001010 "view": WebGPU._tableGet(
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001011 {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.view) }}}),
1012 "depthClearValue": {{{ makeGetValue('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthClearValue, 'float') }}},
1013 "depthLoadOp": WebGPU.LoadOp[
1014 {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthLoadOp) }}}],
1015 "depthStoreOp": WebGPU.StoreOp[
1016 {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthStoreOp) }}}],
1017 "depthReadOnly": {{{ gpu.makeGetBool('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthReadOnly) }}},
1018 "stencilClearValue": {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilClearValue) }}},
1019 "stencilLoadOp": WebGPU.LoadOp[
1020 {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilLoadOp) }}}],
1021 "stencilStoreOp": WebGPU.StoreOp[
1022 {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilStoreOp) }}}],
1023 "stencilReadOnly": {{{ gpu.makeGetBool('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilReadOnly) }}},
1024 };
1025 }
1026
1027 function makeRenderPassTimestampWrites(twPtr) {
1028 if (twPtr === 0) return undefined;
1029
1030 return {
Loko Kung424cda22024-08-17 01:29:10 +00001031 "querySet": WebGPU._tableGet(
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001032 {{{ makeGetValue('twPtr', C_STRUCTS.WGPURenderPassTimestampWrites.querySet, '*') }}}),
1033 "beginningOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPURenderPassTimestampWrites.beginningOfPassWriteIndex) }}},
1034 "endOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPURenderPassTimestampWrites.endOfPassWriteIndex) }}},
1035 };
1036 }
1037
1038 function makeRenderPassDescriptor(descriptor) {
1039 {{{ gpu.makeCheck('descriptor') }}}
1040 var nextInChainPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.nextInChain, '*') }}};
1041
1042 var maxDrawCount = undefined;
1043 if (nextInChainPtr !== 0) {
1044 var sType = {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}};
1045#if ASSERTIONS
Lokbondo Kungb339ed42024-09-06 02:49:19 +00001046 assert(sType === {{{ gpu.SType.RenderPassMaxDrawCount }}});
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001047 assert(0 === {{{ makeGetValue('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.next, '*') }}});
1048#endif
Lokbondo Kungb339ed42024-09-06 02:49:19 +00001049 var renderPassMaxDrawCount = nextInChainPtr;
1050 {{{ gpu.makeCheckDescriptor('renderPassMaxDrawCount') }}}
1051 maxDrawCount = {{{ gpu.makeGetU64('renderPassMaxDrawCount', C_STRUCTS.WGPURenderPassMaxDrawCount.maxDrawCount) }}};
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001052 }
1053
1054 var desc = {
1055 "label": undefined,
1056 "colorAttachments": makeColorAttachments(
1057 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderPassDescriptor.colorAttachmentCount) }}},
1058 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.colorAttachments, '*') }}}),
1059 "depthStencilAttachment": makeDepthStencilAttachment(
1060 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.depthStencilAttachment, '*') }}}),
Loko Kung424cda22024-08-17 01:29:10 +00001061 "occlusionQuerySet": WebGPU._tableGet(
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001062 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.occlusionQuerySet, '*') }}}),
1063 "timestampWrites": makeRenderPassTimestampWrites(
1064 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.timestampWrites, '*') }}}),
1065 "maxDrawCount": maxDrawCount,
1066 };
1067 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.label, '*') }}};
1068 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1069
1070 return desc;
1071 }
1072
1073 var desc = makeRenderPassDescriptor(descriptor);
1074
Loko Kung5a9506d2024-08-17 01:44:45 +00001075 var commandEncoder = WebGPU._tableGet(encoderPtr);
Loko Kung424cda22024-08-17 01:29:10 +00001076 var ptr = _emwgpuCreateRenderPassEncoder();
1077 WebGPU._tableInsert(ptr, commandEncoder.beginRenderPass(desc));
1078 return ptr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001079 },
1080
Loko Kung5a9506d2024-08-17 01:44:45 +00001081 wgpuCommandEncoderClearBuffer: (encoderPtr, bufferPtr, offset, size) => {
1082 var commandEncoder = WebGPU._tableGet(encoderPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001083 {{{ gpu.convertSentinelToUndefined('size') }}}
1084
Loko Kung5a9506d2024-08-17 01:44:45 +00001085 var buffer = WebGPU._tableGet(bufferPtr).object;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001086 commandEncoder.clearBuffer(buffer, offset, size);
1087 },
1088
Loko Kung5a9506d2024-08-17 01:44:45 +00001089 wgpuCommandEncoderCopyBufferToBuffer: (encoderPtr, srcPtr, srcOffset, dstPtr, dstOffset, size) => {
1090 var commandEncoder = WebGPU._tableGet(encoderPtr);
Kai Ninomiya622c78d2024-09-05 23:05:52 +00001091 var src = WebGPU._tableGet(srcPtr).object;
1092 var dst = WebGPU._tableGet(dstPtr).object;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001093 commandEncoder.copyBufferToBuffer(src, srcOffset, dst, dstOffset, size);
1094 },
1095
Loko Kung5a9506d2024-08-17 01:44:45 +00001096 wgpuCommandEncoderCopyBufferToTexture: (encoderPtr, srcPtr, dstPtr, copySizePtr) => {
1097 var commandEncoder = WebGPU._tableGet(encoderPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001098 var copySize = WebGPU.makeExtent3D(copySizePtr);
1099 commandEncoder.copyBufferToTexture(
1100 WebGPU.makeImageCopyBuffer(srcPtr), WebGPU.makeImageCopyTexture(dstPtr), copySize);
1101 },
1102
Loko Kung5a9506d2024-08-17 01:44:45 +00001103 wgpuCommandEncoderCopyTextureToBuffer: (encoderPtr, srcPtr, dstPtr, copySizePtr) => {
1104 var commandEncoder = WebGPU._tableGet(encoderPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001105 var copySize = WebGPU.makeExtent3D(copySizePtr);
1106 commandEncoder.copyTextureToBuffer(
1107 WebGPU.makeImageCopyTexture(srcPtr), WebGPU.makeImageCopyBuffer(dstPtr), copySize);
1108 },
1109
Loko Kung5a9506d2024-08-17 01:44:45 +00001110 wgpuCommandEncoderCopyTextureToTexture: (encoderPtr, srcPtr, dstPtr, copySizePtr) => {
1111 var commandEncoder = WebGPU._tableGet(encoderPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001112 var copySize = WebGPU.makeExtent3D(copySizePtr);
1113 commandEncoder.copyTextureToTexture(
1114 WebGPU.makeImageCopyTexture(srcPtr), WebGPU.makeImageCopyTexture(dstPtr), copySize);
1115 },
1116
Loko Kung424cda22024-08-17 01:29:10 +00001117 wgpuCommandEncoderFinish__deps: ['emwgpuCreateCommandBuffer'],
Loko Kung5a9506d2024-08-17 01:44:45 +00001118 wgpuCommandEncoderFinish: (encoderPtr, descriptor) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001119 // TODO: Use the descriptor.
Loko Kung5a9506d2024-08-17 01:44:45 +00001120 var commandEncoder = WebGPU._tableGet(encoderPtr);
Loko Kung424cda22024-08-17 01:29:10 +00001121 var ptr = _emwgpuCreateCommandBuffer();
1122 WebGPU._tableInsert(ptr, commandEncoder.finish());
1123 return ptr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001124 },
1125
Loko Kung5a9506d2024-08-17 01:44:45 +00001126 wgpuCommandEncoderInsertDebugMarker: (encoderPtr, markerLabelPtr) => {
1127 var encoder = WebGPU._tableGet(encoderPtr);
1128 encoder.insertDebugMarker(UTF8ToString(markerLabelPtr));
1129 },
1130
1131 wgpuCommandEncoderPopDebugGroup: (encoderPtr) => {
1132 var encoder = WebGPU._tableGet(encoderPtr);
1133 encoder.popDebugGroup();
1134 },
1135
1136 wgpuCommandEncoderPushDebugGroup: (encoderPtr, groupLabelPtr) => {
1137 var encoder = WebGPU._tableGet(encoderPtr);
1138 encoder.pushDebugGroup(UTF8ToString(groupLabelPtr));
1139 },
1140
1141 wgpuCommandEncoderResolveQuerySet: (encoderPtr, querySetPtr, firstQuery, queryCount, destinationPtr, destinationOffset) => {
1142 var commandEncoder = WebGPU._tableGet(encoderPtr);
1143 var querySet = WebGPU._tableGet(querySetPtr);
1144 var destination = WebGPU._tableGet(destinationPtr);
1145
1146 commandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset);
1147 },
1148
1149 wgpuCommandEncoderSetLabel: (encoderPtr, labelPtr) => {
1150 var commandEncoder = WebGPU._tableGet(encoderPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001151 commandEncoder.label = UTF8ToString(labelPtr);
1152 },
1153
Loko Kung5a9506d2024-08-17 01:44:45 +00001154 wgpuCommandEncoderWriteTimestamp: (encoderPtr, querySetPtr, queryIndex) => {
1155 var commandEncoder = WebGPU._tableGet(encoderPtr);
1156 var querySet = WebGPU._tableGet(querySetPtr);
1157 commandEncoder.writeTimestamp(querySet, queryIndex);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001158 },
1159
Loko Kung5a9506d2024-08-17 01:44:45 +00001160 // --------------------------------------------------------------------------
1161 // Methods of ComputePassEncoder
1162 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001163
Loko Kung5a9506d2024-08-17 01:44:45 +00001164 wgpuComputePassEncoderDispatchWorkgroups: (passPtr, x, y, z) => {
1165 var pass = WebGPU._tableGet(passPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001166 pass.dispatchWorkgroups(x, y, z);
1167 },
Loko Kung5a9506d2024-08-17 01:44:45 +00001168
1169 wgpuComputePassEncoderDispatchWorkgroupsIndirect: (passPtr, indirectBufferPtr, indirectOffset) => {
1170 var indirectBuffer = WebGPU._tableGet(indirectBufferPtr);
1171 var pass = WebGPU._tableGet(passPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001172 pass.dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset);
1173 },
1174
Loko Kung5a9506d2024-08-17 01:44:45 +00001175 wgpuComputePassEncoderEnd: (passPtr) => {
1176 var pass = WebGPU._tableGet(passPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001177 pass.end();
1178 },
1179
Loko Kung5a9506d2024-08-17 01:44:45 +00001180 wgpuComputePassEncoderInsertDebugMarker: (encoderPtr, markerLabelPtr) => {
1181 var encoder = WebGPU._tableGet(encoderPtr);
1182 encoder.insertDebugMarker(UTF8ToString(markerLabelPtr));
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001183 },
1184
Loko Kung5a9506d2024-08-17 01:44:45 +00001185 wgpuComputePassEncoderPopDebugGroup: (encoderPtr) => {
1186 var encoder = WebGPU._tableGet(encoderPtr);
1187 encoder.popDebugGroup();
1188 },
1189
1190 wgpuComputePassEncoderPushDebugGroup: (encoderPtr, groupLabelPtr) => {
1191 var encoder = WebGPU._tableGet(encoderPtr);
1192 encoder.pushDebugGroup(UTF8ToString(groupLabelPtr));
1193 },
1194
1195 wgpuComputePassEncoderSetBindGroup: (passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) => {
1196 var pass = WebGPU._tableGet(passPtr);
1197 var group = WebGPU._tableGet(groupPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001198 if (dynamicOffsetCount == 0) {
1199 pass.setBindGroup(groupIndex, group);
1200 } else {
1201 var offsets = [];
1202 for (var i = 0; i < dynamicOffsetCount; i++, dynamicOffsetsPtr += 4) {
1203 offsets.push({{{ gpu.makeGetU32('dynamicOffsetsPtr', 0) }}});
1204 }
1205 pass.setBindGroup(groupIndex, group, offsets);
1206 }
1207 },
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001208
Loko Kung5a9506d2024-08-17 01:44:45 +00001209 wgpuComputePassEncoderSetLabel: (passPtr, labelPtr) => {
1210 var pass = WebGPU._tableGet(passPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001211 pass.label = UTF8ToString(labelPtr);
1212 },
1213
Loko Kung5a9506d2024-08-17 01:44:45 +00001214 wgpuComputePassEncoderSetPipeline: (passPtr, pipelinePtr) => {
1215 var pass = WebGPU._tableGet(passPtr);
Loko Kung424cda22024-08-17 01:29:10 +00001216 var pipeline = WebGPU._tableGet(pipelinePtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001217 pass.setPipeline(pipeline);
1218 },
Loko Kung5a9506d2024-08-17 01:44:45 +00001219
1220 wgpuComputePassEncoderWriteTimestamp: (encoderPtr, querySetPtr, queryIndex) => {
1221 var encoder = WebGPU._tableGet(encoderPtr);
1222 var querySet = WebGPU._tableGet(querySetPtr);
1223 encoder.writeTimestamp(querySet, queryIndex);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001224 },
1225
Loko Kung5a9506d2024-08-17 01:44:45 +00001226 // --------------------------------------------------------------------------
1227 // Methods of ComputePipeline
1228 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001229
Loko Kung5a9506d2024-08-17 01:44:45 +00001230 wgpuComputePipelineGetBindGroupLayout__deps: ['emwgpuCreateBindGroupLayout'],
1231 wgpuComputePipelineGetBindGroupLayout: (pipelinePtr, groupIndex) => {
1232 var pipeline = WebGPU._tableGet(pipelinePtr);
1233 var ptr = _emwgpuCreateBindGroupLayout();
1234 WebGPU._tableInsert(ptr, pipeline.getBindGroupLayout(groupIndex));
Loko Kung424cda22024-08-17 01:29:10 +00001235 return ptr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001236 },
1237
Loko Kung5a9506d2024-08-17 01:44:45 +00001238 wgpuComputePipelineSetLabel: (pipelinePtr, labelPtr) => {
1239 var pipeline = WebGPU._tableGet(pipelinePtr);
1240 pipeline.label = UTF8ToString(labelPtr);
1241 },
1242
1243 // --------------------------------------------------------------------------
1244 // Methods of Device
1245 // --------------------------------------------------------------------------
1246
1247 wgpuDeviceCreateBindGroup__deps: ['$readI53FromI64', 'emwgpuCreateBindGroup'],
1248 wgpuDeviceCreateBindGroup: (devicePtr, descriptor) => {
1249 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1250
1251 function makeEntry(entryPtr) {
1252 {{{ gpu.makeCheck('entryPtr') }}}
1253
1254 var bufferPtr = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.buffer) }}};
1255 var samplerPtr = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.sampler) }}};
1256 var textureViewPtr = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.textureView) }}};
1257#if ASSERTIONS
1258 assert((bufferPtr !== 0) + (samplerPtr !== 0) + (textureViewPtr !== 0) === 1);
1259#endif
1260
1261 var binding = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.binding) }}};
1262
1263 if (bufferPtr) {
1264 var size = {{{ makeGetValue('entryPtr', C_STRUCTS.WGPUBindGroupEntry.size, 'i53') }}};
1265 {{{ gpu.convertSentinelToUndefined('size') }}}
1266
1267 return {
1268 "binding": binding,
1269 "resource": {
1270 "buffer": WebGPU._tableGet(bufferPtr).object,
1271 "offset": {{{ gpu.makeGetU64('entryPtr', C_STRUCTS.WGPUBindGroupEntry.offset) }}},
1272 "size": size
1273 },
1274 };
1275 } else if (samplerPtr) {
1276 return {
1277 "binding": binding,
1278 "resource": WebGPU._tableGet(samplerPtr),
1279 };
1280 } else {
1281 return {
1282 "binding": binding,
1283 "resource": WebGPU._tableGet(textureViewPtr),
1284 };
1285 }
1286 }
1287
1288 function makeEntries(count, entriesPtrs) {
1289 var entries = [];
1290 for (var i = 0; i < count; ++i) {
1291 entries.push(makeEntry(entriesPtrs +
1292 {{{C_STRUCTS.WGPUBindGroupEntry.__size__}}} * i));
1293 }
1294 return entries;
1295 }
1296
1297 var desc = {
1298 "label": undefined,
1299 "layout": WebGPU._tableGet(
1300 {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.layout, '*') }}}),
1301 "entries": makeEntries(
1302 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.entryCount) }}},
1303 {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.entries, '*') }}}
1304 ),
1305 };
1306 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.label, '*') }}};
1307 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1308
1309 var device = WebGPU._tableGet(devicePtr);
1310 var ptr = _emwgpuCreateBindGroup();
1311 WebGPU._tableInsert(ptr, device.createBindGroup(desc));
1312 return ptr;
1313 },
1314
1315 wgpuDeviceCreateBindGroupLayout__deps: ['emwgpuCreateBindGroupLayout'],
1316 wgpuDeviceCreateBindGroupLayout: (devicePtr, descriptor) => {
1317 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1318
1319 function makeBufferEntry(entryPtr) {
1320 {{{ gpu.makeCheck('entryPtr') }}}
1321
1322 var typeInt =
1323 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBufferBindingLayout.type) }}};
1324 if (!typeInt) return undefined;
1325
1326 return {
1327 "type": WebGPU.BufferBindingType[typeInt],
1328 "hasDynamicOffset":
1329 {{{ gpu.makeGetBool('entryPtr', C_STRUCTS.WGPUBufferBindingLayout.hasDynamicOffset) }}},
1330 "minBindingSize":
1331 {{{ gpu.makeGetU64('entryPtr', C_STRUCTS.WGPUBufferBindingLayout.minBindingSize) }}},
1332 };
1333 }
1334
1335 function makeSamplerEntry(entryPtr) {
1336 {{{ gpu.makeCheck('entryPtr') }}}
1337
1338 var typeInt =
1339 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUSamplerBindingLayout.type) }}};
1340 if (!typeInt) return undefined;
1341
1342 return {
1343 "type": WebGPU.SamplerBindingType[typeInt],
1344 };
1345 }
1346
1347 function makeTextureEntry(entryPtr) {
1348 {{{ gpu.makeCheck('entryPtr') }}}
1349
1350 var sampleTypeInt =
1351 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUTextureBindingLayout.sampleType) }}};
1352 if (!sampleTypeInt) return undefined;
1353
1354 return {
1355 "sampleType": WebGPU.TextureSampleType[sampleTypeInt],
1356 "viewDimension": WebGPU.TextureViewDimension[
1357 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUTextureBindingLayout.viewDimension) }}}],
1358 "multisampled":
1359 {{{ gpu.makeGetBool('entryPtr', C_STRUCTS.WGPUTextureBindingLayout.multisampled) }}},
1360 };
1361 }
1362
1363 function makeStorageTextureEntry(entryPtr) {
1364 {{{ gpu.makeCheck('entryPtr') }}}
1365
1366 var accessInt =
1367 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUStorageTextureBindingLayout.access) }}}
1368 if (!accessInt) return undefined;
1369
1370 return {
1371 "access": WebGPU.StorageTextureAccess[accessInt],
1372 "format": WebGPU.TextureFormat[
1373 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUStorageTextureBindingLayout.format) }}}],
1374 "viewDimension": WebGPU.TextureViewDimension[
1375 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUStorageTextureBindingLayout.viewDimension) }}}],
1376 };
1377 }
1378
1379 function makeEntry(entryPtr) {
1380 {{{ gpu.makeCheck('entryPtr') }}}
1381
1382 return {
1383 "binding":
1384 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupLayoutEntry.binding) }}},
1385 "visibility":
1386 {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupLayoutEntry.visibility) }}},
1387 "buffer": makeBufferEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.buffer }}}),
1388 "sampler": makeSamplerEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.sampler }}}),
1389 "texture": makeTextureEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.texture }}}),
1390 "storageTexture": makeStorageTextureEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.storageTexture }}}),
1391 };
1392 }
1393
1394 function makeEntries(count, entriesPtrs) {
1395 var entries = [];
1396 for (var i = 0; i < count; ++i) {
1397 entries.push(makeEntry(entriesPtrs +
1398 {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.__size__ }}} * i));
1399 }
1400 return entries;
1401 }
1402
1403 var desc = {
1404 "entries": makeEntries(
1405 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.entryCount) }}},
1406 {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.entries, '*') }}}
1407 ),
1408 };
1409 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.label, '*') }}};
1410 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1411
1412 var device = WebGPU._tableGet(devicePtr);
1413 var ptr = _emwgpuCreateBindGroupLayout();
1414 WebGPU._tableInsert(ptr, device.createBindGroupLayout(desc));
1415 return ptr;
1416 },
1417
1418 wgpuDeviceCreateBuffer__deps: ['emwgpuCreateBuffer'],
1419 wgpuDeviceCreateBuffer: (devicePtr, descriptor) => {
1420 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1421
1422 var mappedAtCreation = {{{ gpu.makeGetBool('descriptor', C_STRUCTS.WGPUBufferDescriptor.mappedAtCreation) }}};
1423
1424 var desc = {
1425 "label": undefined,
1426 "usage": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBufferDescriptor.usage) }}},
1427 "size": {{{ gpu.makeGetU64('descriptor', C_STRUCTS.WGPUBufferDescriptor.size) }}},
1428 "mappedAtCreation": mappedAtCreation,
1429 };
1430 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBufferDescriptor.label, '*') }}};
1431 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1432
1433 var device = WebGPU._tableGet(devicePtr);
1434 var bufferWrapper = {
1435 object: device.createBuffer(desc),
1436 };
1437 var ptr = _emwgpuCreateBuffer();
1438 WebGPU._tableInsert(ptr, bufferWrapper);
1439 if (mappedAtCreation) {
1440 bufferWrapper.mapMode = {{{ gpu.MapMode.Write }}};
1441 bufferWrapper.onUnmap = [];
1442 }
1443 return ptr;
1444 },
1445
1446 wgpuDeviceCreateCommandEncoder__deps: ['emwgpuCreateCommandEncoder'],
1447 wgpuDeviceCreateCommandEncoder: (devicePtr, descriptor) => {
1448 var desc;
1449 if (descriptor) {
1450 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1451 desc = {
1452 "label": undefined,
1453 };
1454 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUCommandEncoderDescriptor.label, '*') }}};
1455 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1456 }
1457 var device = WebGPU._tableGet(devicePtr);
1458 var ptr = _emwgpuCreateCommandEncoder();
1459 WebGPU._tableInsert(ptr, device.createCommandEncoder(desc));
1460 return ptr;
1461 },
1462
1463 wgpuDeviceCreateComputePipeline__deps: ['emwgpuCreateComputePipeline'],
1464 wgpuDeviceCreateComputePipeline: (devicePtr, descriptor) => {
1465 var desc = WebGPU.makeComputePipelineDesc(descriptor);
1466 var device = WebGPU._tableGet(devicePtr);
1467 var ptr = _emwgpuCreateComputePipeline();
1468 WebGPU._tableInsert(ptr, device.createComputePipeline(desc));
1469 return ptr;
1470 },
1471
1472 wgpuDeviceCreateComputePipelineAsync__deps: ['$callUserCallback', '$stringToUTF8OnStack', 'emwgpuCreateComputePipeline'],
1473 wgpuDeviceCreateComputePipelineAsync: (devicePtr, descriptor, callback, userdata) => {
1474 var desc = WebGPU.makeComputePipelineDesc(descriptor);
1475 var device = WebGPU._tableGet(devicePtr);
1476 {{{ runtimeKeepalivePush() }}}
1477 device.createComputePipelineAsync(desc).then((pipeline) => {
1478 {{{ runtimeKeepalivePop() }}}
1479 callUserCallback(() => {
1480 var ptr = _emwgpuCreateComputePipeline();
1481 WebGPU._tableInsert(ptr, pipeline);
1482 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Success }}}, ptr, 0, userdata);
1483 });
1484 }, (pipelineError) => {
1485 {{{ runtimeKeepalivePop() }}}
1486 callUserCallback(() => {
1487 var sp = stackSave();
1488 var messagePtr = stringToUTF8OnStack(pipelineError.message);
1489 if (pipelineError.reason === 'validation') {
1490 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.ValidationError }}}, 0, messagePtr, userdata);
1491 } else if (pipelineError.reason === 'internal') {
1492 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.InternalError }}}, 0, messagePtr, userdata);
1493 } else {
1494 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Unknown }}}, 0, messagePtr, userdata);
1495 }
1496 stackRestore(sp);
1497 });
1498 });
1499 },
1500
1501 wgpuDeviceCreatePipelineLayout__deps: ['emwgpuCreatePipelineLayout'],
1502 wgpuDeviceCreatePipelineLayout: (devicePtr, descriptor) => {
1503 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1504 var bglCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUPipelineLayoutDescriptor.bindGroupLayoutCount) }}};
1505 var bglPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUPipelineLayoutDescriptor.bindGroupLayouts, '*') }}};
1506 var bgls = [];
1507 for (var i = 0; i < bglCount; ++i) {
1508 bgls.push(WebGPU._tableGet(
1509 {{{ makeGetValue('bglPtr', `${POINTER_SIZE} * i`, '*') }}}));
1510 }
1511 var desc = {
1512 "label": undefined,
1513 "bindGroupLayouts": bgls,
1514 };
1515 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUPipelineLayoutDescriptor.label, '*') }}};
1516 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1517
1518 var device = WebGPU._tableGet(devicePtr);
1519 var ptr = _emwgpuCreatePipelineLayout();
1520 WebGPU._tableInsert(ptr, device.createPipelineLayout(desc));
1521 return ptr;
1522 },
1523
1524 wgpuDeviceCreateQuerySet__deps: ['emwgpuCreateQuerySet'],
1525 wgpuDeviceCreateQuerySet: (devicePtr, descriptor) => {
1526 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1527
1528 var desc = {
1529 "type": WebGPU.QueryType[
1530 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUQuerySetDescriptor.type) }}}],
1531 "count": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUQuerySetDescriptor.count) }}},
1532 };
1533
1534 var device = WebGPU._tableGet(devicePtr);
1535 var ptr = _emwgpuCreateQuerySet();
1536 WebGPU._tableInsert(ptr, device.createQuerySet(desc));
1537 return ptr;
1538 },
1539
1540 wgpuDeviceCreateRenderBundleEncoder__deps: ['emwgpuCreateRenderBundleEncoder'],
1541 wgpuDeviceCreateRenderBundleEncoder: (devicePtr, descriptor) => {
1542 {{{ gpu.makeCheck('descriptor') }}}
1543
1544 function makeRenderBundleEncoderDescriptor(descriptor) {
1545 {{{ gpu.makeCheck('descriptor') }}}
1546
1547 function makeColorFormats(count, formatsPtr) {
1548 var formats = [];
1549 for (var i = 0; i < count; ++i, formatsPtr += 4) {
1550 // format could be undefined
1551 formats.push(WebGPU.TextureFormat[{{{ gpu.makeGetU32('formatsPtr', 0) }}}]);
1552 }
1553 return formats;
1554 }
1555
1556 var desc = {
1557 "label": undefined,
1558 "colorFormats": makeColorFormats(
1559 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.colorFormatCount) }}},
1560 {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.colorFormats, '*') }}}),
1561 "depthStencilFormat": WebGPU.TextureFormat[{{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.depthStencilFormat) }}}],
1562 "sampleCount": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.sampleCount) }}},
1563 "depthReadOnly": {{{ gpu.makeGetBool('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.depthReadOnly) }}},
1564 "stencilReadOnly": {{{ gpu.makeGetBool('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.stencilReadOnly) }}},
1565 };
1566 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.label, '*') }}};
1567 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1568 return desc;
1569 }
1570
1571 var desc = makeRenderBundleEncoderDescriptor(descriptor);
1572 var device = WebGPU._tableGet(devicePtr);
1573 var ptr = _emwgpuCreateRenderBundleEncoder();
1574 WebGPU._tableInsert(ptr, device.createRenderBundleEncoder(desc));
1575 return ptr;
1576 },
1577
1578 wgpuDeviceCreateRenderPipeline__deps: ['emwgpuCreateRenderPipeline'],
1579 wgpuDeviceCreateRenderPipeline: (devicePtr, descriptor) => {
1580 var desc = WebGPU.makeRenderPipelineDesc(descriptor);
1581 var device = WebGPU._tableGet(devicePtr);
1582 var ptr = _emwgpuCreateRenderPipeline();
1583 WebGPU._tableInsert(ptr, device.createRenderPipeline(desc));
1584 return ptr;
1585 },
1586
1587 wgpuDeviceCreateRenderPipelineAsync__deps: ['$callUserCallback', '$stringToUTF8OnStack', 'emwgpuCreateRenderPipeline'],
1588 wgpuDeviceCreateRenderPipelineAsync: (devicePtr, descriptor, callback, userdata) => {
1589 var desc = WebGPU.makeRenderPipelineDesc(descriptor);
1590 var device = WebGPU._tableGet(devicePtr);
1591 {{{ runtimeKeepalivePush() }}}
1592 device.createRenderPipelineAsync(desc).then((pipeline) => {
1593 {{{ runtimeKeepalivePop() }}}
1594 callUserCallback(() => {
1595 var ptr = _emwgpuCreateRenderPipeline();
1596 WebGPU._tableInsert(ptr, pipeline);
1597 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Success }}}, ptr, 0, userdata);
1598 });
1599 }, (pipelineError) => {
1600 {{{ runtimeKeepalivePop() }}}
1601 callUserCallback(() => {
1602 var sp = stackSave();
1603 var messagePtr = stringToUTF8OnStack(pipelineError.message);
1604 if (pipelineError.reason === 'validation') {
1605 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.ValidationError }}}, 0, messagePtr, userdata);
1606 } else if (pipelineError.reason === 'internal') {
1607 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.InternalError }}}, 0, messagePtr, userdata);
1608 } else {
1609 {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Unknown }}}, 0, messagePtr, userdata);
1610 }
1611 stackRestore(sp);
1612 });
1613 });
1614 },
1615
1616 wgpuDeviceCreateSampler__deps: ['emwgpuCreateSampler'],
1617 wgpuDeviceCreateSampler: (devicePtr, descriptor) => {
1618 var desc;
1619 if (descriptor) {
1620 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1621
1622 desc = {
1623 "label": undefined,
1624 "addressModeU": WebGPU.AddressMode[
1625 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.addressModeU) }}}],
1626 "addressModeV": WebGPU.AddressMode[
1627 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.addressModeV) }}}],
1628 "addressModeW": WebGPU.AddressMode[
1629 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.addressModeW) }}}],
1630 "magFilter": WebGPU.FilterMode[
1631 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.magFilter) }}}],
1632 "minFilter": WebGPU.FilterMode[
1633 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.minFilter) }}}],
1634 "mipmapFilter": WebGPU.MipmapFilterMode[
1635 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.mipmapFilter) }}}],
1636 "lodMinClamp": {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSamplerDescriptor.lodMinClamp, 'float') }}},
1637 "lodMaxClamp": {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSamplerDescriptor.lodMaxClamp, 'float') }}},
1638 "compare": WebGPU.CompareFunction[
1639 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.compare) }}}],
1640 };
1641 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSamplerDescriptor.label, '*') }}};
1642 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1643 }
1644
1645 var device = WebGPU._tableGet(devicePtr);
1646 var ptr = _emwgpuCreateSampler();
1647 WebGPU._tableInsert(ptr, device.createSampler(desc));
1648 return ptr;
1649 },
1650
1651 wgpuDeviceCreateShaderModule__deps: ['emwgpuCreateShaderModule'],
1652 wgpuDeviceCreateShaderModule: (devicePtr, descriptor) => {
1653 {{{ gpu.makeCheck('descriptor') }}}
1654 var nextInChainPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUShaderModuleDescriptor.nextInChain, '*') }}};
1655#if ASSERTIONS
1656 assert(nextInChainPtr !== 0);
1657#endif
1658 var sType = {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}};
1659
1660 var desc = {
1661 "label": undefined,
1662 "code": "",
1663 };
1664 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUShaderModuleDescriptor.label, '*') }}};
1665 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1666
1667 switch (sType) {
Lokbondo Kungb339ed42024-09-06 02:49:19 +00001668 case {{{ gpu.SType.ShaderSourceSPIRV }}}: {
1669 var count = {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUShaderSourceSPIRV.codeSize) }}};
1670 var start = {{{ makeGetValue('nextInChainPtr', C_STRUCTS.WGPUShaderSourceSPIRV.code, '*') }}};
Loko Kung5a9506d2024-08-17 01:44:45 +00001671 var offset = {{{ getHeapOffset('start', 'u32') }}};
1672#if PTHREADS
1673 // Chrome can't currently handle a SharedArrayBuffer view here, so make a copy.
1674 desc["code"] = HEAPU32.slice(offset, offset + count);
1675#else
1676 desc["code"] = HEAPU32.subarray(offset, offset + count);
1677#endif
1678 break;
1679 }
Lokbondo Kungb339ed42024-09-06 02:49:19 +00001680 case {{{ gpu.SType.ShaderSourceWGSL }}}: {
1681 var sourcePtr = {{{ makeGetValue('nextInChainPtr', C_STRUCTS.WGPUShaderSourceWGSL.code, '*') }}};
Loko Kung5a9506d2024-08-17 01:44:45 +00001682 if (sourcePtr) {
1683 desc["code"] = UTF8ToString(sourcePtr);
1684 }
1685 break;
1686 }
1687#if ASSERTIONS
1688 default: abort('unrecognized ShaderModule sType');
1689#endif
1690 }
1691
1692 var device = WebGPU._tableGet(devicePtr);
1693 var ptr = _emwgpuCreateShaderModule();
1694 WebGPU._tableInsert(ptr, device.createShaderModule(desc));
1695 return ptr;
1696 },
1697
1698 wgpuDeviceCreateSwapChain__deps: ['emwgpuCreateSwapChain'],
1699 wgpuDeviceCreateSwapChain: (devicePtr, surfacePtr, descriptor) => {
1700 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1701 var device = WebGPU._tableGet(devicePtr);
1702 var context = WebGPU._tableGet(surfacePtr);
1703
1704#if ASSERTIONS
1705 assert({{{ gpu.PresentMode.Fifo }}} ===
1706 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.presentMode) }}});
1707#endif
1708
1709 var canvasSize = [
1710 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.width) }}},
1711 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.height) }}}
1712 ];
1713
1714 if (canvasSize[0] !== 0) {
1715 context["canvas"]["width"] = canvasSize[0];
1716 }
1717
1718 if (canvasSize[1] !== 0) {
1719 context["canvas"]["height"] = canvasSize[1];
1720 }
1721
1722 var configuration = {
1723 "device": device,
1724 "format": WebGPU.TextureFormat[
1725 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.format) }}}],
1726 "usage": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.usage) }}},
1727 "alphaMode": "opaque",
1728 };
1729 context.configure(configuration);
1730
1731 var ptr = _emwgpuCreateSwapChain();
1732 WebGPU._tableInsert(ptr, context);
1733 return ptr;
1734 },
1735
1736 wgpuDeviceCreateTexture__deps: ['emwgpuCreateTexture'],
1737 wgpuDeviceCreateTexture: (devicePtr, descriptor) => {
1738 {{{ gpu.makeCheckDescriptor('descriptor') }}}
1739
1740 var desc = {
1741 "label": undefined,
1742 "size": WebGPU.makeExtent3D(descriptor + {{{ C_STRUCTS.WGPUTextureDescriptor.size }}}),
1743 "mipLevelCount": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.mipLevelCount) }}},
1744 "sampleCount": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.sampleCount) }}},
1745 "dimension": WebGPU.TextureDimension[
1746 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.dimension) }}}],
1747 "format": WebGPU.TextureFormat[
1748 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.format) }}}],
1749 "usage": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.usage) }}},
1750 };
1751 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUTextureDescriptor.label, '*') }}};
1752 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
1753
1754 var viewFormatCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.viewFormatCount) }}};
1755 if (viewFormatCount) {
1756 var viewFormatsPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUTextureDescriptor.viewFormats, '*') }}};
1757 // viewFormatsPtr pointer to an array of TextureFormat which is an enum of size uint32_t
1758 desc["viewFormats"] = Array.from({{{ makeHEAPView('32', 'viewFormatsPtr', `viewFormatsPtr + viewFormatCount * 4`) }}},
1759 function(format) { return WebGPU.TextureFormat[format]; });
1760 }
1761
1762 var device = WebGPU._tableGet(devicePtr);
1763 var ptr = _emwgpuCreateTexture();
1764 WebGPU._tableInsert(ptr, device.createTexture(desc));
1765 return ptr;
1766 },
1767
1768 wgpuDeviceDestroy: (devicePtr) => {
1769 WebGPU._tableGet(devicePtr).destroy()
1770 },
1771
1772 wgpuDeviceEnumerateFeatures: (devicePtr, featuresOutPtr) => {
1773 var device = WebGPU._tableGet(devicePtr);
1774 if (featuresOutPtr !== 0) {
1775 var offset = 0;
1776 device.features.forEach(feature => {
1777 var featureEnumValue = WebGPU.FeatureNameString2Enum[feature];
1778 {{{ makeSetValue('featuresOutPtr', 'offset', 'featureEnumValue', 'i32') }}};
1779 offset += 4;
1780 });
1781 }
1782 return device.features.size;
1783 },
1784
1785 wgpuDeviceGetLimits: (devicePtr, limitsOutPtr) => {
1786 var device = WebGPU._tableGet(devicePtr);
1787 WebGPU.fillLimitStruct(device.limits, limitsOutPtr);
1788 return 1;
1789 },
1790
1791 wgpuDeviceHasFeature: (devicePtr, featureEnumValue) => {
1792 var device = WebGPU._tableGet(devicePtr);
1793 return device.features.has(WebGPU.FeatureName[featureEnumValue]);
1794 },
1795
1796 wgpuDevicePopErrorScope__deps: ['$callUserCallback'],
1797 wgpuDevicePopErrorScope: (devicePtr, callback, userdata) => {
1798 var device = WebGPU._tableGet(devicePtr);
1799 {{{ runtimeKeepalivePush() }}}
1800 device.popErrorScope().then((gpuError) => {
1801 {{{ runtimeKeepalivePop() }}}
1802 callUserCallback(() => {
1803 if (!gpuError) {
1804 {{{ makeDynCall('vipp', 'callback') }}}(
1805 {{{ gpu.ErrorType.NoError }}}, 0, userdata);
1806 } else if (gpuError instanceof GPUOutOfMemoryError) {
1807 {{{ makeDynCall('vipp', 'callback') }}}(
1808 {{{ gpu.ErrorType.OutOfMemory }}}, 0, userdata);
1809 } else {
1810#if ASSERTIONS
1811 // TODO: Implement GPUInternalError
1812 assert(gpuError instanceof GPUValidationError);
1813#endif
1814 WebGPU.errorCallback(callback, {{{ gpu.ErrorType.Validation }}}, gpuError.message, userdata);
1815 }
1816 });
1817 }, (ex) => {
1818 {{{ runtimeKeepalivePop() }}}
1819 callUserCallback(() => {
1820 // TODO: This can mean either the device was lost or the error scope stack was empty. Figure
1821 // out how to synthesize the DeviceLost error type. (Could be by simply tracking the error
1822 // scope depth, but that isn't ideal.)
1823 WebGPU.errorCallback(callback, {{{ gpu.ErrorType.Unknown }}}, ex.message, userdata);
1824 });
1825 });
1826 },
1827
1828 wgpuDevicePushErrorScope: (devicePtr, filter) => {
1829 var device = WebGPU._tableGet(devicePtr);
1830 device.pushErrorScope(WebGPU.ErrorFilter[filter]);
1831 },
1832
1833 wgpuDeviceSetLabel: (devicePtr, labelPtr) => {
1834 var device = WebGPU._tableGet(devicePtr);
1835 device.label = UTF8ToString(labelPtr);
1836 },
1837
Lokbondo Kunga8fbe982024-08-30 04:46:53 +00001838 // TODO(42241415) Remove this after verifying that it's not used and/or updating users.
Loko Kung5a9506d2024-08-17 01:44:45 +00001839 wgpuDeviceSetUncapturedErrorCallback__deps: ['$callUserCallback'],
1840 wgpuDeviceSetUncapturedErrorCallback: (devicePtr, callback, userdata) => {
1841 var device = WebGPU._tableGet(devicePtr);
1842 device.onuncapturederror = function(ev) {
1843 // This will skip the callback if the runtime is no longer alive.
1844 callUserCallback(() => {
1845 // WGPUErrorType type, const char* message, void* userdata
1846 var Validation = 0x00000001;
1847 var OutOfMemory = 0x00000002;
1848 var type;
1849#if ASSERTIONS
1850 assert(typeof GPUValidationError != 'undefined');
1851 assert(typeof GPUOutOfMemoryError != 'undefined');
1852#endif
1853 if (ev.error instanceof GPUValidationError) type = Validation;
1854 else if (ev.error instanceof GPUOutOfMemoryError) type = OutOfMemory;
1855 // TODO: Implement GPUInternalError
1856
1857 WebGPU.errorCallback(callback, type, ev.error.message, userdata);
1858 });
1859 };
1860 },
1861
1862 // --------------------------------------------------------------------------
1863 // Methods of Instance
1864 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001865
Loko Kung424cda22024-08-17 01:29:10 +00001866 wgpuInstanceCreateSurface__deps: ['$findCanvasEventTarget', 'emwgpuCreateSurface'],
Loko Kung5a9506d2024-08-17 01:44:45 +00001867 wgpuInstanceCreateSurface: (instancePtr, descriptor) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001868 {{{ gpu.makeCheck('descriptor') }}}
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001869 var nextInChainPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSurfaceDescriptor.nextInChain, '*') }}};
1870#if ASSERTIONS
1871 assert(nextInChainPtr !== 0);
Lokbondo Kungb339ed42024-09-06 02:49:19 +00001872 assert({{{ gpu.SType.SurfaceSourceCanvasHTMLSelector_Emscripten }}} ===
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001873 {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}});
1874#endif
Lokbondo Kungb339ed42024-09-06 02:49:19 +00001875 var sourceCanvasHTMLSelector = nextInChainPtr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001876
Lokbondo Kungb339ed42024-09-06 02:49:19 +00001877 {{{ gpu.makeCheckDescriptor('sourceCanvasHTMLSelector') }}}
1878 var selectorPtr = {{{ makeGetValue('sourceCanvasHTMLSelector', C_STRUCTS.WGPUSurfaceSourceCanvasHTMLSelector_Emscripten.selector, '*') }}};
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001879 {{{ gpu.makeCheck('selectorPtr') }}}
1880 var canvas = findCanvasEventTarget(selectorPtr);
1881#if OFFSCREENCANVAS_SUPPORT
1882 if (canvas.offscreenCanvas) canvas = canvas.offscreenCanvas;
1883#endif
1884 var context = canvas.getContext('webgpu');
1885#if ASSERTIONS
1886 assert(context);
1887#endif
1888 if (!context) return 0;
1889
1890 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSurfaceDescriptor.label, '*') }}};
1891 if (labelPtr) context.surfaceLabelWebGPU = UTF8ToString(labelPtr);
1892
Loko Kung424cda22024-08-17 01:29:10 +00001893 var ptr = _emwgpuCreateSurface();
1894 WebGPU._tableInsert(ptr, context);
1895 return ptr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001896 },
1897
1898 wgpuInstanceHasWGSLLanguageFeature: (instance, featureEnumValue) => {
1899 if (!('wgslLanguageFeatures' in navigator["gpu"])) {
1900 return false;
1901 }
1902 return navigator["gpu"]["wgslLanguageFeatures"].has(WebGPU.WGSLFeatureName[featureEnumValue]);
1903 },
1904
Loko Kung859fb302024-08-17 01:44:58 +00001905 emwgpuInstanceRequestAdapter__i53abi: false,
Kai Ninomiya622c78d2024-09-05 23:05:52 +00001906 emwgpuInstanceRequestAdapter__deps: ['$withStackSave', '$callUserCallback', '$stringToUTF8OnStack', 'emwgpuCreateAdapter', 'emwgpuOnRequestAdapterCompleted'],
Loko Kung859fb302024-08-17 01:44:58 +00001907 emwgpuInstanceRequestAdapter: (instancePtr, futureIdL, futureIdH, options) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001908 var opts;
1909 if (options) {
1910 {{{ gpu.makeCheckDescriptor('options') }}}
1911 opts = {
1912 "powerPreference": WebGPU.PowerPreference[
1913 {{{ gpu.makeGetU32('options', C_STRUCTS.WGPURequestAdapterOptions.powerPreference) }}}],
1914 "forceFallbackAdapter":
1915 {{{ gpu.makeGetBool('options', C_STRUCTS.WGPURequestAdapterOptions.forceFallbackAdapter) }}},
1916 };
1917 }
1918
1919 if (!('gpu' in navigator)) {
Loko Kung859fb302024-08-17 01:44:58 +00001920 withStackSave(() => {
1921 var messagePtr = stringToUTF8OnStack('WebGPU not available on this browser (navigator.gpu is not available)');
1922 _emwgpuOnRequestAdapterCompleted(futureIdL, futureIdH, {{{ gpu.RequestAdapterStatus.Unavailable }}}, 0, messagePtr);
1923 });
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001924 return;
1925 }
1926
1927 {{{ runtimeKeepalivePush() }}}
Loko Kung859fb302024-08-17 01:44:58 +00001928 WebGPU._futureInsert(futureIdL, futureIdH, navigator["gpu"]["requestAdapter"](opts).then((adapter) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001929 {{{ runtimeKeepalivePop() }}}
Loko Kung859fb302024-08-17 01:44:58 +00001930 if (adapter) {
Lokbondo Kunga8fbe982024-08-30 04:46:53 +00001931 var adapterPtr = _emwgpuCreateAdapter(instancePtr);
Loko Kung859fb302024-08-17 01:44:58 +00001932 WebGPU._tableInsert(adapterPtr, adapter);
1933 _emwgpuOnRequestAdapterCompleted(futureIdL, futureIdH, {{{ gpu.RequestAdapterStatus.Success }}}, adapterPtr, 0);
1934 } else {
1935 withStackSave(() => {
1936 var messagePtr = stringToUTF8OnStack('WebGPU not available on this browser (requestAdapter returned null)');
1937 _emwgpuOnRequestAdapterCompleted(futureIdL, futureIdH, {{{ gpu.RequestAdapterStatus.Unavailable }}}, 0, messagePtr);
1938 });
1939 }
1940 return;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001941 }, (ex) => {
1942 {{{ runtimeKeepalivePop() }}}
Loko Kung859fb302024-08-17 01:44:58 +00001943 withStackSave(() => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001944 var messagePtr = stringToUTF8OnStack(ex.message);
Loko Kung859fb302024-08-17 01:44:58 +00001945 _emwgpuOnRequestAdapterCompleted(futureIdL, futureIdH, {{{ gpu.RequestAdapterStatus.Error }}}, 0, messagePtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001946 });
Loko Kung859fb302024-08-17 01:44:58 +00001947 return;
1948 }));
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001949 },
1950
Loko Kung5a9506d2024-08-17 01:44:45 +00001951 // --------------------------------------------------------------------------
1952 // Methods of PipelineLayout
1953 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001954
Loko Kung5a9506d2024-08-17 01:44:45 +00001955 wgpuPipelineLayoutSetLabel: (pipelineLayoutPtr, labelPtr) => {
1956 var pipelineLayout = WebGPU._tableGet(pipelineLayoutPtr);
1957 pipelineLayout.label = UTF8ToString(labelPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001958 },
1959
Loko Kung5a9506d2024-08-17 01:44:45 +00001960 // --------------------------------------------------------------------------
1961 // Methods of QuerySet
1962 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001963
Loko Kung5a9506d2024-08-17 01:44:45 +00001964 wgpuQuerySetDestroy: (querySetPtr) => {
1965 WebGPU._tableGet(querySetPtr).destroy();
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001966 },
1967
Loko Kung5a9506d2024-08-17 01:44:45 +00001968 wgpuQuerySetGetCount: (querySetPtr) => {
1969 var querySet = WebGPU._tableGet(querySetPtr);
1970 return querySet.count;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001971 },
1972
Loko Kung5a9506d2024-08-17 01:44:45 +00001973 wgpuQuerySetGetType: (querySetPtr, labelPtr) => {
1974 var querySet = WebGPU._tableGet(querySetPtr);
1975 return querySet.type;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001976 },
1977
Loko Kung5a9506d2024-08-17 01:44:45 +00001978 wgpuQuerySetSetLabel: (querySetPtr, labelPtr) => {
1979 var querySet = WebGPU._tableGet(querySetPtr);
1980 querySet.label = UTF8ToString(labelPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001981 },
1982
Loko Kung5a9506d2024-08-17 01:44:45 +00001983 // --------------------------------------------------------------------------
1984 // Methods of Queue
1985 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001986
Loko Kung5a9506d2024-08-17 01:44:45 +00001987 wgpuQueueOnSubmittedWorkDone__deps: ['$callUserCallback'],
1988 wgpuQueueOnSubmittedWorkDone: (queuePtr, callback, userdata) => {
1989 var queue = WebGPU._tableGet(queuePtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001990
1991 {{{ runtimeKeepalivePush() }}}
Loko Kung5a9506d2024-08-17 01:44:45 +00001992 queue.onSubmittedWorkDone().then(() => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001993 {{{ runtimeKeepalivePop() }}}
1994 callUserCallback(() => {
Loko Kung5a9506d2024-08-17 01:44:45 +00001995 {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.QueueWorkDoneStatus.Success }}}, userdata);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001996 });
Loko Kung5a9506d2024-08-17 01:44:45 +00001997 }, () => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00001998 {{{ runtimeKeepalivePop() }}}
1999 callUserCallback(() => {
Loko Kung5a9506d2024-08-17 01:44:45 +00002000 {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.QueueWorkDoneStatus.Error }}}, userdata);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002001 });
2002 });
2003 },
2004
Loko Kung5a9506d2024-08-17 01:44:45 +00002005 wgpuQueueSetLabel: (queuePtr, labelPtr) => {
2006 var queue = WebGPU._tableGet(queuePtr);
2007 queue.label = UTF8ToString(labelPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002008 },
2009
Loko Kung5a9506d2024-08-17 01:44:45 +00002010 wgpuQueueSubmit: (queuePtr, commandCount, commands) => {
2011#if ASSERTIONS
2012 assert(commands % 4 === 0);
2013#endif
2014 var queue = WebGPU._tableGet(queuePtr);
2015 var cmds = Array.from({{{ makeHEAPView(`${POINTER_BITS}`, 'commands', `commands + commandCount * ${POINTER_SIZE}`)}}},
2016 (id) => WebGPU._tableGet(id));
2017 queue.submit(cmds);
2018 },
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002019
Loko Kung5a9506d2024-08-17 01:44:45 +00002020 wgpuQueueWriteBuffer: (queuePtr, bufferPtr, bufferOffset, data, size) => {
2021 var queue = WebGPU._tableGet(queuePtr);
2022 var buffer = WebGPU._tableGet(bufferPtr).object;
2023 // There is a size limitation for ArrayBufferView. Work around by passing in a subarray
2024 // instead of the whole heap. crbug.com/1201109
2025 var subarray = HEAPU8.subarray(data, data + size);
2026 queue.writeBuffer(buffer, bufferOffset, subarray, 0, size);
2027 },
2028
2029 wgpuQueueWriteTexture: (queuePtr, destinationPtr, data, dataSize, dataLayoutPtr, writeSizePtr) => {
2030 var queue = WebGPU._tableGet(queuePtr);
2031
2032 var destination = WebGPU.makeImageCopyTexture(destinationPtr);
2033 var dataLayout = WebGPU.makeTextureDataLayout(dataLayoutPtr);
2034 var writeSize = WebGPU.makeExtent3D(writeSizePtr);
2035 // This subarray isn't strictly necessary, but helps work around an issue
2036 // where Chromium makes a copy of the entire heap. crbug.com/1134457
2037 var subarray = HEAPU8.subarray(data, data + dataSize);
2038 queue.writeTexture(destination, subarray, dataLayout, writeSize);
2039 },
2040
2041 // --------------------------------------------------------------------------
2042 // Methods of RenderBundle
2043 // --------------------------------------------------------------------------
2044
2045 wgpuRenderBundleSetLabel: (bundlePtr, labelPtr) => {
2046 var bundle = WebGPU._tableGet(bundlePtr);
2047 bundle.label = UTF8ToString(labelPtr);
2048 },
2049
2050 // --------------------------------------------------------------------------
2051 // Methods of RenderBundleEncoder
2052 // --------------------------------------------------------------------------
2053
2054 wgpuRenderBundleEncoderDraw: (passPtr, vertexCount, instanceCount, firstVertex, firstInstance) => {
2055 var pass = WebGPU._tableGet(passPtr);
2056 pass.draw(vertexCount, instanceCount, firstVertex, firstInstance);
2057 },
2058
2059 wgpuRenderBundleEncoderDrawIndexed: (passPtr, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => {
2060 var pass = WebGPU._tableGet(passPtr);
2061 pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
2062 },
2063
2064 wgpuRenderBundleEncoderDrawIndexedIndirect: (passPtr, indirectBufferPtr, indirectOffset) => {
2065 var indirectBuffer = WebGPU._tableGet(indirectBufferPtr);
2066 var pass = WebGPU._tableGet(passPtr);
2067 pass.drawIndexedIndirect(indirectBuffer, indirectOffset);
2068 },
2069
2070 wgpuRenderBundleEncoderDrawIndirect: (passPtr, indirectBufferPtr, indirectOffset) => {
2071 var indirectBuffer = WebGPU._tableGet(indirectBufferPtr);
2072 var pass = WebGPU._tableGet(passPtr);
2073 pass.drawIndirect(indirectBuffer, indirectOffset);
2074 },
2075
2076 wgpuRenderBundleEncoderFinish__deps: ['emwgpuCreateRenderBundle'],
2077 wgpuRenderBundleEncoderFinish: (encoderPtr, descriptor) => {
2078 var desc;
2079 if (descriptor) {
2080 {{{ gpu.makeCheckDescriptor('descriptor') }}}
2081 desc = {};
2082 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderBundleDescriptor.label, '*') }}};
2083 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
2084 }
2085 var encoder = WebGPU._tableGet(encoderPtr);
2086 var ptr = _emwgpuCreateRenderBundle();
2087 WebGPU._tableInsert(ptr, encoder.finish(desc));
2088 return ptr;
2089 },
2090
2091 wgpuRenderBundleEncoderInsertDebugMarker: (encoderPtr, markerLabelPtr) => {
2092 var encoder = WebGPU._tableGet(encoderPtr);
2093 encoder.insertDebugMarker(UTF8ToString(markerLabelPtr));
2094 },
2095
2096 wgpuRenderBundleEncoderPopDebugGroup: (encoderPtr) => {
2097 var encoder = WebGPU._tableGet(encoderPtr);
2098 encoder.popDebugGroup();
2099 },
2100
2101 wgpuRenderBundleEncoderPushDebugGroup: (encoderPtr, groupLabelPtr) => {
2102 var encoder = WebGPU._tableGet(encoderPtr);
2103 encoder.pushDebugGroup(UTF8ToString(groupLabelPtr));
2104 },
2105
2106 wgpuRenderBundleEncoderSetBindGroup: (passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) => {
2107 var pass = WebGPU._tableGet(passPtr);
2108 var group = WebGPU._tableGet(groupPtr);
2109 if (dynamicOffsetCount == 0) {
2110 pass.setBindGroup(groupIndex, group);
2111 } else {
2112 var offsets = [];
2113 for (var i = 0; i < dynamicOffsetCount; i++, dynamicOffsetsPtr += 4) {
2114 offsets.push({{{ gpu.makeGetU32('dynamicOffsetsPtr', 0) }}});
2115 }
2116 pass.setBindGroup(groupIndex, group, offsets);
2117 }
2118 },
2119
2120 wgpuRenderBundleEncoderSetIndexBuffer: (passPtr, bufferPtr, format, offset, size) => {
2121 var pass = WebGPU._tableGet(passPtr);
2122 var buffer = WebGPU._tableGet(bufferPtr).object;
2123 {{{ gpu.convertSentinelToUndefined('size') }}}
2124 pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size);
2125 },
2126
2127 wgpuRenderBundleEncoderSetLabel: (passPtr, labelPtr) => {
2128 var pass = WebGPU._tableGet(passPtr);
2129 pass.label = UTF8ToString(labelPtr);
2130 },
2131
2132 wgpuRenderBundleEncoderSetPipeline: (passPtr, pipelinePtr) => {
2133 var pass = WebGPU._tableGet(passPtr);
2134 var pipeline = WebGPU._tableGet(pipelinePtr);
2135 pass.setPipeline(pipeline);
2136 },
2137
2138 wgpuRenderBundleEncoderSetVertexBuffer: (passPtr, slot, bufferPtr, offset, size) => {
2139 var pass = WebGPU._tableGet(passPtr);
2140 var buffer = WebGPU._tableGet(bufferPtr).object;
2141 {{{ gpu.convertSentinelToUndefined('size') }}}
2142 pass.setVertexBuffer(slot, buffer, offset, size);
2143 },
2144
2145 // --------------------------------------------------------------------------
2146 // Methods of RenderPassEncoder
2147 // --------------------------------------------------------------------------
2148
2149 wgpuRenderPassEncoderBeginOcclusionQuery: (passPtr, queryIndex) => {
2150 var pass = WebGPU._tableGet(passPtr);
2151 pass.beginOcclusionQuery(queryIndex);
2152 },
2153
2154 wgpuRenderPassEncoderDraw: (passPtr, vertexCount, instanceCount, firstVertex, firstInstance) => {
2155 var pass = WebGPU._tableGet(passPtr);
2156 pass.draw(vertexCount, instanceCount, firstVertex, firstInstance);
2157 },
2158
2159 wgpuRenderPassEncoderDrawIndexed: (passPtr, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => {
2160 var pass = WebGPU._tableGet(passPtr);
2161 pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
2162 },
2163
2164 wgpuRenderPassEncoderDrawIndexedIndirect: (passPtr, indirectBufferPtr, indirectOffset) => {
2165 var indirectBuffer = WebGPU._tableGet(indirectBufferPtr);
2166 var pass = WebGPU._tableGet(passPtr);
2167 pass.drawIndexedIndirect(indirectBuffer, indirectOffset);
2168 },
2169
2170 wgpuRenderPassEncoderDrawIndirect: (passPtr, indirectBufferPtr, indirectOffset) => {
2171 var indirectBuffer = WebGPU._tableGet(indirectBufferPtr);
2172 var pass = WebGPU._tableGet(passPtr);
2173 pass.drawIndirect(indirectBuffer, indirectOffset);
2174 },
2175
2176 wgpuRenderPassEncoderEnd: (encoderPtr) => {
2177 var encoder = WebGPU._tableGet(encoderPtr);
2178 encoder.end();
2179 },
2180
2181 wgpuRenderPassEncoderEndOcclusionQuery: (passPtr) => {
2182 var pass = WebGPU._tableGet(passPtr);
2183 pass.endOcclusionQuery();
2184 },
2185
2186 wgpuRenderPassEncoderExecuteBundles: (passPtr, count, bundlesPtr) => {
2187 var pass = WebGPU._tableGet(passPtr);
2188
2189#if ASSERTIONS
2190 assert(bundlesPtr % 4 === 0);
2191#endif
2192
2193 var bundles = Array.from({{{ makeHEAPView(`${POINTER_BITS}`, 'bundlesPtr', `bundlesPtr + count * ${POINTER_SIZE}`) }}},
2194 (id) => WebGPU._tableGet(id));
2195 pass.executeBundles(bundles);
2196 },
2197
2198 wgpuRenderPassEncoderInsertDebugMarker: (encoderPtr, markerLabelPtr) => {
2199 var encoder = WebGPU._tableGet(encoderPtr);
2200 encoder.insertDebugMarker(UTF8ToString(markerLabelPtr));
2201 },
2202
2203 wgpuRenderPassEncoderPopDebugGroup: (encoderPtr) => {
2204 var encoder = WebGPU._tableGet(encoderPtr);
2205 encoder.popDebugGroup();
2206 },
2207
2208 wgpuRenderPassEncoderPushDebugGroup: (encoderPtr, groupLabelPtr) => {
2209 var encoder = WebGPU._tableGet(encoderPtr);
2210 encoder.pushDebugGroup(UTF8ToString(groupLabelPtr));
2211 },
2212
2213 wgpuRenderPassEncoderSetBindGroup: (passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) => {
2214 var pass = WebGPU._tableGet(passPtr);
2215 var group = WebGPU._tableGet(groupPtr);
2216 if (dynamicOffsetCount == 0) {
2217 pass.setBindGroup(groupIndex, group);
2218 } else {
2219 var offsets = [];
2220 for (var i = 0; i < dynamicOffsetCount; i++, dynamicOffsetsPtr += 4) {
2221 offsets.push({{{ gpu.makeGetU32('dynamicOffsetsPtr', 0) }}});
2222 }
2223 pass.setBindGroup(groupIndex, group, offsets);
2224 }
2225 },
2226
2227 wgpuRenderPassEncoderSetBlendConstant: (passPtr, colorPtr) => {
2228 var pass = WebGPU._tableGet(passPtr);
2229 var color = WebGPU.makeColor(colorPtr);
2230 pass.setBlendConstant(color);
2231 },
2232
2233 wgpuRenderPassEncoderSetIndexBuffer: (passPtr, bufferPtr, format, offset, size) => {
2234 var pass = WebGPU._tableGet(passPtr);
2235 var buffer = WebGPU._tableGet(bufferPtr).object;
2236 {{{ gpu.convertSentinelToUndefined('size') }}}
2237 pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size);
2238 },
2239
2240 wgpuRenderPassEncoderSetLabel: (passPtr, labelPtr) => {
2241 var pass = WebGPU._tableGet(passPtr);
2242 pass.label = UTF8ToString(labelPtr);
2243 },
2244
2245 wgpuRenderPassEncoderSetPipeline: (passPtr, pipelinePtr) => {
2246 var pass = WebGPU._tableGet(passPtr);
2247 var pipeline = WebGPU._tableGet(pipelinePtr);
2248 pass.setPipeline(pipeline);
2249 },
2250
2251 wgpuRenderPassEncoderSetScissorRect: (passPtr, x, y, w, h) => {
2252 var pass = WebGPU._tableGet(passPtr);
2253 pass.setScissorRect(x, y, w, h);
2254 },
2255
2256 wgpuRenderPassEncoderSetStencilReference: (passPtr, reference) => {
2257 var pass = WebGPU._tableGet(passPtr);
2258 pass.setStencilReference(reference);
2259 },
2260
2261 wgpuRenderPassEncoderSetVertexBuffer: (passPtr, slot, bufferPtr, offset, size) => {
2262 var pass = WebGPU._tableGet(passPtr);
2263 var buffer = WebGPU._tableGet(bufferPtr).object;
2264 {{{ gpu.convertSentinelToUndefined('size') }}}
2265 pass.setVertexBuffer(slot, buffer, offset, size);
2266 },
2267
2268 wgpuRenderPassEncoderSetViewport: (passPtr, x, y, w, h, minDepth, maxDepth) => {
2269 var pass = WebGPU._tableGet(passPtr);
2270 pass.setViewport(x, y, w, h, minDepth, maxDepth);
2271 },
2272
2273 wgpuRenderPassEncoderWriteTimestamp: (encoderPtr, querySetPtr, queryIndex) => {
2274 var encoder = WebGPU._tableGet(encoderPtr);
2275 var querySet = WebGPU._tableGet(querySetPtr);
2276 encoder.writeTimestamp(querySet, queryIndex);
2277 },
2278
2279 // --------------------------------------------------------------------------
2280 // Methods of RenderPipeline
2281 // --------------------------------------------------------------------------
2282
2283 wgpuRenderPipelineGetBindGroupLayout__deps: ['emwgpuCreateBindGroupLayout'],
2284 wgpuRenderPipelineGetBindGroupLayout: (pipelinePtr, groupIndex) => {
2285 var pipeline = WebGPU._tableGet(pipelinePtr);
2286 var ptr = _emwgpuCreateBindGroupLayout();
2287 WebGPU._tableInsert(ptr, pipeline.getBindGroupLayout(groupIndex));
2288 },
2289
2290 wgpuRenderPipelineSetLabel: (pipelinePtr, labelPtr) => {
2291 var pipeline = WebGPU._tableGet(pipelinePtr);
2292 pipeline.label = UTF8ToString(labelPtr);
2293 },
2294
2295 // --------------------------------------------------------------------------
2296 // Methods of Sampler
2297 // --------------------------------------------------------------------------
2298
2299 wgpuSamplerSetLabel: (samplerPtr, labelPtr) => {
2300 var sampler = WebGPU._tableGet(samplerPtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002301 sampler.label = UTF8ToString(labelPtr);
2302 },
2303
Loko Kung5a9506d2024-08-17 01:44:45 +00002304 // --------------------------------------------------------------------------
2305 // Methods of ShaderModule
2306 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002307
Loko Kung5a9506d2024-08-17 01:44:45 +00002308 wgpuShaderModuleGetCompilationInfo__deps: ['$callUserCallback', '$stringToUTF8', '$lengthBytesUTF8', 'malloc', 'free'],
2309 wgpuShaderModuleGetCompilationInfo: (shaderModulePtr, callback, userdata) => {
2310 var shaderModule = WebGPU._tableGet(shaderModulePtr);
2311 {{{ runtimeKeepalivePush() }}}
2312 shaderModule.getCompilationInfo().then((compilationInfo) => {
2313 {{{ runtimeKeepalivePop() }}}
2314 callUserCallback(() => {
2315 var compilationMessagesPtr = _malloc({{{ C_STRUCTS.WGPUCompilationMessage.__size__ }}} * compilationInfo.messages.length);
2316 var messageStringPtrs = []; // save these to free later
2317 for (var i = 0; i < compilationInfo.messages.length; ++i) {
2318 var compilationMessage = compilationInfo.messages[i];
2319 var compilationMessagePtr = compilationMessagesPtr + {{{ C_STRUCTS.WGPUCompilationMessage.__size__ }}} * i;
2320 var messageSize = lengthBytesUTF8(compilationMessage.message) + 1;
2321 var messagePtr = _malloc(messageSize);
2322 messageStringPtrs.push(messagePtr);
2323 stringToUTF8(compilationMessage.message, messagePtr, messageSize);
2324 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.message, 'messagePtr', '*') }}};
2325 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.type, 'WebGPU.Int_CompilationMessageType[compilationMessage.type]', 'i32') }}};
2326 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.lineNum, 'compilationMessage.lineNum', 'i64') }}};
2327 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.linePos, 'compilationMessage.linePos', 'i64') }}};
2328 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.offset, 'compilationMessage.offset', 'i64') }}};
2329 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.length, 'compilationMessage.length', 'i64') }}};
2330 // TODO: Convert JavaScript's UTF-16-code-unit offsets to UTF-8-code-unit offsets.
2331 // https://github.com/webgpu-native/webgpu-headers/issues/246
2332 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.utf16LinePos, 'compilationMessage.linePos', 'i64') }}};
2333 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.utf16Offset, 'compilationMessage.offset', 'i64') }}};
2334 {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.utf16Length, 'compilationMessage.length', 'i64') }}};
2335 }
2336 var compilationInfoPtr = _malloc({{{ C_STRUCTS.WGPUCompilationInfo.__size__ }}});
2337 {{{ makeSetValue('compilationInfoPtr', C_STRUCTS.WGPUCompilationInfo.messageCount, 'compilationInfo.messages.length', '*') }}}
2338 {{{ makeSetValue('compilationInfoPtr', C_STRUCTS.WGPUCompilationInfo.messages, 'compilationMessagesPtr', '*') }}};
2339
2340 {{{ makeDynCall('vipp', 'callback') }}}({{{ gpu.CompilationInfoRequestStatus.Success }}}, compilationInfoPtr, userdata);
2341
2342 messageStringPtrs.forEach((ptr) => {
2343 _free(ptr);
2344 });
2345 _free(compilationMessagesPtr);
2346 _free(compilationInfoPtr);
2347 });
2348 });
2349 },
2350
2351 wgpuShaderModuleSetLabel: (shaderModulePtr, labelPtr) => {
2352 var shaderModule = WebGPU._tableGet(shaderModulePtr);
2353 shaderModule.label = UTF8ToString(labelPtr);
2354 },
2355
2356 // --------------------------------------------------------------------------
2357 // Methods of Surface
2358 // --------------------------------------------------------------------------
2359
2360 wgpuSurfaceConfigure: (surfacePtr, config) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002361 {{{ gpu.makeCheckDescriptor('config') }}}
Loko Kung5a9506d2024-08-17 01:44:45 +00002362 var devicePtr = {{{ makeGetValue('config', C_STRUCTS.WGPUSurfaceConfiguration.device, '*') }}};
2363 var context = WebGPU._tableGet(surfacePtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002364
2365#if ASSERTIONS
2366 var viewFormatCount = {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.viewFormatCount) }}};
2367 var viewFormats = {{{ makeGetValue('config', C_STRUCTS.WGPUSurfaceConfiguration.viewFormats, '*') }}};
2368 assert(viewFormatCount === 0 && viewFormats === 0, "TODO: Support viewFormats.");
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002369 assert({{{ gpu.PresentMode.Fifo }}} ===
2370 {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.presentMode) }}});
2371#endif
2372
2373 var canvasSize = [
2374 {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.width) }}},
2375 {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.height) }}}
2376 ];
2377
2378 if (canvasSize[0] !== 0) {
2379 context["canvas"]["width"] = canvasSize[0];
2380 }
2381
2382 if (canvasSize[1] !== 0) {
2383 context["canvas"]["height"] = canvasSize[1];
2384 }
2385
2386 var configuration = {
Loko Kung5a9506d2024-08-17 01:44:45 +00002387 "device": WebGPU._tableGet(devicePtr),
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002388 "format": WebGPU.TextureFormat[
2389 {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.format) }}}],
2390 "usage": {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.usage) }}},
Kai Ninomiya6d1e2132024-09-05 23:05:45 +00002391 "alphaMode": WebGPU.CompositeAlphaMode[
2392 {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.alphaMode) }}}],
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002393 };
2394 context.configure(configuration);
2395 },
2396
Loko Kung424cda22024-08-17 01:29:10 +00002397 wgpuSurfaceGetCurrentTexture__deps: ['emwgpuCreateTexture'],
Loko Kung5a9506d2024-08-17 01:44:45 +00002398 wgpuSurfaceGetCurrentTexture: (surfacePtr, surfaceTexturePtr) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002399 {{{ gpu.makeCheck('surfaceTexturePtr') }}}
Loko Kung5a9506d2024-08-17 01:44:45 +00002400 var context = WebGPU._tableGet(surfacePtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002401
2402 try {
Loko Kung424cda22024-08-17 01:29:10 +00002403 var texturePtr = _emwgpuCreateTexture();
2404 WebGPU._tableInsert(texturePtr, context.getCurrentTexture());
2405 {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.texture, 'texturePtr', '*') }}};
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002406 {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.suboptimal, '0', 'i32') }}};
Kai Ninomiya11784002024-07-03 19:46:03 +00002407 {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.status,
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002408 gpu.SurfaceGetCurrentTextureStatus.Success, 'i32') }}};
2409 } catch (ex) {
2410#if ASSERTIONS
2411 err(`wgpuSurfaceGetCurrentTexture() failed: ${ex}`);
2412#endif
2413 {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.texture, '0', '*') }}};
2414 {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.suboptimal, '0', 'i32') }}};
2415 // TODO(https://github.com/webgpu-native/webgpu-headers/issues/291): What should the status be here?
2416 {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.status,
2417 gpu.SurfaceGetCurrentTextureStatus.DeviceLost, 'i32') }}};
2418 }
2419 },
2420
Loko Kung5a9506d2024-08-17 01:44:45 +00002421 wgpuSurfaceGetPreferredFormat: (surfacePtr, adapterPtr) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002422 var format = navigator["gpu"]["getPreferredCanvasFormat"]();
2423 return WebGPU.Int_PreferredFormat[format];
2424 },
2425
Loko Kung5a9506d2024-08-17 01:44:45 +00002426 wgpuSurfacePresent: (surfacePtr) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002427 // TODO: This could probably be emulated with ASYNCIFY.
2428 abort('wgpuSurfacePresent is unsupported (use requestAnimationFrame via html5.h instead)');
2429 },
2430
Loko Kung5a9506d2024-08-17 01:44:45 +00002431 wgpuSurfaceUnconfigure: (surfacePtr) => {
2432 var context = WebGPU._tableGet(surfacePtr);
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002433 context.unconfigure();
2434 },
2435
Loko Kung5a9506d2024-08-17 01:44:45 +00002436 // --------------------------------------------------------------------------
2437 // Methods of SwapChain
2438 // --------------------------------------------------------------------------
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002439
Loko Kung424cda22024-08-17 01:29:10 +00002440 wgpuSwapChainGetCurrentTexture__deps: ['emwgpuCreateTexture'],
Loko Kung5a9506d2024-08-17 01:44:45 +00002441 wgpuSwapChainGetCurrentTexture: (swapChainPtr) => {
2442 var context = WebGPU._tableGet(swapChainPtr);
Loko Kung424cda22024-08-17 01:29:10 +00002443 var ptr = _emwgpuCreateTexture();
2444 WebGPU._tableInsert(ptr, context.getCurrentTexture());
2445 return ptr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002446 },
Loko Kung424cda22024-08-17 01:29:10 +00002447
2448 wgpuSwapChainGetCurrentTextureView__deps: ['emwgpuCreateTextureView'],
Loko Kung5a9506d2024-08-17 01:44:45 +00002449 wgpuSwapChainGetCurrentTextureView: (swapChainPtr) => {
2450 var context = WebGPU._tableGet(swapChainPtr);
Loko Kung424cda22024-08-17 01:29:10 +00002451 var ptr = _emwgpuCreateTextureView();
2452 WebGPU._tableInsert(ptr, context.getCurrentTexture().createView());
2453 return ptr;
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002454 },
Loko Kung5a9506d2024-08-17 01:44:45 +00002455
2456 wgpuSwapChainPresent: (swapChainPtr) => {
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002457 // TODO: This could probably be emulated with ASYNCIFY.
2458 abort('wgpuSwapChainPresent is unsupported (use requestAnimationFrame via html5.h instead)');
2459 },
Loko Kung5a9506d2024-08-17 01:44:45 +00002460
2461 // --------------------------------------------------------------------------
2462 // Methods of Texture
2463 // --------------------------------------------------------------------------
2464
2465 wgpuTextureCreateView__deps: ['emwgpuCreateTextureView'],
2466 wgpuTextureCreateView: (texturePtr, descriptor) => {
2467 var desc;
2468 if (descriptor) {
2469 {{{ gpu.makeCheckDescriptor('descriptor') }}}
2470 var mipLevelCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.mipLevelCount) }}};
2471 var arrayLayerCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.arrayLayerCount) }}};
2472 desc = {
2473 "format": WebGPU.TextureFormat[
2474 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.format) }}}],
2475 "dimension": WebGPU.TextureViewDimension[
2476 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.dimension) }}}],
2477 "baseMipLevel": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.baseMipLevel) }}},
2478 "mipLevelCount": mipLevelCount === {{{ gpu.MIP_LEVEL_COUNT_UNDEFINED }}} ? undefined : mipLevelCount,
2479 "baseArrayLayer": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.baseArrayLayer) }}},
2480 "arrayLayerCount": arrayLayerCount === {{{ gpu.ARRAY_LAYER_COUNT_UNDEFINED }}} ? undefined : arrayLayerCount,
2481 "aspect": WebGPU.TextureAspect[
2482 {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.aspect) }}}],
2483 };
2484 var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.label, '*') }}};
2485 if (labelPtr) desc["label"] = UTF8ToString(labelPtr);
2486 }
2487
2488 var texture = WebGPU._tableGet(texturePtr);
2489 var ptr = _emwgpuCreateTextureView();
2490 WebGPU._tableInsert(ptr, texture.createView(desc));
2491 return ptr;
2492 },
2493
2494 wgpuTextureDestroy: (texturePtr) => {
2495 WebGPU._tableGet(texturePtr).destroy();
2496 },
2497
2498 wgpuTextureGetDepthOrArrayLayers: (texturePtr) => {
2499 var texture = WebGPU._tableGet(texturePtr);
2500 return texture.depthOrArrayLayers;
2501 },
2502
2503 wgpuTextureGetDimension: (texturePtr) => {
2504 var texture = WebGPU._tableGet(texturePtr);
2505 return WebGPU.TextureDimension.indexOf(texture.dimension);
2506 },
2507
2508 wgpuTextureGetFormat: (texturePtr) => {
2509 var texture = WebGPU._tableGet(texturePtr);
2510 // Should return the enum integer instead of string.
2511 return WebGPU.TextureFormat.indexOf(texture.format);
2512 },
2513
2514 wgpuTextureGetHeight: (texturePtr) => {
2515 var texture = WebGPU._tableGet(texturePtr);
2516 return texture.height;
2517 },
2518
2519 wgpuTextureGetMipLevelCount: (texturePtr) => {
2520 var texture = WebGPU._tableGet(texturePtr);
2521 return texture.mipLevelCount;
2522 },
2523
2524 wgpuTextureGetSampleCount: (texturePtr) => {
2525 var texture = WebGPU._tableGet(texturePtr);
2526 return texture.sampleCount;
2527 },
2528
2529 wgpuTextureGetUsage: (texturePtr) => {
2530 var texture = WebGPU._tableGet(texturePtr);
2531 return texture.usage;
2532 },
2533
2534 wgpuTextureGetWidth: (texturePtr) => {
2535 var texture = WebGPU._tableGet(texturePtr);
2536 return texture.width;
2537 },
2538
2539 wgpuTextureSetLabel: (texturePtr, labelPtr) => {
2540 var texture = WebGPU._tableGet(texturePtr);
2541 texture.label = UTF8ToString(labelPtr);
2542 },
2543
2544 // --------------------------------------------------------------------------
2545 // Methods of TextureView
2546 // --------------------------------------------------------------------------
2547
2548 wgpuTextureViewSetLabel: (textureViewPtr, labelPtr) => {
2549 var textureView = WebGPU._tableGet(textureViewPtr);
2550 textureView.label = UTF8ToString(labelPtr);
2551 },
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002552};
2553
2554// Inverted index used by EnumerateFeatures/HasFeature
2555LibraryWebGPU.$WebGPU.FeatureNameString2Enum = {};
2556for (var value in LibraryWebGPU.$WebGPU.FeatureName) {
2557 LibraryWebGPU.$WebGPU.FeatureNameString2Enum[LibraryWebGPU.$WebGPU.FeatureName[value]] = value;
2558}
2559
2560for (const key of Object.keys(LibraryWebGPU)) {
2561 if (typeof LibraryWebGPU[key] === 'function') {
Loko Kung859fb302024-08-17 01:44:58 +00002562 if (!(key + '__i53abi' in LibraryWebGPU)) {
2563 LibraryWebGPU[key + '__i53abi'] = true;
2564 }
Kai Ninomiyaace5a582024-07-02 20:52:25 +00002565 }
2566}
2567
2568autoAddDeps(LibraryWebGPU, '$WebGPU');
Kai Ninomiya11784002024-07-03 19:46:03 +00002569mergeInto(LibraryManager.library, LibraryWebGPU);