@luma.gl/webgpu 9.0.0-beta.6 → 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.
- package/dist/adapter/helpers/get-bind-group.d.ts +3 -3
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +3 -1
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +14 -8
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +18 -13
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +13 -3
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js +25 -7
- package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.js +2 -0
- package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-query-set.js +3 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +49 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +69 -51
- package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +3 -0
- package/dist/adapter/resources/webgpu-shader.d.ts +1 -4
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +7 -18
- package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.js +3 -0
- package/dist/adapter/resources/webgpu-texture.d.ts +3 -4
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +8 -8
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +2 -1
- package/dist/adapter/webgpu-device.d.ts +2 -7
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +9 -19
- package/dist/dist.dev.js +132 -175
- package/dist/index.cjs +122 -131
- package/dist/index.cjs.map +4 -4
- package/dist.min.js +1 -1
- package/package.json +2 -2
- package/src/adapter/helpers/get-bind-group.ts +4 -4
- package/src/adapter/resources/webgpu-buffer.ts +3 -1
- package/src/adapter/resources/webgpu-compute-pass.ts +19 -14
- package/src/adapter/resources/webgpu-compute-pipeline.ts +36 -9
- package/src/adapter/resources/webgpu-external-texture.ts +2 -0
- package/src/adapter/resources/webgpu-query-set.ts +3 -1
- package/src/adapter/resources/webgpu-render-pipeline.ts +63 -92
- package/src/adapter/resources/webgpu-sampler.ts +3 -0
- package/src/adapter/resources/webgpu-shader.ts +8 -23
- package/src/adapter/resources/webgpu-texture-view.ts +3 -0
- package/src/adapter/resources/webgpu-texture.ts +11 -10
- package/src/adapter/webgpu-canvas-context.ts +2 -1
- package/src/adapter/webgpu-device.ts +11 -20
- package/dist/adapter/helpers/generate-mipmaps.d.ts +0 -10
- package/dist/adapter/helpers/generate-mipmaps.d.ts.map +0 -1
- package/dist/adapter/helpers/generate-mipmaps.js +0 -103
- package/dist/adapter/resources/webgpu-query.d.ts +0 -1
- package/dist/adapter/resources/webgpu-query.d.ts.map +0 -1
- package/dist/adapter/resources/webgpu-query.js +0 -43
- package/dist/adapter/webgpu-types.d.ts +0 -1
- package/dist/adapter/webgpu-types.d.ts.map +0 -1
- package/dist/adapter/webgpu-types.js +0 -0
- package/dist/glsl/glsllang.d.ts +0 -3
- package/dist/glsl/glsllang.d.ts.map +0 -1
- package/dist/glsl/glsllang.js +0 -12
- package/src/adapter/helpers/generate-mipmaps.ts +0 -118
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 he=Object.create;var w=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?w(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)w(i,t,{get:e[t],enumerable:!0})},Y=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of fe(e))!be.call(i,n)&&n!==t&&w(i,n,{get:()=>e[n],enumerable:!(r=me(e,n))||r.enumerable});return i};var p=(i,e,t)=>(t=i!=null?he(Pe(i)):{},Y(e||!i||!i.__esModule?w(t,"default",{value:i,enumerable:!0}):t,i)),xe=i=>Y(w({},"__esModule",{value:!0}),i);var X=(i,e,t)=>(ge(i,typeof e!="symbol"?e+"":e,t),t);var s=ye((Ae,J)=>{J.exports=globalThis.luma});var Te={};ve(Te,{WebGPUBuffer:()=>b,WebGPUDevice:()=>B,WebGPUSampler:()=>c,WebGPUShader:()=>G,WebGPUTexture:()=>x});var l=p(s(),1);var D=p(s(),1);function Ge(i){return i.byteLength||i.data?.byteLength||0}var b=class extends D.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()}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:D.Buffer.MAP_READ|D.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 ee=p(s(),1);function v(i){if(i.includes("webgl"))throw new Error("webgl-only format");return i}var Z=p(s(),1),c=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 K=p(s(),1),T=class extends K.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(){}};var Ue={"1d":"1d","2d":"2d","2d-array":"2d",cube:"2d","cube-array":"2d","3d":"3d"},x=class extends ee.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)}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 c?e.sampler:new c(this.device,e.sampler),this.view=new T(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})}destroy(){this.handle.destroy()}setSampler(e){return this.sampler=e instanceof c?e:new c(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:a=0,sourceY:u=0,mipLevel:d=0,x:g=0,y=0,z:Q=0,aspect:q="all",colorSpace:$="srgb",premultipliedAlpha:ce=!1}=e;return this.device.handle.queue.copyExternalImageToTexture({source:t,origin:[a,u]},{texture:this.handle,origin:[g,y,Q],mipLevel:d,aspect:q,colorSpace:$,premultipliedAlpha:ce},[r,n,o]),{width:r,height:n}}createView(){return this.handle.createView({label:this.id})}};var te=p(s(),1);var R=class extends te.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 c?e:new c(this.device,e),this}};var A=p(s(),1),G=class extends A.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 A.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 f=p(s(),1);function h(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=h(t);r.depthWriteEnabled=e},depthCompare:(i,e,t)=>{let r=h(t);r.depthCompare=e},depthFormat:(i,e,t)=>{let r=h(t);r.format=e},depthBias:(i,e,t)=>{let r=h(t);r.depthBias=e},depthBiasSlopeScale:(i,e,t)=>{let r=h(t);r.depthBiasSlopeScale=e},depthBiasClamp:(i,e,t)=>{let r=h(t);r.depthBiasClamp=e},stencilReadMask:(i,e,t)=>{let r=h(t);r.stencilReadMask=e},stencilWriteMask:(i,e,t)=>{let r=h(t);r.stencilWriteMask=e},stencilCompare:(i,e,t)=>{let r=h(t);r.stencilFront.compare=e,r.stencilBack.compare=e},stencilPassOperation:(i,e,t)=>{let r=h(t);r.stencilFront.passOp=e,r.stencilBack.passOp=e},stencilFailOperation:(i,e,t)=>{let r=h(t);r.stencilFront.failOp=e,r.stencilBack.failOp=e},stencilDepthFailOperation:(i,e,t)=>{let r=h(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=re(t);r[0].writeMask=e},blendColorOperation:(i,e,t)=>{re(t)}},Se={primitive:{cullMode:"back",topology:"triangle-list"},vertex:{module:void 0,entryPoint:"main"},fragment:{module:void 0,entryPoint:"main",targets:[]},layout:"auto"};function ie(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 re(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(s(),1);function ne(i,e,t,r){let n=Be(r,t);return i.createBindGroup({layout:e,entries:n})}function Ce(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 Be(i,e){let t=[];for(let[r,n]of Object.entries(i)){let o=Ce(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(s(),1);function z(i){if(i.endsWith("-webgl"))throw new Error(`WebGPU does not support vertex format ${i}`);return i}function ae(i,e){let t=[],r=new Set;for(let n of e){let o=[],a="vertex",u=0;if(n.attributes)for(let d of n.attributes){let g=d.attribute,y=oe(i,g,r);a=y.stepMode||(y.name.startsWith("instance")?"instance":"vertex"),o.push({format:z(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,a=d.stepMode||(d.name.startsWith("instance")?"instance":"vertex"),o.push({format:z(n.format),offset:0,shaderLocation:d.location})}t.push({arrayStride:n.byteStride||u,stepMode:a,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:z("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 E=class extends f.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();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)}destroy(){}setBindings(e){Object.assign(this.props.bindings,e)}draw(e){let t=(0,f.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||ne(this.device.handle,this._bindGroupLayout,this.props.shaderLayout,this.props.bindings),this._bindGroup}_getRenderPipelineDescriptor(){let e={module:(0,f.cast)(this.props.vs).handle,entryPoint:this.props.vsEntryPoint||"main",buffers:ae(this.props.shaderLayout,this.props.bufferLayout)},t;switch(this.props.fs&&(t={module:(0,f.cast)(this.props.fs).handle,entryPoint:this.props.fsEntryPoint||"main",targets:[{format:v(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 ie(r,this.props.parameters),r}};var se=p(s(),1),L=class extends se.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=p(s(),1),F=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 a=t.timestampQuerySet;n.timestampWrites=a?{querySet:a.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 de=p(s(),1),I=class extends de.ComputePass{device;handle;_bindGroupLayout=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._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=p(s(),1);function S(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 N(){return!(typeof process=="object"&&String(process)==="[object process]"&&!process.browser)||S()}var xt=globalThis.self||globalThis.window||globalThis.global,Gt=globalThis.window||globalThis.self||globalThis.global,Ut=globalThis.document||{},wt=globalThis.process||{},St=globalThis.console,pe=globalThis.navigator||{};var j=globalThis;function V(i){if(!i&&!N())return"Node";if(S(i))return"Electron";let e=i||pe.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 k=class extends W.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&&(W.log.warn("setting index buffer",o?.handle,o?.indexType)(),n.handle.setIndexBuffer(o?.handle,o?.indexType));for(let a=0;a<this.maxVertexAttributes;a++){let u=this.attributes[a];u?.handle&&(W.log.warn(`setting vertex buffer ${a}`,u?.handle)(),n.handle.setVertexBuffer(a,u?.handle))}}unbindAfterRender(e){}static isConstantAttributeZeroSupported(e){return V()==="Chrome"}};var _=p(s(),1);var ue=p(s(),1),M=class extends ue.Framebuffer{device;constructor(e,t){super(e,t),this.device=e,this.autoCreateAttachmentTextures()}};var C=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 M(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}),_.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 le=p(s(),1),O=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()}};var H=class extends l.Device{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.requestMaximalLimits){n.push(...Array.from(t.features));for(let d in t.limits)o[d]=t.limits[d];delete o.minSubgroupSize,delete o.maxSubgroupSize}let a=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 H(a,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 a=await this.handle.lost;this._isLost=!0,o({reason:"destroyed",message:a.message})}),this.canvasContext=new C(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)}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 R(this,e)}createShader(e){return new G(this,e)}createSampler(e){return new c(this,e)}createRenderPipeline(e){return new E(this,e)}createFramebuffer(e){throw new Error("Not implemented")}createComputePipeline(e){return new L(this,e)}createVertexArray(e){return new k(this,e)}beginRenderPass(e){return this.commandEncoder=this.commandEncoder||this.handle.createCommandEncoder(),new F(this,e)}beginComputePass(e){return this.commandEncoder=this.commandEncoder||this.handle.createCommandEncoder(),new I(this,e)}createTransformFeedback(e){throw new Error("Transform feedback not supported in WebGPU")}createQuerySet(e){return new O(this,e)}createCanvasContext(e){return new C(this,this.adapter,e)}getDefaultRenderPass(){throw new Error("a")}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||"",a=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:a,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))}copyExternalImageToTexture(e){let{source:t,sourceX:r=0,sourceY:n=0,texture:o,mipLevel:a=0,aspect:u="all",colorSpace:d="display-p3",premultipliedAlpha:g=!1,width:y=o.width,height:Q=o.height,depth:q=1}=e,$=o;this.handle?.queue.copyExternalImageToTexture({source:t,origin:[r,n]},{texture:$.handle,origin:[0,0,0],mipLevel:a,aspect:u,colorSpace:d,premultipliedAlpha:g},[y,Q,q])}},B=H;X(B,"type","webgpu");return xe(Te);})();
|
|
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.
|
|
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": "
|
|
46
|
+
"gitHead": "e9606a88e0aab3dc27c87020cac89040ea1a8a02"
|
|
47
47
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type {ComputeShaderLayout, BindingDeclaration, Binding} from '@luma.gl/core';
|
|
6
6
|
import {Buffer, Sampler, Texture, log, cast} from '@luma.gl/core';
|
|
7
7
|
import type {WebGPUBuffer} from '../resources/webgpu-buffer';
|
|
8
8
|
import type {WebGPUSampler} from '../resources/webgpu-sampler';
|
|
@@ -30,7 +30,7 @@ export function makeBindGroupLayout(
|
|
|
30
30
|
export function getBindGroup(
|
|
31
31
|
device: GPUDevice,
|
|
32
32
|
bindGroupLayout: GPUBindGroupLayout,
|
|
33
|
-
shaderLayout:
|
|
33
|
+
shaderLayout: ComputeShaderLayout,
|
|
34
34
|
bindings: Record<string, Binding>
|
|
35
35
|
): GPUBindGroup {
|
|
36
36
|
const entries = getBindGroupEntries(bindings, shaderLayout);
|
|
@@ -41,7 +41,7 @@ export function getBindGroup(
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export function getShaderLayoutBinding(
|
|
44
|
-
shaderLayout:
|
|
44
|
+
shaderLayout: ComputeShaderLayout,
|
|
45
45
|
bindingName: string
|
|
46
46
|
): BindingDeclaration {
|
|
47
47
|
const bindingLayout = shaderLayout.bindings.find(
|
|
@@ -60,7 +60,7 @@ export function getShaderLayoutBinding(
|
|
|
60
60
|
*/
|
|
61
61
|
function getBindGroupEntries(
|
|
62
62
|
bindings: Record<string, Binding>,
|
|
63
|
-
shaderLayout:
|
|
63
|
+
shaderLayout: ComputeShaderLayout
|
|
64
64
|
): GPUBindGroupEntry[] {
|
|
65
65
|
const entries: GPUBindGroupEntry[] = [];
|
|
66
66
|
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
import {ComputePass, ComputePassProps, ComputePipeline, Buffer, Binding} from '@luma.gl/core';
|
|
6
6
|
import {WebGPUDevice} from '../webgpu-device';
|
|
7
7
|
import {WebGPUBuffer} from './webgpu-buffer';
|
|
8
|
-
// import {WebGPUCommandEncoder} from './webgpu-command-encoder';
|
|
9
8
|
import {WebGPUComputePipeline} from './webgpu-compute-pipeline';
|
|
10
9
|
import {WebGPUQuerySet} from './webgpu-query-set';
|
|
11
10
|
|
|
12
11
|
export class WebGPUComputePass extends ComputePass {
|
|
13
12
|
readonly device: WebGPUDevice;
|
|
14
13
|
readonly handle: GPUComputePassEncoder;
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
_webgpuPipeline: WebGPUComputePipeline | null = null;
|
|
16
16
|
|
|
17
17
|
constructor(device: WebGPUDevice, props: ComputePassProps) {
|
|
18
18
|
super(device, props);
|
|
@@ -49,21 +49,24 @@ export class WebGPUComputePass extends ComputePass {
|
|
|
49
49
|
setPipeline(pipeline: ComputePipeline): void {
|
|
50
50
|
const wgpuPipeline = pipeline as WebGPUComputePipeline;
|
|
51
51
|
this.handle.setPipeline(wgpuPipeline.handle);
|
|
52
|
-
this.
|
|
52
|
+
this._webgpuPipeline = wgpuPipeline;
|
|
53
|
+
this.setBindings([]);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
/**
|
|
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
|
+
*/
|
|
56
60
|
setBindings(bindings: Binding[]): void {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// this.handle.setBindGroup(0, bindGroup);
|
|
61
|
+
const bindGroup = this._webgpuPipeline._getBindGroup();
|
|
62
|
+
this.handle.setBindGroup(0, bindGroup);
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
/**
|
|
63
66
|
* Dispatch work to be performed with the current ComputePipeline.
|
|
64
|
-
* @param x X dimension of the grid of
|
|
65
|
-
* @param y Y dimension of the grid of
|
|
66
|
-
* @param z Z dimension of the grid of
|
|
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.
|
|
67
70
|
*/
|
|
68
71
|
dispatch(x: number, y?: number, z?: number): void {
|
|
69
72
|
this.handle.dispatchWorkgroups(x, y, z);
|
|
@@ -71,12 +74,14 @@ export class WebGPUComputePass extends ComputePass {
|
|
|
71
74
|
|
|
72
75
|
/**
|
|
73
76
|
* Dispatch work to be performed with the current ComputePipeline.
|
|
74
|
-
*
|
|
75
|
-
*
|
|
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.
|
|
76
81
|
*/
|
|
77
|
-
dispatchIndirect(indirectBuffer: Buffer,
|
|
82
|
+
dispatchIndirect(indirectBuffer: Buffer, indirectByteOffset: number = 0): void {
|
|
78
83
|
const webgpuBuffer = indirectBuffer as WebGPUBuffer;
|
|
79
|
-
this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle,
|
|
84
|
+
this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectByteOffset);
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
pushDebugGroup(groupLabel: string): void {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {ComputePipeline, ComputePipelineProps} from '@luma.gl/core';
|
|
6
|
-
|
|
5
|
+
import {ComputePipeline, ComputePipelineProps, Binding} from '@luma.gl/core';
|
|
6
|
+
import {getBindGroup} from '../helpers/get-bind-group';
|
|
7
7
|
import {WebGPUDevice} from '../webgpu-device';
|
|
8
8
|
import {WebGPUShader} from './webgpu-shader';
|
|
9
9
|
|
|
@@ -14,27 +14,54 @@ export class WebGPUComputePipeline extends ComputePipeline {
|
|
|
14
14
|
device: WebGPUDevice;
|
|
15
15
|
handle: GPUComputePipeline;
|
|
16
16
|
|
|
17
|
+
/** For internal use to create BindGroups */
|
|
18
|
+
private _bindGroupLayout: GPUBindGroupLayout | null = null;
|
|
19
|
+
private _bindGroup: GPUBindGroup | null = null;
|
|
20
|
+
/** For internal use to create BindGroups */
|
|
21
|
+
private _bindings: Record<string, Binding> = {};
|
|
22
|
+
|
|
17
23
|
constructor(device: WebGPUDevice, props: ComputePipelineProps) {
|
|
18
24
|
super(device, props);
|
|
19
25
|
this.device = device;
|
|
20
26
|
|
|
21
|
-
const webgpuShader = this.props.
|
|
27
|
+
const webgpuShader = this.props.shader as WebGPUShader;
|
|
28
|
+
|
|
22
29
|
this.handle =
|
|
23
30
|
this.props.handle ||
|
|
24
31
|
this.device.handle.createComputePipeline({
|
|
25
32
|
label: this.props.id,
|
|
26
33
|
compute: {
|
|
27
34
|
module: webgpuShader.handle,
|
|
28
|
-
entryPoint: this.props.
|
|
29
|
-
|
|
35
|
+
entryPoint: this.props.entryPoint,
|
|
36
|
+
constants: this.props.constants
|
|
30
37
|
},
|
|
31
38
|
layout: 'auto'
|
|
32
39
|
});
|
|
33
40
|
}
|
|
34
41
|
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
/**
|
|
43
|
+
* @todo Use renderpass.setBindings() ?
|
|
44
|
+
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
45
|
+
*/
|
|
46
|
+
setBindings(bindings: Record<string, Binding>): void {
|
|
47
|
+
Object.assign(this._bindings, bindings);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Return a bind group created by setBindings */
|
|
51
|
+
_getBindGroup() {
|
|
52
|
+
// Get hold of the bind group layout. We don't want to do this unless we know there is at least one bind group
|
|
53
|
+
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
54
|
+
|
|
55
|
+
// Set up the bindings
|
|
56
|
+
this._bindGroup =
|
|
57
|
+
this._bindGroup ||
|
|
58
|
+
getBindGroup(
|
|
59
|
+
this.device.handle,
|
|
60
|
+
this._bindGroupLayout,
|
|
61
|
+
this.props.shaderLayout,
|
|
62
|
+
this._bindings
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return this._bindGroup;
|
|
39
66
|
}
|
|
40
67
|
}
|
|
@@ -31,6 +31,8 @@ export class WebGPUExternalTexture extends ExternalTexture {
|
|
|
31
31
|
// External textures are destroyed automatically,
|
|
32
32
|
// as a microtask, instead of manually or upon garbage collection like other resources.
|
|
33
33
|
// this.handle.destroy();
|
|
34
|
+
// @ts-expect-error readonly
|
|
35
|
+
this.handle = null;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/** Set default sampler */
|
|
@@ -25,12 +25,8 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
25
25
|
vs: WebGPUShader;
|
|
26
26
|
fs: WebGPUShader | null = null;
|
|
27
27
|
|
|
28
|
-
// private _bufferSlots: Record<string, number>;
|
|
29
|
-
// private _buffers: Buffer[];
|
|
30
|
-
// private _firstIndex: number;
|
|
31
|
-
// private _lastIndex: number;
|
|
32
|
-
|
|
33
28
|
/** For internal use to create BindGroups */
|
|
29
|
+
private _bindings: Record<string, Binding>;
|
|
34
30
|
private _bindGroupLayout: GPUBindGroupLayout | null = null;
|
|
35
31
|
private _bindGroup: GPUBindGroup | null = null;
|
|
36
32
|
|
|
@@ -50,46 +46,23 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
50
46
|
this.vs = cast<WebGPUShader>(props.vs);
|
|
51
47
|
this.fs = cast<WebGPUShader>(props.fs);
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
// this._buffers = new Array<Buffer>(Object.keys(this._bufferSlots).length).fill(null);
|
|
49
|
+
this._bindings = {...this.props.bindings};
|
|
55
50
|
}
|
|
56
51
|
|
|
57
52
|
override destroy(): void {
|
|
58
53
|
// WebGPURenderPipeline has no destroy method.
|
|
54
|
+
this.handle = null;
|
|
59
55
|
}
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// setAttributes(attributes: Record<string, Buffer>): void {
|
|
66
|
-
// for (const [name, buffer] of Object.entries(attributes)) {
|
|
67
|
-
// const bufferIndex = this._bufferSlots[name];
|
|
68
|
-
// if (bufferIndex >= 0) {
|
|
69
|
-
// this._buffers[bufferIndex] = buffer;
|
|
70
|
-
// } else {
|
|
71
|
-
// throw new Error(
|
|
72
|
-
// `Setting attribute '${name}' not listed in shader layout for program ${this.id}`
|
|
73
|
-
// );
|
|
74
|
-
// }
|
|
75
|
-
// }
|
|
76
|
-
// // for (let i = 0; i < this._bufferSlots.length; ++i) {
|
|
77
|
-
// // const bufferName = this._bufferSlots[i];
|
|
78
|
-
// // if (attributes[bufferName]) {
|
|
79
|
-
// // this.handle
|
|
80
|
-
// // }
|
|
81
|
-
// // }
|
|
82
|
-
// }
|
|
83
|
-
|
|
57
|
+
/**
|
|
58
|
+
* @todo Use renderpass.setBindings() ?
|
|
59
|
+
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
60
|
+
*/
|
|
84
61
|
setBindings(bindings: Record<string, Binding>): void {
|
|
85
|
-
|
|
86
|
-
// return;
|
|
87
|
-
// }
|
|
88
|
-
|
|
89
|
-
// Do we want to save things on CPU side?
|
|
90
|
-
Object.assign(this.props.bindings, bindings);
|
|
62
|
+
Object.assign(this._bindings, bindings);
|
|
91
63
|
}
|
|
92
64
|
|
|
65
|
+
/** @todo - should this be moved to renderpass? */
|
|
93
66
|
draw(options: {
|
|
94
67
|
renderPass: RenderPass;
|
|
95
68
|
vertexArray: VertexArray;
|
|
@@ -100,9 +73,8 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
100
73
|
firstIndex?: number;
|
|
101
74
|
firstInstance?: number;
|
|
102
75
|
baseVertex?: number;
|
|
103
|
-
}):
|
|
104
|
-
const webgpuRenderPass
|
|
105
|
-
cast<WebGPURenderPass>(options.renderPass) || this.device.getDefaultRenderPass();
|
|
76
|
+
}): boolean {
|
|
77
|
+
const webgpuRenderPass = options.renderPass as WebGPURenderPass;
|
|
106
78
|
|
|
107
79
|
// Set pipeline
|
|
108
80
|
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
@@ -136,25 +108,28 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
136
108
|
|
|
137
109
|
// Note: Rebinds constant attributes before each draw call
|
|
138
110
|
options.vertexArray.unbindAfterRender(options.renderPass);
|
|
139
|
-
}
|
|
140
111
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// }
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
144
114
|
|
|
145
115
|
/** Return a bind group created by setBindings */
|
|
146
116
|
_getBindGroup() {
|
|
117
|
+
if (this.props.shaderLayout.bindings.length === 0) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
147
121
|
// Get hold of the bind group layout. We don't want to do this unless we know there is at least one bind group
|
|
148
122
|
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
149
123
|
|
|
150
124
|
// Set up the bindings
|
|
125
|
+
// TODO what if bindings change? We need to rebuild the bind group!
|
|
151
126
|
this._bindGroup =
|
|
152
127
|
this._bindGroup ||
|
|
153
128
|
getBindGroup(
|
|
154
129
|
this.device.handle,
|
|
155
130
|
this._bindGroupLayout,
|
|
156
131
|
this.props.shaderLayout,
|
|
157
|
-
this.
|
|
132
|
+
this._bindings
|
|
158
133
|
);
|
|
159
134
|
|
|
160
135
|
return this._bindGroup;
|
|
@@ -167,24 +142,21 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
167
142
|
// Set up the vertex stage
|
|
168
143
|
const vertex: GPUVertexState = {
|
|
169
144
|
module: cast<WebGPUShader>(this.props.vs).handle,
|
|
170
|
-
entryPoint: this.props.
|
|
145
|
+
entryPoint: this.props.vertexEntryPoint || 'main',
|
|
171
146
|
buffers: getVertexBufferLayout(this.props.shaderLayout, this.props.bufferLayout)
|
|
172
147
|
};
|
|
173
148
|
|
|
174
149
|
// Set up the fragment stage
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
]
|
|
186
|
-
};
|
|
187
|
-
}
|
|
150
|
+
const fragment: GPUFragmentState = {
|
|
151
|
+
module: cast<WebGPUShader>(this.props.fs).handle,
|
|
152
|
+
entryPoint: this.props.fragmentEntryPoint || 'main',
|
|
153
|
+
targets: [
|
|
154
|
+
{
|
|
155
|
+
// TODO exclamation mark hack!
|
|
156
|
+
format: getWebGPUTextureFormat(this.device?.canvasContext?.format)
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
};
|
|
188
160
|
|
|
189
161
|
// WebGPU has more restrictive topology support than WebGL
|
|
190
162
|
switch (this.props.topology) {
|
|
@@ -209,47 +181,46 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
209
181
|
|
|
210
182
|
return descriptor;
|
|
211
183
|
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
_setAttributeBuffers(webgpuRenderPass: WebGPURenderPass) {
|
|
187
|
+
if (this._indexBuffer) {
|
|
188
|
+
webgpuRenderPass.handle.setIndexBuffer(this._indexBuffer.handle, this._indexBuffer.props.indexType);
|
|
189
|
+
}
|
|
212
190
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
191
|
+
const buffers = this._getBuffers();
|
|
192
|
+
for (let i = 0; i < buffers.length; ++i) {
|
|
193
|
+
const buffer = cast<WebGPUBuffer>(buffers[i]);
|
|
194
|
+
if (!buffer) {
|
|
195
|
+
const attribute = this.props.shaderLayout.attributes.find(
|
|
196
|
+
(attribute) => attribute.location === i
|
|
197
|
+
);
|
|
198
|
+
throw new Error(
|
|
199
|
+
`No buffer provided for attribute '${attribute?.name || ''}' in Model '${this.props.id}'`
|
|
200
|
+
);
|
|
217
201
|
}
|
|
202
|
+
webgpuRenderPass.handle.setVertexBuffer(i, buffer.handle);
|
|
203
|
+
}
|
|
218
204
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
throw new Error(
|
|
227
|
-
`No buffer provided for attribute '${attribute?.name || ''}' in Model '${this.props.id}'`
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
webgpuRenderPass.handle.setVertexBuffer(i, buffer.handle);
|
|
205
|
+
// TODO - HANDLE buffer maps
|
|
206
|
+
/*
|
|
207
|
+
for (const [bufferName, attributeMapping] of Object.entries(this.props.bufferLayout)) {
|
|
208
|
+
const buffer = cast<WebGPUBuffer>(this.props.attributes[bufferName]);
|
|
209
|
+
if (!buffer) {
|
|
210
|
+
log.warn(`Missing buffer for buffer map ${bufferName}`)();
|
|
211
|
+
continue;
|
|
231
212
|
}
|
|
232
213
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
log.warn(`Missing buffer for buffer map ${bufferName}`)();
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if ('location' in attributeMapping) {
|
|
214
|
+
if ('location' in attributeMapping) {
|
|
215
|
+
// @ts-expect-error TODO model must not depend on webgpu
|
|
216
|
+
renderPass.handle.setVertexBuffer(layout.location, buffer.handle);
|
|
217
|
+
} else {
|
|
218
|
+
for (const [bufferName, mapping] of Object.entries(attributeMapping)) {
|
|
243
219
|
// @ts-expect-error TODO model must not depend on webgpu
|
|
244
|
-
renderPass.handle.setVertexBuffer(
|
|
245
|
-
} else {
|
|
246
|
-
for (const [bufferName, mapping] of Object.entries(attributeMapping)) {
|
|
247
|
-
// @ts-expect-error TODO model must not depend on webgpu
|
|
248
|
-
renderPass.handle.setVertexBuffer(field.location, buffer.handle);
|
|
249
|
-
}
|
|
220
|
+
renderPass.handle.setVertexBuffer(field.location, buffer.handle);
|
|
250
221
|
}
|
|
251
222
|
}
|
|
252
|
-
*
|
|
253
223
|
}
|
|
254
|
-
|
|
224
|
+
*
|
|
255
225
|
}
|
|
226
|
+
*/
|
|
@@ -6,10 +6,6 @@ import type {ShaderProps, CompilerMessage} from '@luma.gl/core';
|
|
|
6
6
|
import {Shader, log} from '@luma.gl/core';
|
|
7
7
|
import type {WebGPUDevice} from '../webgpu-device';
|
|
8
8
|
|
|
9
|
-
export type WebGPUShaderProps = ShaderProps & {
|
|
10
|
-
handle?: GPUShaderModule;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
9
|
/**
|
|
14
10
|
* Immutable shader
|
|
15
11
|
*/
|
|
@@ -17,7 +13,7 @@ export class WebGPUShader extends Shader {
|
|
|
17
13
|
readonly device: WebGPUDevice;
|
|
18
14
|
readonly handle: GPUShaderModule;
|
|
19
15
|
|
|
20
|
-
constructor(device: WebGPUDevice, props:
|
|
16
|
+
constructor(device: WebGPUDevice, props: ShaderProps) {
|
|
21
17
|
super(device, props);
|
|
22
18
|
this.device = device;
|
|
23
19
|
|
|
@@ -46,6 +42,8 @@ export class WebGPUShader extends Shader {
|
|
|
46
42
|
override destroy(): void {
|
|
47
43
|
// Note: WebGPU does not offer a method to destroy shaders
|
|
48
44
|
// this.handle.destroy();
|
|
45
|
+
// @ts-expect-error readonly
|
|
46
|
+
this.handle = null;
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
/** Returns compilation info for this shader */
|
|
@@ -57,26 +55,13 @@ export class WebGPUShader extends Shader {
|
|
|
57
55
|
// PRIVATE METHODS
|
|
58
56
|
|
|
59
57
|
protected createHandle(): GPUShaderModule {
|
|
60
|
-
const {source
|
|
58
|
+
const {source} = this.props;
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// wgsl uses C++ "auto" style arrow notation
|
|
66
|
-
language = source.includes('->') ? 'wgsl' : 'glsl';
|
|
60
|
+
const isGLSL = source.includes('#version');
|
|
61
|
+
if (this.props.language === 'glsl' || isGLSL) {
|
|
62
|
+
throw new Error('GLSL shaders are not supported in WebGPU');
|
|
67
63
|
}
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
case 'wgsl':
|
|
71
|
-
return this.device.handle.createShaderModule({code: source});
|
|
72
|
-
case 'glsl':
|
|
73
|
-
return this.device.handle.createShaderModule({
|
|
74
|
-
code: source,
|
|
75
|
-
// @ts-expect-error
|
|
76
|
-
transform: glsl => this.device.glslang.compileGLSL(glsl, stage)
|
|
77
|
-
});
|
|
78
|
-
default:
|
|
79
|
-
throw new Error(language);
|
|
80
|
-
}
|
|
65
|
+
return this.device.handle.createShaderModule({code: source});
|
|
81
66
|
}
|
|
82
67
|
}
|