@luma.gl/webgpu 9.0.0-beta.5 → 9.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/adapter/helpers/accessor-to-format.js +4 -1
  2. package/dist/adapter/helpers/convert-texture-format.d.ts.map +1 -1
  3. package/dist/adapter/helpers/convert-texture-format.js +3 -0
  4. package/dist/adapter/helpers/get-bind-group.d.ts +3 -3
  5. package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
  6. package/dist/adapter/helpers/get-bind-group.js +3 -0
  7. package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -1
  8. package/dist/adapter/helpers/get-vertex-buffer-layout.js +9 -2
  9. package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
  10. package/dist/adapter/helpers/webgpu-parameters.js +3 -0
  11. package/dist/adapter/resources/webgpu-buffer.d.ts +1 -1
  12. package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
  13. package/dist/adapter/resources/webgpu-buffer.js +19 -10
  14. package/dist/adapter/resources/webgpu-command-encoder.d.ts +7 -1
  15. package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
  16. package/dist/adapter/resources/webgpu-command-encoder.js +8 -0
  17. package/dist/adapter/resources/webgpu-compute-pass.d.ts +15 -9
  18. package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgpu-compute-pass.js +39 -17
  20. package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +14 -4
  21. package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
  22. package/dist/adapter/resources/webgpu-compute-pipeline.js +37 -15
  23. package/dist/adapter/resources/webgpu-external-texture.d.ts +2 -2
  24. package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgpu-external-texture.js +14 -7
  26. package/dist/adapter/resources/webgpu-framebuffer.d.ts +1 -1
  27. package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
  28. package/dist/adapter/resources/webgpu-framebuffer.js +3 -0
  29. package/dist/adapter/resources/webgpu-query-set.d.ts +17 -0
  30. package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -0
  31. package/dist/adapter/resources/webgpu-query-set.js +27 -0
  32. package/dist/adapter/resources/webgpu-render-pass.d.ts +4 -2
  33. package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
  34. package/dist/adapter/resources/webgpu-render-pass.js +27 -9
  35. package/dist/adapter/resources/webgpu-render-pipeline.d.ts +52 -5
  36. package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
  37. package/dist/adapter/resources/webgpu-render-pipeline.js +76 -66
  38. package/dist/adapter/resources/webgpu-sampler.d.ts +1 -1
  39. package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
  40. package/dist/adapter/resources/webgpu-sampler.js +3 -0
  41. package/dist/adapter/resources/webgpu-shader.d.ts +2 -5
  42. package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
  43. package/dist/adapter/resources/webgpu-shader.js +10 -20
  44. package/dist/adapter/resources/webgpu-texture-view.d.ts +20 -0
  45. package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -0
  46. package/dist/adapter/resources/webgpu-texture-view.js +35 -0
  47. package/dist/adapter/resources/webgpu-texture.d.ts +8 -8
  48. package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
  49. package/dist/adapter/resources/webgpu-texture.js +25 -22
  50. package/dist/adapter/resources/webgpu-vertex-array.d.ts +7 -9
  51. package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -1
  52. package/dist/adapter/resources/webgpu-vertex-array.js +11 -13
  53. package/dist/adapter/webgpu-canvas-context.d.ts +3 -3
  54. package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
  55. package/dist/adapter/webgpu-canvas-context.js +8 -5
  56. package/dist/adapter/webgpu-device.d.ts +26 -28
  57. package/dist/adapter/webgpu-device.d.ts.map +1 -1
  58. package/dist/adapter/webgpu-device.js +81 -74
  59. package/dist/dist.dev.js +339 -305
  60. package/dist/index.cjs +313 -250
  61. package/dist/index.cjs.map +4 -4
  62. package/dist/index.d.ts +5 -5
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +7 -6
  65. package/dist.min.js +1 -1
  66. package/package.json +2 -2
  67. package/src/adapter/helpers/accessor-to-format.ts +5 -1
  68. package/src/adapter/helpers/convert-texture-format.ts +4 -1
  69. package/src/adapter/helpers/get-bind-group.ts +12 -6
  70. package/src/adapter/helpers/get-vertex-buffer-layout.ts +12 -4
  71. package/src/adapter/helpers/webgpu-parameters.ts +79 -15
  72. package/src/adapter/resources/webgpu-buffer.ts +24 -11
  73. package/src/adapter/resources/webgpu-command-encoder.ts +24 -9
  74. package/src/adapter/resources/webgpu-compute-pass.ts +45 -22
  75. package/src/adapter/resources/webgpu-compute-pipeline.ts +48 -16
  76. package/src/adapter/resources/webgpu-external-texture.ts +14 -6
  77. package/src/adapter/resources/webgpu-framebuffer.ts +4 -0
  78. package/src/adapter/resources/webgpu-query-set.ts +37 -0
  79. package/src/adapter/resources/webgpu-render-pass.ts +37 -14
  80. package/src/adapter/resources/webgpu-render-pipeline.ts +75 -115
  81. package/src/adapter/resources/webgpu-sampler.ts +4 -1
  82. package/src/adapter/resources/webgpu-shader.ts +11 -25
  83. package/src/adapter/resources/webgpu-texture-view.ts +46 -0
  84. package/src/adapter/resources/webgpu-texture.ts +33 -28
  85. package/src/adapter/resources/webgpu-vertex-array.ts +25 -20
  86. package/src/adapter/webgpu-canvas-context.ts +10 -5
  87. package/src/adapter/webgpu-device.ts +99 -76
  88. package/src/index.ts +2 -1
  89. package/dist/adapter/helpers/generate-mipmaps.d.ts +0 -10
  90. package/dist/adapter/helpers/generate-mipmaps.d.ts.map +0 -1
  91. package/dist/adapter/helpers/generate-mipmaps.js +0 -94
  92. package/dist/adapter/resources/webgpu-query.d.ts +0 -1
  93. package/dist/adapter/resources/webgpu-query.d.ts.map +0 -1
  94. package/dist/adapter/resources/webgpu-query.js +0 -43
  95. package/dist/adapter/webgpu-types.d.ts +0 -1
  96. package/dist/adapter/webgpu-types.d.ts.map +0 -1
  97. package/dist/adapter/webgpu-types.js +0 -0
  98. package/dist/glsl/glsllang.d.ts +0 -3
  99. package/dist/glsl/glsllang.d.ts.map +0 -1
  100. package/dist/glsl/glsllang.js +0 -12
  101. package/src/adapter/helpers/generate-mipmaps.ts +0 -107
  102. package/src/adapter/resources/webgpu-query.ts +0 -43
  103. package/src/adapter/webgpu-types.ts +0 -0
  104. package/src/glsl/glsllang.ts +0 -14
package/dist.min.js CHANGED
@@ -4,6 +4,6 @@
4
4
  else if (typeof define === 'function' && define.amd) define([], factory);
5
5
  else if (typeof exports === 'object') exports['luma'] = factory();
