| /** |
| * @license |
| * Copyright 2019 The Emscripten Authors |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| /* |
| * Dawn's fork of Emscripten's WebGPU bindings. This will be contributed back to |
| * Emscripten after reaching approximately webgpu.h "1.0". |
| * |
| * IMPORTANT: See //src/emdawnwebgpu/README.md for info on how to use this. |
| */ |
| |
| {{{ |
| if (USE_WEBGPU || !__HAVE_EMDAWNWEBGPU_STRUCT_INFO || !__HAVE_EMDAWNWEBGPU_ENUM_TABLES || !__HAVE_EMDAWNWEBGPU_SIG_INFO) { |
| 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)"); |
| } |
| |
| // Helper functions for code generation |
| globalThis.gpu = { |
| convertSentinelToUndefined: function(name) { |
| return `if (${name} == -1) ${name} = undefined;`; |
| }, |
| |
| makeGetBool: function(struct, offset) { |
| return `!!(${makeGetValue(struct, offset, 'u32')})`; |
| }, |
| makeGetU32: function(struct, offset) { |
| return makeGetValue(struct, offset, 'u32'); |
| }, |
| makeGetU64: function(struct, offset) { |
| var l = makeGetValue(struct, offset, 'u32'); |
| var h = makeGetValue(`(${struct} + 4)`, offset, 'u32') |
| return `${h} * 0x100000000 + ${l}` |
| }, |
| makeCheck: function(str) { |
| if (!ASSERTIONS) return ''; |
| return `assert(${str});`; |
| }, |
| makeCheckDescriptor: function(descriptor) { |
| // Assert descriptor is non-null, then that its nextInChain is null. |
| // For descriptors that aren't the first in the chain (e.g |
| // ShaderSourceSPIRV), there is no .nextInChain pointer, but |
| // instead a ChainedStruct object: .chain. So we need to check if |
| // .chain.nextInChain is null. As long as nextInChain and chain are always |
| // the first member in the struct, descriptor.nextInChain and |
| // descriptor.chain.nextInChain should have the same offset (0) to the |
| // descriptor pointer and we can check it to be null. |
| var OffsetOfNextInChainMember = 0; |
| return this.makeCheck(descriptor) + this.makeCheck(makeGetValue(descriptor, OffsetOfNextInChainMember, '*') + ' === 0'); |
| }, |
| makeImportJsObject: function(object) { |
| return ` |
| importJs${object}__deps: ['emwgpuCreate${object}'], |
| importJs${object}: (obj, parentPtr = 0) => { |
| var ptr = _emwgpuCreate${object}(parentPtr); |
| WebGPU.Internals.jsObjects[ptr] = obj; |
| return ptr; |
| }, |
| ` |
| }, |
| |
| // Compile-time table for enum integer values used with templating. |
| // Must be in sync with webgpu.h. |
| // TODO: Generate this to keep it in sync with webgpu.h |
| COPY_STRIDE_UNDEFINED: 0xFFFFFFFF, |
| LIMIT_U32_UNDEFINED: 0xFFFFFFFF, |
| MIP_LEVEL_COUNT_UNDEFINED: 0xFFFFFFFF, |
| ARRAY_LAYER_COUNT_UNDEFINED: 0xFFFFFFFF, |
| ...WEBGPU_ENUM_CONSTANT_TABLES, |
| }; |
| null; |
| }}} |
| |
| var LibraryWebGPU = { |
| $WebGPU__deps: [], |
| $WebGPU: { |
| // Note that external users should not depend on any of the internal |
| // implementation details in this sub-object, as they are subject to |
| // change to support new features or optimizations. Instead, external |
| // users should rely only on the public APIs. |
| Internals: { |
| // Object management is consolidated into a single table that doesn't |
| // care about object type, and is keyed on the pointer address. |
| jsObjects: [], |
| jsObjectInsert: (ptr, jsObject) => { |
| WebGPU.Internals.jsObjects[ptr] = jsObject; |
| }, |
| |
| // Buffer unmapping callbacks are stored in a separate table to keep |
| // the jsObject table simple. |
| bufferOnUnmaps: [], |
| |
| // Future to promise management, and temporary list allocated up-front for |
| // WaitAny implementation on the promises. Note that all FutureIDs |
| // (uint64_t) are passed either as a low and high value or by pointer |
| // because they need to be passed back and forth between JS and C++, and JS |
| // is currently unable to pass a value to a C++ function as a uint64_t. |
| // This might be possible with -sWASM_BIGINT, but I was unable to get that |
| // to work properly at the time of writing. |
| futures: [], |
| futureInsert: (futureId, promise) => { |
| #if ASYNCIFY |
| WebGPU.Internals.futures[futureId] = |
| new Promise((resolve) => promise.finally(() => resolve(futureId))); |
| #endif |
| }, |
| waitAnyPromisesList: [], |
| }, |
| |
| // Public utility functions useful for translating between WASM/JS. Most of |
| // the import utilities are generated, with some exceptions that are |
| // explicitly implemented because they have some slight differences. Note |
| // that all import functions take the expected GPUObject JS types as the |
| // first argument and an optional second argument that is WGPUObject C type |
| // (i.e. pointer), that should extend EventSource from webgpu.cpp. The |
| // second argument is a "parent" object that's needed in order to handle |
| // WGPUFutures when using in non-AllowSpontaneous mode. For most objects, |
| // a WGPUDevice would suffice as a parent. For a WGPUDevice, either a |
| // WGPUAdapter or WGPUInstance would be valid. |
| getJsObject: (ptr) => { |
| if (!ptr) return undefined; |
| #if ASSERTIONS |
| assert(ptr in WebGPU.Internals.jsObjects); |
| #endif |
| return WebGPU.Internals.jsObjects[ptr]; |
| }, |
| {{{ gpu.makeImportJsObject('Adapter') }}} |
| {{{ gpu.makeImportJsObject('BindGroup') }}} |
| {{{ gpu.makeImportJsObject('BindGroupLayout') }}} |
| {{{ gpu.makeImportJsObject('Buffer') }}} |
| {{{ gpu.makeImportJsObject('CommandBuffer') }}} |
| {{{ gpu.makeImportJsObject('CommandEncoder') }}} |
| {{{ gpu.makeImportJsObject('ComputePassEncoder') }}} |
| {{{ gpu.makeImportJsObject('ComputePipeline') }}} |
| importJsDevice__deps: ['emwgpuCreateDevice', 'emwgpuCreateQueue'], |
| importJsDevice: (device, parentPtr = 0) => { |
| var queuePtr = _emwgpuCreateQueue(parentPtr); |
| var devicePtr = _emwgpuCreateDevice(parentPtr, queuePtr); |
| WebGPU.Internals.jsObjectInsert(queuePtr, device.queue); |
| WebGPU.Internals.jsObjectInsert(devicePtr, device); |
| return devicePtr; |
| }, |
| {{{ gpu.makeImportJsObject('BindGroup') }}} |
| {{{ gpu.makeImportJsObject('PipelineLayout') }}} |
| {{{ gpu.makeImportJsObject('QuerySet') }}} |
| {{{ gpu.makeImportJsObject('Queue') }}} |
| {{{ gpu.makeImportJsObject('RenderBundle') }}} |
| {{{ gpu.makeImportJsObject('RenderBundleEncoder') }}} |
| {{{ gpu.makeImportJsObject('RenderPassEncoder') }}} |
| {{{ gpu.makeImportJsObject('RenderPipeline') }}} |
| {{{ gpu.makeImportJsObject('Sampler') }}} |
| {{{ gpu.makeImportJsObject('ShaderModule') }}} |
| {{{ gpu.makeImportJsObject('Surface') }}} |
| {{{ gpu.makeImportJsObject('Texture') }}} |
| {{{ gpu.makeImportJsObject('TextureView') }}} |
| |
| errorCallback__deps: ['$stackSave', '$stackRestore', '$stringToUTF8OnStack'], |
| errorCallback: (callback, type, message, userdata) => { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(message); |
| {{{ makeDynCall('vipp', 'callback') }}}(type, messagePtr, userdata); |
| stackRestore(sp); |
| }, |
| |
| setStringView: (ptr, data, length) => { |
| {{{ makeSetValue('ptr', C_STRUCTS.WGPUStringView.data, 'data', '*') }}}; |
| {{{ makeSetValue('ptr', C_STRUCTS.WGPUStringView.length, 'length', '*') }}}; |
| }, |
| |
| makeStringFromStringView__deps: ['$UTF8ToString'], |
| makeStringFromStringView: (stringViewPtr) => { |
| var ptr = {{{ makeGetValue('stringViewPtr', C_STRUCTS.WGPUStringView.data, '*') }}}; |
| var length = {{{ makeGetValue('stringViewPtr', C_STRUCTS.WGPUStringView.length, '*') }}}; |
| // UTF8ToString stops at the first null terminator character in the |
| // string regardless of the length. |
| return UTF8ToString(ptr, length); |
| }, |
| makeStringFromOptionalStringView__deps: ['$UTF8ToString'], |
| makeStringFromOptionalStringView: (stringViewPtr) => { |
| var ptr = {{{ makeGetValue('stringViewPtr', C_STRUCTS.WGPUStringView.data, '*') }}}; |
| var length = {{{ makeGetValue('stringViewPtr', C_STRUCTS.WGPUStringView.length, '*') }}}; |
| // If we don't have a valid string pointer, just return undefined when |
| // optional. |
| if (!ptr) { |
| if (length === 0) { |
| return ""; |
| } |
| return undefined; |
| } |
| // UTF8ToString stops at the first null terminator character in the |
| // string regardless of the length. |
| return UTF8ToString(ptr, length); |
| }, |
| |
| makeColor: (ptr) => { |
| return { |
| "r": {{{ makeGetValue('ptr', 0, 'double') }}}, |
| "g": {{{ makeGetValue('ptr', 8, 'double') }}}, |
| "b": {{{ makeGetValue('ptr', 16, 'double') }}}, |
| "a": {{{ makeGetValue('ptr', 24, 'double') }}}, |
| }; |
| }, |
| |
| makeExtent3D: (ptr) => { |
| return { |
| "width": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUExtent3D.width) }}}, |
| "height": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUExtent3D.height) }}}, |
| "depthOrArrayLayers": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUExtent3D.depthOrArrayLayers) }}}, |
| }; |
| }, |
| |
| makeOrigin3D: (ptr) => { |
| return { |
| "x": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUOrigin3D.x) }}}, |
| "y": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUOrigin3D.y) }}}, |
| "z": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUOrigin3D.z) }}}, |
| }; |
| }, |
| |
| makeImageCopyTexture: (ptr) => { |
| {{{ gpu.makeCheck('ptr') }}} |
| return { |
| "texture": WebGPU.getJsObject( |
| {{{ makeGetValue('ptr', C_STRUCTS.WGPUImageCopyTexture.texture, '*') }}}), |
| "mipLevel": {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUImageCopyTexture.mipLevel) }}}, |
| "origin": WebGPU.makeOrigin3D(ptr + {{{ C_STRUCTS.WGPUImageCopyTexture.origin }}}), |
| "aspect": WebGPU.TextureAspect[{{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUImageCopyTexture.aspect) }}}], |
| }; |
| }, |
| |
| makeTextureDataLayout: (ptr) => { |
| {{{ gpu.makeCheckDescriptor('ptr') }}} |
| var bytesPerRow = {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUTextureDataLayout.bytesPerRow) }}}; |
| var rowsPerImage = {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUTextureDataLayout.rowsPerImage) }}}; |
| return { |
| "offset": {{{ gpu.makeGetU64('ptr', C_STRUCTS.WGPUTextureDataLayout.offset) }}}, |
| "bytesPerRow": bytesPerRow === {{{ gpu.COPY_STRIDE_UNDEFINED }}} ? undefined : bytesPerRow, |
| "rowsPerImage": rowsPerImage === {{{ gpu.COPY_STRIDE_UNDEFINED }}} ? undefined : rowsPerImage, |
| }; |
| }, |
| |
| makeImageCopyBuffer: (ptr) => { |
| {{{ gpu.makeCheck('ptr') }}} |
| var layoutPtr = ptr + {{{ C_STRUCTS.WGPUImageCopyBuffer.layout }}}; |
| var bufferCopyView = WebGPU.makeTextureDataLayout(layoutPtr); |
| bufferCopyView["buffer"] = WebGPU.getJsObject( |
| {{{ makeGetValue('ptr', C_STRUCTS.WGPUImageCopyBuffer.buffer, '*') }}}); |
| return bufferCopyView; |
| }, |
| |
| makePipelineConstants: (constantCount, constantsPtr) => { |
| if (!constantCount) return; |
| var constants = {}; |
| for (var i = 0; i < constantCount; ++i) { |
| var entryPtr = constantsPtr + {{{ C_STRUCTS.WGPUConstantEntry.__size__ }}} * i; |
| var key = WebGPU.makeStringFromStringView(entryPtr + {{{ C_STRUCTS.WGPUConstantEntry.key }}}); |
| constants[key] = {{{ makeGetValue('entryPtr', C_STRUCTS.WGPUConstantEntry.value, 'double') }}}; |
| } |
| return constants; |
| }, |
| |
| makePipelineLayout: (layoutPtr) => { |
| if (!layoutPtr) return 'auto'; |
| return WebGPU.getJsObject(layoutPtr); |
| }, |
| |
| makeProgrammableStageDescriptor: (ptr) => { |
| if (!ptr) return undefined; |
| {{{ gpu.makeCheckDescriptor('ptr') }}} |
| var desc = { |
| "module": WebGPU.getJsObject( |
| {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.module, '*') }}}), |
| "constants": WebGPU.makePipelineConstants( |
| {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.constantCount) }}}, |
| {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.constants, '*') }}}), |
| "entryPoint": WebGPU.makeStringFromOptionalStringView( |
| ptr + {{{ C_STRUCTS.WGPUProgrammableStageDescriptor.entryPoint }}}), |
| }; |
| return desc; |
| }, |
| |
| makeComputePipelineDesc: (descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUComputePipelineDescriptor.label }}}), |
| "layout": WebGPU.makePipelineLayout( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePipelineDescriptor.layout, '*') }}}), |
| "compute": WebGPU.makeProgrammableStageDescriptor( |
| descriptor + {{{ C_STRUCTS.WGPUComputePipelineDescriptor.compute }}}), |
| }; |
| return desc; |
| }, |
| |
| makeRenderPipelineDesc: (descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| function makePrimitiveState(psPtr) { |
| if (!psPtr) return undefined; |
| {{{ gpu.makeCheckDescriptor('psPtr') }}} |
| return { |
| "topology": WebGPU.PrimitiveTopology[ |
| {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.topology) }}}], |
| "stripIndexFormat": WebGPU.IndexFormat[ |
| {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.stripIndexFormat) }}}], |
| "frontFace": WebGPU.FrontFace[ |
| {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.frontFace) }}}], |
| "cullMode": WebGPU.CullMode[ |
| {{{ gpu.makeGetU32('psPtr', C_STRUCTS.WGPUPrimitiveState.cullMode) }}}], |
| "unclippedDepth": |
| {{{ gpu.makeGetBool('psPtr', C_STRUCTS.WGPUPrimitiveState.unclippedDepth) }}}, |
| }; |
| } |
| |
| function makeBlendComponent(bdPtr) { |
| if (!bdPtr) return undefined; |
| return { |
| "operation": WebGPU.BlendOperation[ |
| {{{ gpu.makeGetU32('bdPtr', C_STRUCTS.WGPUBlendComponent.operation) }}}], |
| "srcFactor": WebGPU.BlendFactor[ |
| {{{ gpu.makeGetU32('bdPtr', C_STRUCTS.WGPUBlendComponent.srcFactor) }}}], |
| "dstFactor": WebGPU.BlendFactor[ |
| {{{ gpu.makeGetU32('bdPtr', C_STRUCTS.WGPUBlendComponent.dstFactor) }}}], |
| }; |
| } |
| |
| function makeBlendState(bsPtr) { |
| if (!bsPtr) return undefined; |
| return { |
| "alpha": makeBlendComponent(bsPtr + {{{ C_STRUCTS.WGPUBlendState.alpha }}}), |
| "color": makeBlendComponent(bsPtr + {{{ C_STRUCTS.WGPUBlendState.color }}}), |
| }; |
| } |
| |
| function makeColorState(csPtr) { |
| {{{ gpu.makeCheckDescriptor('csPtr') }}} |
| var formatInt = {{{ gpu.makeGetU32('csPtr', C_STRUCTS.WGPUColorTargetState.format) }}}; |
| return formatInt === {{{ gpu.TextureFormat.Undefined }}} ? undefined : { |
| "format": WebGPU.TextureFormat[formatInt], |
| "blend": makeBlendState({{{ makeGetValue('csPtr', C_STRUCTS.WGPUColorTargetState.blend, '*') }}}), |
| "writeMask": {{{ gpu.makeGetU32('csPtr', C_STRUCTS.WGPUColorTargetState.writeMask) }}}, |
| }; |
| } |
| |
| function makeColorStates(count, csArrayPtr) { |
| var states = []; |
| for (var i = 0; i < count; ++i) { |
| states.push(makeColorState(csArrayPtr + {{{ C_STRUCTS.WGPUColorTargetState.__size__ }}} * i)); |
| } |
| return states; |
| } |
| |
| function makeStencilStateFace(ssfPtr) { |
| {{{ gpu.makeCheck('ssfPtr') }}} |
| return { |
| "compare": WebGPU.CompareFunction[ |
| {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.compare) }}}], |
| "failOp": WebGPU.StencilOperation[ |
| {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.failOp) }}}], |
| "depthFailOp": WebGPU.StencilOperation[ |
| {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.depthFailOp) }}}], |
| "passOp": WebGPU.StencilOperation[ |
| {{{ gpu.makeGetU32('ssfPtr', C_STRUCTS.WGPUStencilFaceState.passOp) }}}], |
| }; |
| } |
| |
| function makeDepthStencilState(dssPtr) { |
| if (!dssPtr) return undefined; |
| |
| {{{ gpu.makeCheck('dssPtr') }}} |
| return { |
| "format": WebGPU.TextureFormat[ |
| {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.format) }}}], |
| "depthWriteEnabled": {{{ gpu.makeGetBool('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthWriteEnabled) }}}, |
| "depthCompare": WebGPU.CompareFunction[ |
| {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthCompare) }}}], |
| "stencilFront": makeStencilStateFace(dssPtr + {{{ C_STRUCTS.WGPUDepthStencilState.stencilFront }}}), |
| "stencilBack": makeStencilStateFace(dssPtr + {{{ C_STRUCTS.WGPUDepthStencilState.stencilBack }}}), |
| "stencilReadMask": {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.stencilReadMask) }}}, |
| "stencilWriteMask": {{{ gpu.makeGetU32('dssPtr', C_STRUCTS.WGPUDepthStencilState.stencilWriteMask) }}}, |
| "depthBias": {{{ makeGetValue('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthBias, 'i32') }}}, |
| "depthBiasSlopeScale": {{{ makeGetValue('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthBiasSlopeScale, 'float') }}}, |
| "depthBiasClamp": {{{ makeGetValue('dssPtr', C_STRUCTS.WGPUDepthStencilState.depthBiasClamp, 'float') }}}, |
| }; |
| } |
| |
| function makeVertexAttribute(vaPtr) { |
| {{{ gpu.makeCheck('vaPtr') }}} |
| return { |
| "format": WebGPU.VertexFormat[ |
| {{{ gpu.makeGetU32('vaPtr', C_STRUCTS.WGPUVertexAttribute.format) }}}], |
| "offset": {{{ gpu.makeGetU64('vaPtr', C_STRUCTS.WGPUVertexAttribute.offset) }}}, |
| "shaderLocation": {{{ gpu.makeGetU32('vaPtr', C_STRUCTS.WGPUVertexAttribute.shaderLocation) }}}, |
| }; |
| } |
| |
| function makeVertexAttributes(count, vaArrayPtr) { |
| var vas = []; |
| for (var i = 0; i < count; ++i) { |
| vas.push(makeVertexAttribute(vaArrayPtr + i * {{{ C_STRUCTS.WGPUVertexAttribute.__size__ }}})); |
| } |
| return vas; |
| } |
| |
| function makeVertexBuffer(vbPtr) { |
| if (!vbPtr) return undefined; |
| var stepModeInt = {{{ gpu.makeGetU32('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.stepMode) }}}; |
| return stepModeInt === {{{ gpu.VertexStepMode.VertexBufferNotUsed }}} ? null : { |
| "arrayStride": {{{ gpu.makeGetU64('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.arrayStride) }}}, |
| "stepMode": WebGPU.VertexStepMode[stepModeInt], |
| "attributes": makeVertexAttributes( |
| {{{ gpu.makeGetU32('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.attributeCount) }}}, |
| {{{ makeGetValue('vbPtr', C_STRUCTS.WGPUVertexBufferLayout.attributes, '*') }}}), |
| }; |
| } |
| |
| function makeVertexBuffers(count, vbArrayPtr) { |
| if (!count) return undefined; |
| |
| var vbs = []; |
| for (var i = 0; i < count; ++i) { |
| vbs.push(makeVertexBuffer(vbArrayPtr + i * {{{ C_STRUCTS.WGPUVertexBufferLayout.__size__ }}})); |
| } |
| return vbs; |
| } |
| |
| function makeVertexState(viPtr) { |
| if (!viPtr) return undefined; |
| {{{ gpu.makeCheckDescriptor('viPtr') }}} |
| var desc = { |
| "module": WebGPU.getJsObject( |
| {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.module, '*') }}}), |
| "constants": WebGPU.makePipelineConstants( |
| {{{ gpu.makeGetU32('viPtr', C_STRUCTS.WGPUVertexState.constantCount) }}}, |
| {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.constants, '*') }}}), |
| "buffers": makeVertexBuffers( |
| {{{ gpu.makeGetU32('viPtr', C_STRUCTS.WGPUVertexState.bufferCount) }}}, |
| {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.buffers, '*') }}}), |
| "entryPoint": WebGPU.makeStringFromOptionalStringView( |
| viPtr + {{{ C_STRUCTS.WGPUVertexState.entryPoint }}}), |
| }; |
| return desc; |
| } |
| |
| function makeMultisampleState(msPtr) { |
| if (!msPtr) return undefined; |
| {{{ gpu.makeCheckDescriptor('msPtr') }}} |
| return { |
| "count": {{{ gpu.makeGetU32('msPtr', C_STRUCTS.WGPUMultisampleState.count) }}}, |
| "mask": {{{ gpu.makeGetU32('msPtr', C_STRUCTS.WGPUMultisampleState.mask) }}}, |
| "alphaToCoverageEnabled": {{{ gpu.makeGetBool('msPtr', C_STRUCTS.WGPUMultisampleState.alphaToCoverageEnabled) }}}, |
| }; |
| } |
| |
| function makeFragmentState(fsPtr) { |
| if (!fsPtr) return undefined; |
| {{{ gpu.makeCheckDescriptor('fsPtr') }}} |
| var desc = { |
| "module": WebGPU.getJsObject( |
| {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.module, '*') }}}), |
| "constants": WebGPU.makePipelineConstants( |
| {{{ gpu.makeGetU32('fsPtr', C_STRUCTS.WGPUFragmentState.constantCount) }}}, |
| {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.constants, '*') }}}), |
| "targets": makeColorStates( |
| {{{ gpu.makeGetU32('fsPtr', C_STRUCTS.WGPUFragmentState.targetCount) }}}, |
| {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.targets, '*') }}}), |
| "entryPoint": WebGPU.makeStringFromOptionalStringView( |
| fsPtr + {{{ C_STRUCTS.WGPUFragmentState.entryPoint }}}), |
| }; |
| return desc; |
| } |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPURenderPipelineDescriptor.label }}}), |
| "layout": WebGPU.makePipelineLayout( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.layout, '*') }}}), |
| "vertex": makeVertexState( |
| descriptor + {{{ C_STRUCTS.WGPURenderPipelineDescriptor.vertex }}}), |
| "primitive": makePrimitiveState( |
| descriptor + {{{ C_STRUCTS.WGPURenderPipelineDescriptor.primitive }}}), |
| "depthStencil": makeDepthStencilState( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.depthStencil, '*') }}}), |
| "multisample": makeMultisampleState( |
| descriptor + {{{ C_STRUCTS.WGPURenderPipelineDescriptor.multisample }}}), |
| "fragment": makeFragmentState( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.fragment, '*') }}}), |
| }; |
| return desc; |
| }, |
| |
| fillLimitStruct: (limits, supportedLimitsOutPtr) => { |
| var limitsOutPtr = supportedLimitsOutPtr + {{{ C_STRUCTS.WGPUSupportedLimits.limits }}}; |
| |
| function setLimitValueU32(name, limitOffset) { |
| var limitValue = limits[name]; |
| {{{ makeSetValue('limitsOutPtr', 'limitOffset', 'limitValue', 'i32') }}}; |
| } |
| function setLimitValueU64(name, limitOffset) { |
| var limitValue = limits[name]; |
| {{{ makeSetValue('limitsOutPtr', 'limitOffset', 'limitValue', 'i64') }}}; |
| } |
| |
| setLimitValueU32('maxTextureDimension1D', {{{ C_STRUCTS.WGPULimits.maxTextureDimension1D }}}); |
| setLimitValueU32('maxTextureDimension2D', {{{ C_STRUCTS.WGPULimits.maxTextureDimension2D }}}); |
| setLimitValueU32('maxTextureDimension3D', {{{ C_STRUCTS.WGPULimits.maxTextureDimension3D }}}); |
| setLimitValueU32('maxTextureArrayLayers', {{{ C_STRUCTS.WGPULimits.maxTextureArrayLayers }}}); |
| setLimitValueU32('maxBindGroups', {{{ C_STRUCTS.WGPULimits.maxBindGroups }}}); |
| setLimitValueU32('maxBindGroupsPlusVertexBuffers', {{{ C_STRUCTS.WGPULimits.maxBindGroupsPlusVertexBuffers }}}); |
| setLimitValueU32('maxBindingsPerBindGroup', {{{ C_STRUCTS.WGPULimits.maxBindingsPerBindGroup }}}); |
| setLimitValueU32('maxDynamicUniformBuffersPerPipelineLayout', {{{ C_STRUCTS.WGPULimits.maxDynamicUniformBuffersPerPipelineLayout }}}); |
| setLimitValueU32('maxDynamicStorageBuffersPerPipelineLayout', {{{ C_STRUCTS.WGPULimits.maxDynamicStorageBuffersPerPipelineLayout }}}); |
| setLimitValueU32('maxSampledTexturesPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxSampledTexturesPerShaderStage }}}); |
| setLimitValueU32('maxSamplersPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxSamplersPerShaderStage }}}); |
| setLimitValueU32('maxStorageBuffersPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxStorageBuffersPerShaderStage }}}); |
| setLimitValueU32('maxStorageTexturesPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxStorageTexturesPerShaderStage }}}); |
| setLimitValueU32('maxUniformBuffersPerShaderStage', {{{ C_STRUCTS.WGPULimits.maxUniformBuffersPerShaderStage }}}); |
| setLimitValueU32('minUniformBufferOffsetAlignment', {{{ C_STRUCTS.WGPULimits.minUniformBufferOffsetAlignment }}}); |
| setLimitValueU32('minStorageBufferOffsetAlignment', {{{ C_STRUCTS.WGPULimits.minStorageBufferOffsetAlignment }}}); |
| |
| setLimitValueU64('maxUniformBufferBindingSize', {{{ C_STRUCTS.WGPULimits.maxUniformBufferBindingSize }}}); |
| setLimitValueU64('maxStorageBufferBindingSize', {{{ C_STRUCTS.WGPULimits.maxStorageBufferBindingSize }}}); |
| |
| setLimitValueU32('maxVertexBuffers', {{{ C_STRUCTS.WGPULimits.maxVertexBuffers }}}); |
| setLimitValueU64('maxBufferSize', {{{ C_STRUCTS.WGPULimits.maxBufferSize }}}); |
| setLimitValueU32('maxVertexAttributes', {{{ C_STRUCTS.WGPULimits.maxVertexAttributes }}}); |
| setLimitValueU32('maxVertexBufferArrayStride', {{{ C_STRUCTS.WGPULimits.maxVertexBufferArrayStride }}}); |
| setLimitValueU32('maxInterStageShaderComponents', {{{ C_STRUCTS.WGPULimits.maxInterStageShaderComponents }}}); |
| setLimitValueU32('maxInterStageShaderVariables', {{{ C_STRUCTS.WGPULimits.maxInterStageShaderVariables }}}); |
| setLimitValueU32('maxColorAttachments', {{{ C_STRUCTS.WGPULimits.maxColorAttachments }}}); |
| setLimitValueU32('maxColorAttachmentBytesPerSample', {{{ C_STRUCTS.WGPULimits.maxColorAttachmentBytesPerSample }}}); |
| setLimitValueU32('maxComputeWorkgroupStorageSize', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupStorageSize }}}); |
| setLimitValueU32('maxComputeInvocationsPerWorkgroup', {{{ C_STRUCTS.WGPULimits.maxComputeInvocationsPerWorkgroup }}}); |
| setLimitValueU32('maxComputeWorkgroupSizeX', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeX }}}); |
| setLimitValueU32('maxComputeWorkgroupSizeY', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeY }}}); |
| setLimitValueU32('maxComputeWorkgroupSizeZ', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeZ }}}); |
| setLimitValueU32('maxComputeWorkgroupsPerDimension', {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupsPerDimension }}}); |
| }, |
| |
| // Maps from enum string back to enum number, for callbacks. |
| {{{ WEBGPU_STRING_TO_INT_TABLES }}} |
| |
| // Maps from enum number to enum string. |
| {{{ WEBGPU_INT_TO_STRING_TABLES }}} |
| }, |
| |
| // TODO(374150686): Remove this once it has been fully deprecated in users. |
| emscripten_webgpu_get_device__deps: ['wgpuDeviceAddRef'], |
| emscripten_webgpu_get_device: () => { |
| #if ASSERTIONS |
| assert(Module['preinitializedWebGPUDevice']); |
| #endif |
| if (WebGPU.preinitializedDeviceId === undefined) { |
| WebGPU.preinitializedDeviceId = WebGPU.importJsDevice(Module['preinitializedWebGPUDevice']); |
| // Some users depend on this keeping the device alive, so we add an |
| // additional reference when we first initialize it. |
| _wgpuDeviceAddRef(WebGPU.preinitializedDeviceId); |
| } |
| _wgpuDeviceAddRef(WebGPU.preinitializedDeviceId); |
| return WebGPU.preinitializedDeviceId; |
| }, |
| |
| // ---------------------------------------------------------------------------- |
| // Definitions for standalone JS emwgpu functions (callable from webgpu.cpp and |
| // library_html5_html.js) |
| // ---------------------------------------------------------------------------- |
| |
| emwgpuDelete__sig: 'vp', |
| emwgpuDelete: (ptr) => { |
| delete WebGPU.Internals.jsObjects[ptr]; |
| }, |
| |
| emwgpuSetLabel__deps: ['$UTF8ToString'], |
| emwgpuSetLabel__sig: 'vppp', |
| emwgpuSetLabel: (ptr, data, length) => { |
| var obj = WebGPU.getJsObject(ptr); |
| obj.label = UTF8ToString(data, length); |
| }, |
| |
| // Returns a FutureID that was resolved, or kNullFutureId if timed out. |
| #if ASYNCIFY |
| emwgpuWaitAny__async: true, |
| #endif |
| emwgpuWaitAny__i53abi: false, |
| emwgpuWaitAny__sig: 'jppp', |
| emwgpuWaitAny: (futurePtr, futureCount, timeoutNSPtr) => { |
| #if ASYNCIFY |
| var promises = WebGPU.Internals.waitAnyPromisesList; |
| if (timeoutNSPtr) { |
| var timeoutMS = {{{ gpu.makeGetU64('timeoutNSPtr', 0) }}} / 1000000; |
| promises.length = futureCount + 1; |
| promises[futureCount] = new Promise((resolve) => setTimeout(resolve, timeoutMS, 0)); |
| } else { |
| promises.length = futureCount; |
| } |
| |
| for (var i = 0; i < futureCount; ++i) { |
| // If any of the FutureIDs are not tracked, it means it must be done. |
| var futureId = {{{ gpu.makeGetU64('(futurePtr + i * 8)', 0) }}}; |
| if (!(futureId in WebGPU.Internals.futures)) { |
| return futureId; |
| } |
| promises[i] = WebGPU.Internals.futures[futureId]; |
| } |
| |
| var result = Asyncify.handleAsync(async () => { |
| return await Promise.race(promises); |
| }); |
| |
| // Clean up internal futures state. |
| delete WebGPU.Internals.futures[result]; |
| WebGPU.Internals.waitAnyPromisesList.length = 0; |
| return result; |
| #else |
| assert(false); |
| #endif |
| }, |
| |
| emwgpuGetPreferredFormat__sig: 'i', |
| emwgpuGetPreferredFormat: () => { |
| var format = navigator["gpu"]["getPreferredCanvasFormat"](); |
| return WebGPU.Int_PreferredFormat[format]; |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // WebGPU function definitions, with methods organized by "class". |
| // |
| // Also note that the full set of functions declared in webgpu.h are only |
| // partially implemeted here. The remaining ones are implemented via |
| // webgpu.cpp. |
| // -------------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------------- |
| // Standalone (non-method) functions |
| // -------------------------------------------------------------------------- |
| |
| wgpuGetInstanceFeatures: (featuresPtr) => { |
| abort('TODO: wgpuGetInstanceFeatures unimplemented'); |
| return 0; |
| }, |
| |
| wgpuGetProcAddress: (device, procName) => { |
| abort('TODO(#11526): wgpuGetProcAddress unimplemented'); |
| return 0; |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Adapter |
| // -------------------------------------------------------------------------- |
| |
| wgpuAdapterGetFeatures__deps: ['malloc'], |
| wgpuAdapterGetFeatures: (adapterPtr, supportedFeatures) => { |
| var adapter = WebGPU.getJsObject(adapterPtr); |
| |
| // Always allocate enough space for all the features, though some may be unused. |
| var featuresPtr = _malloc(adapter.features.size * 4); |
| var offset = 0; |
| var numFeatures = 0; |
| adapter.features.forEach(feature => { |
| var featureEnumValue = WebGPU.FeatureNameString2Enum[feature]; |
| if (featureEnumValue !== undefined) { |
| {{{ makeSetValue('featuresPtr', 'offset', 'featureEnumValue', 'i32') }}}; |
| offset += 4; |
| numFeatures++; |
| } |
| }); |
| {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.features, 'featuresPtr', '*') }}}; |
| {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.featureCount, 'numFeatures', '*') }}}; |
| }, |
| |
| wgpuAdapterGetInfo__deps: ['$stringToNewUTF8', '$lengthBytesUTF8'], |
| wgpuAdapterGetInfo: (adapterPtr, info) => { |
| var adapter = WebGPU.getJsObject(adapterPtr); |
| {{{ gpu.makeCheckDescriptor('info') }}} |
| |
| // Append all the strings together to condense into a single malloc. |
| var strs = adapter.info.vendor + adapter.info.architecture + adapter.info.device + adapter.info.description; |
| var strPtr = stringToNewUTF8(strs); |
| |
| var vendorLen = lengthBytesUTF8(adapter.info.vendor); |
| WebGPU.setStringView(info + {{{ C_STRUCTS.WGPUAdapterInfo.vendor }}}, strPtr, vendorLen); |
| strPtr += vendorLen; |
| |
| var architectureLen = lengthBytesUTF8(adapter.info.architecture); |
| WebGPU.setStringView(info + {{{ C_STRUCTS.WGPUAdapterInfo.architecture }}}, strPtr, architectureLen); |
| strPtr += architectureLen; |
| |
| var deviceLen = lengthBytesUTF8(adapter.info.device); |
| WebGPU.setStringView(info + {{{ C_STRUCTS.WGPUAdapterInfo.device }}}, strPtr, deviceLen); |
| strPtr += deviceLen; |
| |
| var descriptionLen = lengthBytesUTF8(adapter.info.description); |
| WebGPU.setStringView(info + {{{ C_STRUCTS.WGPUAdapterInfo.description }}}, strPtr, descriptionLen); |
| strPtr += descriptionLen; |
| |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.backendType, gpu.BackendType.WebGPU, 'i32') }}}; |
| var adapterType = adapter.isFallbackAdapter ? {{{ gpu.AdapterType.CPU }}} : {{{ gpu.AdapterType.Unknown }}}; |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.adapterType, 'adapterType', 'i32') }}}; |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.vendorID, '0', 'i32') }}}; |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.deviceID, '0', 'i32') }}}; |
| }, |
| |
| wgpuAdapterGetLimits: (adapterPtr, limitsOutPtr) => { |
| var adapter = WebGPU.getJsObject(adapterPtr); |
| WebGPU.fillLimitStruct(adapter.limits, limitsOutPtr); |
| return 1; |
| }, |
| |
| wgpuAdapterHasFeature: (adapterPtr, featureEnumValue) => { |
| var adapter = WebGPU.getJsObject(adapterPtr); |
| return adapter.features.has(WebGPU.FeatureName[featureEnumValue]); |
| }, |
| |
| emwgpuAdapterRequestDevice__deps: ['emwgpuCreateQueue', 'emwgpuOnDeviceLostCompleted', 'emwgpuOnRequestDeviceCompleted', 'emwgpuOnUncapturedError'], |
| emwgpuAdapterRequestDevice__sig: 'vpjjppp', |
| emwgpuAdapterRequestDevice: (adapterPtr, futureId, deviceLostFutureId, devicePtr, queuePtr, descriptor) => { |
| var adapter = WebGPU.getJsObject(adapterPtr); |
| |
| var desc = {}; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| var requiredFeatureCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUDeviceDescriptor.requiredFeatureCount) }}}; |
| if (requiredFeatureCount) { |
| var requiredFeaturesPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.requiredFeatures, '*') }}}; |
| // requiredFeaturesPtr is a pointer to an array of FeatureName which is an enum of size uint32_t |
| desc["requiredFeatures"] = Array.from({{{ makeHEAPView('U32', 'requiredFeaturesPtr', `requiredFeaturesPtr + requiredFeatureCount * 4`) }}}, |
| (feature) => WebGPU.FeatureName[feature]); |
| } |
| var requiredLimitsPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.requiredLimits, '*') }}}; |
| if (requiredLimitsPtr) { |
| {{{ gpu.makeCheckDescriptor('requiredLimitsPtr') }}} |
| var limitsPtr = requiredLimitsPtr + {{{ C_STRUCTS.WGPURequiredLimits.limits }}}; |
| var requiredLimits = {}; |
| function setLimitU32IfDefined(name, limitOffset) { |
| var ptr = limitsPtr + limitOffset; |
| var value = {{{ gpu.makeGetU32('ptr', 0) }}}; |
| if (value != {{{ gpu.LIMIT_U32_UNDEFINED }}}) { |
| requiredLimits[name] = value; |
| } |
| } |
| function setLimitU64IfDefined(name, limitOffset) { |
| var ptr = limitsPtr + limitOffset; |
| // Handle WGPU_LIMIT_U64_UNDEFINED. |
| var limitPart1 = {{{ gpu.makeGetU32('ptr', 0) }}}; |
| var limitPart2 = {{{ gpu.makeGetU32('ptr', 4) }}}; |
| if (limitPart1 != 0xFFFFFFFF || limitPart2 != 0xFFFFFFFF) { |
| requiredLimits[name] = {{{ gpu.makeGetU64('ptr', 0) }}} |
| } |
| } |
| |
| setLimitU32IfDefined("maxTextureDimension1D", {{{ C_STRUCTS.WGPULimits.maxTextureDimension1D }}}); |
| setLimitU32IfDefined("maxTextureDimension2D", {{{ C_STRUCTS.WGPULimits.maxTextureDimension2D }}}); |
| setLimitU32IfDefined("maxTextureDimension3D", {{{ C_STRUCTS.WGPULimits.maxTextureDimension3D }}}); |
| setLimitU32IfDefined("maxTextureArrayLayers", {{{ C_STRUCTS.WGPULimits.maxTextureArrayLayers }}}); |
| setLimitU32IfDefined("maxBindGroups", {{{ C_STRUCTS.WGPULimits.maxBindGroups }}}); |
| setLimitU32IfDefined('maxBindGroupsPlusVertexBuffers', {{{ C_STRUCTS.WGPULimits.maxBindGroupsPlusVertexBuffers }}}); |
| setLimitU32IfDefined("maxDynamicUniformBuffersPerPipelineLayout", {{{ C_STRUCTS.WGPULimits.maxDynamicUniformBuffersPerPipelineLayout }}}); |
| setLimitU32IfDefined("maxDynamicStorageBuffersPerPipelineLayout", {{{ C_STRUCTS.WGPULimits.maxDynamicStorageBuffersPerPipelineLayout }}}); |
| setLimitU32IfDefined("maxSampledTexturesPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxSampledTexturesPerShaderStage }}}); |
| setLimitU32IfDefined("maxSamplersPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxSamplersPerShaderStage }}}); |
| setLimitU32IfDefined("maxStorageBuffersPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxStorageBuffersPerShaderStage }}}); |
| setLimitU32IfDefined("maxStorageTexturesPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxStorageTexturesPerShaderStage }}}); |
| setLimitU32IfDefined("maxUniformBuffersPerShaderStage", {{{ C_STRUCTS.WGPULimits.maxUniformBuffersPerShaderStage }}}); |
| setLimitU32IfDefined("minUniformBufferOffsetAlignment", {{{ C_STRUCTS.WGPULimits.minUniformBufferOffsetAlignment }}}); |
| setLimitU32IfDefined("minStorageBufferOffsetAlignment", {{{ C_STRUCTS.WGPULimits.minStorageBufferOffsetAlignment }}}); |
| setLimitU64IfDefined("maxUniformBufferBindingSize", {{{ C_STRUCTS.WGPULimits.maxUniformBufferBindingSize }}}); |
| setLimitU64IfDefined("maxStorageBufferBindingSize", {{{ C_STRUCTS.WGPULimits.maxStorageBufferBindingSize }}}); |
| setLimitU32IfDefined("maxVertexBuffers", {{{ C_STRUCTS.WGPULimits.maxVertexBuffers }}}); |
| setLimitU64IfDefined("maxBufferSize", {{{ C_STRUCTS.WGPULimits.maxBufferSize }}}); |
| setLimitU32IfDefined("maxVertexAttributes", {{{ C_STRUCTS.WGPULimits.maxVertexAttributes }}}); |
| setLimitU32IfDefined("maxVertexBufferArrayStride", {{{ C_STRUCTS.WGPULimits.maxVertexBufferArrayStride }}}); |
| setLimitU32IfDefined("maxInterStageShaderComponents", {{{ C_STRUCTS.WGPULimits.maxInterStageShaderComponents }}}); |
| setLimitU32IfDefined("maxInterStageShaderVariables", {{{ C_STRUCTS.WGPULimits.maxInterStageShaderVariables }}}); |
| setLimitU32IfDefined("maxColorAttachments", {{{ C_STRUCTS.WGPULimits.maxColorAttachments }}}); |
| setLimitU32IfDefined("maxColorAttachmentBytesPerSample", {{{ C_STRUCTS.WGPULimits.maxColorAttachmentBytesPerSample }}}); |
| setLimitU32IfDefined("maxComputeWorkgroupStorageSize", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupStorageSize }}}); |
| setLimitU32IfDefined("maxComputeInvocationsPerWorkgroup", {{{ C_STRUCTS.WGPULimits.maxComputeInvocationsPerWorkgroup }}}); |
| setLimitU32IfDefined("maxComputeWorkgroupSizeX", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeX }}}); |
| setLimitU32IfDefined("maxComputeWorkgroupSizeY", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeY }}}); |
| setLimitU32IfDefined("maxComputeWorkgroupSizeZ", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupSizeZ }}}); |
| setLimitU32IfDefined("maxComputeWorkgroupsPerDimension", {{{ C_STRUCTS.WGPULimits.maxComputeWorkgroupsPerDimension }}}); |
| desc["requiredLimits"] = requiredLimits; |
| } |
| |
| var defaultQueuePtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.defaultQueue, '*') }}}; |
| if (defaultQueuePtr) { |
| var defaultQueueDesc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| defaultQueuePtr + {{{ C_STRUCTS.WGPUQueueDescriptor.label }}}), |
| }; |
| desc["defaultQueue"] = defaultQueueDesc; |
| } |
| desc["label"] = WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUDeviceDescriptor.label }}} |
| ); |
| } |
| |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, adapter.requestDevice(desc).then((device) => { |
| {{{ runtimeKeepalivePop() }}} |
| WebGPU.Internals.jsObjectInsert(queuePtr, device.queue); |
| WebGPU.Internals.jsObjectInsert(devicePtr, device); |
| |
| // Set up device lost promise resolution. |
| if (deviceLostFutureId) { |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(deviceLostFutureId, device.lost.then((info) => { |
| {{{ runtimeKeepalivePop() }}} |
| // Unset the uncaptured error handler. |
| device.onuncapturederror = (ev) => {}; |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(info.message); |
| _emwgpuOnDeviceLostCompleted(deviceLostFutureId, WebGPU.Int_DeviceLostReason[info.reason], messagePtr); |
| stackRestore(sp); |
| })); |
| } |
| |
| // Set up uncaptured error handlers. |
| #if ASSERTIONS |
| assert(typeof GPUValidationError != 'undefined'); |
| assert(typeof GPUOutOfMemoryError != 'undefined'); |
| assert(typeof GPUInternalError != 'undefined'); |
| #endif |
| device.onuncapturederror = (ev) => { |
| var type = {{{ gpu.ErrorType.Unknown }}}; |
| if (ev.error instanceof GPUValidationError) type = {{{ gpu.ErrorType.Validation }}}; |
| else if (ev.error instanceof GPUOutOfMemoryError) type = {{{ gpu.ErrorType.OutOfMemory }}}; |
| else if (ev.error instanceof GPUInternalError) type = {{{ gpu.ErrorType.Internal }}}; |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(ev.error.message); |
| _emwgpuOnUncapturedError(devicePtr, type, messagePtr); |
| stackRestore(sp); |
| }; |
| |
| _emwgpuOnRequestDeviceCompleted(futureId, {{{ gpu.RequestDeviceStatus.Success }}}, devicePtr, 0); |
| }, (ex) => { |
| {{{ runtimeKeepalivePop() }}} |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(ex.message); |
| _emwgpuOnRequestDeviceCompleted(futureId, {{{ gpu.RequestDeviceStatus.Error }}}, devicePtr, messagePtr); |
| if (deviceLostFutureId) { |
| _emwgpuOnDeviceLostCompleted(deviceLostFutureId, {{{ gpu.DeviceLostReason.FailedCreation }}}, messagePtr); |
| } |
| stackRestore(sp); |
| })); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of BindGroup |
| // -------------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------------- |
| // Methods of BindGroupLayout |
| // -------------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Buffer |
| // -------------------------------------------------------------------------- |
| |
| emwgpuBufferDestroy__sig: 'vp', |
| emwgpuBufferDestroy: (bufferPtr) => { |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| var onUnmap = WebGPU.Internals.bufferOnUnmaps[bufferPtr]; |
| if (onUnmap) { |
| for (var i = 0; i < onUnmap.length; ++i) { |
| onUnmap[i](); |
| } |
| delete WebGPU.Internals.bufferOnUnmaps[bufferPtr]; |
| } |
| |
| buffer.destroy(); |
| }, |
| |
| // In webgpu.h offset and size are passed in as size_t. |
| // And library_webgpu assumes that size_t is always 32bit in emscripten. |
| emwgpuBufferGetConstMappedRange__deps: ['$warnOnce', 'memalign', 'free'], |
| emwgpuBufferGetConstMappedRange__sig: 'pppp', |
| emwgpuBufferGetConstMappedRange: (bufferPtr, offset, size) => { |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| |
| if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE'); |
| |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| var mapped; |
| try { |
| mapped = buffer.getMappedRange(offset, size); |
| } catch (ex) { |
| #if ASSERTIONS |
| err(`wgpuBufferGetConstMappedRange(${offset}, ${size}) failed: ${ex}`); |
| #endif |
| // TODO(kainino0x): Somehow inject a validation error? |
| return 0; |
| } |
| var data = _memalign(16, mapped.byteLength); |
| HEAPU8.set(new Uint8Array(mapped), data); |
| WebGPU.Internals.bufferOnUnmaps[bufferPtr].push(() => _free(data)); |
| return data; |
| }, |
| |
| // In webgpu.h offset and size are passed in as size_t. |
| // And library_webgpu assumes that size_t is always 32bit in emscripten. |
| emwgpuBufferGetMappedRange__deps: ['$warnOnce', 'memalign', 'free'], |
| emwgpuBufferGetMappedRange__sig: 'pppp', |
| emwgpuBufferGetMappedRange: (bufferPtr, offset, size) => { |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| |
| if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE'); |
| |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| var mapped; |
| try { |
| mapped = buffer.getMappedRange(offset, size); |
| } catch (ex) { |
| #if ASSERTIONS |
| err(`wgpuBufferGetMappedRange(${offset}, ${size}) failed: ${ex}`); |
| #endif |
| // TODO(kainino0x): Somehow inject a validation error? |
| return 0; |
| } |
| |
| var data = _memalign(16, mapped.byteLength); |
| HEAPU8.fill(0, data, mapped.byteLength); |
| WebGPU.Internals.bufferOnUnmaps[bufferPtr].push(() => { |
| new Uint8Array(mapped).set(HEAPU8.subarray(data, data + mapped.byteLength)); |
| _free(data); |
| }); |
| return data; |
| }, |
| |
| wgpuBufferGetSize: (bufferPtr) => { |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| // 64-bit |
| return buffer.size; |
| }, |
| |
| wgpuBufferGetUsage: (bufferPtr) => { |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| return buffer.usage; |
| }, |
| |
| // In webgpu.h offset and size are passed in as size_t. |
| // And library_webgpu assumes that size_t is always 32bit in emscripten. |
| emwgpuBufferMapAsync__deps: ['emwgpuOnMapAsyncCompleted'], |
| emwgpuBufferMapAsync__sig: 'vpjjpp', |
| emwgpuBufferMapAsync: (bufferPtr, futureId, mode, offset, size) => { |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| WebGPU.Internals.bufferOnUnmaps[bufferPtr] = []; |
| |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, buffer.mapAsync(mode, offset, size).then(() => { |
| {{{ runtimeKeepalivePop() }}} |
| _emwgpuOnMapAsyncCompleted(futureId, {{{ gpu.MapAsyncStatus.Success }}}, 0); |
| }, (ex) => { |
| {{{ runtimeKeepalivePop() }}} |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(ex.message); |
| var status = |
| ex instanceof AbortError ? {{{ gpu.MapAsyncStatus.Aborted }}} : |
| ex instanceof OperationError ? {{{ gpu.MapAsyncStatus.Error }}} : |
| {{{ gpu.MapAsyncStatus.Unknown }}}; |
| _emwgpuOnMapAsyncCompleted(futureId, status, messagePtr); |
| delete WebGPU.Internals.bufferOnUnmaps[bufferPtr]; |
| })); |
| }, |
| |
| emwgpuBufferUnmap__sig: 'vp', |
| emwgpuBufferUnmap: (bufferPtr) => { |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| |
| var onUnmap = WebGPU.Internals.bufferOnUnmaps[bufferPtr]; |
| if (!onUnmap) { |
| // Already unmapped |
| return; |
| } |
| |
| for (var i = 0; i < onUnmap.length; ++i) { |
| onUnmap[i](); |
| } |
| delete WebGPU.Internals.bufferOnUnmaps[bufferPtr] |
| |
| buffer.unmap(); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of CommandBuffer |
| // -------------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------------- |
| // Methods of CommandEncoder |
| // -------------------------------------------------------------------------- |
| |
| wgpuCommandEncoderBeginComputePass__deps: ['emwgpuCreateComputePassEncoder'], |
| wgpuCommandEncoderBeginComputePass: (encoderPtr, descriptor) => { |
| var desc; |
| |
| function makeComputePassTimestampWrites(twPtr) { |
| if (twPtr === 0) return undefined; |
| |
| return { |
| "querySet": WebGPU.getJsObject( |
| {{{ makeGetValue('twPtr', C_STRUCTS.WGPUComputePassTimestampWrites.querySet, '*') }}}), |
| "beginningOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPUComputePassTimestampWrites.beginningOfPassWriteIndex) }}}, |
| "endOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPUComputePassTimestampWrites.endOfPassWriteIndex) }}}, |
| }; |
| } |
| |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUComputePassDescriptor.label }}}), |
| "timestampWrites": makeComputePassTimestampWrites( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePassDescriptor.timestampWrites, '*') }}}), |
| }; |
| } |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var ptr = _emwgpuCreateComputePassEncoder(); |
| WebGPU.Internals.jsObjectInsert(ptr, commandEncoder.beginComputePass(desc)); |
| return ptr; |
| }, |
| |
| wgpuCommandEncoderBeginRenderPass__deps: ['emwgpuCreateRenderPassEncoder'], |
| wgpuCommandEncoderBeginRenderPass: (encoderPtr, descriptor) => { |
| {{{ gpu.makeCheck('descriptor') }}} |
| |
| function makeColorAttachment(caPtr) { |
| var viewPtr = {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.view) }}}; |
| if (viewPtr === 0) { |
| // view could be undefined. |
| return undefined; |
| } |
| |
| var depthSlice = {{{ makeGetValue('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.depthSlice, 'i32') }}}; |
| {{{ gpu.convertSentinelToUndefined('depthSlice') }}} |
| |
| var loadOpInt = {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.loadOp) }}}; |
| #if ASSERTIONS |
| assert(loadOpInt !== {{{ gpu.LoadOp.Undefined }}}); |
| #endif |
| |
| var storeOpInt = {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.storeOp) }}}; |
| #if ASSERTIONS |
| assert(storeOpInt !== {{{ gpu.StoreOp.Undefined }}}); |
| #endif |
| |
| var clearValue = WebGPU.makeColor(caPtr + {{{ C_STRUCTS.WGPURenderPassColorAttachment.clearValue }}}); |
| |
| return { |
| "view": WebGPU.getJsObject(viewPtr), |
| "depthSlice": depthSlice, |
| "resolveTarget": WebGPU.getJsObject( |
| {{{ gpu.makeGetU32('caPtr', C_STRUCTS.WGPURenderPassColorAttachment.resolveTarget) }}}), |
| "clearValue": clearValue, |
| "loadOp": WebGPU.LoadOp[loadOpInt], |
| "storeOp": WebGPU.StoreOp[storeOpInt], |
| }; |
| } |
| |
| function makeColorAttachments(count, caPtr) { |
| var attachments = []; |
| for (var i = 0; i < count; ++i) { |
| attachments.push(makeColorAttachment(caPtr + {{{ C_STRUCTS.WGPURenderPassColorAttachment.__size__ }}} * i)); |
| } |
| return attachments; |
| } |
| |
| function makeDepthStencilAttachment(dsaPtr) { |
| if (dsaPtr === 0) return undefined; |
| |
| return { |
| "view": WebGPU.getJsObject( |
| {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.view) }}}), |
| "depthClearValue": {{{ makeGetValue('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthClearValue, 'float') }}}, |
| "depthLoadOp": WebGPU.LoadOp[ |
| {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthLoadOp) }}}], |
| "depthStoreOp": WebGPU.StoreOp[ |
| {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthStoreOp) }}}], |
| "depthReadOnly": {{{ gpu.makeGetBool('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.depthReadOnly) }}}, |
| "stencilClearValue": {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilClearValue) }}}, |
| "stencilLoadOp": WebGPU.LoadOp[ |
| {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilLoadOp) }}}], |
| "stencilStoreOp": WebGPU.StoreOp[ |
| {{{ gpu.makeGetU32('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilStoreOp) }}}], |
| "stencilReadOnly": {{{ gpu.makeGetBool('dsaPtr', C_STRUCTS.WGPURenderPassDepthStencilAttachment.stencilReadOnly) }}}, |
| }; |
| } |
| |
| function makeRenderPassTimestampWrites(twPtr) { |
| if (twPtr === 0) return undefined; |
| |
| return { |
| "querySet": WebGPU.getJsObject( |
| {{{ makeGetValue('twPtr', C_STRUCTS.WGPURenderPassTimestampWrites.querySet, '*') }}}), |
| "beginningOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPURenderPassTimestampWrites.beginningOfPassWriteIndex) }}}, |
| "endOfPassWriteIndex": {{{ gpu.makeGetU32('twPtr', C_STRUCTS.WGPURenderPassTimestampWrites.endOfPassWriteIndex) }}}, |
| }; |
| } |
| |
| function makeRenderPassDescriptor(descriptor) { |
| {{{ gpu.makeCheck('descriptor') }}} |
| var nextInChainPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.nextInChain, '*') }}}; |
| |
| var maxDrawCount = undefined; |
| if (nextInChainPtr !== 0) { |
| var sType = {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}}; |
| #if ASSERTIONS |
| assert(sType === {{{ gpu.SType.RenderPassMaxDrawCount }}}); |
| assert(0 === {{{ makeGetValue('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.next, '*') }}}); |
| #endif |
| var renderPassMaxDrawCount = nextInChainPtr; |
| {{{ gpu.makeCheckDescriptor('renderPassMaxDrawCount') }}} |
| maxDrawCount = {{{ gpu.makeGetU64('renderPassMaxDrawCount', C_STRUCTS.WGPURenderPassMaxDrawCount.maxDrawCount) }}}; |
| } |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPURenderPassDescriptor.label }}}), |
| "colorAttachments": makeColorAttachments( |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderPassDescriptor.colorAttachmentCount) }}}, |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.colorAttachments, '*') }}}), |
| "depthStencilAttachment": makeDepthStencilAttachment( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.depthStencilAttachment, '*') }}}), |
| "occlusionQuerySet": WebGPU.getJsObject( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.occlusionQuerySet, '*') }}}), |
| "timestampWrites": makeRenderPassTimestampWrites( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.timestampWrites, '*') }}}), |
| "maxDrawCount": maxDrawCount, |
| }; |
| return desc; |
| } |
| |
| var desc = makeRenderPassDescriptor(descriptor); |
| |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var ptr = _emwgpuCreateRenderPassEncoder(); |
| WebGPU.Internals.jsObjectInsert(ptr, commandEncoder.beginRenderPass(desc)); |
| return ptr; |
| }, |
| |
| wgpuCommandEncoderClearBuffer: (encoderPtr, bufferPtr, offset, size) => { |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| commandEncoder.clearBuffer(buffer, offset, size); |
| }, |
| |
| wgpuCommandEncoderCopyBufferToBuffer: (encoderPtr, srcPtr, srcOffset, dstPtr, dstOffset, size) => { |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var src = WebGPU.getJsObject(srcPtr); |
| var dst = WebGPU.getJsObject(dstPtr); |
| commandEncoder.copyBufferToBuffer(src, srcOffset, dst, dstOffset, size); |
| }, |
| |
| wgpuCommandEncoderCopyBufferToTexture: (encoderPtr, srcPtr, dstPtr, copySizePtr) => { |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var copySize = WebGPU.makeExtent3D(copySizePtr); |
| commandEncoder.copyBufferToTexture( |
| WebGPU.makeImageCopyBuffer(srcPtr), WebGPU.makeImageCopyTexture(dstPtr), copySize); |
| }, |
| |
| wgpuCommandEncoderCopyTextureToBuffer: (encoderPtr, srcPtr, dstPtr, copySizePtr) => { |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var copySize = WebGPU.makeExtent3D(copySizePtr); |
| commandEncoder.copyTextureToBuffer( |
| WebGPU.makeImageCopyTexture(srcPtr), WebGPU.makeImageCopyBuffer(dstPtr), copySize); |
| }, |
| |
| wgpuCommandEncoderCopyTextureToTexture: (encoderPtr, srcPtr, dstPtr, copySizePtr) => { |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var copySize = WebGPU.makeExtent3D(copySizePtr); |
| commandEncoder.copyTextureToTexture( |
| WebGPU.makeImageCopyTexture(srcPtr), WebGPU.makeImageCopyTexture(dstPtr), copySize); |
| }, |
| |
| wgpuCommandEncoderFinish__deps: ['emwgpuCreateCommandBuffer'], |
| wgpuCommandEncoderFinish: (encoderPtr, descriptor) => { |
| // TODO: Use the descriptor. |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var ptr = _emwgpuCreateCommandBuffer(); |
| WebGPU.Internals.jsObjectInsert(ptr, commandEncoder.finish()); |
| return ptr; |
| }, |
| |
| wgpuCommandEncoderInsertDebugMarker2: (encoderPtr, markerLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.insertDebugMarker(WebGPU.makeStringFromStringView(markerLabelPtr)); |
| }, |
| |
| wgpuCommandEncoderPopDebugGroup: (encoderPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.popDebugGroup(); |
| }, |
| |
| wgpuCommandEncoderPushDebugGroup2: (encoderPtr, groupLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.pushDebugGroup(WebGPU.makeStringFromStringView(groupLabelPtr)); |
| }, |
| |
| wgpuCommandEncoderResolveQuerySet: (encoderPtr, querySetPtr, firstQuery, queryCount, destinationPtr, destinationOffset) => { |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var querySet = WebGPU.getJsObject(querySetPtr); |
| var destination = WebGPU.getJsObject(destinationPtr); |
| |
| commandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset); |
| }, |
| |
| wgpuCommandEncoderWriteTimestamp: (encoderPtr, querySetPtr, queryIndex) => { |
| var commandEncoder = WebGPU.getJsObject(encoderPtr); |
| var querySet = WebGPU.getJsObject(querySetPtr); |
| commandEncoder.writeTimestamp(querySet, queryIndex); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of ComputePassEncoder |
| // -------------------------------------------------------------------------- |
| |
| wgpuComputePassEncoderDispatchWorkgroups: (passPtr, x, y, z) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.dispatchWorkgroups(x, y, z); |
| }, |
| |
| wgpuComputePassEncoderDispatchWorkgroupsIndirect: (passPtr, indirectBufferPtr, indirectOffset) => { |
| var indirectBuffer = WebGPU.getJsObject(indirectBufferPtr); |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuComputePassEncoderEnd: (passPtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.end(); |
| }, |
| |
| wgpuComputePassEncoderInsertDebugMarker2: (encoderPtr, markerLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.insertDebugMarker(WebGPU.makeStringFromStringView(markerLabelPtr)); |
| }, |
| |
| wgpuComputePassEncoderPopDebugGroup: (encoderPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.popDebugGroup(); |
| }, |
| |
| wgpuComputePassEncoderPushDebugGroup2: (encoderPtr, groupLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.pushDebugGroup(WebGPU.makeStringFromStringView(groupLabelPtr)); |
| }, |
| |
| wgpuComputePassEncoderSetBindGroup: (passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var group = WebGPU.getJsObject(groupPtr); |
| if (dynamicOffsetCount == 0) { |
| pass.setBindGroup(groupIndex, group); |
| } else { |
| var offsets = []; |
| for (var i = 0; i < dynamicOffsetCount; i++, dynamicOffsetsPtr += 4) { |
| offsets.push({{{ gpu.makeGetU32('dynamicOffsetsPtr', 0) }}}); |
| } |
| pass.setBindGroup(groupIndex, group, offsets); |
| } |
| }, |
| |
| wgpuComputePassEncoderSetPipeline: (passPtr, pipelinePtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var pipeline = WebGPU.getJsObject(pipelinePtr); |
| pass.setPipeline(pipeline); |
| }, |
| |
| wgpuComputePassEncoderWriteTimestamp: (encoderPtr, querySetPtr, queryIndex) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| var querySet = WebGPU.getJsObject(querySetPtr); |
| encoder.writeTimestamp(querySet, queryIndex); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of ComputePipeline |
| // -------------------------------------------------------------------------- |
| |
| wgpuComputePipelineGetBindGroupLayout__deps: ['emwgpuCreateBindGroupLayout'], |
| wgpuComputePipelineGetBindGroupLayout: (pipelinePtr, groupIndex) => { |
| var pipeline = WebGPU.getJsObject(pipelinePtr); |
| var ptr = _emwgpuCreateBindGroupLayout(); |
| WebGPU.Internals.jsObjectInsert(ptr, pipeline.getBindGroupLayout(groupIndex)); |
| return ptr; |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Device |
| // -------------------------------------------------------------------------- |
| |
| wgpuDeviceCreateBindGroup__deps: ['$readI53FromI64', 'emwgpuCreateBindGroup'], |
| wgpuDeviceCreateBindGroup: (devicePtr, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| function makeEntry(entryPtr) { |
| {{{ gpu.makeCheck('entryPtr') }}} |
| |
| var bufferPtr = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.buffer) }}}; |
| var samplerPtr = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.sampler) }}}; |
| var textureViewPtr = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.textureView) }}}; |
| #if ASSERTIONS |
| assert((bufferPtr !== 0) + (samplerPtr !== 0) + (textureViewPtr !== 0) === 1); |
| #endif |
| |
| var binding = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.binding) }}}; |
| |
| if (bufferPtr) { |
| var size = {{{ makeGetValue('entryPtr', C_STRUCTS.WGPUBindGroupEntry.size, 'i53') }}}; |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| return { |
| "binding": binding, |
| "resource": { |
| "buffer": WebGPU.getJsObject(bufferPtr), |
| "offset": {{{ gpu.makeGetU64('entryPtr', C_STRUCTS.WGPUBindGroupEntry.offset) }}}, |
| "size": size |
| }, |
| }; |
| } else if (samplerPtr) { |
| return { |
| "binding": binding, |
| "resource": WebGPU.getJsObject(samplerPtr), |
| }; |
| } else { |
| return { |
| "binding": binding, |
| "resource": WebGPU.getJsObject(textureViewPtr), |
| }; |
| } |
| } |
| |
| function makeEntries(count, entriesPtrs) { |
| var entries = []; |
| for (var i = 0; i < count; ++i) { |
| entries.push(makeEntry(entriesPtrs + |
| {{{C_STRUCTS.WGPUBindGroupEntry.__size__}}} * i)); |
| } |
| return entries; |
| } |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUBindGroupDescriptor.label }}}), |
| "layout": WebGPU.getJsObject( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.layout, '*') }}}), |
| "entries": makeEntries( |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.entryCount) }}}, |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.entries, '*') }}} |
| ), |
| }; |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateBindGroup(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createBindGroup(desc)); |
| return ptr; |
| }, |
| |
| wgpuDeviceCreateBindGroupLayout__deps: ['emwgpuCreateBindGroupLayout'], |
| wgpuDeviceCreateBindGroupLayout: (devicePtr, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| function makeBufferEntry(entryPtr) { |
| {{{ gpu.makeCheck('entryPtr') }}} |
| |
| var typeInt = |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBufferBindingLayout.type) }}}; |
| if (!typeInt) return undefined; |
| |
| return { |
| "type": WebGPU.BufferBindingType[typeInt], |
| "hasDynamicOffset": |
| {{{ gpu.makeGetBool('entryPtr', C_STRUCTS.WGPUBufferBindingLayout.hasDynamicOffset) }}}, |
| "minBindingSize": |
| {{{ gpu.makeGetU64('entryPtr', C_STRUCTS.WGPUBufferBindingLayout.minBindingSize) }}}, |
| }; |
| } |
| |
| function makeSamplerEntry(entryPtr) { |
| {{{ gpu.makeCheck('entryPtr') }}} |
| |
| var typeInt = |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUSamplerBindingLayout.type) }}}; |
| if (!typeInt) return undefined; |
| |
| return { |
| "type": WebGPU.SamplerBindingType[typeInt], |
| }; |
| } |
| |
| function makeTextureEntry(entryPtr) { |
| {{{ gpu.makeCheck('entryPtr') }}} |
| |
| var sampleTypeInt = |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUTextureBindingLayout.sampleType) }}}; |
| if (!sampleTypeInt) return undefined; |
| |
| return { |
| "sampleType": WebGPU.TextureSampleType[sampleTypeInt], |
| "viewDimension": WebGPU.TextureViewDimension[ |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUTextureBindingLayout.viewDimension) }}}], |
| "multisampled": |
| {{{ gpu.makeGetBool('entryPtr', C_STRUCTS.WGPUTextureBindingLayout.multisampled) }}}, |
| }; |
| } |
| |
| function makeStorageTextureEntry(entryPtr) { |
| {{{ gpu.makeCheck('entryPtr') }}} |
| |
| var accessInt = |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUStorageTextureBindingLayout.access) }}} |
| if (!accessInt) return undefined; |
| |
| return { |
| "access": WebGPU.StorageTextureAccess[accessInt], |
| "format": WebGPU.TextureFormat[ |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUStorageTextureBindingLayout.format) }}}], |
| "viewDimension": WebGPU.TextureViewDimension[ |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUStorageTextureBindingLayout.viewDimension) }}}], |
| }; |
| } |
| |
| function makeEntry(entryPtr) { |
| {{{ gpu.makeCheck('entryPtr') }}} |
| |
| return { |
| "binding": |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupLayoutEntry.binding) }}}, |
| "visibility": |
| {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupLayoutEntry.visibility) }}}, |
| "buffer": makeBufferEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.buffer }}}), |
| "sampler": makeSamplerEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.sampler }}}), |
| "texture": makeTextureEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.texture }}}), |
| "storageTexture": makeStorageTextureEntry(entryPtr + {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.storageTexture }}}), |
| }; |
| } |
| |
| function makeEntries(count, entriesPtrs) { |
| var entries = []; |
| for (var i = 0; i < count; ++i) { |
| entries.push(makeEntry(entriesPtrs + |
| {{{ C_STRUCTS.WGPUBindGroupLayoutEntry.__size__ }}} * i)); |
| } |
| return entries; |
| } |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUBindGroupLayoutDescriptor.label }}}), |
| "entries": makeEntries( |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.entryCount) }}}, |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.entries, '*') }}} |
| ), |
| }; |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateBindGroupLayout(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createBindGroupLayout(desc)); |
| return ptr; |
| }, |
| |
| emwgpuDeviceCreateBuffer__sig: 'vppp', |
| emwgpuDeviceCreateBuffer: (devicePtr, descriptor, bufferPtr) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| var mappedAtCreation = {{{ gpu.makeGetBool('descriptor', C_STRUCTS.WGPUBufferDescriptor.mappedAtCreation) }}}; |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUBufferDescriptor.label }}}), |
| "usage": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBufferDescriptor.usage) }}}, |
| "size": {{{ gpu.makeGetU64('descriptor', C_STRUCTS.WGPUBufferDescriptor.size) }}}, |
| "mappedAtCreation": mappedAtCreation, |
| }; |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| WebGPU.Internals.jsObjectInsert(bufferPtr, device.createBuffer(desc)); |
| if (mappedAtCreation) { |
| WebGPU.Internals.bufferOnUnmaps[bufferPtr] = []; |
| } |
| }, |
| |
| wgpuDeviceCreateCommandEncoder__deps: ['emwgpuCreateCommandEncoder'], |
| wgpuDeviceCreateCommandEncoder: (devicePtr, descriptor) => { |
| var desc; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUCommandEncoderDescriptor.label }}}), |
| }; |
| } |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateCommandEncoder(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createCommandEncoder(desc)); |
| return ptr; |
| }, |
| |
| wgpuDeviceCreateComputePipeline__deps: ['emwgpuCreateComputePipeline'], |
| wgpuDeviceCreateComputePipeline: (devicePtr, descriptor) => { |
| var desc = WebGPU.makeComputePipelineDesc(descriptor); |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateComputePipeline(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createComputePipeline(desc)); |
| return ptr; |
| }, |
| |
| emwgpuDeviceCreateComputePipelineAsync__deps: ['emwgpuCreateComputePipeline', 'emwgpuOnCreateComputePipelineCompleted'], |
| emwgpuDeviceCreateComputePipelineAsync__sig: 'vpjp', |
| emwgpuDeviceCreateComputePipelineAsync: (devicePtr, futureId, descriptor) => { |
| var desc = WebGPU.makeComputePipelineDesc(descriptor); |
| var device = WebGPU.getJsObject(devicePtr); |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, device.createComputePipelineAsync(desc).then((pipeline) => { |
| {{{ runtimeKeepalivePop() }}} |
| var pipelinePtr = _emwgpuCreateComputePipeline(); |
| WebGPU.Internals.jsObjectInsert(pipelinePtr, pipeline); |
| _emwgpuOnCreateComputePipelineCompleted(futureId, {{{ gpu.CreatePipelineAsyncStatus.Success }}}, pipelinePtr, 0); |
| }, (pipelineError) => { |
| {{{ runtimeKeepalivePop() }}} |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(pipelineError.message); |
| var status = |
| pipeline.reason === 'validation' ? {{{ gpu.CreatePipelineAsyncStatus.ValidationError }}} : |
| pipeline.reason === 'internal' ? {{{ gpu.CreatePipelineAsyncStatus.InternalError }}} : |
| {{{ gpu.CreatePipelineAsyncStatus.Unknown }}}; |
| _emwgpuOnCreateComputePipelineCompleted(futureId, status, 0, messagePtr); |
| stackRestore(sp); |
| })); |
| }, |
| |
| wgpuDeviceCreatePipelineLayout__deps: ['emwgpuCreatePipelineLayout'], |
| wgpuDeviceCreatePipelineLayout: (devicePtr, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| var bglCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUPipelineLayoutDescriptor.bindGroupLayoutCount) }}}; |
| var bglPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUPipelineLayoutDescriptor.bindGroupLayouts, '*') }}}; |
| var bgls = []; |
| for (var i = 0; i < bglCount; ++i) { |
| bgls.push(WebGPU.getJsObject( |
| {{{ makeGetValue('bglPtr', `${POINTER_SIZE} * i`, '*') }}})); |
| } |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUPipelineLayoutDescriptor.label }}}), |
| "bindGroupLayouts": bgls, |
| }; |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreatePipelineLayout(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createPipelineLayout(desc)); |
| return ptr; |
| }, |
| |
| wgpuDeviceCreateQuerySet__deps: ['emwgpuCreateQuerySet'], |
| wgpuDeviceCreateQuerySet: (devicePtr, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| var desc = { |
| "type": WebGPU.QueryType[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUQuerySetDescriptor.type) }}}], |
| "count": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUQuerySetDescriptor.count) }}}, |
| }; |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateQuerySet(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createQuerySet(desc)); |
| return ptr; |
| }, |
| |
| wgpuDeviceCreateRenderBundleEncoder__deps: ['emwgpuCreateRenderBundleEncoder'], |
| wgpuDeviceCreateRenderBundleEncoder: (devicePtr, descriptor) => { |
| {{{ gpu.makeCheck('descriptor') }}} |
| |
| function makeRenderBundleEncoderDescriptor(descriptor) { |
| {{{ gpu.makeCheck('descriptor') }}} |
| |
| function makeColorFormats(count, formatsPtr) { |
| var formats = []; |
| for (var i = 0; i < count; ++i, formatsPtr += 4) { |
| // format could be undefined |
| formats.push(WebGPU.TextureFormat[{{{ gpu.makeGetU32('formatsPtr', 0) }}}]); |
| } |
| return formats; |
| } |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPURenderBundleEncoderDescriptor.label }}}), |
| "colorFormats": makeColorFormats( |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.colorFormatCount) }}}, |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.colorFormats, '*') }}}), |
| "depthStencilFormat": WebGPU.TextureFormat[{{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.depthStencilFormat) }}}], |
| "sampleCount": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.sampleCount) }}}, |
| "depthReadOnly": {{{ gpu.makeGetBool('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.depthReadOnly) }}}, |
| "stencilReadOnly": {{{ gpu.makeGetBool('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.stencilReadOnly) }}}, |
| }; |
| return desc; |
| } |
| |
| var desc = makeRenderBundleEncoderDescriptor(descriptor); |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateRenderBundleEncoder(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createRenderBundleEncoder(desc)); |
| return ptr; |
| }, |
| |
| wgpuDeviceCreateRenderPipeline__deps: ['emwgpuCreateRenderPipeline'], |
| wgpuDeviceCreateRenderPipeline: (devicePtr, descriptor) => { |
| var desc = WebGPU.makeRenderPipelineDesc(descriptor); |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateRenderPipeline(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createRenderPipeline(desc)); |
| return ptr; |
| }, |
| |
| emwgpuDeviceCreateRenderPipelineAsync__deps: ['emwgpuCreateRenderPipeline', 'emwgpuOnCreateRenderPipelineCompleted'], |
| emwgpuDeviceCreateRenderPipelineAsync__sig: 'vpjp', |
| emwgpuDeviceCreateRenderPipelineAsync: (devicePtr, futureId, descriptor) => { |
| var desc = WebGPU.makeRenderPipelineDesc(descriptor); |
| var device = WebGPU.getJsObject(devicePtr); |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, device.createRenderPipelineAsync(desc).then((pipeline) => { |
| {{{ runtimeKeepalivePop() }}} |
| var pipelinePtr = _emwgpuCreateRenderPipeline(); |
| WebGPU.Internals.jsObjectInsert(pipelinePtr, pipeline); |
| _emwgpuOnCreateRenderPipelineCompleted(futureId, {{{ gpu.CreatePipelineAsyncStatus.Success }}}, pipelinePtr, 0); |
| }, (pipelineError) => { |
| {{{ runtimeKeepalivePop() }}} |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(pipelineError.message); |
| var status = |
| pipeline.reason === 'validation' ? {{{ gpu.CreatePipelineAsyncStatus.ValidationError }}} : |
| pipeline.reason === 'internal' ? {{{ gpu.CreatePipelineAsyncStatus.InternalError }}} : |
| {{{ gpu.CreatePipelineAsyncStatus.Unknown }}}; |
| _emwgpuOnCreateRenderPipelineCompleted(futureId, status, 0, messagePtr); |
| stackRestore(sp); |
| })); |
| }, |
| |
| wgpuDeviceCreateSampler__deps: ['emwgpuCreateSampler'], |
| wgpuDeviceCreateSampler: (devicePtr, descriptor) => { |
| var desc; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUSamplerDescriptor.label }}}), |
| "addressModeU": WebGPU.AddressMode[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.addressModeU) }}}], |
| "addressModeV": WebGPU.AddressMode[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.addressModeV) }}}], |
| "addressModeW": WebGPU.AddressMode[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.addressModeW) }}}], |
| "magFilter": WebGPU.FilterMode[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.magFilter) }}}], |
| "minFilter": WebGPU.FilterMode[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.minFilter) }}}], |
| "mipmapFilter": WebGPU.MipmapFilterMode[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.mipmapFilter) }}}], |
| "lodMinClamp": {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSamplerDescriptor.lodMinClamp, 'float') }}}, |
| "lodMaxClamp": {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSamplerDescriptor.lodMaxClamp, 'float') }}}, |
| "compare": WebGPU.CompareFunction[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSamplerDescriptor.compare) }}}], |
| }; |
| } |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateSampler(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createSampler(desc)); |
| return ptr; |
| }, |
| |
| emwgpuDeviceCreateShaderModule__sig: 'vppp', |
| emwgpuDeviceCreateShaderModule: (devicePtr, descriptor, shaderModulePtr) => { |
| {{{ gpu.makeCheck('descriptor') }}} |
| var nextInChainPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUShaderModuleDescriptor.nextInChain, '*') }}}; |
| #if ASSERTIONS |
| assert(nextInChainPtr !== 0); |
| #endif |
| var sType = {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}}; |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUShaderModuleDescriptor.label }}}), |
| "code": "", |
| }; |
| |
| switch (sType) { |
| case {{{ gpu.SType.ShaderSourceWGSL }}}: { |
| desc["code"] = WebGPU.makeStringFromStringView( |
| nextInChainPtr + {{{ C_STRUCTS.WGPUShaderSourceWGSL.code }}} |
| ); |
| break; |
| } |
| #if ASSERTIONS |
| default: abort('unrecognized ShaderModule sType'); |
| #endif |
| } |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| WebGPU.Internals.jsObjectInsert(shaderModulePtr, device.createShaderModule(desc)); |
| }, |
| |
| wgpuDeviceCreateTexture__deps: ['emwgpuCreateTexture'], |
| wgpuDeviceCreateTexture: (devicePtr, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| var desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUTextureDescriptor.label }}}), |
| "size": WebGPU.makeExtent3D(descriptor + {{{ C_STRUCTS.WGPUTextureDescriptor.size }}}), |
| "mipLevelCount": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.mipLevelCount) }}}, |
| "sampleCount": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.sampleCount) }}}, |
| "dimension": WebGPU.TextureDimension[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.dimension) }}}], |
| "format": WebGPU.TextureFormat[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.format) }}}], |
| "usage": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.usage) }}}, |
| }; |
| |
| var viewFormatCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureDescriptor.viewFormatCount) }}}; |
| if (viewFormatCount) { |
| var viewFormatsPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUTextureDescriptor.viewFormats, '*') }}}; |
| // viewFormatsPtr pointer to an array of TextureFormat which is an enum of size uint32_t |
| desc['viewFormats'] = Array.from({{{ makeHEAPView('32', 'viewFormatsPtr', 'viewFormatsPtr + viewFormatCount * 4') }}}, |
| format => WebGPU.TextureFormat[format]); |
| } |
| |
| var device = WebGPU.getJsObject(devicePtr); |
| var ptr = _emwgpuCreateTexture(); |
| WebGPU.Internals.jsObjectInsert(ptr, device.createTexture(desc)); |
| return ptr; |
| }, |
| |
| emwgpuDeviceDestroy: (devicePtr) => { |
| WebGPU.getJsObject(devicePtr).destroy() |
| }, |
| |
| wgpuDeviceGetFeatures__deps: ['malloc'], |
| wgpuDeviceGetFeatures: (devicePtr, supportedFeatures) => { |
| var device = WebGPU.getJsObject(devicePtr); |
| |
| // Always allocate enough space for all the features, though some may be unused. |
| var featuresPtr = _malloc(device.features.size * 4); |
| var offset = 0; |
| var numFeatures = 0; |
| device.features.forEach(feature => { |
| var featureEnumValue = WebGPU.FeatureNameString2Enum[feature]; |
| if (featureEnumValue !== undefined) { |
| {{{ makeSetValue('featuresPtr', 'offset', 'featureEnumValue', 'i32') }}}; |
| offset += 4; |
| numFeatures++; |
| } |
| }); |
| {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.features, 'featuresPtr', '*') }}}; |
| {{{ makeSetValue('supportedFeatures', C_STRUCTS.WGPUSupportedFeatures.featureCount, 'numFeatures', '*') }}}; |
| }, |
| |
| wgpuDeviceGetLimits: (devicePtr, limitsOutPtr) => { |
| var device = WebGPU.getJsObject(devicePtr); |
| WebGPU.fillLimitStruct(device.limits, limitsOutPtr); |
| return 1; |
| }, |
| |
| wgpuDeviceHasFeature: (devicePtr, featureEnumValue) => { |
| var device = WebGPU.getJsObject(devicePtr); |
| return device.features.has(WebGPU.FeatureName[featureEnumValue]); |
| }, |
| |
| wgpuDeviceGetAdapterInfo__deps: ['$stringToNewUTF8', '$lengthBytesUTF8'], |
| wgpuDeviceGetAdapterInfo: (devicePtr, adapterInfo) => { |
| // TODO(crbug.com/377760848): Avoid duplicated code with wgpuAdapterGetInfo, |
| // for example by deferring to wgpuAdapterGetInfo from webgpu.cpp. |
| var device = WebGPU.getJsObject(devicePtr); |
| {{{ gpu.makeCheckDescriptor('adapterInfo') }}} |
| |
| // Append all the strings together to condense into a single malloc. |
| var strs = device.adapterInfo.vendor + device.adapterInfo.architecture + device.adapterInfo.device + device.adapterInfo.description; |
| var strPtr = stringToNewUTF8(strs); |
| |
| var vendorLen = lengthBytesUTF8(device.adapterInfo.vendor); |
| WebGPU.setStringView(adapterInfo + {{{ C_STRUCTS.WGPUAdapterInfo.vendor }}}, strPtr, vendorLen); |
| strPtr += vendorLen; |
| |
| var architectureLen = lengthBytesUTF8(device.adapterInfo.architecture); |
| WebGPU.setStringView(adapterInfo + {{{ C_STRUCTS.WGPUAdapterInfo.architecture }}}, strPtr, architectureLen); |
| strPtr += architectureLen; |
| |
| var deviceLen = lengthBytesUTF8(device.adapterInfo.device); |
| WebGPU.setStringView(adapterInfo + {{{ C_STRUCTS.WGPUAdapterInfo.device }}}, strPtr, deviceLen); |
| strPtr += deviceLen; |
| |
| var descriptionLen = lengthBytesUTF8(device.adapterInfo.description); |
| WebGPU.setStringView(adapterInfo + {{{ C_STRUCTS.WGPUAdapterInfo.description }}}, strPtr, descriptionLen); |
| strPtr += descriptionLen; |
| |
| {{{ makeSetValue('adapterInfo', C_STRUCTS.WGPUAdapterInfo.backendType, gpu.BackendType.WebGPU, 'i32') }}}; |
| // TODO: Set the adapter type from adapter.isFallbackAdapter (not easily available here). |
| var adapterType = {{{ gpu.AdapterType.Unknown }}}; |
| {{{ makeSetValue('adapterInfo', C_STRUCTS.WGPUAdapterInfo.adapterType, 'adapterType', 'i32') }}}; |
| {{{ makeSetValue('adapterInfo', C_STRUCTS.WGPUAdapterInfo.vendorID, '0', 'i32') }}}; |
| {{{ makeSetValue('adapterInfo', C_STRUCTS.WGPUAdapterInfo.deviceID, '0', 'i32') }}}; |
| }, |
| |
| emwgpuDevicePopErrorScope__deps: ['emwgpuOnPopErrorScopeCompleted'], |
| emwgpuDevicePopErrorScope__sig: 'vpj', |
| emwgpuDevicePopErrorScope: (devicePtr, futureId) => { |
| var device = WebGPU.getJsObject(devicePtr); |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, device.popErrorScope().then((gpuError) => { |
| {{{ runtimeKeepalivePop() }}} |
| var type = {{{ gpu.ErrorType.Unknown }}}; |
| if (!gpuError) type = {{{ gpu.ErrorType.NoError }}}; |
| else if (gpuError instanceof GPUValidationError) type = {{{ gpu.ErrorType.Validation }}}; |
| else if (gpuError instanceof GPUOutOfMemoryError) type = {{{ gpu.ErrorType.OutOfMemory }}}; |
| else if (gpuError instanceof GPUInternalError) type = {{{ gpu.ErrorType.Internal }}}; |
| #if ASSERTIONS |
| else assert(false); |
| #endif |
| var sp = stackSave(); |
| var messagePtr = gpuError ? stringToUTF8OnStack(gpuError.message) : 0; |
| _emwgpuOnPopErrorScopeCompleted(futureId, {{{ gpu.PopErrorScopeStatus.Success }}}, type, messagePtr); |
| stackRestore(sp); |
| }, (ex) => { |
| {{{ runtimeKeepalivePop() }}} |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(ex.message); |
| _emwgpuOnPopErrorScopeCompleted(futureId, {{{ gpu.PopErrorScopeStatus.Success }}}, {{{ gpu.ErrorType.Unknown }}}, messagePtr); |
| stackRestore(sp); |
| })); |
| }, |
| |
| wgpuDevicePushErrorScope: (devicePtr, filter) => { |
| var device = WebGPU.getJsObject(devicePtr); |
| device.pushErrorScope(WebGPU.ErrorFilter[filter]); |
| }, |
| |
| // TODO(42241415) Remove this after verifying that it's not used and/or updating users. |
| wgpuDeviceSetUncapturedErrorCallback__deps: ['$callUserCallback'], |
| wgpuDeviceSetUncapturedErrorCallback: (devicePtr, callback, userdata) => { |
| var device = WebGPU.getJsObject(devicePtr); |
| device.onuncapturederror = function(ev) { |
| // This will skip the callback if the runtime is no longer alive. |
| callUserCallback(() => { |
| // WGPUErrorType type, const char* message, void* userdata |
| var Validation = 0x00000001; |
| var OutOfMemory = 0x00000002; |
| var type; |
| #if ASSERTIONS |
| assert(typeof GPUValidationError != 'undefined'); |
| assert(typeof GPUOutOfMemoryError != 'undefined'); |
| #endif |
| if (ev.error instanceof GPUValidationError) type = Validation; |
| else if (ev.error instanceof GPUOutOfMemoryError) type = OutOfMemory; |
| // TODO: Implement GPUInternalError |
| |
| WebGPU.errorCallback(callback, type, ev.error.message, userdata); |
| }); |
| }; |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Instance |
| // -------------------------------------------------------------------------- |
| |
| wgpuInstanceCreateSurface__deps: ['$findCanvasEventTarget', 'emwgpuCreateSurface'], |
| wgpuInstanceCreateSurface: (instancePtr, descriptor) => { |
| {{{ gpu.makeCheck('descriptor') }}} |
| var nextInChainPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSurfaceDescriptor.nextInChain, '*') }}}; |
| #if ASSERTIONS |
| assert(nextInChainPtr !== 0); |
| assert({{{ gpu.SType.SurfaceSourceCanvasHTMLSelector_Emscripten }}} === |
| {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}}); |
| #endif |
| var sourceCanvasHTMLSelector = nextInChainPtr; |
| |
| {{{ gpu.makeCheckDescriptor('sourceCanvasHTMLSelector') }}} |
| var selectorPtr = {{{ makeGetValue('sourceCanvasHTMLSelector', C_STRUCTS.WGPUSurfaceSourceCanvasHTMLSelector_Emscripten.selector, '*') }}}; |
| {{{ gpu.makeCheck('selectorPtr') }}} |
| var canvas = findCanvasEventTarget(selectorPtr); |
| #if OFFSCREENCANVAS_SUPPORT |
| if (canvas.offscreenCanvas) canvas = canvas.offscreenCanvas; |
| #endif |
| var context = canvas.getContext('webgpu'); |
| #if ASSERTIONS |
| assert(context); |
| #endif |
| if (!context) return 0; |
| |
| context.surfaceLabelWebGPU = WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUSurfaceDescriptor.label }}} |
| ); |
| |
| var ptr = _emwgpuCreateSurface(); |
| WebGPU.Internals.jsObjectInsert(ptr, context); |
| return ptr; |
| }, |
| |
| wgpuInstanceHasWGSLLanguageFeature: (instance, featureEnumValue) => { |
| if (!('wgslLanguageFeatures' in navigator["gpu"])) { |
| return false; |
| } |
| return navigator["gpu"]["wgslLanguageFeatures"].has(WebGPU.WGSLFeatureName[featureEnumValue]); |
| }, |
| |
| emwgpuInstanceRequestAdapter__deps: ['emwgpuCreateAdapter', 'emwgpuOnRequestAdapterCompleted'], |
| emwgpuInstanceRequestAdapter__sig: 'vpjp', |
| emwgpuInstanceRequestAdapter: (instancePtr, futureId, options) => { |
| var opts; |
| if (options) { |
| {{{ gpu.makeCheckDescriptor('options') }}} |
| opts = { |
| "powerPreference": WebGPU.PowerPreference[ |
| {{{ gpu.makeGetU32('options', C_STRUCTS.WGPURequestAdapterOptions.powerPreference) }}}], |
| "forceFallbackAdapter": |
| {{{ gpu.makeGetBool('options', C_STRUCTS.WGPURequestAdapterOptions.forceFallbackAdapter) }}}, |
| }; |
| } |
| |
| if (!('gpu' in navigator)) { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack('WebGPU not available on this browser (navigator.gpu is not available)'); |
| _emwgpuOnRequestAdapterCompleted(futureId, {{{ gpu.RequestAdapterStatus.Unavailable }}}, 0, messagePtr); |
| stackRestore(sp); |
| return; |
| } |
| |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, navigator["gpu"]["requestAdapter"](opts).then((adapter) => { |
| {{{ runtimeKeepalivePop() }}} |
| if (adapter) { |
| var adapterPtr = _emwgpuCreateAdapter(instancePtr); |
| WebGPU.Internals.jsObjectInsert(adapterPtr, adapter); |
| _emwgpuOnRequestAdapterCompleted(futureId, {{{ gpu.RequestAdapterStatus.Success }}}, adapterPtr, 0); |
| } else { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack('WebGPU not available on this browser (requestAdapter returned null)'); |
| _emwgpuOnRequestAdapterCompleted(futureId, {{{ gpu.RequestAdapterStatus.Unavailable }}}, 0, messagePtr); |
| stackRestore(sp); |
| } |
| }, (ex) => { |
| {{{ runtimeKeepalivePop() }}} |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(ex.message); |
| _emwgpuOnRequestAdapterCompleted(futureId, {{{ gpu.RequestAdapterStatus.Error }}}, 0, messagePtr); |
| stackRestore(sp); |
| })); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of PipelineLayout |
| // -------------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------------- |
| // Methods of QuerySet |
| // -------------------------------------------------------------------------- |
| |
| wgpuQuerySetDestroy: (querySetPtr) => { |
| WebGPU.getJsObject(querySetPtr).destroy(); |
| }, |
| |
| wgpuQuerySetGetCount: (querySetPtr) => { |
| var querySet = WebGPU.getJsObject(querySetPtr); |
| return querySet.count; |
| }, |
| |
| wgpuQuerySetGetType: (querySetPtr, labelPtr) => { |
| var querySet = WebGPU.getJsObject(querySetPtr); |
| return querySet.type; |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Queue |
| // -------------------------------------------------------------------------- |
| |
| emwgpuQueueOnSubmittedWorkDone__deps: ['emwgpuOnWorkDoneCompleted'], |
| emwgpuQueueOnSubmittedWorkDone__sig: 'vpj', |
| emwgpuQueueOnSubmittedWorkDone: (queuePtr, futureId) => { |
| var queue = WebGPU.getJsObject(queuePtr); |
| |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, queue.onSubmittedWorkDone().then(() => { |
| {{{ runtimeKeepalivePop() }}} |
| _emwgpuOnWorkDoneCompleted(futureId, {{{ gpu.QueueWorkDoneStatus.Success }}}); |
| }, () => { |
| {{{ runtimeKeepalivePop() }}} |
| _emwgpuOnWorkDoneCompleted(futureId, {{{ gpu.QueueWorkDoneStatus.Error }}}); |
| })); |
| }, |
| |
| wgpuQueueSubmit: (queuePtr, commandCount, commands) => { |
| #if ASSERTIONS |
| assert(commands % 4 === 0); |
| #endif |
| var queue = WebGPU.getJsObject(queuePtr); |
| var cmds = Array.from({{{ makeHEAPView(`${POINTER_BITS}`, 'commands', `commands + commandCount * ${POINTER_SIZE}`)}}}, |
| (id) => WebGPU.getJsObject(id)); |
| queue.submit(cmds); |
| }, |
| |
| wgpuQueueWriteBuffer: (queuePtr, bufferPtr, bufferOffset, data, size) => { |
| var queue = WebGPU.getJsObject(queuePtr); |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| // There is a size limitation for ArrayBufferView. Work around by passing in a subarray |
| // instead of the whole heap. crbug.com/1201109 |
| var subarray = HEAPU8.subarray(data, data + size); |
| queue.writeBuffer(buffer, bufferOffset, subarray, 0, size); |
| }, |
| |
| wgpuQueueWriteTexture: (queuePtr, destinationPtr, data, dataSize, dataLayoutPtr, writeSizePtr) => { |
| var queue = WebGPU.getJsObject(queuePtr); |
| |
| var destination = WebGPU.makeImageCopyTexture(destinationPtr); |
| var dataLayout = WebGPU.makeTextureDataLayout(dataLayoutPtr); |
| var writeSize = WebGPU.makeExtent3D(writeSizePtr); |
| // This subarray isn't strictly necessary, but helps work around an issue |
| // where Chromium makes a copy of the entire heap. crbug.com/1134457 |
| var subarray = HEAPU8.subarray(data, data + dataSize); |
| queue.writeTexture(destination, subarray, dataLayout, writeSize); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of RenderBundle |
| // -------------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------------- |
| // Methods of RenderBundleEncoder |
| // -------------------------------------------------------------------------- |
| |
| wgpuRenderBundleEncoderDraw: (passPtr, vertexCount, instanceCount, firstVertex, firstInstance) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.draw(vertexCount, instanceCount, firstVertex, firstInstance); |
| }, |
| |
| wgpuRenderBundleEncoderDrawIndexed: (passPtr, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance); |
| }, |
| |
| wgpuRenderBundleEncoderDrawIndexedIndirect: (passPtr, indirectBufferPtr, indirectOffset) => { |
| var indirectBuffer = WebGPU.getJsObject(indirectBufferPtr); |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.drawIndexedIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuRenderBundleEncoderDrawIndirect: (passPtr, indirectBufferPtr, indirectOffset) => { |
| var indirectBuffer = WebGPU.getJsObject(indirectBufferPtr); |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.drawIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuRenderBundleEncoderFinish__deps: ['emwgpuCreateRenderBundle'], |
| wgpuRenderBundleEncoderFinish: (encoderPtr, descriptor) => { |
| var desc; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPURenderBundleDescriptor.label }}}), |
| }; |
| } |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| var ptr = _emwgpuCreateRenderBundle(); |
| WebGPU.Internals.jsObjectInsert(ptr, encoder.finish(desc)); |
| return ptr; |
| }, |
| |
| wgpuRenderBundleEncoderInsertDebugMarker2: (encoderPtr, markerLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.insertDebugMarker(WebGPU.makeStringFromStringView(markerLabelPtr)); |
| }, |
| |
| wgpuRenderBundleEncoderPopDebugGroup: (encoderPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.popDebugGroup(); |
| }, |
| |
| wgpuRenderBundleEncoderPushDebugGroup2: (encoderPtr, groupLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.pushDebugGroup(WebGPU.makeStringFromStringView(groupLabelPtr)); |
| }, |
| |
| wgpuRenderBundleEncoderSetBindGroup: (passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var group = WebGPU.getJsObject(groupPtr); |
| if (dynamicOffsetCount == 0) { |
| pass.setBindGroup(groupIndex, group); |
| } else { |
| var offsets = []; |
| for (var i = 0; i < dynamicOffsetCount; i++, dynamicOffsetsPtr += 4) { |
| offsets.push({{{ gpu.makeGetU32('dynamicOffsetsPtr', 0) }}}); |
| } |
| pass.setBindGroup(groupIndex, group, offsets); |
| } |
| }, |
| |
| wgpuRenderBundleEncoderSetIndexBuffer: (passPtr, bufferPtr, format, offset, size) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size); |
| }, |
| |
| wgpuRenderBundleEncoderSetPipeline: (passPtr, pipelinePtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var pipeline = WebGPU.getJsObject(pipelinePtr); |
| pass.setPipeline(pipeline); |
| }, |
| |
| wgpuRenderBundleEncoderSetVertexBuffer: (passPtr, slot, bufferPtr, offset, size) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setVertexBuffer(slot, buffer, offset, size); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of RenderPassEncoder |
| // -------------------------------------------------------------------------- |
| |
| wgpuRenderPassEncoderBeginOcclusionQuery: (passPtr, queryIndex) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.beginOcclusionQuery(queryIndex); |
| }, |
| |
| wgpuRenderPassEncoderDraw: (passPtr, vertexCount, instanceCount, firstVertex, firstInstance) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.draw(vertexCount, instanceCount, firstVertex, firstInstance); |
| }, |
| |
| wgpuRenderPassEncoderDrawIndexed: (passPtr, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance); |
| }, |
| |
| wgpuRenderPassEncoderDrawIndexedIndirect: (passPtr, indirectBufferPtr, indirectOffset) => { |
| var indirectBuffer = WebGPU.getJsObject(indirectBufferPtr); |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.drawIndexedIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuRenderPassEncoderDrawIndirect: (passPtr, indirectBufferPtr, indirectOffset) => { |
| var indirectBuffer = WebGPU.getJsObject(indirectBufferPtr); |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.drawIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuRenderPassEncoderEnd: (encoderPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.end(); |
| }, |
| |
| wgpuRenderPassEncoderEndOcclusionQuery: (passPtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.endOcclusionQuery(); |
| }, |
| |
| wgpuRenderPassEncoderExecuteBundles: (passPtr, count, bundlesPtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| |
| #if ASSERTIONS |
| assert(bundlesPtr % 4 === 0); |
| #endif |
| |
| var bundles = Array.from({{{ makeHEAPView(`${POINTER_BITS}`, 'bundlesPtr', `bundlesPtr + count * ${POINTER_SIZE}`) }}}, |
| (id) => WebGPU.getJsObject(id)); |
| pass.executeBundles(bundles); |
| }, |
| |
| wgpuRenderPassEncoderInsertDebugMarker2: (encoderPtr, markerLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.insertDebugMarker(WebGPU.makeStringFromStringView(markerLabelPtr)); |
| }, |
| |
| wgpuRenderPassEncoderPopDebugGroup: (encoderPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.popDebugGroup(); |
| }, |
| |
| wgpuRenderPassEncoderPushDebugGroup2: (encoderPtr, groupLabelPtr) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| encoder.pushDebugGroup(WebGPU.makeStringFromStringView(groupLabelPtr)); |
| }, |
| |
| wgpuRenderPassEncoderSetBindGroup: (passPtr, groupIndex, groupPtr, dynamicOffsetCount, dynamicOffsetsPtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var group = WebGPU.getJsObject(groupPtr); |
| if (dynamicOffsetCount == 0) { |
| pass.setBindGroup(groupIndex, group); |
| } else { |
| var offsets = []; |
| for (var i = 0; i < dynamicOffsetCount; i++, dynamicOffsetsPtr += 4) { |
| offsets.push({{{ gpu.makeGetU32('dynamicOffsetsPtr', 0) }}}); |
| } |
| pass.setBindGroup(groupIndex, group, offsets); |
| } |
| }, |
| |
| wgpuRenderPassEncoderSetBlendConstant: (passPtr, colorPtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var color = WebGPU.makeColor(colorPtr); |
| pass.setBlendConstant(color); |
| }, |
| |
| wgpuRenderPassEncoderSetIndexBuffer: (passPtr, bufferPtr, format, offset, size) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size); |
| }, |
| |
| wgpuRenderPassEncoderSetPipeline: (passPtr, pipelinePtr) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var pipeline = WebGPU.getJsObject(pipelinePtr); |
| pass.setPipeline(pipeline); |
| }, |
| |
| wgpuRenderPassEncoderSetScissorRect: (passPtr, x, y, w, h) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.setScissorRect(x, y, w, h); |
| }, |
| |
| wgpuRenderPassEncoderSetStencilReference: (passPtr, reference) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.setStencilReference(reference); |
| }, |
| |
| wgpuRenderPassEncoderSetVertexBuffer: (passPtr, slot, bufferPtr, offset, size) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| var buffer = WebGPU.getJsObject(bufferPtr); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setVertexBuffer(slot, buffer, offset, size); |
| }, |
| |
| wgpuRenderPassEncoderSetViewport: (passPtr, x, y, w, h, minDepth, maxDepth) => { |
| var pass = WebGPU.getJsObject(passPtr); |
| pass.setViewport(x, y, w, h, minDepth, maxDepth); |
| }, |
| |
| wgpuRenderPassEncoderWriteTimestamp: (encoderPtr, querySetPtr, queryIndex) => { |
| var encoder = WebGPU.getJsObject(encoderPtr); |
| var querySet = WebGPU.getJsObject(querySetPtr); |
| encoder.writeTimestamp(querySet, queryIndex); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of RenderPipeline |
| // -------------------------------------------------------------------------- |
| |
| wgpuRenderPipelineGetBindGroupLayout__deps: ['emwgpuCreateBindGroupLayout'], |
| wgpuRenderPipelineGetBindGroupLayout: (pipelinePtr, groupIndex) => { |
| var pipeline = WebGPU.getJsObject(pipelinePtr); |
| var ptr = _emwgpuCreateBindGroupLayout(); |
| WebGPU.Internals.jsObjectInsert(ptr, pipeline.getBindGroupLayout(groupIndex)); |
| return ptr; |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Sampler |
| // -------------------------------------------------------------------------- |
| |
| // -------------------------------------------------------------------------- |
| // Methods of ShaderModule |
| // -------------------------------------------------------------------------- |
| |
| emwgpuShaderModuleGetCompilationInfo__deps: ['emwgpuOnCompilationInfoCompleted', '$stringToUTF8', '$lengthBytesUTF8', 'malloc'], |
| emwgpuShaderModuleGetCompilationInfo__sig: 'vpjp', |
| emwgpuShaderModuleGetCompilationInfo: (shaderModulePtr, futureId, compilationInfoPtr) => { |
| var shaderModule = WebGPU.getJsObject(shaderModulePtr); |
| {{{ runtimeKeepalivePush() }}} |
| WebGPU.Internals.futureInsert(futureId, shaderModule.getCompilationInfo().then((compilationInfo) => { |
| {{{ runtimeKeepalivePop() }}} |
| // Calculate the total length of strings and offsets here to malloc them |
| // all at once. Note that we start at 1 instead of 0 for the total size |
| // to ensure there's enough space for the null terminator that is always |
| // added by stringToUTF8. |
| var totalMessagesSize = 1; |
| var messageLengths = []; |
| for (var i = 0; i < compilationInfo.messages.length; ++i) { |
| var messageLength = lengthBytesUTF8(compilationInfo.messages[i].message); |
| totalMessagesSize += messageLength; |
| messageLengths.push(messageLength); |
| } |
| var messagesPtr = _malloc(totalMessagesSize); |
| |
| // Allocate and fill out each CompilationMessage. |
| var compilationMessagesPtr = _malloc({{{ C_STRUCTS.WGPUCompilationMessage.__size__ }}} * compilationInfo.messages.length); |
| for (var i = 0; i < compilationInfo.messages.length; ++i) { |
| var compilationMessage = compilationInfo.messages[i]; |
| var compilationMessagePtr = compilationMessagesPtr + {{{ C_STRUCTS.WGPUCompilationMessage.__size__ }}} * i; |
| |
| // Write out the values to the CompilationMessage. |
| WebGPU.setStringView(compilationMessagePtr + {{{ C_STRUCTS.WGPUCompilationMessage.message }}}, messagesPtr, messageLengths[i]); |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.type, 'WebGPU.Int_CompilationMessageType[compilationMessage.type]', 'i32') }}}; |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.lineNum, 'compilationMessage.lineNum', 'i64') }}}; |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.linePos, 'compilationMessage.linePos', 'i64') }}}; |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.offset, 'compilationMessage.offset', 'i64') }}}; |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.length, 'compilationMessage.length', 'i64') }}}; |
| // TODO: Convert JavaScript's UTF-16-code-unit offsets to UTF-8-code-unit offsets. |
| // https://github.com/webgpu-native/webgpu-headers/issues/246 |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.utf16LinePos, 'compilationMessage.linePos', 'i64') }}}; |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.utf16Offset, 'compilationMessage.offset', 'i64') }}}; |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.utf16Length, 'compilationMessage.length', 'i64') }}}; |
| |
| // Write the string out to the allocated buffer. Note we have to add 1 |
| // to the length of the string to ensure enough space for the null |
| // terminator. However, we only increment the pointer by the exact |
| // length so we overwrite the null terminators except for the last one. |
| stringToUTF8(compilationMessage.message, messagesPtr, messageLengths[i] + 1); |
| messagesPtr += messageLengths[i]; |
| } |
| |
| // Allocate and fill out the wrapping CompilationInfo struct. |
| {{{ makeSetValue('compilationInfoPtr', C_STRUCTS.WGPUCompilationInfo.messageCount, 'compilationInfo.messages.length', '*') }}} |
| {{{ makeSetValue('compilationInfoPtr', C_STRUCTS.WGPUCompilationInfo.messages, 'compilationMessagesPtr', '*') }}}; |
| |
| _emwgpuOnCompilationInfoCompleted(futureId, {{{ gpu.CompilationInfoRequestStatus.Success }}}, compilationInfoPtr); |
| }, () => { |
| _emwgpuOnCompilationInfoCompleted(futureId, {{{ gpu.CompilationInfoRequestStatus.Error }}}, compilationInfoPtr); |
| })); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Surface |
| // -------------------------------------------------------------------------- |
| |
| wgpuSurfaceConfigure: (surfacePtr, config) => { |
| {{{ gpu.makeCheckDescriptor('config') }}} |
| var devicePtr = {{{ makeGetValue('config', C_STRUCTS.WGPUSurfaceConfiguration.device, '*') }}}; |
| var context = WebGPU.getJsObject(surfacePtr); |
| |
| #if ASSERTIONS |
| assert({{{ gpu.PresentMode.Fifo }}} === |
| {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.presentMode) }}}); |
| #endif |
| |
| var canvasSize = [ |
| {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.width) }}}, |
| {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.height) }}} |
| ]; |
| |
| if (canvasSize[0] !== 0) { |
| context["canvas"]["width"] = canvasSize[0]; |
| } |
| |
| if (canvasSize[1] !== 0) { |
| context["canvas"]["height"] = canvasSize[1]; |
| } |
| |
| var configuration = { |
| "device": WebGPU.getJsObject(devicePtr), |
| "format": WebGPU.TextureFormat[ |
| {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.format) }}}], |
| "usage": {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.usage) }}}, |
| "alphaMode": WebGPU.CompositeAlphaMode[ |
| {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.alphaMode) }}}], |
| }; |
| |
| var viewFormatCount = {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.viewFormatCount) }}}; |
| if (viewFormatCount) { |
| var viewFormatsPtr = {{{ makeGetValue('config', C_STRUCTS.WGPUSurfaceConfiguration.viewFormats, '*') }}}; |
| // viewFormatsPtr pointer to an array of TextureFormat which is an enum of size uint32_t |
| configuration['viewFormats'] = Array.from({{{ makeHEAPView('32', 'viewFormatsPtr', 'viewFormatsPtr + viewFormatCount * 4') }}}, |
| format => WebGPU.TextureFormat[format]); |
| } |
| |
| context.configure(configuration); |
| }, |
| |
| wgpuSurfaceGetCurrentTexture__deps: ['emwgpuCreateTexture'], |
| wgpuSurfaceGetCurrentTexture: (surfacePtr, surfaceTexturePtr) => { |
| {{{ gpu.makeCheck('surfaceTexturePtr') }}} |
| var context = WebGPU.getJsObject(surfacePtr); |
| |
| try { |
| var texturePtr = _emwgpuCreateTexture(); |
| WebGPU.Internals.jsObjectInsert(texturePtr, context.getCurrentTexture()); |
| {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.texture, 'texturePtr', '*') }}}; |
| {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.suboptimal, '0', 'i32') }}}; |
| {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.status, |
| gpu.SurfaceGetCurrentTextureStatus.Success, 'i32') }}}; |
| } catch (ex) { |
| #if ASSERTIONS |
| err(`wgpuSurfaceGetCurrentTexture() failed: ${ex}`); |
| #endif |
| {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.texture, '0', '*') }}}; |
| {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.suboptimal, '0', 'i32') }}}; |
| // TODO(https://github.com/webgpu-native/webgpu-headers/issues/291): What should the status be here? |
| {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.status, |
| gpu.SurfaceGetCurrentTextureStatus.DeviceLost, 'i32') }}}; |
| } |
| }, |
| |
| wgpuSurfacePresent: (surfacePtr) => { |
| // TODO: This could probably be emulated with ASYNCIFY. |
| abort('wgpuSurfacePresent is unsupported (use requestAnimationFrame via html5.h instead)'); |
| }, |
| |
| wgpuSurfaceUnconfigure: (surfacePtr) => { |
| var context = WebGPU.getJsObject(surfacePtr); |
| context.unconfigure(); |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of Texture |
| // -------------------------------------------------------------------------- |
| |
| wgpuTextureCreateView__deps: ['emwgpuCreateTextureView'], |
| wgpuTextureCreateView: (texturePtr, descriptor) => { |
| var desc; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| var mipLevelCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.mipLevelCount) }}}; |
| var arrayLayerCount = {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.arrayLayerCount) }}}; |
| desc = { |
| "label": WebGPU.makeStringFromOptionalStringView( |
| descriptor + {{{ C_STRUCTS.WGPUTextureViewDescriptor.label }}}), |
| "format": WebGPU.TextureFormat[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.format) }}}], |
| "dimension": WebGPU.TextureViewDimension[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.dimension) }}}], |
| "baseMipLevel": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.baseMipLevel) }}}, |
| "mipLevelCount": mipLevelCount === {{{ gpu.MIP_LEVEL_COUNT_UNDEFINED }}} ? undefined : mipLevelCount, |
| "baseArrayLayer": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.baseArrayLayer) }}}, |
| "arrayLayerCount": arrayLayerCount === {{{ gpu.ARRAY_LAYER_COUNT_UNDEFINED }}} ? undefined : arrayLayerCount, |
| "aspect": WebGPU.TextureAspect[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.aspect) }}}], |
| }; |
| } |
| |
| var texture = WebGPU.getJsObject(texturePtr); |
| var ptr = _emwgpuCreateTextureView(); |
| WebGPU.Internals.jsObjectInsert(ptr, texture.createView(desc)); |
| return ptr; |
| }, |
| |
| wgpuTextureDestroy: (texturePtr) => { |
| WebGPU.getJsObject(texturePtr).destroy(); |
| }, |
| |
| wgpuTextureGetDepthOrArrayLayers: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| return texture.depthOrArrayLayers; |
| }, |
| |
| wgpuTextureGetDimension: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| return WebGPU.TextureDimension.indexOf(texture.dimension); |
| }, |
| |
| wgpuTextureGetFormat: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| // Should return the enum integer instead of string. |
| return WebGPU.TextureFormat.indexOf(texture.format); |
| }, |
| |
| wgpuTextureGetHeight: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| return texture.height; |
| }, |
| |
| wgpuTextureGetMipLevelCount: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| return texture.mipLevelCount; |
| }, |
| |
| wgpuTextureGetSampleCount: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| return texture.sampleCount; |
| }, |
| |
| wgpuTextureGetUsage: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| return texture.usage; |
| }, |
| |
| wgpuTextureGetWidth: (texturePtr) => { |
| var texture = WebGPU.getJsObject(texturePtr); |
| return texture.width; |
| }, |
| |
| // -------------------------------------------------------------------------- |
| // Methods of TextureView |
| // -------------------------------------------------------------------------- |
| }; |
| |
| // Inverted index used by EnumerateFeatures/HasFeature |
| LibraryWebGPU.$WebGPU.FeatureNameString2Enum = {}; |
| for (var value in LibraryWebGPU.$WebGPU.FeatureName) { |
| LibraryWebGPU.$WebGPU.FeatureNameString2Enum[LibraryWebGPU.$WebGPU.FeatureName[value]] = value; |
| } |
| |
| // Add and set __i53abi to true for functions with 64-bit value in their |
| // signatures, if not explicitly set otherwise. |
| for (const key of Object.keys(LibraryWebGPU)) { |
| if (typeof LibraryWebGPU[key] !== 'function') continue; |
| if (key + '__i53abi' in LibraryWebGPU) continue; |
| const sigKey = key + '__sig'; |
| const sig = LibraryWebGPU[sigKey] ? LibraryWebGPU[sigKey] : LibraryManager.library[sigKey]; |
| if (!sig?.includes('j')) continue; |
| LibraryWebGPU[key + '__i53abi'] = true; |
| } |
| |
| // Based on autoAddDeps, this helper iterates the object and moves the |
| // deps upwards into targetDeps and remove them from the object. |
| function moveDeps(object, targetDeps) { |
| for (var item in object) { |
| if (!item.endsWith('__deps')) { |
| if (object[item + '__deps']) { |
| targetDeps.push(...object[item + '__deps']); |
| delete object[item + '__deps'] |
| } |
| } |
| } |
| } |
| moveDeps(LibraryWebGPU.$WebGPU, LibraryWebGPU.$WebGPU__deps) |
| |
| autoAddDeps(LibraryWebGPU, '$WebGPU'); |
| mergeInto(LibraryManager.library, LibraryWebGPU); |