| /** |
| * @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 = { |
| makeInitManager: function(type) { |
| var mgr = `WebGPU.mgr${type}`; |
| return `${mgr} = ${mgr} || new Manager();`; |
| }, |
| |
| makeAddRefRelease: function(type) { |
| return ` |
| wgpu${type}AddRef: (id) => WebGPU.mgr${type}.addRef(id), |
| wgpu${type}Release: (id) => WebGPU.mgr${type}.release(id),`; |
| }, |
| |
| 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});`; |
| }, |
| makeCheckDefined: function(name) { |
| return this.makeCheck(`typeof ${name} != "undefined"`); |
| }, |
| 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 |
| // ShaderModuleSPIRVDescriptor), 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'); |
| }, |
| |
| // 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__postset: 'WebGPU.initManagers();', |
| $WebGPU__deps: ['$stackSave', '$stackRestore', '$stringToUTF8OnStack'], |
| $WebGPU: { |
| errorCallback: (callback, type, message, userdata) => { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(message); |
| {{{ makeDynCall('vipp', 'callback') }}}(type, messagePtr, userdata); |
| stackRestore(sp); |
| }, |
| |
| initManagers: () => { |
| if (WebGPU.mgrDevice) return; |
| |
| /** @constructor */ |
| function Manager() { |
| this.objects = {}; |
| this.nextId = 1; |
| this.create = function(object, wrapper = {}) { |
| var id = this.nextId++; |
| {{{ gpu.makeCheck("typeof this.objects[id] == 'undefined'") }}} |
| wrapper.refcount = 1; |
| wrapper.object = object; |
| this.objects[id] = wrapper; |
| return id; |
| }; |
| this.get = function(id) { |
| if (!id) return undefined; |
| var o = this.objects[id]; |
| {{{ gpu.makeCheckDefined('o') }}} |
| return o.object; |
| }; |
| this.addRef = function(id) { |
| var o = this.objects[id]; |
| {{{ gpu.makeCheckDefined('o') }}} |
| o.refcount++; |
| }; |
| this.release = function(id) { |
| var o = this.objects[id]; |
| {{{ gpu.makeCheckDefined('o') }}} |
| {{{ gpu.makeCheck('o.refcount > 0') }}} |
| o.refcount--; |
| if (o.refcount <= 0) { |
| delete this.objects[id]; |
| } |
| }; |
| } |
| |
| {{{ gpu.makeInitManager('Surface') }}} |
| {{{ gpu.makeInitManager('SwapChain') }}} |
| |
| {{{ gpu.makeInitManager('Adapter') }}} |
| // TODO: Release() the device's default queue when the device is freed. |
| {{{ gpu.makeInitManager('Device') }}} |
| {{{ gpu.makeInitManager('Queue') }}} |
| |
| {{{ gpu.makeInitManager('CommandBuffer') }}} |
| {{{ gpu.makeInitManager('CommandEncoder') }}} |
| {{{ gpu.makeInitManager('RenderPassEncoder') }}} |
| {{{ gpu.makeInitManager('ComputePassEncoder') }}} |
| |
| {{{ gpu.makeInitManager('BindGroup') }}} |
| {{{ gpu.makeInitManager('Buffer') }}} |
| {{{ gpu.makeInitManager('Sampler') }}} |
| {{{ gpu.makeInitManager('Texture') }}} |
| {{{ gpu.makeInitManager('TextureView') }}} |
| {{{ gpu.makeInitManager('QuerySet') }}} |
| |
| {{{ gpu.makeInitManager('BindGroupLayout') }}} |
| {{{ gpu.makeInitManager('PipelineLayout') }}} |
| {{{ gpu.makeInitManager('RenderPipeline') }}} |
| {{{ gpu.makeInitManager('ComputePipeline') }}} |
| {{{ gpu.makeInitManager('ShaderModule') }}} |
| |
| {{{ gpu.makeInitManager('RenderBundleEncoder') }}} |
| {{{ gpu.makeInitManager('RenderBundle') }}} |
| }, |
| |
| 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.mgrTexture.get( |
| {{{ 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.mgrBuffer.get( |
| {{{ 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 = UTF8ToString({{{ makeGetValue('entryPtr', C_STRUCTS.WGPUConstantEntry.key, '*') }}}); |
| constants[key] = {{{ makeGetValue('entryPtr', C_STRUCTS.WGPUConstantEntry.value, 'double') }}}; |
| } |
| return constants; |
| }, |
| |
| makePipelineLayout: (layoutPtr) => { |
| if (!layoutPtr) return 'auto'; |
| return WebGPU.mgrPipelineLayout.get(layoutPtr); |
| }, |
| |
| makeProgrammableStageDescriptor: (ptr) => { |
| if (!ptr) return undefined; |
| {{{ gpu.makeCheckDescriptor('ptr') }}} |
| var desc = { |
| "module": WebGPU.mgrShaderModule.get( |
| {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.module, '*') }}}), |
| "constants": WebGPU.makePipelineConstants( |
| {{{ gpu.makeGetU32('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.constantCount) }}}, |
| {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.constants, '*') }}}), |
| }; |
| var entryPointPtr = {{{ makeGetValue('ptr', C_STRUCTS.WGPUProgrammableStageDescriptor.entryPoint, '*') }}}; |
| if (entryPointPtr) desc["entryPoint"] = UTF8ToString(entryPointPtr); |
| return desc; |
| }, |
| |
| makeComputePipelineDesc: (descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| var desc = { |
| "label": undefined, |
| "layout": WebGPU.makePipelineLayout( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePipelineDescriptor.layout, '*') }}}), |
| "compute": WebGPU.makeProgrammableStageDescriptor( |
| descriptor + {{{ C_STRUCTS.WGPUComputePipelineDescriptor.compute }}}), |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePipelineDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| return desc; |
| }, |
| |
| makeRenderPipelineDesc: (descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| function makePrimitiveState(rsPtr) { |
| if (!rsPtr) return undefined; |
| {{{ gpu.makeCheck('rsPtr') }}} |
| |
| // TODO: This small hack assumes that there's only one type that can be in the chain of |
| // WGPUPrimitiveState. The correct thing would be to traverse the chain, but unclippedDepth |
| // is going to move into the core object soon, so we'll just do this for now. See: |
| // https://github.com/webgpu-native/webgpu-headers/issues/212#issuecomment-1682801259 |
| var nextInChainPtr = {{{ makeGetValue('rsPtr', C_STRUCTS.WGPUPrimitiveState.nextInChain, '*') }}}; |
| var sType = nextInChainPtr ? {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}} : 0; |
| |
| return { |
| "topology": WebGPU.PrimitiveTopology[ |
| {{{ gpu.makeGetU32('rsPtr', C_STRUCTS.WGPUPrimitiveState.topology) }}}], |
| "stripIndexFormat": WebGPU.IndexFormat[ |
| {{{ gpu.makeGetU32('rsPtr', C_STRUCTS.WGPUPrimitiveState.stripIndexFormat) }}}], |
| "frontFace": WebGPU.FrontFace[ |
| {{{ gpu.makeGetU32('rsPtr', C_STRUCTS.WGPUPrimitiveState.frontFace) }}}], |
| "cullMode": WebGPU.CullMode[ |
| {{{ gpu.makeGetU32('rsPtr', C_STRUCTS.WGPUPrimitiveState.cullMode) }}}], |
| "unclippedDepth": sType === {{{ gpu.SType.PrimitiveDepthClipControl }}} && {{{ gpu.makeGetBool('nextInChainPtr', C_STRUCTS.WGPUPrimitiveDepthClipControl.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.mgrShaderModule.get( |
| {{{ 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, '*') }}}), |
| }; |
| var entryPointPtr = {{{ makeGetValue('viPtr', C_STRUCTS.WGPUVertexState.entryPoint, '*') }}}; |
| if (entryPointPtr) desc["entryPoint"] = UTF8ToString(entryPointPtr); |
| 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.mgrShaderModule.get( |
| {{{ 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, '*') }}}), |
| }; |
| var entryPointPtr = {{{ makeGetValue('fsPtr', C_STRUCTS.WGPUFragmentState.entryPoint, '*') }}}; |
| if (entryPointPtr) desc["entryPoint"] = UTF8ToString(entryPointPtr); |
| return desc; |
| } |
| |
| var desc = { |
| "label": undefined, |
| "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, '*') }}}), |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPipelineDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| 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 }}} |
| }, |
| |
| // Non-method functions |
| |
| wgpuGetInstanceFeatures: (featuresPtr) => { |
| abort('TODO: wgpuGetInstanceFeatures unimplemented'); |
| return 0; |
| }, |
| |
| wgpuGetProcAddress: (device, procName) => { |
| abort('TODO(#11526): wgpuGetProcAddress unimplemented'); |
| return 0; |
| }, |
| |
| // *AddRef/*Release |
| |
| {{{ gpu.makeAddRefRelease('Surface') }}} |
| {{{ gpu.makeAddRefRelease('SwapChain') }}} |
| |
| {{{ gpu.makeAddRefRelease('Adapter') }}} |
| {{{ gpu.makeAddRefRelease('Device') }}} |
| {{{ gpu.makeAddRefRelease('Queue') }}} |
| |
| {{{ gpu.makeAddRefRelease('CommandBuffer') }}} |
| {{{ gpu.makeAddRefRelease('CommandEncoder') }}} |
| {{{ gpu.makeAddRefRelease('RenderPassEncoder') }}} |
| {{{ gpu.makeAddRefRelease('ComputePassEncoder') }}} |
| |
| {{{ gpu.makeAddRefRelease('BindGroup') }}} |
| {{{ gpu.makeAddRefRelease('Buffer') }}} |
| {{{ gpu.makeAddRefRelease('Sampler') }}} |
| {{{ gpu.makeAddRefRelease('Texture') }}} |
| {{{ gpu.makeAddRefRelease('TextureView') }}} |
| {{{ gpu.makeAddRefRelease('QuerySet') }}} |
| |
| {{{ gpu.makeAddRefRelease('BindGroupLayout') }}} |
| {{{ gpu.makeAddRefRelease('PipelineLayout') }}} |
| {{{ gpu.makeAddRefRelease('RenderPipeline') }}} |
| {{{ gpu.makeAddRefRelease('ComputePipeline') }}} |
| {{{ gpu.makeAddRefRelease('ShaderModule') }}} |
| |
| {{{ gpu.makeAddRefRelease('RenderBundleEncoder') }}} |
| {{{ gpu.makeAddRefRelease('RenderBundle') }}} |
| |
| // *Destroy |
| |
| wgpuBufferDestroy: (bufferId) => { |
| var bufferWrapper = WebGPU.mgrBuffer.objects[bufferId]; |
| {{{ gpu.makeCheckDefined('bufferWrapper') }}} |
| if (bufferWrapper.onUnmap) { |
| for (var i = 0; i < bufferWrapper.onUnmap.length; ++i) { |
| bufferWrapper.onUnmap[i](); |
| } |
| bufferWrapper.onUnmap = undefined; |
| } |
| |
| WebGPU.mgrBuffer.get(bufferId).destroy(); |
| }, |
| wgpuTextureDestroy: (textureId) => WebGPU.mgrTexture.get(textureId).destroy(), |
| wgpuQuerySetDestroy: (querySetId) => WebGPU.mgrQuerySet.get(querySetId).destroy(), |
| |
| // wgpuDevice |
| |
| wgpuDeviceEnumerateFeatures: (deviceId, featuresOutPtr) => { |
| var device = WebGPU.mgrDevice.get(deviceId); |
| if (featuresOutPtr !== 0) { |
| var offset = 0; |
| device.features.forEach(feature => { |
| var featureEnumValue = WebGPU.FeatureNameString2Enum[feature]; |
| {{{ makeSetValue('featuresOutPtr', 'offset', 'featureEnumValue', 'i32') }}}; |
| offset += 4; |
| }); |
| } |
| return device.features.size; |
| }, |
| |
| wgpuDeviceDestroy: (deviceId) => WebGPU.mgrDevice.get(deviceId).destroy(), |
| |
| wgpuDeviceGetLimits: (deviceId, limitsOutPtr) => { |
| var device = WebGPU.mgrDevice.objects[deviceId].object; |
| WebGPU.fillLimitStruct(device.limits, limitsOutPtr); |
| return 1; |
| }, |
| |
| wgpuDeviceGetQueue: (deviceId) => { |
| var queueId = WebGPU.mgrDevice.objects[deviceId].queueId; |
| #if ASSERTIONS |
| assert(queueId, 'wgpuDeviceGetQueue: queue was missing or null'); |
| #endif |
| // Returns a new reference to the existing queue. |
| WebGPU.mgrQueue.addRef(queueId); |
| return queueId; |
| }, |
| |
| wgpuDeviceHasFeature: (deviceId, featureEnumValue) => { |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return device.features.has(WebGPU.FeatureName[featureEnumValue]); |
| }, |
| |
| wgpuDevicePushErrorScope: (deviceId, filter) => { |
| var device = WebGPU.mgrDevice.get(deviceId); |
| device.pushErrorScope(WebGPU.ErrorFilter[filter]); |
| }, |
| |
| wgpuDevicePopErrorScope__deps: ['$callUserCallback'], |
| wgpuDevicePopErrorScope: (deviceId, callback, userdata) => { |
| var device = WebGPU.mgrDevice.get(deviceId); |
| {{{ runtimeKeepalivePush() }}} |
| device.popErrorScope().then((gpuError) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| if (!gpuError) { |
| {{{ makeDynCall('vipp', 'callback') }}}( |
| {{{ gpu.ErrorType.NoError }}}, 0, userdata); |
| } else if (gpuError instanceof GPUOutOfMemoryError) { |
| {{{ makeDynCall('vipp', 'callback') }}}( |
| {{{ gpu.ErrorType.OutOfMemory }}}, 0, userdata); |
| } else { |
| #if ASSERTIONS |
| // TODO: Implement GPUInternalError |
| assert(gpuError instanceof GPUValidationError); |
| #endif |
| WebGPU.errorCallback(callback, {{{ gpu.ErrorType.Validation }}}, gpuError.message, userdata); |
| } |
| }); |
| }, (ex) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| // TODO: This can mean either the device was lost or the error scope stack was empty. Figure |
| // out how to synthesize the DeviceLost error type. (Could be by simply tracking the error |
| // scope depth, but that isn't ideal.) |
| WebGPU.errorCallback(callback, {{{ gpu.ErrorType.Unknown }}}, ex.message, userdata); |
| }); |
| }); |
| }, |
| |
| wgpuDeviceSetLabel: (deviceId, labelPtr) => { |
| var device = WebGPU.mgrDevice.get(deviceId); |
| device.label = UTF8ToString(labelPtr); |
| }, |
| |
| wgpuDeviceSetUncapturedErrorCallback__deps: ['$callUserCallback'], |
| wgpuDeviceSetUncapturedErrorCallback: (deviceId, callback, userdata) => { |
| var device = WebGPU.mgrDevice.get(deviceId); |
| 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); |
| }); |
| }; |
| }, |
| |
| // wgpuDeviceCreate* |
| |
| wgpuDeviceCreateCommandEncoder: (deviceId, descriptor) => { |
| var desc; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| desc = { |
| "label": undefined, |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUCommandEncoderDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| } |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrCommandEncoder.create(device.createCommandEncoder(desc)); |
| }, |
| |
| wgpuDeviceCreateBuffer: (deviceId, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| var mappedAtCreation = {{{ gpu.makeGetBool('descriptor', C_STRUCTS.WGPUBufferDescriptor.mappedAtCreation) }}}; |
| |
| var desc = { |
| "label": undefined, |
| "usage": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBufferDescriptor.usage) }}}, |
| "size": {{{ gpu.makeGetU64('descriptor', C_STRUCTS.WGPUBufferDescriptor.size) }}}, |
| "mappedAtCreation": mappedAtCreation, |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBufferDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| var device = WebGPU.mgrDevice.get(deviceId); |
| var bufferWrapper = {}; |
| var id = WebGPU.mgrBuffer.create(device.createBuffer(desc), bufferWrapper); |
| if (mappedAtCreation) { |
| bufferWrapper.mapMode = {{{ gpu.MapMode.Write }}}; |
| bufferWrapper.onUnmap = []; |
| } |
| return id; |
| }, |
| |
| wgpuDeviceCreateTexture: (deviceId, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| var desc = { |
| "label": undefined, |
| "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 labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUTextureDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| 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`) }}}, |
| function(format) { return WebGPU.TextureFormat[format]; }); |
| } |
| |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrTexture.create(device.createTexture(desc)); |
| }, |
| |
| wgpuDeviceCreateSampler: (deviceId, descriptor) => { |
| var desc; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| desc = { |
| "label": undefined, |
| "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 labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSamplerDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| } |
| |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrSampler.create(device.createSampler(desc)); |
| }, |
| |
| wgpuDeviceCreateBindGroupLayout: (deviceId, 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 = { |
| "entries": makeEntries( |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.entryCount) }}}, |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.entries, '*') }}} |
| ), |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupLayoutDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrBindGroupLayout.create(device.createBindGroupLayout(desc)); |
| }, |
| |
| wgpuDeviceCreateBindGroup__deps: ['$readI53FromI64'], |
| wgpuDeviceCreateBindGroup: (deviceId, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| |
| function makeEntry(entryPtr) { |
| {{{ gpu.makeCheck('entryPtr') }}} |
| |
| var bufferId = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.buffer) }}}; |
| var samplerId = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.sampler) }}}; |
| var textureViewId = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.textureView) }}}; |
| #if ASSERTIONS |
| assert((bufferId !== 0) + (samplerId !== 0) + (textureViewId !== 0) === 1); |
| #endif |
| |
| var binding = {{{ gpu.makeGetU32('entryPtr', C_STRUCTS.WGPUBindGroupEntry.binding) }}}; |
| |
| if (bufferId) { |
| var size = {{{ makeGetValue('entryPtr', C_STRUCTS.WGPUBindGroupEntry.size, 'i53') }}}; |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| return { |
| "binding": binding, |
| "resource": { |
| "buffer": WebGPU.mgrBuffer.get(bufferId), |
| "offset": {{{ gpu.makeGetU64('entryPtr', C_STRUCTS.WGPUBindGroupEntry.offset) }}}, |
| "size": size |
| }, |
| }; |
| } else if (samplerId) { |
| return { |
| "binding": binding, |
| "resource": WebGPU.mgrSampler.get(samplerId), |
| }; |
| } else { |
| return { |
| "binding": binding, |
| "resource": WebGPU.mgrTextureView.get(textureViewId), |
| }; |
| } |
| } |
| |
| 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": undefined, |
| "layout": WebGPU.mgrBindGroupLayout.get( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.layout, '*') }}}), |
| "entries": makeEntries( |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.entryCount) }}}, |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.entries, '*') }}} |
| ), |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUBindGroupDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrBindGroup.create(device.createBindGroup(desc)); |
| }, |
| |
| wgpuDeviceCreatePipelineLayout: (deviceId, 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.mgrBindGroupLayout.get( |
| {{{ makeGetValue('bglPtr', `${POINTER_SIZE} * i`, '*') }}})); |
| } |
| var desc = { |
| "label": undefined, |
| "bindGroupLayouts": bgls, |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUPipelineLayoutDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrPipelineLayout.create(device.createPipelineLayout(desc)); |
| }, |
| |
| wgpuDeviceCreateQuerySet: (deviceId, 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.mgrDevice.get(deviceId); |
| return WebGPU.mgrQuerySet.create(device.createQuerySet(desc)); |
| }, |
| |
| wgpuDeviceCreateRenderBundleEncoder: (deviceId, 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": undefined, |
| "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) }}}, |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderBundleEncoderDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| return desc; |
| } |
| |
| var desc = makeRenderBundleEncoderDescriptor(descriptor); |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrRenderBundleEncoder.create(device.createRenderBundleEncoder(desc)); |
| }, |
| |
| wgpuDeviceCreateComputePipeline: (deviceId, descriptor) => { |
| var desc = WebGPU.makeComputePipelineDesc(descriptor); |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrComputePipeline.create(device.createComputePipeline(desc)); |
| }, |
| |
| wgpuDeviceCreateComputePipelineAsync__deps: ['$callUserCallback', '$stringToUTF8OnStack'], |
| wgpuDeviceCreateComputePipelineAsync: (deviceId, descriptor, callback, userdata) => { |
| var desc = WebGPU.makeComputePipelineDesc(descriptor); |
| var device = WebGPU.mgrDevice.get(deviceId); |
| {{{ runtimeKeepalivePush() }}} |
| device.createComputePipelineAsync(desc).then((pipeline) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var pipelineId = WebGPU.mgrComputePipeline.create(pipeline); |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Success }}}, pipelineId, 0, userdata); |
| }); |
| }, (pipelineError) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(pipelineError.message); |
| if (pipelineError.reason === 'validation') { |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.ValidationError }}}, 0, messagePtr, userdata); |
| } else if (pipelineError.reason === 'internal') { |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.InternalError }}}, 0, messagePtr, userdata); |
| } else { |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Unknown }}}, 0, messagePtr, userdata); |
| } |
| stackRestore(sp); |
| }); |
| }); |
| }, |
| |
| wgpuDeviceCreateRenderPipeline: (deviceId, descriptor) => { |
| var desc = WebGPU.makeRenderPipelineDesc(descriptor); |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrRenderPipeline.create(device.createRenderPipeline(desc)); |
| }, |
| |
| wgpuDeviceCreateRenderPipelineAsync__deps: ['$callUserCallback', '$stringToUTF8OnStack'], |
| wgpuDeviceCreateRenderPipelineAsync: (deviceId, descriptor, callback, userdata) => { |
| var desc = WebGPU.makeRenderPipelineDesc(descriptor); |
| var device = WebGPU.mgrDevice.get(deviceId); |
| {{{ runtimeKeepalivePush() }}} |
| device.createRenderPipelineAsync(desc).then((pipeline) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var pipelineId = WebGPU.mgrRenderPipeline.create(pipeline); |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Success }}}, pipelineId, 0, userdata); |
| }); |
| }, (pipelineError) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(pipelineError.message); |
| if (pipelineError.reason === 'validation') { |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.ValidationError }}}, 0, messagePtr, userdata); |
| } else if (pipelineError.reason === 'internal') { |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.InternalError }}}, 0, messagePtr, userdata); |
| } else { |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.CreatePipelineAsyncStatus.Unknown }}}, 0, messagePtr, userdata); |
| } |
| stackRestore(sp); |
| }); |
| }); |
| }, |
| |
| wgpuDeviceCreateShaderModule: (deviceId, descriptor) => { |
| {{{ 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": undefined, |
| "code": "", |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUShaderModuleDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| switch (sType) { |
| case {{{ gpu.SType.ShaderModuleSPIRVDescriptor }}}: { |
| var count = {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUShaderModuleSPIRVDescriptor.codeSize) }}}; |
| var start = {{{ makeGetValue('nextInChainPtr', C_STRUCTS.WGPUShaderModuleSPIRVDescriptor.code, '*') }}}; |
| var offset = {{{ getHeapOffset('start', 'u32') }}}; |
| #if PTHREADS |
| // Chrome can't currently handle a SharedArrayBuffer view here, so make a copy. |
| desc["code"] = HEAPU32.slice(offset, offset + count); |
| #else |
| desc["code"] = HEAPU32.subarray(offset, offset + count); |
| #endif |
| break; |
| } |
| case {{{ gpu.SType.ShaderModuleWGSLDescriptor }}}: { |
| var sourcePtr = {{{ makeGetValue('nextInChainPtr', C_STRUCTS.WGPUShaderModuleWGSLDescriptor.code, '*') }}}; |
| if (sourcePtr) { |
| desc["code"] = UTF8ToString(sourcePtr); |
| } |
| break; |
| } |
| #if ASSERTIONS |
| default: abort('unrecognized ShaderModule sType'); |
| #endif |
| } |
| |
| var device = WebGPU.mgrDevice.get(deviceId); |
| return WebGPU.mgrShaderModule.create(device.createShaderModule(desc)); |
| }, |
| |
| // wgpuQuerySet |
| |
| wgpuQuerySetGetCount: (querySetId) => { |
| var querySet = WebGPU.mgrQuerySet.get(querySetId); |
| return querySet.count; |
| }, |
| |
| wgpuQuerySetGetType: (querySetId, labelPtr) => { |
| var querySet = WebGPU.mgrQuerySet.get(querySetId); |
| return querySet.type; |
| }, |
| |
| wgpuQuerySetSetLabel: (querySetId, labelPtr) => { |
| var querySet = WebGPU.mgrQuerySet.get(querySetId); |
| querySet.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuQueue |
| |
| wgpuQueueSetLabel: (queueId, labelPtr) => { |
| var queue = WebGPU.mgrQueue.get(queueId); |
| queue.label = UTF8ToString(labelPtr); |
| }, |
| |
| wgpuQueueSubmit: (queueId, commandCount, commands) => { |
| #if ASSERTIONS |
| assert(commands % 4 === 0); |
| #endif |
| var queue = WebGPU.mgrQueue.get(queueId); |
| var cmds = Array.from({{{ makeHEAPView(`${POINTER_BITS}`, 'commands', `commands + commandCount * ${POINTER_SIZE}`)}}}, |
| (id) => WebGPU.mgrCommandBuffer.get(id)); |
| queue.submit(cmds); |
| }, |
| |
| wgpuQueueOnSubmittedWorkDone__deps: ['$callUserCallback'], |
| wgpuQueueOnSubmittedWorkDone: (queueId, callback, userdata) => { |
| var queue = WebGPU.mgrQueue.get(queueId); |
| |
| {{{ runtimeKeepalivePush() }}} |
| queue.onSubmittedWorkDone().then(() => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.QueueWorkDoneStatus.Success }}}, userdata); |
| }); |
| }, () => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.QueueWorkDoneStatus.Error }}}, userdata); |
| }); |
| }); |
| }, |
| |
| wgpuQueueWriteBuffer: (queueId, bufferId, bufferOffset, data, size) => { |
| var queue = WebGPU.mgrQueue.get(queueId); |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| // 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: (queueId, |
| destinationPtr, data, dataSize, dataLayoutPtr, writeSizePtr) => { |
| var queue = WebGPU.mgrQueue.get(queueId); |
| |
| 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); |
| }, |
| |
| // wgpuCommandEncoder |
| |
| wgpuCommandEncoderBeginComputePass: (encoderId, descriptor) => { |
| var desc; |
| |
| function makeComputePassTimestampWrites(twPtr) { |
| if (twPtr === 0) return undefined; |
| |
| return { |
| "querySet": WebGPU.mgrQuerySet.get( |
| {{{ 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": undefined, |
| "timestampWrites": makeComputePassTimestampWrites( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePassDescriptor.timestampWrites, '*') }}}), |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUComputePassDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| } |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| return WebGPU.mgrComputePassEncoder.create(commandEncoder.beginComputePass(desc)); |
| }, |
| |
| wgpuCommandEncoderBeginRenderPass: (encoderId, 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.mgrTextureView.get(viewPtr), |
| "depthSlice": depthSlice, |
| "resolveTarget": WebGPU.mgrTextureView.get( |
| {{{ 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.mgrTextureView.get( |
| {{{ 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.mgrQuerySet.get( |
| {{{ 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.RenderPassDescriptorMaxDrawCount }}}); |
| assert(0 === {{{ makeGetValue('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.next, '*') }}}); |
| #endif |
| var renderPassDescriptorMaxDrawCount = nextInChainPtr; |
| {{{ gpu.makeCheckDescriptor('renderPassDescriptorMaxDrawCount') }}} |
| maxDrawCount = {{{ gpu.makeGetU64('renderPassDescriptorMaxDrawCount', C_STRUCTS.WGPURenderPassDescriptorMaxDrawCount.maxDrawCount) }}}; |
| } |
| |
| var desc = { |
| "label": undefined, |
| "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.mgrQuerySet.get( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.occlusionQuerySet, '*') }}}), |
| "timestampWrites": makeRenderPassTimestampWrites( |
| {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.timestampWrites, '*') }}}), |
| "maxDrawCount": maxDrawCount, |
| }; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderPassDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| |
| return desc; |
| } |
| |
| var desc = makeRenderPassDescriptor(descriptor); |
| |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| return WebGPU.mgrRenderPassEncoder.create(commandEncoder.beginRenderPass(desc)); |
| }, |
| |
| wgpuCommandEncoderClearBuffer: (encoderId, bufferId, offset, size) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| commandEncoder.clearBuffer(buffer, offset, size); |
| }, |
| |
| wgpuCommandEncoderCopyBufferToBuffer: (encoderId, srcId, srcOffset, dstId, dstOffset, size) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| var src = WebGPU.mgrBuffer.get(srcId); |
| var dst = WebGPU.mgrBuffer.get(dstId); |
| commandEncoder.copyBufferToBuffer(src, srcOffset, dst, dstOffset, size); |
| }, |
| |
| wgpuCommandEncoderCopyBufferToTexture: (encoderId, srcPtr, dstPtr, copySizePtr) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| var copySize = WebGPU.makeExtent3D(copySizePtr); |
| commandEncoder.copyBufferToTexture( |
| WebGPU.makeImageCopyBuffer(srcPtr), WebGPU.makeImageCopyTexture(dstPtr), copySize); |
| }, |
| |
| wgpuCommandEncoderCopyTextureToBuffer: (encoderId, srcPtr, dstPtr, copySizePtr) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| var copySize = WebGPU.makeExtent3D(copySizePtr); |
| commandEncoder.copyTextureToBuffer( |
| WebGPU.makeImageCopyTexture(srcPtr), WebGPU.makeImageCopyBuffer(dstPtr), copySize); |
| }, |
| |
| wgpuCommandEncoderCopyTextureToTexture: (encoderId, srcPtr, dstPtr, copySizePtr) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| var copySize = WebGPU.makeExtent3D(copySizePtr); |
| commandEncoder.copyTextureToTexture( |
| WebGPU.makeImageCopyTexture(srcPtr), WebGPU.makeImageCopyTexture(dstPtr), copySize); |
| }, |
| |
| wgpuCommandEncoderResolveQuerySet: (encoderId, querySetId, firstQuery, queryCount, |
| destinationId, destinationOffset) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| var querySet = WebGPU.mgrQuerySet.get(querySetId); |
| var destination = WebGPU.mgrBuffer.get(destinationId); |
| |
| commandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset); |
| }, |
| |
| wgpuCommandEncoderWriteTimestamp: (encoderId, querySetId, queryIndex) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| var querySet = WebGPU.mgrQuerySet.get(querySetId); |
| commandEncoder.writeTimestamp(querySet, queryIndex); |
| }, |
| |
| wgpuCommandEncoderPushDebugGroup: (encoderId, groupLabelPtr) => { |
| var encoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| encoder.pushDebugGroup(UTF8ToString(groupLabelPtr)); |
| }, |
| wgpuCommandEncoderPopDebugGroup: (encoderId) => { |
| var encoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| encoder.popDebugGroup(); |
| }, |
| wgpuCommandEncoderInsertDebugMarker: (encoderId, markerLabelPtr) => { |
| var encoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| encoder.insertDebugMarker(UTF8ToString(markerLabelPtr)); |
| }, |
| |
| wgpuCommandEncoderFinish: (encoderId, descriptor) => { |
| // TODO: Use the descriptor. |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| return WebGPU.mgrCommandBuffer.create(commandEncoder.finish()); |
| }, |
| |
| wgpuCommandEncoderSetLabel: (encoderId, labelPtr) => { |
| var commandEncoder = WebGPU.mgrCommandEncoder.get(encoderId); |
| commandEncoder.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuCommandBuffer |
| |
| wgpuCommandBufferSetLabel: (commandBufferId, labelPtr) => { |
| var commandBuffer = WebGPU.mgrCommandBuffer.get(commandBufferId); |
| commandBuffer.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuPipelineLayout |
| |
| wgpuPipelineLayoutSetLabel: (pipelineLayoutId, labelPtr) => { |
| var pipelineLayout = WebGPU.mgrPipelineLayout.get(pipelineLayoutId); |
| pipelineLayout.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuShaderModule |
| |
| wgpuShaderModuleGetCompilationInfo__deps: ['$callUserCallback', '$stringToUTF8', '$lengthBytesUTF8', 'malloc', 'free'], |
| wgpuShaderModuleGetCompilationInfo: (shaderModuleId, callback, userdata) => { |
| var shaderModule = WebGPU.mgrShaderModule.get(shaderModuleId); |
| {{{ runtimeKeepalivePush() }}} |
| shaderModule.getCompilationInfo().then((compilationInfo) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var compilationMessagesPtr = _malloc({{{ C_STRUCTS.WGPUCompilationMessage.__size__ }}} * compilationInfo.messages.length); |
| var messageStringPtrs = []; // save these to free later |
| for (var i = 0; i < compilationInfo.messages.length; ++i) { |
| var compilationMessage = compilationInfo.messages[i]; |
| var compilationMessagePtr = compilationMessagesPtr + {{{ C_STRUCTS.WGPUCompilationMessage.__size__ }}} * i; |
| var messageSize = lengthBytesUTF8(compilationMessage.message) + 1; |
| var messagePtr = _malloc(messageSize); |
| messageStringPtrs.push(messagePtr); |
| stringToUTF8(compilationMessage.message, messagePtr, messageSize); |
| {{{ makeSetValue('compilationMessagePtr', C_STRUCTS.WGPUCompilationMessage.message, 'messagePtr', '*') }}}; |
| {{{ 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') }}}; |
| } |
| var compilationInfoPtr = _malloc({{{ C_STRUCTS.WGPUCompilationInfo.__size__ }}}); |
| {{{ makeSetValue('compilationInfoPtr', C_STRUCTS.WGPUCompilationInfo.messageCount, 'compilationInfo.messages.length', '*') }}} |
| {{{ makeSetValue('compilationInfoPtr', C_STRUCTS.WGPUCompilationInfo.messages, 'compilationMessagesPtr', '*') }}}; |
| |
| {{{ makeDynCall('vipp', 'callback') }}}({{{ gpu.CompilationInfoRequestStatus.Success }}}, compilationInfoPtr, userdata); |
| |
| messageStringPtrs.forEach((ptr) => { |
| _free(ptr); |
| }); |
| _free(compilationMessagesPtr); |
| _free(compilationInfoPtr); |
| }); |
| }); |
| }, |
| wgpuShaderModuleSetLabel: (shaderModuleId, labelPtr) => { |
| var shaderModule = WebGPU.mgrShaderModule.get(shaderModuleId); |
| shaderModule.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuComputePipeline |
| |
| wgpuComputePipelineGetBindGroupLayout: (pipelineId, groupIndex) => { |
| var pipeline = WebGPU.mgrComputePipeline.get(pipelineId); |
| return WebGPU.mgrBindGroupLayout.create(pipeline.getBindGroupLayout(groupIndex)); |
| }, |
| wgpuComputePipelineSetLabel: (pipelineId, labelPtr) => { |
| var pipeline = WebGPU.mgrComputePipeline.get(pipelineId); |
| pipeline.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuRenderPipeline |
| |
| wgpuRenderPipelineGetBindGroupLayout: (pipelineId, groupIndex) => { |
| var pipeline = WebGPU.mgrRenderPipeline.get(pipelineId); |
| return WebGPU.mgrBindGroupLayout.create(pipeline.getBindGroupLayout(groupIndex)); |
| }, |
| wgpuRenderPipelineSetLabel: (pipelineId, labelPtr) => { |
| var pipeline = WebGPU.mgrRenderPipeline.get(pipelineId); |
| pipeline.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuBindGroup |
| |
| wgpuBindGroupSetLabel: (bindGroupId, labelPtr) => { |
| var bindGroup = WebGPU.mgrBindGroup.get(bindGroupId); |
| bindGroup.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuBindGroupLayout |
| |
| wgpuBindGroupLayoutSetLabel: (bindGroupLayoutId, labelPtr) => { |
| var bindGroupLayout = WebGPU.mgrBindGroupLayout.get(bindGroupLayoutId); |
| bindGroupLayout.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuBuffer |
| |
| // In webgpu.h offset and size are passed in as size_t. |
| // And library_webgpu assumes that size_t is always 32bit in emscripten. |
| wgpuBufferGetConstMappedRange__deps: ['$warnOnce', 'memalign', 'free'], |
| wgpuBufferGetConstMappedRange: (bufferId, offset, size) => { |
| var bufferWrapper = WebGPU.mgrBuffer.objects[bufferId]; |
| {{{ gpu.makeCheckDefined('bufferWrapper') }}} |
| |
| if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE'); |
| |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| var mapped; |
| try { |
| mapped = bufferWrapper.object.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); |
| bufferWrapper.onUnmap.push(() => _free(data)); |
| return data; |
| }, |
| |
| wgpuBufferGetMapState: (bufferId) => { |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| return WebGPU.Int_BufferMapState[buffer.mapState]; |
| }, |
| |
| // In webgpu.h offset and size are passed in as size_t. |
| // And library_webgpu assumes that size_t is always 32bit in emscripten. |
| wgpuBufferGetMappedRange__deps: ['$warnOnce', 'memalign', 'free'], |
| wgpuBufferGetMappedRange: (bufferId, offset, size) => { |
| var bufferWrapper = WebGPU.mgrBuffer.objects[bufferId]; |
| {{{ gpu.makeCheckDefined('bufferWrapper') }}} |
| |
| if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE'); |
| |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| if (bufferWrapper.mapMode !== {{{ gpu.MapMode.Write }}}) { |
| #if ASSERTIONS |
| abort("GetMappedRange called, but buffer not mapped for writing"); |
| #endif |
| // TODO(kainino0x): Somehow inject a validation error? |
| return 0; |
| } |
| |
| var mapped; |
| try { |
| mapped = bufferWrapper.object.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); |
| bufferWrapper.onUnmap.push(() => { |
| new Uint8Array(mapped).set(HEAPU8.subarray(data, data + mapped.byteLength)); |
| _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. |
| wgpuBufferMapAsync__deps: ['$callUserCallback'], |
| wgpuBufferMapAsync: (bufferId, mode, offset, size, callback, userdata) => { |
| var bufferWrapper = WebGPU.mgrBuffer.objects[bufferId]; |
| {{{ gpu.makeCheckDefined('bufferWrapper') }}} |
| bufferWrapper.mapMode = mode; |
| bufferWrapper.onUnmap = []; |
| var buffer = bufferWrapper.object; |
| |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| |
| // `callback` takes (WGPUBufferMapAsyncStatus status, void * userdata) |
| |
| {{{ runtimeKeepalivePush() }}} |
| buffer.mapAsync(mode, offset, size).then(() => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.BufferMapAsyncStatus.Success }}}, userdata); |
| }); |
| }, () => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| // TODO(kainino0x): Figure out how to pick other error status values. |
| {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.BufferMapAsyncStatus.ValidationError }}}, userdata); |
| }); |
| }); |
| }, |
| |
| wgpuBufferGetSize: (bufferId) => { |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| // 64-bit |
| return buffer.size; |
| }, |
| |
| wgpuBufferGetUsage: (bufferId) => { |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| return buffer.usage; |
| }, |
| |
| wgpuBufferSetLabel: (bufferId, labelPtr) => { |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| buffer.label = UTF8ToString(labelPtr); |
| }, |
| |
| wgpuBufferUnmap: (bufferId) => { |
| var bufferWrapper = WebGPU.mgrBuffer.objects[bufferId]; |
| {{{ gpu.makeCheckDefined('bufferWrapper') }}} |
| |
| if (!bufferWrapper.onUnmap) { |
| // Already unmapped |
| return; |
| } |
| |
| for (var i = 0; i < bufferWrapper.onUnmap.length; ++i) { |
| bufferWrapper.onUnmap[i](); |
| } |
| bufferWrapper.onUnmap = undefined; |
| |
| bufferWrapper.object.unmap(); |
| }, |
| |
| // wgpuTexture |
| |
| wgpuTextureGetDepthOrArrayLayers: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return texture.depthOrArrayLayers; |
| }, |
| |
| wgpuTextureGetDimension: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return WebGPU.TextureDimension.indexOf(texture.dimension); |
| }, |
| |
| wgpuTextureGetFormat: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| // Should return the enum integer instead of string. |
| return WebGPU.TextureFormat.indexOf(texture.format); |
| }, |
| |
| wgpuTextureGetHeight: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return texture.height; |
| }, |
| |
| wgpuTextureGetMipLevelCount: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return texture.mipLevelCount; |
| }, |
| |
| wgpuTextureGetSampleCount: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return texture.sampleCount; |
| }, |
| |
| wgpuTextureGetUsage: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return texture.usage; |
| }, |
| |
| wgpuTextureGetWidth: (textureId) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return texture.width; |
| }, |
| |
| wgpuTextureSetLabel: (textureId, labelPtr) => { |
| var texture = WebGPU.mgrTexture.get(textureId); |
| texture.label = UTF8ToString(labelPtr); |
| }, |
| |
| wgpuTextureCreateView: (textureId, 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 = { |
| "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 labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUTextureViewDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| } |
| |
| var texture = WebGPU.mgrTexture.get(textureId); |
| return WebGPU.mgrTextureView.create(texture.createView(desc)); |
| }, |
| |
| // wgpuTextureView |
| |
| wgpuTextureViewSetLabel: (textureViewId, labelPtr) => { |
| var textureView = WebGPU.mgrTextureView.get(textureViewId); |
| textureView.label = UTF8ToString(labelPtr); |
| }, |
| |
| // wgpuComputePass |
| |
| wgpuComputePassEncoderSetBindGroup: (passId, groupIndex, groupId, dynamicOffsetCount, dynamicOffsetsPtr) => { |
| var pass = WebGPU.mgrComputePassEncoder.get(passId); |
| var group = WebGPU.mgrBindGroup.get(groupId); |
| 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); |
| } |
| }, |
| wgpuComputePassEncoderSetLabel: (passId, labelPtr) => { |
| var pass = WebGPU.mgrComputePassEncoder.get(passId); |
| pass.label = UTF8ToString(labelPtr); |
| }, |
| wgpuComputePassEncoderSetPipeline: (passId, pipelineId) => { |
| var pass = WebGPU.mgrComputePassEncoder.get(passId); |
| var pipeline = WebGPU.mgrComputePipeline.get(pipelineId); |
| pass.setPipeline(pipeline); |
| }, |
| |
| wgpuComputePassEncoderDispatchWorkgroups: (passId, x, y, z) => { |
| var pass = WebGPU.mgrComputePassEncoder.get(passId); |
| pass.dispatchWorkgroups(x, y, z); |
| }, |
| wgpuComputePassEncoderDispatchWorkgroupsIndirect: (passId, indirectBufferId, indirectOffset) => { |
| var indirectBuffer = WebGPU.mgrBuffer.get(indirectBufferId); |
| var pass = WebGPU.mgrComputePassEncoder.get(passId); |
| pass.dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuComputePassEncoderWriteTimestamp: (encoderId, querySetId, queryIndex) => { |
| var pass = WebGPU.mgrComputePassEncoder.get(encoderId); |
| var querySet = WebGPU.mgrQuerySet.get(querySetId); |
| pass.writeTimestamp(querySet, queryIndex); |
| }, |
| |
| wgpuComputePassEncoderPushDebugGroup: (encoderId, groupLabelPtr) => { |
| var encoder = WebGPU.mgrComputePassEncoder.get(encoderId); |
| encoder.pushDebugGroup(UTF8ToString(groupLabelPtr)); |
| }, |
| wgpuComputePassEncoderPopDebugGroup: (encoderId) => { |
| var encoder = WebGPU.mgrComputePassEncoder.get(encoderId); |
| encoder.popDebugGroup(); |
| }, |
| wgpuComputePassEncoderInsertDebugMarker: (encoderId, markerLabelPtr) => { |
| var encoder = WebGPU.mgrComputePassEncoder.get(encoderId); |
| encoder.insertDebugMarker(UTF8ToString(markerLabelPtr)); |
| }, |
| |
| wgpuComputePassEncoderEnd: (passId) => { |
| var pass = WebGPU.mgrComputePassEncoder.get(passId); |
| pass.end(); |
| }, |
| |
| // wgpuRenderPass |
| |
| wgpuRenderPassEncoderSetLabel: (passId, labelPtr) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.label = UTF8ToString(labelPtr); |
| }, |
| |
| wgpuRenderPassEncoderSetBindGroup: (passId, groupIndex, groupId, dynamicOffsetCount, dynamicOffsetsPtr) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| var group = WebGPU.mgrBindGroup.get(groupId); |
| 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: (passId, colorPtr) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| var color = WebGPU.makeColor(colorPtr); |
| pass.setBlendConstant(color); |
| }, |
| wgpuRenderPassEncoderSetIndexBuffer: (passId, bufferId, format, offset, size) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size); |
| }, |
| wgpuRenderPassEncoderSetPipeline: (passId, pipelineId) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| var pipeline = WebGPU.mgrRenderPipeline.get(pipelineId); |
| pass.setPipeline(pipeline); |
| }, |
| wgpuRenderPassEncoderSetScissorRect: (passId, x, y, w, h) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.setScissorRect(x, y, w, h); |
| }, |
| wgpuRenderPassEncoderSetViewport: (passId, x, y, w, h, minDepth, maxDepth) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.setViewport(x, y, w, h, minDepth, maxDepth); |
| }, |
| wgpuRenderPassEncoderSetStencilReference: (passId, reference) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.setStencilReference(reference); |
| }, |
| wgpuRenderPassEncoderSetVertexBuffer: (passId, slot, bufferId, offset, size) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setVertexBuffer(slot, buffer, offset, size); |
| }, |
| |
| wgpuRenderPassEncoderDraw: (passId, vertexCount, instanceCount, firstVertex, firstInstance) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.draw(vertexCount, instanceCount, firstVertex, firstInstance); |
| }, |
| wgpuRenderPassEncoderDrawIndexed: (passId, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance); |
| }, |
| wgpuRenderPassEncoderDrawIndirect: (passId, indirectBufferId, indirectOffset) => { |
| var indirectBuffer = WebGPU.mgrBuffer.get(indirectBufferId); |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.drawIndirect(indirectBuffer, indirectOffset); |
| }, |
| wgpuRenderPassEncoderDrawIndexedIndirect: (passId, indirectBufferId, indirectOffset) => { |
| var indirectBuffer = WebGPU.mgrBuffer.get(indirectBufferId); |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.drawIndexedIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuRenderPassEncoderExecuteBundles: (passId, count, bundlesPtr) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| |
| #if ASSERTIONS |
| assert(bundlesPtr % 4 === 0); |
| #endif |
| |
| var bundles = Array.from({{{ makeHEAPView(`${POINTER_BITS}`, 'bundlesPtr', `bundlesPtr + count * ${POINTER_SIZE}`) }}}, |
| (id) => WebGPU.mgrRenderBundle.get(id)); |
| pass.executeBundles(bundles); |
| }, |
| |
| wgpuRenderPassEncoderBeginOcclusionQuery: (passId, queryIndex) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.beginOcclusionQuery(queryIndex); |
| }, |
| wgpuRenderPassEncoderEndOcclusionQuery: (passId) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(passId); |
| pass.endOcclusionQuery(); |
| }, |
| |
| wgpuRenderPassEncoderWriteTimestamp: (encoderId, querySetId, queryIndex) => { |
| var pass = WebGPU.mgrRenderPassEncoder.get(encoderId); |
| var querySet = WebGPU.mgrQuerySet.get(querySetId); |
| pass.writeTimestamp(querySet, queryIndex); |
| }, |
| |
| wgpuRenderPassEncoderPushDebugGroup: (encoderId, groupLabelPtr) => { |
| var encoder = WebGPU.mgrRenderPassEncoder.get(encoderId); |
| encoder.pushDebugGroup(UTF8ToString(groupLabelPtr)); |
| }, |
| wgpuRenderPassEncoderPopDebugGroup: (encoderId) => { |
| var encoder = WebGPU.mgrRenderPassEncoder.get(encoderId); |
| encoder.popDebugGroup(); |
| }, |
| wgpuRenderPassEncoderInsertDebugMarker: (encoderId, markerLabelPtr) => { |
| var encoder = WebGPU.mgrRenderPassEncoder.get(encoderId); |
| encoder.insertDebugMarker(UTF8ToString(markerLabelPtr)); |
| }, |
| wgpuRenderPassEncoderEnd: (encoderId) => { |
| var encoder = WebGPU.mgrRenderPassEncoder.get(encoderId); |
| encoder.end(); |
| }, |
| |
| // Render bundle |
| |
| wgpuRenderBundleSetLabel: (bundleId, labelPtr) => { |
| var bundle = WebGPU.mgrRenderBundle.get(bundleId); |
| bundle.label = UTF8ToString(labelPtr); |
| }, |
| |
| // Render bundle encoder |
| |
| wgpuRenderBundleEncoderSetLabel: (bundleId, labelPtr) => { |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| pass.label = UTF8ToString(labelPtr); |
| }, |
| |
| wgpuRenderBundleEncoderSetBindGroup: (bundleId, groupIndex, groupId, dynamicOffsetCount, dynamicOffsetsPtr) => { |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| var group = WebGPU.mgrBindGroup.get(groupId); |
| 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: (bundleId, bufferId, format, offset, size) => { |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size); |
| }, |
| wgpuRenderBundleEncoderSetPipeline: (bundleId, pipelineId) => { |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| var pipeline = WebGPU.mgrRenderPipeline.get(pipelineId); |
| pass.setPipeline(pipeline); |
| }, |
| wgpuRenderBundleEncoderSetVertexBuffer: (bundleId, slot, bufferId, offset, size) => { |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| var buffer = WebGPU.mgrBuffer.get(bufferId); |
| {{{ gpu.convertSentinelToUndefined('size') }}} |
| pass.setVertexBuffer(slot, buffer, offset, size); |
| }, |
| |
| wgpuRenderBundleEncoderDraw: (bundleId, vertexCount, instanceCount, firstVertex, firstInstance) => { |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| pass.draw(vertexCount, instanceCount, firstVertex, firstInstance); |
| }, |
| wgpuRenderBundleEncoderDrawIndexed: (bundleId, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => { |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance); |
| }, |
| wgpuRenderBundleEncoderDrawIndirect: (bundleId, indirectBufferId, indirectOffset) => { |
| var indirectBuffer = WebGPU.mgrBuffer.get(indirectBufferId); |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| pass.drawIndirect(indirectBuffer, indirectOffset); |
| }, |
| wgpuRenderBundleEncoderDrawIndexedIndirect: (bundleId, indirectBufferId, indirectOffset) => { |
| var indirectBuffer = WebGPU.mgrBuffer.get(indirectBufferId); |
| var pass = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| pass.drawIndexedIndirect(indirectBuffer, indirectOffset); |
| }, |
| |
| wgpuRenderBundleEncoderPushDebugGroup: (encoderId, groupLabelPtr) => { |
| var encoder = WebGPU.mgrRenderBundleEncoder.get(encoderId); |
| encoder.pushDebugGroup(UTF8ToString(groupLabelPtr)); |
| }, |
| wgpuRenderBundleEncoderPopDebugGroup: (encoderId) => { |
| var encoder = WebGPU.mgrRenderBundleEncoder.get(encoderId); |
| encoder.popDebugGroup(); |
| }, |
| wgpuRenderBundleEncoderInsertDebugMarker: (encoderId, markerLabelPtr) => { |
| var encoder = WebGPU.mgrRenderBundleEncoder.get(encoderId); |
| encoder.insertDebugMarker(UTF8ToString(markerLabelPtr)); |
| }, |
| |
| wgpuRenderBundleEncoderFinish: (bundleId, descriptor) => { |
| var desc; |
| if (descriptor) { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| desc = {}; |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPURenderBundleDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| } |
| var encoder = WebGPU.mgrRenderBundleEncoder.get(bundleId); |
| return WebGPU.mgrRenderBundle.create(encoder.finish(desc)); |
| }, |
| |
| // Instance |
| |
| wgpuInstanceCreateSurface__deps: ['$findCanvasEventTarget'], |
| wgpuInstanceCreateSurface: (instanceId, descriptor) => { |
| {{{ gpu.makeCheck('descriptor') }}} |
| {{{ gpu.makeCheck('instanceId === 1, "WGPUInstance must be created by wgpuCreateInstance"') }}} |
| var nextInChainPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSurfaceDescriptor.nextInChain, '*') }}}; |
| #if ASSERTIONS |
| assert(nextInChainPtr !== 0); |
| assert({{{ gpu.SType.SurfaceDescriptorFromCanvasHTMLSelector }}} === |
| {{{ gpu.makeGetU32('nextInChainPtr', C_STRUCTS.WGPUChainedStruct.sType) }}}); |
| #endif |
| var descriptorFromCanvasHTMLSelector = nextInChainPtr; |
| |
| {{{ gpu.makeCheckDescriptor('descriptorFromCanvasHTMLSelector') }}} |
| var selectorPtr = {{{ makeGetValue('descriptorFromCanvasHTMLSelector', C_STRUCTS.WGPUSurfaceDescriptorFromCanvasHTMLSelector.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; |
| |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUSurfaceDescriptor.label, '*') }}}; |
| if (labelPtr) context.surfaceLabelWebGPU = UTF8ToString(labelPtr); |
| |
| return WebGPU.mgrSurface.create(context); |
| }, |
| |
| wgpuInstanceHasWGSLLanguageFeature: (instance, featureEnumValue) => { |
| if (!('wgslLanguageFeatures' in navigator["gpu"])) { |
| return false; |
| } |
| return navigator["gpu"]["wgslLanguageFeatures"].has(WebGPU.WGSLFeatureName[featureEnumValue]); |
| }, |
| |
| wgpuInstanceProcessEvents: (instance) => { |
| // TODO: This could probably be emulated with ASYNCIFY. |
| #if ASSERTIONS |
| abort('wgpuInstanceProcessEvents is unsupported (use requestAnimationFrame via html5.h instead)'); |
| #endif |
| }, |
| |
| wgpuInstanceRequestAdapter__deps: ['$callUserCallback', '$stringToUTF8OnStack'], |
| wgpuInstanceRequestAdapter: (instanceId, options, callback, userdata) => { |
| {{{ gpu.makeCheck('instanceId === 1, "WGPUInstance must be created by wgpuCreateInstance"') }}} |
| |
| 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)'); |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.RequestAdapterStatus.Unavailable }}}, 0, messagePtr, userdata); |
| stackRestore(sp); |
| return; |
| } |
| |
| {{{ runtimeKeepalivePush() }}} |
| navigator["gpu"]["requestAdapter"](opts).then((adapter) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| if (adapter) { |
| var adapterId = WebGPU.mgrAdapter.create(adapter); |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.RequestAdapterStatus.Success }}}, adapterId, 0, userdata); |
| } else { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack('WebGPU not available on this system (requestAdapter returned null)'); |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.RequestAdapterStatus.Unavailable }}}, 0, messagePtr, userdata); |
| stackRestore(sp); |
| } |
| }); |
| }, (ex) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(ex.message); |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.RequestAdapterStatus.Error }}}, 0, messagePtr, userdata); |
| stackRestore(sp); |
| }); |
| }); |
| }, |
| |
| // WGPUAdapter |
| |
| wgpuAdapterEnumerateFeatures: (adapterId, featuresOutPtr) => { |
| var adapter = WebGPU.mgrAdapter.get(adapterId); |
| if (featuresOutPtr !== 0) { |
| var offset = 0; |
| adapter.features.forEach(feature => { |
| var featureEnumValue = WebGPU.FeatureNameString2Enum[feature]; |
| {{{ makeSetValue('featuresOutPtr', 'offset', 'featureEnumValue', 'i32') }}}; |
| offset += 4; |
| }); |
| } |
| return adapter.features.size; |
| }, |
| |
| wgpuAdapterGetInfo__deps: ['$stringToNewUTF8'], |
| wgpuAdapterGetInfo: (adapterId, info) => { |
| var adapter = WebGPU.mgrAdapter.get(adapterId); |
| {{{ gpu.makeCheckDescriptor('info') }}} |
| |
| var vendorPtr = stringToNewUTF8(adapter.info.vendor); |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.vendor, 'vendorPtr', '*') }}}; |
| var architecturePtr = stringToNewUTF8(adapter.info.architecture); |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.architecture, 'architecturePtr', '*') }}}; |
| var devicePtr = stringToNewUTF8(adapter.info.device); |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.device, 'devicePtr', '*') }}}; |
| var descriptionPtr = stringToNewUTF8(adapter.info.description); |
| {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.description, 'descriptionPtr', '*') }}}; |
| {{{ 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') }}}; |
| }, |
| |
| wgpuAdapterGetProperties__deps: ['$warnOnce'], |
| wgpuAdapterGetProperties: (adapterId, properties) => { |
| warnOnce('wgpuAdapterGetProperties is deprecated, use wgpuAdapterGetInfo instead'); |
| |
| {{{ gpu.makeCheckDescriptor('properties') }}} |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.vendorID, '0', 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.vendorName, '0', 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.architecture, '0', 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.deviceID, '0', 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.name, '0', 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.driverDescription, '0', 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.adapterType, gpu.AdapterType.Unknown, 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.backendType, gpu.BackendType.WebGPU, 'i32') }}}; |
| {{{ makeSetValue('properties', C_STRUCTS.WGPUAdapterProperties.compatibilityMode, '0', 'i32') }}}; |
| }, |
| |
| wgpuAdapterGetLimits: (adapterId, limitsOutPtr) => { |
| var adapter = WebGPU.mgrAdapter.get(adapterId); |
| WebGPU.fillLimitStruct(adapter.limits, limitsOutPtr); |
| return 1; |
| }, |
| |
| wgpuAdapterHasFeature: (adapterId, featureEnumValue) => { |
| var adapter = WebGPU.mgrAdapter.get(adapterId); |
| return adapter.features.has(WebGPU.FeatureName[featureEnumValue]); |
| }, |
| |
| wgpuAdapterRequestDevice__deps: ['$callUserCallback', '$stringToUTF8OnStack'], |
| wgpuAdapterRequestDevice: (adapterId, descriptor, callback, userdata) => { |
| var adapter = WebGPU.mgrAdapter.get(adapterId); |
| |
| 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, '*') }}}; |
| desc["requiredFeatures"] = Array.from({{{ makeHEAPView('32', 'requiredFeaturesPtr', `requiredFeaturesPtr + requiredFeatureCount * ${POINTER_SIZE}`) }}}, |
| (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 = {}; |
| var labelPtr = {{{ makeGetValue('defaultQueuePtr', C_STRUCTS.WGPUQueueDescriptor.label, '*') }}}; |
| if (labelPtr) defaultQueueDesc["label"] = UTF8ToString(labelPtr); |
| desc["defaultQueue"] = defaultQueueDesc; |
| } |
| |
| var deviceLostCallbackPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.deviceLostCallbackInfo + C_STRUCTS.WGPUDeviceLostCallbackInfo.callback, '*') }}}; |
| var deviceLostUserdataPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.deviceLostCallbackInfo + C_STRUCTS.WGPUDeviceLostCallbackInfo.userdata, '*') }}}; |
| |
| var labelPtr = {{{ makeGetValue('descriptor', C_STRUCTS.WGPUDeviceDescriptor.label, '*') }}}; |
| if (labelPtr) desc["label"] = UTF8ToString(labelPtr); |
| } |
| |
| {{{ runtimeKeepalivePush() }}} |
| adapter.requestDevice(desc).then((device) => { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var deviceWrapper = { queueId: WebGPU.mgrQueue.create(device.queue) }; |
| var deviceId = WebGPU.mgrDevice.create(device, deviceWrapper); |
| if (deviceLostCallbackPtr) { |
| device.lost.then((info) => { |
| callUserCallback(() => WebGPU.errorCallback(deviceLostCallbackPtr, |
| WebGPU.Int_DeviceLostReason[info.reason], info.message, deviceLostUserdataPtr)); |
| }); |
| } |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.RequestDeviceStatus.Success }}}, deviceId, 0, userdata); |
| }); |
| }, function(ex) { |
| {{{ runtimeKeepalivePop() }}} |
| callUserCallback(() => { |
| var sp = stackSave(); |
| var messagePtr = stringToUTF8OnStack(ex.message); |
| {{{ makeDynCall('vippp', 'callback') }}}({{{ gpu.RequestDeviceStatus.Error }}}, 0, messagePtr, userdata); |
| stackRestore(sp); |
| }); |
| }); |
| }, |
| |
| // WGPUAdapterProperties |
| |
| wgpuAdapterPropertiesFreeMembers: (value) => { |
| // wgpuAdapterGetProperties doesn't currently allocate anything. |
| }, |
| |
| // WGPUSampler |
| |
| wgpuSamplerSetLabel: (samplerId, labelPtr) => { |
| var sampler = WebGPU.mgrSampler.get(samplerId); |
| sampler.label = UTF8ToString(labelPtr); |
| }, |
| |
| // WGPUSurface |
| |
| wgpuSurfaceConfigure: (surfaceId, config) => { |
| {{{ gpu.makeCheckDescriptor('config') }}} |
| var deviceId = {{{ makeGetValue('config', C_STRUCTS.WGPUSurfaceConfiguration.device, '*') }}}; |
| var context = WebGPU.mgrSurface.get(surfaceId); |
| |
| #if ASSERTIONS |
| var viewFormatCount = {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.viewFormatCount) }}}; |
| var viewFormats = {{{ makeGetValue('config', C_STRUCTS.WGPUSurfaceConfiguration.viewFormats, '*') }}}; |
| assert(viewFormatCount === 0 && viewFormats === 0, "TODO: Support viewFormats."); |
| var alphaMode = {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.alphaMode) }}}; |
| assert(alphaMode === {{{ gpu.CompositeAlphaMode.Auto }}} || |
| alphaMode === {{{ gpu.CompositeAlphaMode.Opaque }}}, |
| "TODO: Support WGPUCompositeAlphaMode_Premultiplied."); |
| 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.mgrDevice.get(deviceId), |
| "format": WebGPU.TextureFormat[ |
| {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.format) }}}], |
| "usage": {{{ gpu.makeGetU32('config', C_STRUCTS.WGPUSurfaceConfiguration.usage) }}}, |
| "alphaMode": "opaque", |
| }; |
| context.configure(configuration); |
| }, |
| |
| wgpuSurfaceGetCurrentTexture: (surfaceId, surfaceTexturePtr) => { |
| {{{ gpu.makeCheck('surfaceTexturePtr') }}} |
| var context = WebGPU.mgrSurface.get(surfaceId); |
| |
| try { |
| var texture = WebGPU.mgrTexture.create(context.getCurrentTexture()); |
| {{{ makeSetValue('surfaceTexturePtr', C_STRUCTS.WGPUSurfaceTexture.texture, 'texture', '*') }}}; |
| {{{ 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') }}}; |
| } |
| }, |
| |
| wgpuSurfaceGetPreferredFormat: (surfaceId, adapterId) => { |
| var format = navigator["gpu"]["getPreferredCanvasFormat"](); |
| return WebGPU.Int_PreferredFormat[format]; |
| }, |
| |
| wgpuSurfacePresent: (surfaceId) => { |
| // TODO: This could probably be emulated with ASYNCIFY. |
| abort('wgpuSurfacePresent is unsupported (use requestAnimationFrame via html5.h instead)'); |
| }, |
| |
| wgpuSurfaceUnconfigure: (surfaceId) => { |
| var context = WebGPU.mgrSurface.get(surfaceId); |
| context.unconfigure(); |
| }, |
| |
| // WGPUSwapChain |
| |
| wgpuDeviceCreateSwapChain: (deviceId, surfaceId, descriptor) => { |
| {{{ gpu.makeCheckDescriptor('descriptor') }}} |
| var device = WebGPU.mgrDevice.get(deviceId); |
| var context = WebGPU.mgrSurface.get(surfaceId); |
| |
| #if ASSERTIONS |
| assert({{{ gpu.PresentMode.Fifo }}} === |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.presentMode) }}}); |
| #endif |
| |
| var canvasSize = [ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.width) }}}, |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.height) }}} |
| ]; |
| |
| if (canvasSize[0] !== 0) { |
| context["canvas"]["width"] = canvasSize[0]; |
| } |
| |
| if (canvasSize[1] !== 0) { |
| context["canvas"]["height"] = canvasSize[1]; |
| } |
| |
| var configuration = { |
| "device": device, |
| "format": WebGPU.TextureFormat[ |
| {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.format) }}}], |
| "usage": {{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.usage) }}}, |
| "alphaMode": "opaque", |
| }; |
| context.configure(configuration); |
| |
| return WebGPU.mgrSwapChain.create(context); |
| }, |
| |
| wgpuSwapChainGetCurrentTexture: (swapChainId) => { |
| var context = WebGPU.mgrSwapChain.get(swapChainId); |
| return WebGPU.mgrTexture.create(context.getCurrentTexture()); |
| }, |
| wgpuSwapChainGetCurrentTextureView: (swapChainId) => { |
| var context = WebGPU.mgrSwapChain.get(swapChainId); |
| return WebGPU.mgrTextureView.create(context.getCurrentTexture().createView()); |
| }, |
| wgpuSwapChainPresent: (swapChainId) => { |
| // TODO: This could probably be emulated with ASYNCIFY. |
| abort('wgpuSwapChainPresent is unsupported (use requestAnimationFrame via html5.h instead)'); |
| }, |
| }; |
| |
| // Inverted index used by EnumerateFeatures/HasFeature |
| LibraryWebGPU.$WebGPU.FeatureNameString2Enum = {}; |
| for (var value in LibraryWebGPU.$WebGPU.FeatureName) { |
| LibraryWebGPU.$WebGPU.FeatureNameString2Enum[LibraryWebGPU.$WebGPU.FeatureName[value]] = value; |
| } |
| |
| for (const key of Object.keys(LibraryWebGPU)) { |
| if (typeof LibraryWebGPU[key] === 'function') { |
| LibraryWebGPU[key + '__i53abi'] = true; |
| } |
| } |
| |
| autoAddDeps(LibraryWebGPU, '$WebGPU'); |
| mergeInto(LibraryManager.library, LibraryWebGPU); |