6
6
  else root['luma'] = factory();})(globalThis, function () {
7
- var __exports__=(()=>{var le=Object.create;var D=Object.defineProperty;var ue=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var he=Object.getPrototypeOf,me=Object.prototype.hasOwnProperty;var fe=(i,e,t)=>e in i?D(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var Pe=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),be=(i,e)=>{for(var t in e)D(i,t,{get:e[t],enumerable:!0})},Y=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ce(e))!me.call(i,n)&&n!==t&&D(i,n,{get:()=>e[n],enumerable:!(r=ue(e,n))||r.enumerable});return i};var d=(i,e,t)=>(t=i!=null?le(he(i)):{},Y(e||!i||!i.__esModule?D(t,"default",{value:i,enumerable:!0}):t,i)),ge=i=>Y(D({},"__esModule",{value:!0}),i);var X=(i,e,t)=>(fe(i,typeof e!="symbol"?e+"":e,t),t);var a=Pe((We,J)=>{J.exports=globalThis.luma});var Ce={};be(Ce,{WebGPUBuffer:()=>g,WebGPUDevice:()=>R,WebGPUSampler:()=>u,WebGPUShader:()=>G,WebGPUTexture:()=>x});var h=d(a(),1);var E=d(a(),1);function ve(i){return i.byteLength||i.data?.byteLength||0}var g=class extends E.Buffer{device;handle;byteLength;constructor(e,t){super(e,t),this.device=e,this.byteLength=ve(t);let r=Boolean(t.data),n=Math.ceil(this.byteLength/4)*4;this.handle=this.props.handle||this.device.handle.createBuffer({size:n,usage:this.props.usage||GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:this.props.mappedAtCreation||r,label:this.props.id}),t.data&&this._writeMapped(t.data),r&&!t.mappedAtCreation&&this.handle.unmap()}destroy(){this.handle.destroy()}write(e,t=0){this.device.handle.queue.writeBuffer(this.handle,t,e.buffer,e.byteOffset,e.byteLength)}async readAsync(e=0,t=this.byteLength){let r=new g(this.device,{usage:E.Buffer.MAP_READ|E.Buffer.COPY_DST,byteLength:t}),n=this.device.handle.createCommandEncoder();n.copyBufferToBuffer(this.handle,e,r.handle,0,t),this.device.handle.queue.submit([n.finish()]),await r.handle.mapAsync(GPUMapMode.READ,e,t);let o=r.handle.getMappedRange().slice(0);return r.handle.unmap(),r.destroy(),new Uint8Array(o)}_writeMapped(e){let t=this.handle.getMappedRange();new e.constructor(t).set(e)}mapAsync(e,t=0,r){return this.handle.mapAsync(e,t,r)}getMappedRange(e=0,t){return this.handle.getMappedRange(e,t)}unmap(){this.handle.unmap()}};var K=d(a(),1);function y(i){if(i.includes("webgl"))throw new Error("webgl-only format");return i}var Z=d(a(),1),u=class extends Z.Sampler{device;handle;constructor(e,t){super(e,t),this.device=e;let r={...this.props};r.type!=="comparison-sampler"&&delete r.compare,this.handle=this.handle||this.device.handle.createSampler(r),this.handle.label=this.props.id}destroy(){}};var ye={"1d":"1d","2d":"2d","2d-array":"2d",cube:"2d","cube-array":"2d","3d":"3d"},x=class extends K.Texture{device;handle;view;sampler;height=1;width=1;constructor(e,t){if(super(e,t),this.device=e,t.data instanceof Promise){t.data.then(r=>{this.props={...t,data:r},this.initialize(this.props)});return}this.initialize(t)}initialize(e){this.handle=this.props.handle||this.createHandle(),this.handle.label||=this.id,this.props.data&&this.setData({data:this.props.data}),this.width=this.handle.width,this.height=this.handle.height,this.sampler=e.sampler instanceof u?e.sampler:new u(this.device,e.sampler),this.view=this.createView()}createHandle(){let e=this.props.width||this.props.data?.width||1,t=this.props.height||this.props.data?.height||1;return this.device.handle.createTexture({label:this.id,size:{width:e,height:t,depthOrArrayLayers:this.props.depth},dimension:ye[this.props.dimension],format:y(this.props.format),usage:this.props.usage,mipLevelCount:this.props.mipLevels,sampleCount:this.props.samples})}destroy(){this.handle.destroy()}setSampler(e){return this.sampler=e instanceof u?e:new u(this.device,e),this}setData(e){return this.setImage({source:e.data})}setImage(e){let{source:t,width:r=e.source.width,height:n=e.source.height,depth:o=1,sourceX:s=0,sourceY:p=0,mipLevel:l=0,x:v=0,y:b=0,z:S=0,aspect:B="all",colorSpace:C="srgb",premultipliedAlpha:z=!1}=e;return this.device.handle.queue.copyExternalImageToTexture({source:t,origin:[s,p]},{texture:this.handle,origin:[v,b,S],mipLevel:l,aspect:B,colorSpace:C,premultipliedAlpha:z},[r,n,o]),{width:r,height:n}}createView(){return this.handle.createView({label:this.id})}};var Q=d(a(),1);var A=class extends Q.ExternalTexture{device;handle;sampler;constructor(e,t){super(e,t),this.device=e,this.handle=this.props.handle||this.device.handle.importExternalTexture({source:t.source,colorSpace:t.colorSpace}),this.sampler=null}destroy(){}setSampler(e){return this.sampler=e instanceof u?e:new u(this.device,e),this}};var L=d(a(),1),G=class extends L.Shader{device;handle;constructor(e,t){super(e,t),this.device=e,this.device.handle.pushErrorScope("validation"),this.handle=this.props.handle||this.createHandle(),this.handle.label=this.props.id,this._checkCompilationError(this.device.handle.popErrorScope())}async _checkCompilationError(e){let t=await e;if(t){this.debugShader();let r=await this.getCompilationInfo();throw L.log.error(`Shader compilation error: ${t.message}`,r)(),new Error(`Shader compilation error: ${t.message}`)}}destroy(){}async getCompilationInfo(){return(await this.handle.getCompilationInfo()).messages}createHandle(){let{source:e,stage:t}=this.props,r=this.props.language;switch(r==="auto"&&(r=e.includes("->")?"wgsl":"glsl"),r){case"wgsl":return this.device.handle.createShaderModule({code:e});case"glsl":return this.device.handle.createShaderModule({code:e,transform:n=>this.device.glslang.compileGLSL(n,t)});default:throw new Error(r)}}};var c=d(a(),1);function m(i){return i.depthStencil=i.depthStencil||{format:"depth24plus",stencilFront:{},stencilBack:{},depthWriteEnabled:!1,depthCompare:"less-equal"},i.depthStencil}var xe={cullMode:(i,e,t)=>{t.primitive=t.primitive||{},t.primitive.cullMode=e},frontFace:(i,e,t)=>{t.primitive=t.primitive||{},t.primitive.frontFace=e},depthWriteEnabled:(i,e,t)=>{let r=m(t);r.depthWriteEnabled=e},depthCompare:(i,e,t)=>{let r=m(t);r.depthCompare=e},depthFormat:(i,e,t)=>{let r=m(t);r.format=e},depthBias:(i,e,t)=>{let r=m(t);r.depthBias=e},depthBiasSlopeScale:(i,e,t)=>{let r=m(t);r.depthBiasSlopeScale=e},depthBiasClamp:(i,e,t)=>{let r=m(t);r.depthBiasClamp=e},stencilReadMask:(i,e,t)=>{let r=m(t);r.stencilReadMask=e},stencilWriteMask:(i,e,t)=>{let r=m(t);r.stencilWriteMask=e},stencilCompare:(i,e,t)=>{let r=m(t);r.stencilFront.compare=e,r.stencilBack.compare=e},stencilPassOperation:(i,e,t)=>{let r=m(t);r.stencilFront.passOp=e,r.stencilBack.passOp=e},stencilFailOperation:(i,e,t)=>{let r=m(t);r.stencilFront.failOp=e,r.stencilBack.failOp=e},stencilDepthFailOperation:(i,e,t)=>{let r=m(t);r.stencilFront.depthFailOp=e,r.stencilBack.depthFailOp=e},sampleCount:(i,e,t)=>{t.multisample=t.multisample||{},t.multisample.count=e},sampleMask:(i,e,t)=>{t.multisample=t.multisample||{},t.multisample.mask=e},sampleAlphaToCoverageEnabled:(i,e,t)=>{t.multisample=t.multisample||{},t.multisample.alphaToCoverageEnabled=e},colorMask:(i,e,t)=>{let r=ee(t);r[0].writeMask=e},blendColorOperation:(i,e,t)=>{ee(t)}},Ge={primitive:{cullMode:"back",topology:"triangle-list"},vertex:{module:void 0,entryPoint:"main"},fragment:{module:void 0,entryPoint:"main",targets:[]},layout:"auto"};function te(i,e={}){Object.assign(i,{...Ge,...i}),Ue(i,e)}function Ue(i,e){for(let[t,r]of Object.entries(e)){let n=xe[t];if(!n)throw new Error(`Illegal parameter ${t}`);n(t,r,i)}}function ee(i){if(i.fragment.targets=i.fragment?.targets||[],!Array.isArray(i.fragment?.targets))throw new Error("colorstate");return i.fragment?.targets?.length===0&&i.fragment.targets?.push({}),i.fragment?.targets}var f=d(a(),1);function re(i,e,t,r){let n=Se(r,t);return i.createBindGroup({layout:e,entries:n})}function we(i,e){let t=i.bindings.find(r=>r.name===e||`${r.name}uniforms`===e.toLocaleLowerCase());return t||f.log.warn(`Binding ${e} not set: Not found in shader layout.`)(),t}function Se(i,e){let t=[];for(let[r,n]of Object.entries(i)){let o=we(e,r);o&&t.push(Be(n,o.location))}return t}function Be(i,e){if(i instanceof f.Buffer)return{binding:e,resource:{buffer:(0,f.cast)(i).handle}};if(i instanceof f.Sampler)return{binding:e,resource:(0,f.cast)(i).handle};if(i instanceof f.Texture)return{binding:e,resource:(0,f.cast)(i).handle.createView({label:"bind-group-auto-created"})};throw new Error("invalid binding")}var U=d(a(),1);function N(i){if(i.endsWith("-webgl"))throw new Error(`WebGPU does not support vertex format ${i}`);return i}function ne(i,e){let t=[],r=new Set;for(let n of e){let o=[],s="vertex",p=0;if(n.attributes)for(let l of n.attributes){let v=l.attribute,b=ie(i,v,r);s=b.stepMode||(b.name.startsWith("instance")?"instance":"vertex"),o.push({format:N(l.format||n.format),offset:l.byteOffset,shaderLocation:b.location}),p+=(0,U.decodeVertexFormat)(n.format).byteLength}else{let l=ie(i,n.name,r);if(!l)continue;p=(0,U.decodeVertexFormat)(n.format).byteLength,s=l.stepMode||(l.name.startsWith("instance")?"instance":"vertex"),o.push({format:N(n.format),offset:0,shaderLocation:l.location})}t.push({arrayStride:n.byteStride||p,stepMode:s,attributes:o})}for(let n of i.attributes)r.has(n.name)||t.push({arrayStride:(0,U.decodeVertexFormat)("float32x3").byteLength,stepMode:n.stepMode||(n.name.startsWith("instance")?"instance":"vertex"),attributes:[{format:N("float32x3"),offset:0,shaderLocation:n.location}]});return t}function ie(i,e,t){let r=i.attributes.find(n=>n.name===e);if(!r)return U.log.warn(`Unknown attribute ${e}`)(),null;if(t.has(e))throw new Error(`Duplicate attribute ${e}`);return t.add(e),r}var F=class extends c.RenderPipeline{device;handle;vs;fs=null;_bindGroupLayout=null;_bindGroup=null;constructor(e,t){if(super(e,t),this.device=e,this.handle=this.props.handle,!this.handle){let r=this._getRenderPipelineDescriptor();c.log.groupCollapsed(1,`new WebGPURenderPipeline(${this.id})`)(),c.log.probe(1,JSON.stringify(r,null,2))(),c.log.groupEnd(1)(),this.handle=this.device.handle.createRenderPipeline(r)}this.handle.label=this.props.id,this.vs=(0,c.cast)(t.vs),this.fs=(0,c.cast)(t.fs)}destroy(){}setBindings(e){Object.assign(this.props.bindings,e)}setUniforms(e){if(!(0,c.isObjectEmpty)(e))throw new Error("WebGPU does not support uniforms")}draw(e){let t=(0,c.cast)(e.renderPass)||this.device.getDefaultRenderPass();t.handle.setPipeline(this.handle);let r=this._getBindGroup();r&&t.handle.setBindGroup(0,r),e.vertexArray.bindBeforeRender(e.renderPass),e.indexCount?t.handle.drawIndexed(e.indexCount,e.instanceCount,e.firstIndex,e.baseVertex,e.firstInstance):t.handle.draw(e.vertexCount||0,e.instanceCount||1,e.firstInstance),e.vertexArray.unbindAfterRender(e.renderPass)}_getBindGroup(){return this._bindGroupLayout=this._bindGroupLayout||this.handle.getBindGroupLayout(0),this._bindGroup=this._bindGroup||re(this.device.handle,this._bindGroupLayout,this.props.shaderLayout,this.props.bindings),this._bindGroup}_getRenderPipelineDescriptor(){let e={module:(0,c.cast)(this.props.vs).handle,entryPoint:this.props.vsEntryPoint||"main",buffers:ne(this.props.shaderLayout,this.props.bufferLayout)},t;switch(this.props.fs&&(t={module:(0,c.cast)(this.props.fs).handle,entryPoint:this.props.fsEntryPoint||"main",targets:[{format:y(this.device?.canvasContext?.format)}]}),this.props.topology){case"triangle-fan-webgl":case"line-loop-webgl":throw new Error(`WebGPU does not support primitive topology ${this.props.topology}`);default:}let r={vertex:e,fragment:t,primitive:{topology:this.props.topology},layout:"auto"};return te(r,this.props.parameters),r}};var oe=d(a(),1),k=class extends oe.ComputePipeline{device;handle;constructor(e,t){super(e,t),this.device=e;let r=this.props.cs;this.handle=this.props.handle||this.device.handle.createComputePipeline({label:this.props.id,compute:{module:r.handle,entryPoint:this.props.csEntryPoint},layout:"auto"})}_getBindGroupLayout(){return this.handle.getBindGroupLayout(0)}};var P=d(a(),1),V=class extends P.RenderPass{device;handle;pipeline=null;constructor(e,t={}){super(e,t),this.device=e;let r=t.framebuffer||e.canvasContext.getCurrentFramebuffer(),n=this.getRenderPassDescriptor(r);P.log.groupCollapsed(3,`new WebGPURenderPass(${this.id})`)(),P.log.probe(3,JSON.stringify(n,null,2))(),P.log.groupEnd(3)(),this.handle=this.props.handle||e.commandEncoder.beginRenderPass(n),this.handle.label=this.props.id}destroy(){}end(){this.handle.end()}setPipeline(e){this.pipeline=(0,P.cast)(e),this.handle.setPipeline(this.pipeline.handle)}setBindings(e){this.pipeline?.setBindings(e);let t=this.pipeline?._getBindGroup();t&&this.handle.setBindGroup(0,t)}setIndexBuffer(e,t,r=0,n){this.handle.setIndexBuffer((0,P.cast)(e).handle,t,r,n)}setVertexBuffer(e,t,r=0){this.handle.setVertexBuffer(e,(0,P.cast)(t).handle,r)}draw(e){e.indexCount?this.handle.drawIndexed(e.indexCount,e.instanceCount,e.firstIndex,e.baseVertex,e.firstInstance):this.handle.draw(e.vertexCount||0,e.instanceCount||1,e.firstIndex,e.firstInstance)}drawIndirect(){}setParameters(e){let{blendConstant:t,stencilReference:r,scissorRect:n,viewport:o}=e;t&&this.handle.setBlendConstant(t),r&&this.handle.setStencilReference(r),n&&this.handle.setScissorRect(n[0],n[1],n[2],n[3]),o&&this.handle.setViewport(o[0],o[1],o[2],o[3],o[4],o[5])}pushDebugGroup(e){this.handle.pushDebugGroup(e)}popDebugGroup(){this.handle.popDebugGroup()}insertDebugMarker(e){this.handle.insertDebugMarker(e)}getRenderPassDescriptor(e){let t={colorAttachments:[]};if(t.colorAttachments=e.colorAttachments.map(r=>({loadOp:this.props.clearColor!==!1?"clear":"load",colorClearValue:this.props.clearColor||[0,0,0,0],storeOp:this.props.discard?"discard":"store",view:r.createView()})),e.depthStencilAttachment){t.depthStencilAttachment={view:e.depthStencilAttachment.createView()};let{depthStencilAttachment:r}=t;this.props.depthReadOnly&&(r.depthReadOnly=!0),r.depthClearValue=this.props.clearDepth||0,!0&&(r.depthLoadOp=this.props.clearDepth!==!1?"clear":"load",r.depthStoreOp="store"),!1&&(r.stencilLoadOp=this.props.clearStencil!==!1?"clear":"load",r.stencilStoreOp="store")}return t}};var ae=d(a(),1),M=class extends ae.ComputePass{device;handle;_bindGroupLayout=null;constructor(e,t){super(e,t),this.device=e,this.handle=this.props.handle||e.commandEncoder?.beginComputePass({label:this.props.id})}destroy(){}end(){this.handle.end()}setPipeline(e){let t=e;this.handle.setPipeline(t.handle),this._bindGroupLayout=t._getBindGroupLayout()}setBindings(e){throw new Error("fix me")}dispatch(e,t,r){this.handle.dispatchWorkgroups(e,t,r)}dispatchIndirect(e,t=0){let r=e;this.handle.dispatchWorkgroupsIndirect(r.handle,t)}pushDebugGroup(e){this.handle.pushDebugGroup(e)}popDebugGroup(){this.handle.popDebugGroup()}insertDebugMarker(e){this.handle.insertDebugMarker(e)}};var w=d(a(),1);function W(i){if(typeof window<"u"&&typeof window.process=="object"&&window.process.type==="renderer"||typeof process<"u"&&typeof process.versions=="object"&&Boolean(process.versions.electron))return!0;let e=typeof navigator=="object"&&typeof navigator.userAgent=="string"&&navigator.userAgent,t=i||e;return!!(t&&t.indexOf("Electron")>=0)}function q(){return!(typeof process=="object"&&String(process)==="[object process]"&&!process.browser)||W()}var ft=globalThis.self||globalThis.window||globalThis.global,Pt=globalThis.window||globalThis.self||globalThis.global,bt=globalThis.document||{},gt=globalThis.process||{},vt=globalThis.console,se=globalThis.navigator||{};var j=globalThis;function _(i){if(!i&&!q())return"Node";if(W(i))return"Electron";let e=i||se.userAgent||"";if(e.indexOf("Edge")>-1)return"Edge";let t=e.indexOf("MSIE ")!==-1,r=e.indexOf("Trident/")!==-1;return t||r?"IE":j.chrome?"Chrome":j.safari?"Safari":j.mozInnerScreenX?"Firefox":"Unknown"}var I=class extends w.VertexArray{get[Symbol.toStringTag](){return"WebGPUVertexArray"}device;handle;static isConstantAttributeZeroSupported(e){return _()==="Chrome"}constructor(e,t){super(e,t),this.device=e}destroy(){}setIndexBuffer(e){this.indexBuffer=e}setBuffer(e,t){this.attributes[e]=t}setConstant(e,t){w.log.warn(`${this.id} constant attributes not supported on WebGPU`)}bindBeforeRender(e,t,r){let n=e,o=this.indexBuffer;o?.handle&&(w.log.warn("setting index buffer",o?.handle,o?.indexType)(),n.handle.setIndexBuffer(o?.handle,o?.indexType));for(let s=0;s<this.maxVertexAttributes;s++){let p=this.attributes[s];p?.handle&&(w.log.warn(`setting vertex buffer ${s}`,p?.handle)(),n.handle.setVertexBuffer(s,p?.handle))}}unbindAfterRender(e){}};var $=d(a(),1);var de=d(a(),1),O=class extends de.Framebuffer{device;constructor(e,t){super(e,t),this.device=e,this.autoCreateAttachmentTextures()}};var T=class extends $.CanvasContext{device;gpuCanvasContext;format=navigator.gpu.getPreferredCanvasFormat();depthStencilFormat="depth24plus";depthStencilAttachment=null;constructor(e,t,r){super(r),this.device=e,this.width=-1,this.height=-1,this._setAutoCreatedCanvasId(`${this.device.id}-canvas`),this.gpuCanvasContext=this.canvas.getContext("webgpu"),this.format="bgra8unorm"}destroy(){this.gpuCanvasContext.unconfigure()}getCurrentFramebuffer(){this.update();let e=this.getCurrentTexture();return this.width=e.width,this.height=e.height,this._createDepthStencilAttachment(),new O(this.device,{colorAttachments:[e],depthStencilAttachment:this.depthStencilAttachment})}update(){let[e,t]=this.getPixelSize();(e!==this.width||t!==this.height)&&(this.width=e,this.height=t,this.depthStencilAttachment&&(this.depthStencilAttachment.destroy(),this.depthStencilAttachment=null),this.gpuCanvasContext.configure({device:this.device.handle,format:y(this.format),colorSpace:this.props.colorSpace,alphaMode:this.props.alphaMode}),$.log.log(1,`Resized to ${this.width}x${this.height}px`)())}resize(e){this.update()}getCurrentTexture(){return this.device._createTexture({id:`${this.id}#color-texture`,handle:this.gpuCanvasContext.getCurrentTexture()})}_createDepthStencilAttachment(){return this.depthStencilAttachment||(this.depthStencilAttachment=this.device.createTexture({id:`${this.id}#depth-stencil-texture`,format:this.depthStencilFormat,width:this.width,height:this.height,usage:GPUTextureUsage.RENDER_ATTACHMENT})),this.depthStencilAttachment}};var H=class extends h.Device{handle;adapter;lost;canvasContext=null;commandEncoder=null;renderPass=null;_info;_isLost=!1;static isSupported(){return Boolean(typeof navigator<"u"&&navigator.gpu)}static async create(e){if(!navigator.gpu)throw new Error("WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu");h.log.groupCollapsed(1,"WebGPUDevice created")();let t=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});if(!t)throw new Error("Failed to request WebGPU adapter");let r=await t.requestAdapterInfo();h.log.probe(2,"Adapter available",r)();let n=await t.requestDevice({requiredFeatures:t.features});h.log.probe(1,"GPUDevice available")(),typeof e.canvas=="string"&&(await h.CanvasContext.pageLoaded,h.log.probe(1,"DOM is loaded")());let o=new H(n,t,r,e);return h.log.probe(1,"Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")(),h.log.table(1,o.info)(),h.log.groupEnd(1)(),o}constructor(e,t,r,n){super({...n,id:n.id||(0,h.uid)("webgpu-device")}),this.handle=e,this.adapter=t;let[o,s]=(r.driver||"").split(" Version "),p=r.vendor||this.adapter.__brand||"unknown",l=o||"",v=s||"",b=p==="apple"?"apple":"unknown",S=r.architecture||"unknown",B=r.backend||"unknown",C=(r.type||"").split(" ")[0].toLowerCase()||"unknown";this._info={type:"webgpu",vendor:p,renderer:l,version:v,gpu:b,gpuType:C,gpuBackend:B,gpuArchitecture:S,shadingLanguage:"wgsl",shadingLanguageVersion:100},this.lost=new Promise(async z=>{let pe=await this.handle.lost;this._isLost=!0,z({reason:"destroyed",message:pe.message})}),this.canvasContext=new T(this,this.adapter,{canvas:n.canvas,height:n.height,width:n.width,container:n.container}),this.features=this._getFeatures()}destroy(){this.handle.destroy()}get info(){return this._info}features;get limits(){return this.handle.limits}isTextureFormatSupported(e){return!e.includes("webgl")}isTextureFormatFilterable(e){return this.isTextureFormatSupported(e)}isTextureFormatRenderable(e){return this.isTextureFormatSupported(e)}get isLost(){return this._isLost}createBuffer(e){let t=this._getBufferProps(e);return new g(this,t)}_createTexture(e){return new x(this,e)}createExternalTexture(e){return new A(this,e)}createShader(e){return new G(this,e)}createSampler(e){return new u(this,e)}createRenderPipeline(e){return new F(this,e)}createFramebuffer(e){throw new Error("Not implemented")}createComputePipeline(e){return new k(this,e)}createVertexArray(e){return new I(this,e)}beginRenderPass(e){return this.commandEncoder=this.commandEncoder||this.handle.createCommandEncoder(),new V(this,e)}beginComputePass(e){return this.commandEncoder=this.commandEncoder||this.handle.createCommandEncoder(),new M(this,e)}createTransformFeedback(e){throw new Error("Transform feedback not supported in WebGPU")}createCanvasContext(e){return new T(this,this.adapter,e)}getDefaultRenderPass(){throw new Error("a")}submit(){let e=this.commandEncoder?.finish();e&&this.handle.queue.submit([e]),this.commandEncoder=null}_getFeatures(){let e=new Set(this.handle.features);e.has("depth-clamping")&&(e.delete("depth-clamping"),e.add("depth-clip-control")),e.has("texture-compression-bc")&&e.add("texture-compression-bc5-webgl");let t=["webgpu","wgsl","timer-query-webgl","float32-filterable-linear-webgl","float16-filterable-linear-webgl","texture-filterable-anisotropic-webgl","float32-renderable-webgl","float16-renderable-webgl"];for(let r of t)e.add(r);return e}copyExternalImageToTexture(e){let{source:t,sourceX:r=0,sourceY:n=0,texture:o,mipLevel:s=0,aspect:p="all",colorSpace:l="display-p3",premultipliedAlpha:v=!1,width:b=o.width,height:S=o.height,depth:B=1}=e,C=o;this.handle?.queue.copyExternalImageToTexture({source:t,origin:[r,n]},{texture:C.handle,origin:[0,0,0],mipLevel:s,aspect:p,colorSpace:l,premultipliedAlpha:v},[b,S,B])}},R=H;X(R,"type","webgpu");return ge(Ce);})();
7
+ var __exports__=(()=>{var ce=Object.create;var S=Object.defineProperty;var me=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var Pe=Object.getPrototypeOf,be=Object.prototype.hasOwnProperty;var ge=(i,e,t)=>e in i?S(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var ye=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),ve=(i,e)=>{for(var t in e)S(i,t,{get:e[t],enumerable:!0})},X=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of fe(e))!be.call(i,n)&&n!==t&&S(i,n,{get:()=>e[n],enumerable:!(r=me(e,n))||r.enumerable});return i};var p=(i,e,t)=>(t=i!=null?ce(Pe(i)):{},X(e||!i||!i.__esModule?S(t,"default",{value:i,enumerable:!0}):t,i)),xe=i=>X(S({},"__esModule",{value:!0}),i);var J=(i,e,t)=>(ge(i,typeof e!="symbol"?e+"":e,t),t);var a=ye((Ae,Z)=>{Z.exports=globalThis.luma});var Te={};ve(Te,{WebGPUBuffer:()=>b,WebGPUDevice:()=>T,WebGPUSampler:()=>h,WebGPUShader:()=>G,WebGPUTexture:()=>x});var l=p(a(),1);var R=p(a(),1);function Ge(i){return i.byteLength||i.data?.byteLength||0}var b=class extends R.Buffer{device;handle;byteLength;constructor(e,t){super(e,t),this.device=e,this.byteLength=Ge(t);let r=Boolean(t.data),n=Math.ceil(this.byteLength/4)*4;this.handle=this.props.handle||this.device.handle.createBuffer({size:n,usage:this.props.usage||GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:this.props.mappedAtCreation||r,label:this.props.id}),t.data&&this._writeMapped(t.data),r&&!t.mappedAtCreation&&this.handle.unmap()}destroy(){this.handle?.destroy(),this.handle=null}write(e,t=0){this.device.handle.queue.writeBuffer(this.handle,t,e.buffer,e.byteOffset,e.byteLength)}async readAsync(e=0,t=this.byteLength){let r=new b(this.device,{usage:R.Buffer.MAP_READ|R.Buffer.COPY_DST,byteLength:t}),n=this.device.handle.createCommandEncoder();n.copyBufferToBuffer(this.handle,e,r.handle,0,t),this.device.handle.queue.submit([n.finish()]),await r.handle.mapAsync(GPUMapMode.READ,e,t);let o=r.handle.getMappedRange().slice(0);return r.handle.unmap(),r.destroy(),new Uint8Array(o)}_writeMapped(e){let t=this.handle.getMappedRange();new e.constructor(t).set(e)}mapAsync(e,t=0,r){return this.handle.mapAsync(e,t,r)}getMappedRange(e=0,t){return this.handle.getMappedRange(e,t)}unmap(){this.handle.unmap()}};var te=p(a(),1);function v(i){if(i.includes("webgl"))throw new Error("webgl-only format");return i}var K=p(a(),1),h=class extends K.Sampler{device;handle;constructor(e,t){super(e,t),this.device=e;let r={...this.props};r.type!=="comparison-sampler"&&delete r.compare,this.handle=this.handle||this.device.handle.createSampler(r),this.handle.label=this.props.id}destroy(){this.handle=null}};var ee=p(a(),1),W=class extends ee.TextureView{device;handle;texture;constructor(e,t){super(e,t),this.device=e,this.texture=t.texture,this.handle=this.handle||this.texture.handle.createView({format:t.format||this.texture.format,dimension:t.dimension||this.texture.dimension,aspect:t.aspect,baseMipLevel:t.baseMipLevel,mipLevelCount:t.mipLevelCount,baseArrayLayer:t.baseArrayLayer,arrayLayerCount:t.arrayLayerCount}),this.handle.label=this.props.id}destroy(){this.handle=null}};var Ue={"1d":"1d","2d":"2d","2d-array":"2d",cube:"2d","cube-array":"2d","3d":"3d"},x=class extends te.Texture{device;handle;height=1;width=1;sampler;view;constructor(e,t){if(super(e,t),this.device=e,t.data instanceof Promise){t.data.then(r=>{this.props={...t,data:r},this.initialize(this.props)});return}this.initialize(t)}destroy(){this.handle?.destroy(),this.handle=null}createView(e){return new W(this.device,{...e,texture:this})}initialize(e){this.handle=this.props.handle||this.createHandle(),this.handle.label||=this.id,this.props.data&&this.setData({data:this.props.data}),this.width=this.handle.width,this.height=this.handle.height,this.sampler=e.sampler instanceof h?e.sampler:new h(this.device,e.sampler),this.view=new W(this.device,{...this.props,texture:this})}createHandle(){let e=this.props.width||this.props.data?.width||1,t=this.props.height||this.props.data?.height||1;return this.device.handle.createTexture({label:this.id,size:{width:e,height:t,depthOrArrayLayers:this.props.depth},dimension:Ue[this.props.dimension],format:v(this.props.format),usage:this.props.usage,mipLevelCount:this.props.mipLevels,sampleCount:this.props.samples})}setSampler(e){return this.sampler=e instanceof h?e:new h(this.device,e),this}setData(e){return this.setImage({source:e.data})}setImage(e){let{source:t,width:r=e.source.width,height:n=e.source.height,depth:o=1,sourceX:s=0,sourceY:u=0,mipLevel:d=0,x:g=0,y=0,z:q=0,aspect:$="all",colorSpace:z="srgb",premultipliedAlpha:he=!1}=e;return this.device.handle.queue.copyExternalImageToTexture({source:t,origin:[s,u]},{texture:this.handle,origin:[g,y,q],mipLevel:d,aspect:$,colorSpace:z,premultipliedAlpha:he},[r,n,o]),{width:r,height:n}}};var re=p(a(),1);var A=class extends re.ExternalTexture{device;handle;sampler;constructor(e,t){super(e,t),this.device=e,this.handle=this.props.handle||this.device.handle.importExternalTexture({source:t.source,colorSpace:t.colorSpace}),this.sampler=null}destroy(){this.handle=null}setSampler(e){return this.sampler=e instanceof h?e:new h(this.device,e),this}};var E=p(a(),1),G=class extends E.Shader{device;handle;constructor(e,t){super(e,t),this.device=e,this.device.handle.pushErrorScope("validation"),this.handle=this.props.handle||this.createHandle(),this.handle.label=this.props.id,this._checkCompilationError(this.device.handle.popErrorScope())}async _checkCompilationError(e){let t=await e;if(t){this.debugShader();let r=await this.getCompilationInfo();throw E.log.error(`Shader compilation error: ${t.message}`,r)(),new Error(`Shader compilation error: ${t.message}`)}}destroy(){this.handle=null}async getCompilationInfo(){return(await this.handle.getCompilationInfo()).messages}createHandle(){let{source:e}=this.props,t=e.includes("#version");if(this.props.language==="glsl"||t)throw new Error("GLSL shaders are not supported in WebGPU");return this.device.handle.createShaderModule({code:e})}};var f=p(a(),1);function c(i){return i.depthStencil=i.depthStencil||{format:"depth24plus",stencilFront:{},stencilBack:{},depthWriteEnabled:!1,depthCompare:"less-equal"},i.depthStencil}var we={cullMode:(i,e,t)=>{t.primitive=t.primitive||{},t.primitive.cullMode=e},frontFace:(i,e,t)=>{t.primitive=t.primitive||{},t.primitive.frontFace=e},depthWriteEnabled:(i,e,t)=>{let r=c(t);r.depthWriteEnabled=e},depthCompare:(i,e,t)=>{let r=c(t);r.depthCompare=e},depthFormat:(i,e,t)=>{let r=c(t);r.format=e},depthBias:(i,e,t)=>{let r=c(t);r.depthBias=e},depthBiasSlopeScale:(i,e,t)=>{let r=c(t);r.depthBiasSlopeScale=e},depthBiasClamp:(i,e,t)=>{let r=c(t);r.depthBiasClamp=e},stencilReadMask:(i,e,t)=>{let r=c(t);r.stencilReadMask=e},stencilWriteMask:(i,e,t)=>{let r=c(t);r.stencilWriteMask=e},stencilCompare:(i,e,t)=>{let r=c(t);r.stencilFront.compare=e,r.stencilBack.compare=e},stencilPassOperation:(i,e,t)=>{let r=c(t);r.stencilFront.passOp=e,r.stencilBack.passOp=e},stencilFailOperation:(i,e,t)=>{let r=c(t);r.stencilFront.failOp=e,r.stencilBack.failOp=e},stencilDepthFailOperation:(i,e,t)=>{let r=c(t);r.stencilFront.depthFailOp=e,r.stencilBack.depthFailOp=e},sampleCount:(i,e,t)=>{t.multisample=t.multisample||{},t.multisample.count=e},sampleMask:(i,e,t)=>{t.multisample=t.multisample||{},t.multisample.mask=e},sampleAlphaToCoverageEnabled:(i,e,t)=>{t.multisample=t.multisample||{},t.multisample.alphaToCoverageEnabled=e},colorMask:(i,e,t)=>{let r=ie(t);r[0].writeMask=e},blendColorOperation:(i,e,t)=>{ie(t)}},Se={primitive:{cullMode:"back",topology:"triangle-list"},vertex:{module:void 0,entryPoint:"main"},fragment:{module:void 0,entryPoint:"main",targets:[]},layout:"auto"};function ne(i,e={}){Object.assign(i,{...Se,...i}),We(i,e)}function We(i,e){for(let[t,r]of Object.entries(e)){let n=we[t];if(!n)throw new Error(`Illegal parameter ${t}`);n(t,r,i)}}function ie(i){if(i.fragment.targets=i.fragment?.targets||[],!Array.isArray(i.fragment?.targets))throw new Error("colorstate");return i.fragment?.targets?.length===0&&i.fragment.targets?.push({}),i.fragment?.targets}var m=p(a(),1);function L(i,e,t,r){let n=Ce(r,t);return i.createBindGroup({layout:e,entries:n})}function Be(i,e){let t=i.bindings.find(r=>r.name===e||`${r.name}uniforms`===e.toLocaleLowerCase());return t||m.log.warn(`Binding ${e} not set: Not found in shader layout.`)(),t}function Ce(i,e){let t=[];for(let[r,n]of Object.entries(i)){let o=Be(e,r);o&&t.push(De(n,o.location))}return t}function De(i,e){if(i instanceof m.Buffer)return{binding:e,resource:{buffer:(0,m.cast)(i).handle}};if(i instanceof m.Sampler)return{binding:e,resource:(0,m.cast)(i).handle};if(i instanceof m.Texture)return{binding:e,resource:(0,m.cast)(i).handle.createView({label:"bind-group-auto-created"})};throw new Error("invalid binding")}var U=p(a(),1);function N(i){if(i.endsWith("-webgl"))throw new Error(`WebGPU does not support vertex format ${i}`);return i}function se(i,e){let t=[],r=new Set;for(let n of e){let o=[],s="vertex",u=0;if(n.attributes)for(let d of n.attributes){let g=d.attribute,y=oe(i,g,r);s=y.stepMode||(y.name.startsWith("instance")?"instance":"vertex"),o.push({format:N(d.format||n.format),offset:d.byteOffset,shaderLocation:y.location}),u+=(0,U.decodeVertexFormat)(n.format).byteLength}else{let d=oe(i,n.name,r);if(!d)continue;u=(0,U.decodeVertexFormat)(n.format).byteLength,s=d.stepMode||(d.name.startsWith("instance")?"instance":"vertex"),o.push({format:N(n.format),offset:0,shaderLocation:d.location})}t.push({arrayStride:n.byteStride||u,stepMode:s,attributes:o})}for(let n of i.attributes)r.has(n.name)||t.push({arrayStride:(0,U.decodeVertexFormat)("float32x3").byteLength,stepMode:n.stepMode||(n.name.startsWith("instance")?"instance":"vertex"),attributes:[{format:N("float32x3"),offset:0,shaderLocation:n.location}]});return t}function oe(i,e,t){let r=i.attributes.find(n=>n.name===e);if(!r)return U.log.warn(`Unknown attribute ${e}`)(),null;if(t.has(e))throw new Error(`Duplicate attribute ${e}`);return t.add(e),r}var F=class extends f.RenderPipeline{device;handle;vs;fs=null;_bindings;_bindGroupLayout=null;_bindGroup=null;constructor(e,t){if(super(e,t),this.device=e,this.handle=this.props.handle,!this.handle){let r=this._getRenderPipelineDescriptor();f.log.groupCollapsed(1,`new WebGPURenderPipeline(${this.id})`)(),f.log.probe(1,JSON.stringify(r,null,2))(),f.log.groupEnd(1)(),this.handle=this.device.handle.createRenderPipeline(r)}this.handle.label=this.props.id,this.vs=(0,f.cast)(t.vs),this.fs=(0,f.cast)(t.fs),this._bindings={...this.props.bindings}}destroy(){this.handle=null}setBindings(e){Object.assign(this._bindings,e)}draw(e){let t=e.renderPass;t.handle.setPipeline(this.handle);let r=this._getBindGroup();return r&&t.handle.setBindGroup(0,r),e.vertexArray.bindBeforeRender(e.renderPass),e.indexCount?t.handle.drawIndexed(e.indexCount,e.instanceCount,e.firstIndex,e.baseVertex,e.firstInstance):t.handle.draw(e.vertexCount||0,e.instanceCount||1,e.firstInstance),e.vertexArray.unbindAfterRender(e.renderPass),!0}_getBindGroup(){return this.props.shaderLayout.bindings.length===0?null:(this._bindGroupLayout=this._bindGroupLayout||this.handle.getBindGroupLayout(0),this._bindGroup=this._bindGroup||L(this.device.handle,this._bindGroupLayout,this.props.shaderLayout,this._bindings),this._bindGroup)}_getRenderPipelineDescriptor(){let e={module:(0,f.cast)(this.props.vs).handle,entryPoint:this.props.vertexEntryPoint||"main",buffers:se(this.props.shaderLayout,this.props.bufferLayout)},t={module:(0,f.cast)(this.props.fs).handle,entryPoint:this.props.fragmentEntryPoint||"main",targets:[{format:v(this.device?.canvasContext?.format)}]};switch(this.props.topology){case"triangle-fan-webgl":case"line-loop-webgl":throw new Error(`WebGPU does not support primitive topology ${this.props.topology}`);default:}let r={vertex:e,fragment:t,primitive:{topology:this.props.topology},layout:"auto"};return ne(r,this.props.parameters),r}};var ae=p(a(),1),w=class extends ae.Framebuffer{device;constructor(e,t){super(e,t),this.device=e,this.autoCreateAttachmentTextures()}};var de=p(a(),1);var I=class extends de.ComputePipeline{device;handle;_bindGroupLayout=null;_bindGroup=null;_bindings={};constructor(e,t){super(e,t),this.device=e;let r=this.props.shader;this.handle=this.props.handle||this.device.handle.createComputePipeline({label:this.props.id,compute:{module:r.handle,entryPoint:this.props.entryPoint,constants:this.props.constants},layout:"auto"})}setBindings(e){Object.assign(this._bindings,e)}_getBindGroup(){return this._bindGroupLayout=this._bindGroupLayout||this.handle.getBindGroupLayout(0),this._bindGroup=this._bindGroup||L(this.device.handle,this._bindGroupLayout,this.props.shaderLayout,this._bindings),this._bindGroup}};var P=p(a(),1),_=class extends P.RenderPass{device;handle;pipeline=null;constructor(e,t={}){super(e,t),this.device=e;let r=t.framebuffer||e.canvasContext.getCurrentFramebuffer(),n=this.getRenderPassDescriptor(r),o=t.timestampQuerySet;if(o&&(n.occlusionQuerySet=o.handle),e.features.has("timestamp-query")){let s=t.timestampQuerySet;n.timestampWrites=s?{querySet:s.handle,beginningOfPassWriteIndex:t.beginTimestampIndex,endOfPassWriteIndex:t.endTimestampIndex}:void 0}this.handle=this.props.handle||e.commandEncoder.beginRenderPass(n),this.handle.label=this.props.id,P.log.groupCollapsed(3,`new WebGPURenderPass(${this.id})`)(),P.log.probe(3,JSON.stringify(n,null,2))(),P.log.groupEnd(3)()}destroy(){}end(){this.handle.end()}setPipeline(e){this.pipeline=(0,P.cast)(e),this.handle.setPipeline(this.pipeline.handle)}setBindings(e){this.pipeline?.setBindings(e);let t=this.pipeline?._getBindGroup();t&&this.handle.setBindGroup(0,t)}setIndexBuffer(e,t,r=0,n){this.handle.setIndexBuffer((0,P.cast)(e).handle,t,r,n)}setVertexBuffer(e,t,r=0){this.handle.setVertexBuffer(e,(0,P.cast)(t).handle,r)}draw(e){e.indexCount?this.handle.drawIndexed(e.indexCount,e.instanceCount,e.firstIndex,e.baseVertex,e.firstInstance):this.handle.draw(e.vertexCount||0,e.instanceCount||1,e.firstIndex,e.firstInstance)}drawIndirect(){}setParameters(e){let{blendConstant:t,stencilReference:r,scissorRect:n,viewport:o}=e;t&&this.handle.setBlendConstant(t),r&&this.handle.setStencilReference(r),n&&this.handle.setScissorRect(n[0],n[1],n[2],n[3]),o&&this.handle.setViewport(o[0],o[1],o[2],o[3],o[4],o[5])}pushDebugGroup(e){this.handle.pushDebugGroup(e)}popDebugGroup(){this.handle.popDebugGroup()}insertDebugMarker(e){this.handle.insertDebugMarker(e)}beginOcclusionQuery(e){this.handle.beginOcclusionQuery(e)}endOcclusionQuery(){this.handle.endOcclusionQuery()}getRenderPassDescriptor(e){let t={colorAttachments:[]};if(t.colorAttachments=e.colorAttachments.map(r=>({loadOp:this.props.clearColor!==!1?"clear":"load",colorClearValue:this.props.clearColor||[0,0,0,0],storeOp:this.props.discard?"discard":"store",view:r.handle})),e.depthStencilAttachment){t.depthStencilAttachment={view:e.depthStencilAttachment.handle};let{depthStencilAttachment:r}=t;this.props.depthReadOnly&&(r.depthReadOnly=!0),r.depthClearValue=this.props.clearDepth||0,!0&&(r.depthLoadOp=this.props.clearDepth!==!1?"clear":"load",r.depthStoreOp="store"),!1&&(r.stencilLoadOp=this.props.clearStencil!==!1?"clear":"load",r.stencilStoreOp="store")}return t}};var pe=p(a(),1),V=class extends pe.ComputePass{device;handle;_webgpuPipeline=null;constructor(e,t){super(e,t),this.device=e;let r;if(e.features.has("timestamp-query")){let n=t.timestampQuerySet;n&&(r={querySet:n.handle,beginningOfPassWriteIndex:t.beginTimestampIndex,endOfPassWriteIndex:t.endTimestampIndex})}this.handle=this.props.handle||e.commandEncoder?.beginComputePass({label:this.props.id,timestampWrites:r})}destroy(){}end(){this.handle.end()}setPipeline(e){let t=e;this.handle.setPipeline(t.handle),this._webgpuPipeline=t,this.setBindings([])}setBindings(e){let t=this._webgpuPipeline._getBindGroup();this.handle.setBindGroup(0,t)}dispatch(e,t,r){this.handle.dispatchWorkgroups(e,t,r)}dispatchIndirect(e,t=0){let r=e;this.handle.dispatchWorkgroupsIndirect(r.handle,t)}pushDebugGroup(e){this.handle.pushDebugGroup(e)}popDebugGroup(){this.handle.popDebugGroup()}insertDebugMarker(e){this.handle.insertDebugMarker(e)}};var C=p(a(),1);function B(i){if(typeof window<"u"&&typeof window.process=="object"&&window.process.type==="renderer"||typeof process<"u"&&typeof process.versions=="object"&&Boolean(process.versions.electron))return!0;let e=typeof navigator=="object"&&typeof navigator.userAgent=="string"&&navigator.userAgent,t=i||e;return!!(t&&t.indexOf("Electron")>=0)}function j(){return!(typeof process=="object"&&String(process)==="[object process]"&&!process.browser)||B()}var St=globalThis.self||globalThis.window||globalThis.global,Wt=globalThis.window||globalThis.self||globalThis.global,Bt=globalThis.document||{},Ct=globalThis.process||{},Dt=globalThis.console,ue=globalThis.navigator||{};var H=globalThis;function k(i){if(!i&&!j())return"Node";if(B(i))return"Electron";let e=i||ue.userAgent||"";if(e.indexOf("Edge")>-1)return"Edge";let t=e.indexOf("MSIE ")!==-1,r=e.indexOf("Trident/")!==-1;return t||r?"IE":H.chrome?"Chrome":H.safari?"Safari":H.mozInnerScreenX?"Firefox":"Unknown"}var M=class extends C.VertexArray{get[Symbol.toStringTag](){return"WebGPUVertexArray"}device;handle;constructor(e,t){super(e,t),this.device=e}destroy(){}setIndexBuffer(e){this.indexBuffer=e}setBuffer(e,t){this.attributes[e]=t}bindBeforeRender(e,t,r){let n=e,o=this.indexBuffer;o?.handle&&(C.log.warn("setting index buffer",o?.handle,o?.indexType)(),n.handle.setIndexBuffer(o?.handle,o?.indexType));for(let s=0;s<this.maxVertexAttributes;s++){let u=this.attributes[s];u?.handle&&(C.log.warn(`setting vertex buffer ${s}`,u?.handle)(),n.handle.setVertexBuffer(s,u?.handle))}}unbindAfterRender(e){}static isConstantAttributeZeroSupported(e){return k()==="Chrome"}};var O=p(a(),1);var D=class extends O.CanvasContext{device;gpuCanvasContext;format=navigator.gpu.getPreferredCanvasFormat();depthStencilFormat="depth24plus";depthStencilAttachment=null;constructor(e,t,r){super(r),this.device=e,this.width=-1,this.height=-1,this._setAutoCreatedCanvasId(`${this.device.id}-canvas`),this.gpuCanvasContext=this.canvas.getContext("webgpu"),this.format="bgra8unorm"}destroy(){this.gpuCanvasContext.unconfigure()}getCurrentFramebuffer(){this.update();let e=this.getCurrentTexture();return this.width=e.width,this.height=e.height,this._createDepthStencilAttachment(),new w(this.device,{colorAttachments:[e],depthStencilAttachment:this.depthStencilAttachment})}update(){let[e,t]=this.getPixelSize();(e!==this.width||t!==this.height)&&(this.width=e,this.height=t,this.depthStencilAttachment&&(this.depthStencilAttachment.destroy(),this.depthStencilAttachment=null),this.gpuCanvasContext.configure({device:this.device.handle,format:v(this.format),colorSpace:this.props.colorSpace,alphaMode:this.props.alphaMode}),O.log.log(1,`Resized to ${this.width}x${this.height}px`)())}resize(e){this.update()}getCurrentTexture(){return this.device._createTexture({id:`${this.id}#color-texture`,handle:this.gpuCanvasContext.getCurrentTexture(),format:this.format})}_createDepthStencilAttachment(){return this.depthStencilAttachment||(this.depthStencilAttachment=this.device.createTexture({id:`${this.id}#depth-stencil-texture`,format:this.depthStencilFormat,width:this.width,height:this.height,usage:GPUTextureUsage.RENDER_ATTACHMENT})),this.depthStencilAttachment}};var le=p(a(),1),Q=class extends le.QuerySet{device;handle;constructor(e,t){super(e,t),this.device=e,this.handle=this.props.handle||this.device.handle.createQuerySet({type:this.props.type,count:this.props.count}),this.handle.label=this.props.id}destroy(){this.handle?.destroy(),this.handle=null}};var Y=class extends l.Device{type="webgpu";handle;adapter;adapterInfo;features;info;limits;lost;canvasContext=null;_isLost=!1;commandEncoder=null;renderPass=null;static isSupported(){return Boolean(typeof navigator<"u"&&navigator.gpu)}static async create(e){if(!navigator.gpu)throw new Error("WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu");l.log.groupCollapsed(1,"WebGPUDevice created")();let t=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});if(!t)throw new Error("Failed to request WebGPU adapter");let r=await t.requestAdapterInfo();l.log.probe(2,"Adapter available",r)();let n=[],o={};if(e.requestMaxLimits){n.push(...Array.from(t.features));for(let d in t.limits)o[d]=t.limits[d];delete o.minSubgroupSize,delete o.maxSubgroupSize}let s=await t.requestDevice({requiredFeatures:n,requiredLimits:o});l.log.probe(1,"GPUDevice available")(),typeof e.canvas=="string"&&(await l.CanvasContext.pageLoaded,l.log.probe(1,"DOM is loaded")());let u=new Y(s,t,r,e);return l.log.probe(1,"Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")(),l.log.table(1,u.info)(),l.log.groupEnd(1)(),u}constructor(e,t,r,n){super({...n,id:n.id||(0,l.uid)("webgpu-device")}),this.handle=e,this.adapter=t,this.adapterInfo=r,this.info=this._getInfo(),this.features=this._getFeatures(),this.limits=this.handle.limits,this.lost=new Promise(async o=>{let s=await this.handle.lost;this._isLost=!0,o({reason:"destroyed",message:s.message})}),this.canvasContext=new D(this,this.adapter,{canvas:n.canvas,height:n.height,width:n.width,container:n.container})}destroy(){this.handle.destroy()}isTextureFormatSupported(e){return!e.includes("webgl")}isTextureFormatFilterable(e){return this.isTextureFormatSupported(e)&&!e.startsWith("depth")&&!e.startsWith("stencil")}isTextureFormatRenderable(e){return this.isTextureFormatSupported(e)}get isLost(){return this._isLost}createBuffer(e){let t=this._getBufferProps(e);return new b(this,t)}_createTexture(e){return new x(this,e)}createExternalTexture(e){return new A(this,e)}createShader(e){return new G(this,e)}createSampler(e){return new h(this,e)}createRenderPipeline(e){return new F(this,e)}createFramebuffer(e){return new w(this,e)}createComputePipeline(e){return new I(this,e)}createVertexArray(e){return new M(this,e)}beginRenderPass(e){return this.commandEncoder=this.commandEncoder||this.handle.createCommandEncoder(),new _(this,e)}beginComputePass(e){return this.commandEncoder=this.commandEncoder||this.handle.createCommandEncoder(),new V(this,e)}createTransformFeedback(e){throw new Error("Transform feedback not supported in WebGPU")}createQuerySet(e){return new Q(this,e)}createCanvasContext(e){return new D(this,this.adapter,e)}submit(){let e=this.commandEncoder?.finish();e&&this.handle.queue.submit([e]),this.commandEncoder=null}_getInfo(){let[e,t]=(this.adapterInfo.driver||"").split(" Version "),r=this.adapterInfo.vendor||this.adapter.__brand||"unknown",n=e||"",o=t||"",s=r==="apple"?"apple":"unknown",u=this.adapterInfo.architecture||"unknown",d=this.adapterInfo.backend||"unknown",g=(this.adapterInfo.type||"").split(" ")[0].toLowerCase()||"unknown";return{type:"webgpu",vendor:r,renderer:n,version:o,gpu:s,gpuType:g,gpuBackend:d,gpuArchitecture:u,shadingLanguage:"wgsl",shadingLanguageVersion:100}}_getFeatures(){let e=new Set(this.handle.features);e.has("depth-clamping")&&(e.delete("depth-clamping"),e.add("depth-clip-control")),e.has("texture-compression-bc")&&e.add("texture-compression-bc5-webgl");let t=["timer-query-webgl","compilation-status-async-webgl","float32-renderable-webgl","float16-renderable-webgl","norm16-renderable-webgl","texture-filterable-anisotropic-webgl","shader-noperspective-interpolation-webgl"];for(let r of t)e.add(r);return new l.DeviceFeatures(Array.from(e),this.props.disabledFeatures)}copyExternalImageToTexture(e){let{source:t,sourceX:r=0,sourceY:n=0,texture:o,mipLevel:s=0,aspect:u="all",colorSpace:d="display-p3",premultipliedAlpha:g=!1,width:y=o.width,height:q=o.height,depth:$=1}=e,z=o;this.handle?.queue.copyExternalImageToTexture({source:t,origin:[r,n]},{texture:z.handle,origin:[0,0,0],mipLevel:s,aspect:u,colorSpace:d,premultipliedAlpha:g},[y,q,$])}},T=Y;J(T,"type","webgpu");return xe(Te);})();
8
8
  return __exports__;
