UNPKG

@animech-public/playcanvas

Version:
2 lines (1 loc) 5.27 kB
import{math as e}from"../../../core/math/math.js";import{isCompressedPixelFormat as t,PIXELFORMAT_DEPTHSTENCIL as r,SAMPLETYPE_DEPTH as a,SAMPLETYPE_INT as i,SAMPLETYPE_UINT as s,SAMPLETYPE_UNFILTERABLE_FLOAT as l,PIXELFORMAT_RGBA32F as n,PIXELFORMAT_RGBA16F as o,isIntegerPixelFormat as m,pixelFormatInfo as p,ADDRESS_REPEAT as u,ADDRESS_CLAMP_TO_EDGE as d,ADDRESS_MIRRORED_REPEAT as h,FILTER_NEAREST as c,FILTER_LINEAR as g,FILTER_NEAREST_MIPMAP_NEAREST as f,FILTER_NEAREST_MIPMAP_LINEAR as x,FILTER_LINEAR_MIPMAP_NEAREST as y,FILTER_LINEAR_MIPMAP_LINEAR as v}from"../constants.js";import{TextureUtils as T}from"../texture-utils.js";import{gpuTextureFormats as w}from"./constants.js";const L=[];L[u]="repeat",L[d]="clamp-to-edge",L[h]="mirror-repeat";const _=[];_[c]={level:"nearest",mip:"nearest"},_[g]={level:"linear",mip:"nearest"},_[f]={level:"nearest",mip:"nearest"},_[x]={level:"nearest",mip:"linear"},_[y]={level:"linear",mip:"nearest"},_[v]={level:"linear",mip:"linear"};class F{constructor(e){this.gpuTexture=void 0,this.view=void 0,this.samplers=[],this.descr=void 0,this.format=void 0,this.texture=e,this.format=w[e.format],this.create(e.device)}create(e){const a=this.texture,i=e.wgpu,s=a.requiredMipLevels;let l;this.descr={size:{width:a.width,height:a.height,depthOrArrayLayers:a.cubemap?6:a.array?a.arrayLength:1},format:this.format,mipLevelCount:s,sampleCount:1,dimension:a.volume?"3d":"2d",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.COPY_SRC|(t(a.format)?0:GPUTextureUsage.RENDER_ATTACHMENT)|(a.storage?GPUTextureUsage.STORAGE_BINDING:0)},this.gpuTexture=i.createTexture(this.descr),this.texture.format===r&&(l={format:"depth24plus",aspect:"depth-only"}),this.view=this.createView(l)}destroy(e){}propertyChanged(e){this.samplers.length=0}getView(e){return this.uploadImmediate(e,this.texture),this.view}createView(e){var t,r,a,i,s,l,n;const o=null!=e?e:{},m=this.descr,p=this.texture,u={format:null!=(t=o.format)?t:m.format,dimension:null!=(r=o.dimension)?r:p.cubemap?"cube":p.volume?"3d":p.array?"2d-array":"2d",aspect:null!=(a=o.aspect)?a:"all",baseMipLevel:null!=(i=o.baseMipLevel)?i:0,mipLevelCount:null!=(s=o.mipLevelCount)?s:m.mipLevelCount,baseArrayLayer:null!=(l=o.baseArrayLayer)?l:0,arrayLayerCount:null!=(n=o.arrayLayerCount)?n:m.depthOrArrayLayers};return this.gpuTexture.createView(u)}getSampler(t,p){let u=this.samplers[p];if(!u){const d=this.texture,h={addressModeU:L[d.addressU],addressModeV:L[d.addressV],addressModeW:L[d.addressW]};if(!p&&d.compareOnRead&&(p=a),p===a||p===i||p===s)h.compare="less",h.magFilter="linear",h.minFilter="linear";else if(p===l)h.magFilter="nearest",h.minFilter="nearest",h.mipmapFilter="nearest";else{!t.textureFloatFilterable&&(d.format===n||d.format===o)||this.texture.format===r||m(this.texture.format)?(h.magFilter="nearest",h.minFilter="nearest",h.mipmapFilter="nearest"):(h.magFilter=_[d.magFilter].level,h.minFilter=_[d.minFilter].level,h.mipmapFilter=_[d.minFilter].mip)}const c="linear"===h.minFilter&&"linear"===h.magFilter&&"linear"===h.mipmapFilter;h.maxAnisotropy=c?e.clamp(Math.round(d._anisotropy),1,t.maxTextureAnisotropy):1,u=t.wgpu.createSampler(h),this.samplers[p]=u}return u}loseContext(){}uploadImmediate(e,t){(t._needsUpload||t._needsMipmapsUpload)&&(this.uploadData(e),t._needsUpload=!1,t._needsMipmapsUpload=!1)}uploadData(e){const r=this.texture;if(r._levels){let a=!1,i=!1;const s=r.requiredMipLevels;for(let t=0;t<s;t++){const s=r._levels[t];if(s)if(r.cubemap)for(let r=0;r<6;r++){const l=s[r];l?this.isExternalImage(l)?(this.uploadExternalImage(e,l,t,r),a=!0):ArrayBuffer.isView(l)&&(this.uploadTypedArrayData(e,l,t,r),a=!0):i=!0}else if(r._volume);else if(r.array)if(r.arrayLength===s.length)for(let i=0;i<r._arrayLength;i++){const r=s[i];this.isExternalImage(r)?(this.uploadExternalImage(e,r,t,i),a=!0):ArrayBuffer.isView(r)&&(this.uploadTypedArrayData(e,r,t,i),a=!0)}else i=!0;else this.isExternalImage(s)?(this.uploadExternalImage(e,s,t,0),a=!0):ArrayBuffer.isView(s)&&(this.uploadTypedArrayData(e,s,t,0),a=!0);else i=!0}a&&i&&r.mipmaps&&!t(r.format)&&e.mipmapRenderer.generate(this),r._gpuSize&&r.adjustVramSizeTracking(e._vram,-r._gpuSize),r._gpuSize=r.gpuSize,r.adjustVramSizeTracking(e._vram,r._gpuSize)}}isExternalImage(e){return e instanceof ImageBitmap||e instanceof HTMLVideoElement||e instanceof HTMLCanvasElement||e instanceof OffscreenCanvas}uploadExternalImage(e,t,r,a){const i={source:t,origin:[0,0],flipY:!1},s={texture:this.gpuTexture,mipLevel:r,origin:[0,0,a],aspect:"all"},l={width:this.descr.size.width,height:this.descr.size.height,depthOrArrayLayers:1};e.submit(),t instanceof HTMLCanvasElement&&t.getContext("2d"),e.wgpu.queue.copyExternalImageToTexture(i,s,l)}uploadTypedArrayData(e,t,r,a){const i=this.texture,s=e.wgpu,l={texture:this.gpuTexture,origin:[0,0,a],mipLevel:r},n=T.calcLevelDimension(i.width,r),o=T.calcLevelDimension(i.height,r);T.calcLevelGpuSize(n,o,1,i.format);const m=p.get(i.format);let u,d;if(m.size)u={offset:0,bytesPerRow:m.size*n,rowsPerImage:o},d={width:n,height:o};else if(m.blockSize){const e=e=>Math.floor((e+3)/4);u={offset:0,bytesPerRow:m.blockSize*e(n),rowsPerImage:e(o)},d={width:Math.max(4,n),height:Math.max(4,o)}}e.submit(),s.queue.writeTexture(l,t,u,d)}}export{F as WebgpuTexture};