9
9
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luma.gl/webgpu",
3
- "version": "9.0.0-beta.5",
3
+ "version": "9.0.0-beta.7",
4
4
  "description": "WebGPU adapter for the luma.gl core API",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,5 +43,5 @@
43
43
  "@probe.gl/env": "^4.0.2",
44
44
  "@webgpu/types": "^0.1.34"
45
45
  },
46
- "gitHead": "793d3ab42f5a572b6cb603ea78aabaa73a873301"
46
+ "gitHead": "e9606a88e0aab3dc27c87020cac89040ea1a8a02"
47
47
  }
@@ -1,3 +1,7 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
1
5
  /*
2
6
  import {assert} from '@luma.gl/core';
3
7
 
@@ -97,4 +101,4 @@ export function mapAccessorToWebGPUFormat(accessor) {
97
101
  }
98
102
  throw new Error('illegal accessor');
99
103
  }
100
- */
104
+ */
@@ -1,4 +1,7 @@
1
- // luma.gl, MIT license
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
2
5
  import {TextureFormat} from '@luma.gl/core';
3
6
 
4
7
  /** Ensure a texture format is WebGPU compatible */
@@ -1,5 +1,8 @@
1
- // luma.gl, MIT license
2
- import type {ShaderLayout, BindingDeclaration, Binding} from '@luma.gl/core';
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import type {ComputeShaderLayout, BindingDeclaration, Binding} from '@luma.gl/core';
3
6
  import {Buffer, Sampler, Texture, log, cast} from '@luma.gl/core';
4
7
  import type {WebGPUBuffer} from '../resources/webgpu-buffer';
5
8
  import type {WebGPUSampler} from '../resources/webgpu-sampler';
@@ -27,7 +30,7 @@ export function makeBindGroupLayout(
27
30
  export function getBindGroup(
28
31
  device: GPUDevice,
29
32
  bindGroupLayout: GPUBindGroupLayout,
30
- shaderLayout: ShaderLayout,
33
+ shaderLayout: ComputeShaderLayout,
31
34
  bindings: Record<string, Binding>
32
35
  ): GPUBindGroup {
33
36
  const entries = getBindGroupEntries(bindings, shaderLayout);
@@ -38,10 +41,13 @@ export function getBindGroup(
38
41
  }
39
42
 
40
43
  export function getShaderLayoutBinding(
41
- shaderLayout: ShaderLayout,
44
+ shaderLayout: ComputeShaderLayout,
42
45
  bindingName: string
43
46
  ): BindingDeclaration {
44
- const bindingLayout = shaderLayout.bindings.find(binding => binding.name === bindingName || `${binding.name}uniforms` === bindingName.toLocaleLowerCase());
47
+ const bindingLayout = shaderLayout.bindings.find(
48
+ binding =>
49
+ binding.name === bindingName || `${binding.name}uniforms` === bindingName.toLocaleLowerCase()
50
+ );
45
51
  if (!bindingLayout) {
46
52
  log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
47
53
  }
@@ -54,7 +60,7 @@ export function getShaderLayoutBinding(
54
60
  */
55
61
  function getBindGroupEntries(
56
62
  bindings: Record<string, Binding>,
57
- shaderLayout: ShaderLayout
63
+ shaderLayout: ComputeShaderLayout
58
64
  ): GPUBindGroupEntry[] {
59
65
  const entries: GPUBindGroupEntry[] = [];
60
66
 
@@ -1,4 +1,7 @@
1
- // luma.gl, MIT license
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
2
5
  import type {ShaderLayout, BufferLayout, AttributeDeclaration, VertexFormat} from '@luma.gl/core';
3
6
  import {log, decodeVertexFormat} from '@luma.gl/core';
4
7
  // import {getAttributeInfosFromLayouts} from '@luma.gl/core';
@@ -40,7 +43,9 @@ export function getVertexBufferLayout(
40
43
  const attributeName = attributeMapping.attribute;
41
44
  const attributeLayout = findAttributeLayout(shaderLayout, attributeName, usedAttributes);
42
45
 
43
- stepMode = attributeLayout.stepMode || (attributeLayout.name.startsWith('instance') ? 'instance' : 'vertex');
46
+ stepMode =
47
+ attributeLayout.stepMode ||
48
+ (attributeLayout.name.startsWith('instance') ? 'instance' : 'vertex');
44
49
  vertexAttributes.push({
45
50
  format: getWebGPUVertexFormat(attributeMapping.format || mapping.format),
46
51
  offset: attributeMapping.byteOffset,
@@ -57,7 +62,9 @@ export function getVertexBufferLayout(
57
62
  }
58
63
  byteStride = decodeVertexFormat(mapping.format).byteLength;
59
64
 
60
- stepMode = attributeLayout.stepMode || (attributeLayout.name.startsWith('instance') ? 'instance' : 'vertex');
65
+ stepMode =
66
+ attributeLayout.stepMode ||
67
+ (attributeLayout.name.startsWith('instance') ? 'instance' : 'vertex');
61
68
  vertexAttributes.push({
62
69
  format: getWebGPUVertexFormat(mapping.format),
63
70
  // We only support 0 offset for non-interleaved buffer layouts
@@ -79,7 +86,8 @@ export function getVertexBufferLayout(
79
86
  if (!usedAttributes.has(attribute.name)) {
80
87
  vertexBufferLayouts.push({
81
88
  arrayStride: decodeVertexFormat('float32x3').byteLength,
82
- stepMode: attribute.stepMode || (attribute.name.startsWith('instance') ? 'instance' : 'vertex'),
89
+ stepMode:
90
+ attribute.stepMode || (attribute.name.startsWith('instance') ? 'instance' : 'vertex'),
83
91
  attributes: [
84
92
  {
85
93
  format: getWebGPUVertexFormat('float32x3'),
@@ -1,3 +1,7 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
1
5
  import {Parameters} from '@luma.gl/core';
2
6
 
3
7
  function addDepthStencil(descriptor: GPURenderPipelineDescriptor): GPUDepthStencilState {
@@ -33,17 +37,29 @@ export const PARAMETER_TABLE: Record<keyof Parameters, Function> = {
33
37
 
34
38
  // DEPTH
35
39
 
36
- depthWriteEnabled: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
40
+ depthWriteEnabled: (
41
+ parameter: keyof Parameters,
42
+ value: any,
43
+ descriptor: GPURenderPipelineDescriptor
44
+ ) => {
37
45
  const depthStencil = addDepthStencil(descriptor);
38
46
  depthStencil.depthWriteEnabled = value;
39
47
  },
40
48
 
41
- depthCompare: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
49
+ depthCompare: (
50
+ parameter: keyof Parameters,
51
+ value: any,
52
+ descriptor: GPURenderPipelineDescriptor
53
+ ) => {
42
54
  const depthStencil = addDepthStencil(descriptor);
43
55
  depthStencil.depthCompare = value;
44
56
  },
45
57
 
46
- depthFormat: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
58
+ depthFormat: (
59
+ parameter: keyof Parameters,
60
+ value: any,
61
+ descriptor: GPURenderPipelineDescriptor
62
+ ) => {
47
63
  const depthStencil = addDepthStencil(descriptor);
48
64
  depthStencil.format = value;
49
65
  },
@@ -53,47 +69,79 @@ export const PARAMETER_TABLE: Record<keyof Parameters, Function> = {
53
69
  depthStencil.depthBias = value;
54
70
  },
55
71
 
56
- depthBiasSlopeScale: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
72
+ depthBiasSlopeScale: (
73
+ parameter: keyof Parameters,
74
+ value: any,
75
+ descriptor: GPURenderPipelineDescriptor
76
+ ) => {
57
77
  const depthStencil = addDepthStencil(descriptor);
58
78
  depthStencil.depthBiasSlopeScale = value;
59
79
  },
60
80
 
61
- depthBiasClamp: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
81
+ depthBiasClamp: (
82
+ parameter: keyof Parameters,
83
+ value: any,
84
+ descriptor: GPURenderPipelineDescriptor
85
+ ) => {
62
86
  const depthStencil = addDepthStencil(descriptor);
63
87
  depthStencil.depthBiasClamp = value;
64
88
  },
65
89
 
66
90
  // STENCIL
67
91
 
68
- stencilReadMask: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
92
+ stencilReadMask: (
93
+ parameter: keyof Parameters,
94
+ value: any,
95
+ descriptor: GPURenderPipelineDescriptor
96
+ ) => {
69
97
  const depthStencil = addDepthStencil(descriptor);
70
98
  depthStencil.stencilReadMask = value;
71
99
  },
72
100
 
73
- stencilWriteMask: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
101
+ stencilWriteMask: (
102
+ parameter: keyof Parameters,
103
+ value: any,
104
+ descriptor: GPURenderPipelineDescriptor
105
+ ) => {
74
106
  const depthStencil = addDepthStencil(descriptor);
75
107
  depthStencil.stencilWriteMask = value;
76
108
  },
77
109
 
78
- stencilCompare: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
110
+ stencilCompare: (
111
+ parameter: keyof Parameters,
112
+ value: any,
113
+ descriptor: GPURenderPipelineDescriptor
114
+ ) => {
79
115
  const depthStencil = addDepthStencil(descriptor);
80
116
  depthStencil.stencilFront.compare = value;
81
117
  depthStencil.stencilBack.compare = value;
82
118
  },
83
119
 
84
- stencilPassOperation: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
120
+ stencilPassOperation: (
121
+ parameter: keyof Parameters,
122
+ value: any,
123
+ descriptor: GPURenderPipelineDescriptor
124
+ ) => {
85
125
  const depthStencil = addDepthStencil(descriptor);
86
126
  depthStencil.stencilFront.passOp = value;
87
127
  depthStencil.stencilBack.passOp = value;
88
128
  },
89
129
 
90
- stencilFailOperation: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
130
+ stencilFailOperation: (
131
+ parameter: keyof Parameters,
132
+ value: any,
133
+ descriptor: GPURenderPipelineDescriptor
134
+ ) => {
91
135
  const depthStencil = addDepthStencil(descriptor);
92
136
  depthStencil.stencilFront.failOp = value;
93
137
  depthStencil.stencilBack.failOp = value;
94
138
  },
95
139
 
96
- stencilDepthFailOperation: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
140
+ stencilDepthFailOperation: (
141
+ parameter: keyof Parameters,
142
+ value: any,
143
+ descriptor: GPURenderPipelineDescriptor
144
+ ) => {
97
145
  const depthStencil = addDepthStencil(descriptor);
98
146
  depthStencil.stencilFront.depthFailOp = value;
99
147
  depthStencil.stencilBack.depthFailOp = value;
@@ -101,17 +149,29 @@ export const PARAMETER_TABLE: Record<keyof Parameters, Function> = {
101
149
 
102
150
  // MULTISAMPLE
103
151
 
104
- sampleCount: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
152
+ sampleCount: (
153
+ parameter: keyof Parameters,
154
+ value: any,
155
+ descriptor: GPURenderPipelineDescriptor
156
+ ) => {
105
157
  descriptor.multisample = descriptor.multisample || {};
106
158
  descriptor.multisample.count = value;
107
159
  },
108
160
 
109
- sampleMask: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
161
+ sampleMask: (
162
+ parameter: keyof Parameters,
163
+ value: any,
164
+ descriptor: GPURenderPipelineDescriptor
165
+ ) => {
110
166
  descriptor.multisample = descriptor.multisample || {};
111
167
  descriptor.multisample.mask = value;
112
168
  },
113
169
 
114
- sampleAlphaToCoverageEnabled: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
170
+ sampleAlphaToCoverageEnabled: (
171
+ parameter: keyof Parameters,
172
+ value: any,
173
+ descriptor: GPURenderPipelineDescriptor
174
+ ) => {
115
175
  descriptor.multisample = descriptor.multisample || {};
116
176
  descriptor.multisample.alphaToCoverageEnabled = value;
117
177
  },
@@ -123,7 +183,11 @@ export const PARAMETER_TABLE: Record<keyof Parameters, Function> = {
123
183
  targets[0].writeMask = value;
124
184
  },
125
185
 
126
- blendColorOperation: (parameter: keyof Parameters, value: any, descriptor: GPURenderPipelineDescriptor) => {
186
+ blendColorOperation: (
187
+ parameter: keyof Parameters,
188
+ value: any,
189
+ descriptor: GPURenderPipelineDescriptor
190
+ ) => {
127
191
  addColorState(descriptor);
128
192
  // const targets = addColorState(descriptor);
129
193
  // const target = targets[0];
@@ -1,4 +1,7 @@
1
- // WEBGPU Buffer implementation
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
2
5
  import {Buffer, BufferProps} from '@luma.gl/core';
3
6
  import type {WebGPUDevice} from '../webgpu-device';
4
7
 
@@ -21,13 +24,15 @@ export class WebGPUBuffer extends Buffer {
21
24
  // WebGPU buffers must be aligned to 4 bytes
22
25
  const size = Math.ceil(this.byteLength / 4) * 4;
23
26
 
24
- this.handle = this.props.handle || this.device.handle.createBuffer({
25
- size,
26
- // usage defaults to vertex
27
- usage: this.props.usage || (GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST),
28
- mappedAtCreation: this.props.mappedAtCreation || mapBuffer,
29
- label: this.props.id
30
- });
27
+ this.handle =
28
+ this.props.handle ||
29
+ this.device.handle.createBuffer({
30
+ size,
31
+ // usage defaults to vertex
32
+ usage: this.props.usage || GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
33
+ mappedAtCreation: this.props.mappedAtCreation || mapBuffer,
34
+ label: this.props.id
35
+ });
31
36
 
32
37
  if (props.data) {
33
38
  this._writeMapped(props.data);
@@ -40,7 +45,9 @@ export class WebGPUBuffer extends Buffer {
40
45
  }
41
46
 
42
47
  override destroy(): void {
43
- this.handle.destroy();
48
+ this.handle?.destroy();
49
+ // @ts-expect-error readonly
50
+ this.handle = null;
44
51
  }
45
52
 
46
53
  // WebGPU provides multiple ways to write a buffer...
@@ -54,9 +61,15 @@ export class WebGPUBuffer extends Buffer {
54
61
  );
55
62
  }
56
63
 
57
- override async readAsync(byteOffset: number = 0, byteLength: number = this.byteLength): Promise<Uint8Array> {
64
+ override async readAsync(
65
+ byteOffset: number = 0,
66
+ byteLength: number = this.byteLength
67
+ ): Promise<Uint8Array> {
58
68
  // We need MAP_READ flag, but only COPY_DST buffers can have MAP_READ flag, so we need to create a temp buffer
59
- const tempBuffer = new WebGPUBuffer(this.device, {usage: Buffer.MAP_READ | Buffer.COPY_DST, byteLength});
69
+ const tempBuffer = new WebGPUBuffer(this.device, {
70
+ usage: Buffer.MAP_READ | Buffer.COPY_DST,
71
+ byteLength
72
+ });
60
73
 
61
74
  // Now do a GPU-side copy into the temp buffer we can actually read.
62
75
  // TODO - we are spinning up an independent command queue here, what does this mean
@@ -1,8 +1,13 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
1
5
  import {CommandEncoder, CommandEncoderProps, Buffer, Texture} from '@luma.gl/core';
2
6
  import type {CopyTextureToTextureOptions, CopyTextureToBufferOptions} from '@luma.gl/core';
3
7
  import {WebGPUDevice} from '../webgpu-device';
4
8
  import {WebGPUBuffer} from './webgpu-buffer';
5
9
  import {WebGPUTexture} from './webgpu-texture';
10
+ import {WebGPUQuerySet} from './webgpu-query-set';
6
11
 
7
12
  export class WebGPUCommandEncoder extends CommandEncoder {
8
13
  readonly device: WebGPUDevice;
@@ -120,13 +125,23 @@ export class WebGPUCommandEncoder extends CommandEncoder {
120
125
  this.handle.insertDebugMarker(markerLabel);
121
126
  }
122
127
 
123
- // writeTimestamp(querySet: Query, queryIndex: number): void {}
124
-
125
- // resolveQuerySet(options: {
126
- // querySet: GPUQuerySet,
127
- // firstQuery: number,
128
- // queryCount: number,
129
- // destination: Buffer,
130
- // destinationOffset?: number;
131
- // }): void;
128
+ override resolveQuerySet(
129
+ querySet: WebGPUQuerySet,
130
+ destination: Buffer,
131
+ options?: {
132
+ firstQuery?: number;
133
+ queryCount?: number;
134
+ destinationOffset?: number;
135
+ }
136
+ ): void {
137
+ const webgpuQuerySet = querySet;
138
+ const webgpuBuffer = destination as WebGPUBuffer;
139
+ this.handle.resolveQuerySet(
140
+ webgpuQuerySet.handle,
141
+ options.firstQuery || 0,
142
+ options.queryCount || querySet.props.count - (options.firstQuery || 0),
143
+ webgpuBuffer.handle,
144
+ options.destinationOffset || 0
145
+ );
146
+ }
132
147
  }
@@ -1,22 +1,42 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
1
5
  import {ComputePass, ComputePassProps, ComputePipeline, Buffer, Binding} from '@luma.gl/core';
2
6
  import {WebGPUDevice} from '../webgpu-device';
3
7
  import {WebGPUBuffer} from './webgpu-buffer';
4
- // import {WebGPUCommandEncoder} from './webgpu-command-encoder';
5
8
  import {WebGPUComputePipeline} from './webgpu-compute-pipeline';
9
+ import {WebGPUQuerySet} from './webgpu-query-set';
6
10
 
7
11
  export class WebGPUComputePass extends ComputePass {
8
12
  readonly device: WebGPUDevice;
9
13
  readonly handle: GPUComputePassEncoder;
10
- _bindGroupLayout: GPUBindGroupLayout | null = null;
14
+
15
+ _webgpuPipeline: WebGPUComputePipeline | null = null;
11
16
 
12
17
  constructor(device: WebGPUDevice, props: ComputePassProps) {
13
18
  super(device, props);
14
19
  this.device = device;
15
20
 
16
- this.handle = this.props.handle || device.commandEncoder?.beginComputePass({
17
- label: this.props.id,
18
- // timestampWrites?: GPUComputePassTimestampWrites;
19
- });
21
+ // Set up queries
22
+ let timestampWrites: GPUComputePassTimestampWrites | undefined;
23
+ if (device.features.has('timestamp-query')) {
24
+ const webgpuQuerySet = props.timestampQuerySet as WebGPUQuerySet;
25
+ if (webgpuQuerySet) {
26
+ timestampWrites = {
27
+ querySet: webgpuQuerySet.handle,
28
+ beginningOfPassWriteIndex: props.beginTimestampIndex,
29
+ endOfPassWriteIndex: props.endTimestampIndex
30
+ };
31
+ }
32
+ }
33
+
34
+ this.handle =
35
+ this.props.handle ||
36
+ device.commandEncoder?.beginComputePass({
37
+ label: this.props.id,
38
+ timestampWrites
39
+ });
20
40
  }
21
41
 
22
42
  /** @note no WebGPU destroy method, just gc */
@@ -29,21 +49,24 @@ export class WebGPUComputePass extends ComputePass {
29
49
  setPipeline(pipeline: ComputePipeline): void {
30
50
  const wgpuPipeline = pipeline as WebGPUComputePipeline;
31
51
  this.handle.setPipeline(wgpuPipeline.handle);
32
- this._bindGroupLayout = wgpuPipeline._getBindGroupLayout();
52
+ this._webgpuPipeline = wgpuPipeline;
53
+ this.setBindings([]);
33
54
  }
34
55
 
35
- /** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
56
+ /**
57
+ * Sets an array of bindings (uniform buffers, samplers, textures, ...)
58
+ * TODO - still some API confusion - does this method go here or on the pipeline?
59
+ */
36
60
  setBindings(bindings: Binding[]): void {
37
- throw new Error('fix me');
38
- // const bindGroup = getBindGroup(this.device.handle, this._bindGroupLayout, this.props.bindings);
39
- // this.handle.setBindGroup(0, bindGroup);
61
+ const bindGroup = this._webgpuPipeline._getBindGroup();
62
+ this.handle.setBindGroup(0, bindGroup);
40
63
  }
41
64
 
42
65
  /**
43
66
  * Dispatch work to be performed with the current ComputePipeline.
44
- * @param x X dimension of the grid of workgroups to dispatch.
45
- * @param y Y dimension of the grid of workgroups to dispatch.
46
- * @param z Z dimension of the grid of workgroups to dispatch.
67
+ * @param x X dimension of the grid of work groups to dispatch.
68
+ * @param y Y dimension of the grid of work groups to dispatch.
69
+ * @param z Z dimension of the grid of work groups to dispatch.
47
70
  */
48
71
  dispatch(x: number, y?: number, z?: number): void {
49
72
  this.handle.dispatchWorkgroups(x, y, z);
@@ -51,25 +74,25 @@ export class WebGPUComputePass extends ComputePass {
51
74
 
52
75
  /**
53
76
  * Dispatch work to be performed with the current ComputePipeline.
54
- * @param indirectBuffer buffer must be a tightly packed block of three 32-bit unsigned integer values (12 bytes total), given in the same order as the arguments for dispatch()
55
- * @param indirectOffset
77
+ *
78
+ * Buffer must be a tightly packed block of three 32-bit unsigned integer values (12 bytes total), given in the same order as the arguments for dispatch()
79
+ * @param indirectBuffer
80
+ * @param indirectOffset offset in buffer to the beginning of the dispatch data.
56
81
  */
57
- dispatchIndirect(indirectBuffer: Buffer, indirectOffset: number = 0): void {
82
+ dispatchIndirect(indirectBuffer: Buffer, indirectByteOffset: number = 0): void {
58
83
  const webgpuBuffer = indirectBuffer as WebGPUBuffer;
59
- this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectOffset);
84
+ this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectByteOffset);
60
85
  }
61
86
 
62
87
  pushDebugGroup(groupLabel: string): void {
63
88
  this.handle.pushDebugGroup(groupLabel);
64
89
  }
90
+
65
91
  popDebugGroup(): void {
66
92
  this.handle.popDebugGroup();
67
93
  }
94
+
68
95
  insertDebugMarker(markerLabel: string): void {
69
96
  this.handle.insertDebugMarker(markerLabel);
70
97
  }
71
-
72
- // writeTimestamp(querySet: GPUQuerySet, queryIndex: number): void;
73
- // beginPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
74
- // endPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
75
98
  }