Math.max(1,Math.floor(t/2**e))))}function ce(t,e,s,n){const i=function(t,e){if(r(t))return t;const{Type:s}=ae(e);return new s(t)}(s.data||s,e.format),o=ue(e,0),{bytesPerElement:a}=ae(e.format),u=n.origin||[0,0,0];t.queue.writeTexture({texture:e,origin:u},i,{bytesPerRow:a*o[0],rowsPerImage:o[1]},o)}function le(t,e,r,s={}){r.forEach(((r,n)=>{const i=[0,0,n+(s.baseArrayLayer||0)];if(se(r))ce(t,e,r,{origin:i});else{const n=r,{flipY:o,premultipliedAlpha:a,colorSpace:u}=s;t.queue.copyExternalImageToTexture({source:n,flipY:o},{texture:e,premultipliedAlpha:a,colorSpace:u,origin:i},he(n,s))}})),e.mipLevelCount>1&&Dt(t,e)}function he(t,e){if(t instanceof HTMLVideoElement)return[t.videoWidth,t.videoHeight,1];{const s=t,{width:n,height:i}=s;if(n>0&&i>0&&!se(t))return[n,i,1];const o=e.format||"rgba8unorm",{bytesPerElement:a,bytesPerChannel:u}=ae(o),c=r(t)||Array.isArray(t)?t:t.data;return function(t,e,r,s="2d"){if(r%1!=0)throw new Error("can't guess dimensions");if(t||e){if(e){if(!t&&(t=r/e)%1)throw new Error("can't guess dimensions")}else if((e=r/t)%1)throw new Error("can't guess dimensions")}else{const n=Math.sqrt(r/("cube"===s?6:1));n%1==0?(t=n,e=n):(t=r,e=1)}const n=r/t/e;if(n%1)throw new Error("can't guess dimensions");return[t,e,n]}(n,i,(r(c)?c.byteLength:c.length*u)/a)}}function _e(t,e,r={}){const s=he(e[0],r);s[2]=s[2]>1?s[2]:e.length;const n=t.createTexture({dimension:ne(r.dimension),format:r.format||"rgba8unorm",mipLevelCount:r.mipLevelCount?r.mipLevelCount:r.mips?jt(s):1,size:s,usage:(r.usage??0)|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});return le(t,n,e,r),n}async function pe(t,e={}){const r=await fetch(t),s=await r.blob(),n={...e,...void 0!==e.colorSpaceConversion&&{colorSpaceConversion:"none"}};return await createImageBitmap(s,n)}async function de(t,e,r={}){return _e(t,await Promise.all(e.map((t=>pe(t)))),r)}class me{typedArray;cursor=0;numComponents;constructor(t,e){this.typedArray=t,this.numComponents=e}get numElements(){return this.typedArray.length/this.numComponents}push(...t){for(const e of t)if(Array.isArray(e)||r(e)){const e=t;this.typedArray.set(e,this.cursor),this.cursor+=e.length}else this.typedArray[this.cursor++]=e}reset(t=0){this.cursor=t}}function fe(t,e,r){return new me(new r(t*e),t)}const ye=[[3,7,5,1],[6,2,0,4],[6,7,3,2],[0,1,5,4],[7,6,4,5],[2,3,1,0]];function ge(t=1,e=0,r=1,s=24,n=1,i=!0,o=!0){if(s<3)throw new Error("radialSubdivisions must be 3 or greater");if(n<1)throw new Error("verticalSubdivisions must be 1 or greater");const a=(i?2:0)+(o?2:0),u=(s+1)*(n+1+a),c=fe(3,u,Float32Array),l=fe(3,u,Float32Array),h=fe(2,u,Float32Array),_=fe(3,s*(n+a/2)*2,Uint16Array),p=s+1,d=Math.atan2(t-e,r),m=Math.cos(d),f=Math.sin(d),y=n+(o?2:0);for(let o=i?-2:0;o<=y;++o){let i,a=o/n,u=r*a;o<0?(u=0,a=1,i=t):o>n?(u=r,a=1,i=e):i=t+o/n*(e-t),-2!==o&&o!==n+2||(i=0,a=0),u-=r/2;for(let t=0;tn?l.push(0,1,0):0===i?l.push(0,0,0):l.push(e*m,f,r*m),h.push(t/s,1-a)}}for(let t=0;t[t,e.typedArray])))},createCrescentVertices:function(t,e,r,s,n,i,o){if(n<=0)throw new Error("subdivisionDown must be > 0");const a=o-i,u=2*(n+1)*4,c=fe(3,u,Float32Array),l=fe(3,u,Float32Array),h=fe(2,u,Float32Array);function _(t,e,r){return t+(e-t)*r}function p(t,e){return t.map(((t,r)=>t+e[r]))}function d(t,e){return t.map(((t,r)=>t*e[r]))}function m(e,r,o,u,m,f){for(let y=0;y<=n;y++){const g=r/1,w=y/n,k=2*(g-.5),x=(i+w*a)*Math.PI,b=Math.sin(x),v=Math.cos(x),A=_(t,e,b),E=k*s,T=v*t,S=b*A;c.push(E,T,S);const z=p(d([0,b,v],o),u);l.push(z),h.push(g*m+f,w)}}for(let t=0;t<2;t++){const s=2*(t/1-.5);m(e,t,[1,1,1],[0,0,0],1,0),m(e,t,[0,0,0],[s,0,0],0,0),m(r,t,[1,1,1],[0,0,0],1,0),m(r,t,[0,0,0],[s,0,0],0,1)}const f=fe(3,2*n*4,Uint16Array);function y(t,e){for(let r=0;r0&&s!==e){const t=l+(s+1),e=l+s,r=l+s-_,n=l+(s+1)-_;c.push(t,e,r),c.push(t,r,n)}}l+=e+1}return{position:o.typedArray,normal:a.typedArray,texcoord:u.typedArray,indices:c.typedArray}},createPlaneVertices:function(t=1,e=1,r=1,s=1){const n=(r+1)*(s+1),i=fe(3,n,Float32Array),o=fe(3,n,Float32Array),a=fe(2,n,Float32Array);for(let n=0;n<=s;n++)for(let u=0;u<=r;u++){const c=u/r,l=n/s;i.push(t*c-.5*t,0,e*l-.5*e),o.push(0,1,0),a.push(c,l)}const u=r+1,c=fe(3,r*s*2,Uint16Array);for(let t=0;t 0");const a=n-s,u=o-i,c=(e+1)*(r+1),l=fe(3,c,Float32Array),h=fe(3,c,Float32Array),_=fe(2,c,Float32Array);for(let n=0;n<=r;n++)for(let o=0;o<=e;o++){const c=o/e,p=n/r,d=u*c+i,m=a*p+s,f=Math.sin(d),y=Math.cos(d),g=Math.sin(m),w=y*g,k=Math.cos(m),x=f*g;l.push(t*w,t*k,t*x),h.push(w,k,x),_.push(1-c,p)}const p=e+1,d=fe(3,e*r*2,Uint16Array);for(let t=0;tWt(t)));if(l){const e=Ht(l[1],"indices"),r=t.createBuffer({size:e.byteLength,usage:GPUBufferUsage.INDEX|s,mappedAtCreation:!0});Kt(e,r.getMappedRange()).set(e),r.unmap(),c.indexBuffer=r,c.indexFormat=e instanceof Uint16Array?"uint16":"uint32",c.numElements=e.length}return c},t.createTextureFromImage=async function(t,e,r={}){return de(t,[e],r)},t.createTextureFromImages=de,t.createTextureFromSource=function(t,e,r={}){return _e(t,[e],r)},t.createTextureFromSources=_e,t.generateMipmap=Dt,t.getSizeForMipFromTexture=ue,t.getSizeFromSource=he,t.interleaveVertexData=re,t.isTypedArray=r,t.kTypes=i,t.loadImageBitmap=pe,t.makeShaderDataDefinitions=function(t){const e=new Ot(t),r=Object.fromEntries(e.structs.map((t=>[t.name,Pt(e,t,0)]))),s=Lt(e,e.uniforms);return{structs:r,storages:Lt(e,e.storage),uniforms:s}},t.makeStructuredView=function(t,e,r=0){const s=t,n=h(void 0===s.group?t:s.typeDefinition,e,r);return{...n,set(t){_(t,n.views)}}},t.makeTypedArrayViews=h,t.normalizeGPUExtent3D=$t,t.numMipLevels=jt,t.primitives=ke,t.setIntrinsicsToView=a,t.setStructuredValues=function(t,e,r,s=0){f(t.typeDefinition,e,r,s)},t.setStructuredView=_,t.setTypedValues=f,t.subarray=function(t,e,r){return t.subarray(e,e+r)}}));
+//# sourceMappingURL=webgpu-utils.min.js.map
diff --git a/dist/0.x/webgpu-utils.min.js.map b/dist/0.x/webgpu-utils.min.js.map
new file mode 100644
index 0000000..6ed20a1
--- /dev/null
+++ b/dist/0.x/webgpu-utils.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"webgpu-utils.min.js","sources":["../../../src/utils.ts","../../../src/typed-arrays.ts","../../../src/buffer-views.ts","../../node_modules/wgsl_reflect/wgsl_reflect.module.js","../../../src/data-definitions.ts","../../../src/generate-mipmap.ts","../../../src/attribute-utils.ts","../../../src/texture-utils.ts","../../../src/primitives.ts"],"sourcesContent":["export const roundUpToMultipleOf = (v: number, multiple: number) => (((v + multiple - 1) / multiple) | 0) * multiple;\n\nexport function keysOf(obj: { [k in T]: unknown }): readonly T[] {\n return (Object.keys(obj) as unknown[]) as T[];\n}\n\nexport function range(count: number, fn: (i: number) => T) {\n return new Array(count).fill(0).map((_, i) => fn(i));\n}\n","import {\n roundUpToMultipleOf,\n} from './utils.js';\n\nexport type TypedArrayConstructor =\n | Int8ArrayConstructor\n | Uint8ArrayConstructor\n | Int16ArrayConstructor\n | Uint16ArrayConstructor\n | Int32ArrayConstructor\n | Uint32ArrayConstructor\n | Float32ArrayConstructor\n | Float64ArrayConstructor;\n\nexport type TypedArray =\n | Int8Array\n | Uint8Array\n | Int16Array\n | Uint16Array\n | Int32Array\n | Uint32Array\n | Float32Array\n | Float64Array;\n\nexport class TypedArrayViewGenerator {\n arrayBuffer: ArrayBuffer;\n byteOffset: number;\n\n constructor(sizeInBytes: number) {\n this.arrayBuffer = new ArrayBuffer(sizeInBytes);\n this.byteOffset = 0;\n }\n align(alignment: number) {\n this.byteOffset = roundUpToMultipleOf(this.byteOffset, alignment);\n }\n pad(numBytes: number) {\n this.byteOffset += numBytes;\n }\n getView(Ctor: TypedArrayConstructor, numElements: number): T {\n const view = new Ctor(this.arrayBuffer, this.byteOffset, numElements);\n this.byteOffset += view.byteLength;\n return view as T;\n }\n}\n\nexport function subarray(arr: TypedArray, offset: number, length: number): T {\n return arr.subarray(offset, offset + length) as T;\n}\n\n// TODO: fix better?\nexport const isTypedArray = (arr: any) =>\n arr && typeof arr.length === 'number' && arr.buffer instanceof ArrayBuffer && typeof arr.byteLength === 'number';\n","import {\n IntrinsicDefinition,\n StructDefinition,\n ArrayDefinition,\n TypeDefinition,\n VariableDefinition,\n} from './data-definitions.js';\nimport {\n isTypedArray,\n TypedArrayConstructor,\n TypedArray,\n} from './typed-arrays.js';\nimport { roundUpToMultipleOf, keysOf, range } from './utils.js';\n\ntype TypeDef = {\n numElements: number;\n align: number;\n size: number;\n type: string;\n View: TypedArrayConstructor;\n flatten?: boolean,\n pad?: readonly number[];\n};\n\nconst b: { readonly [K: string]: TypeDef } = {\n i32: { numElements: 1, align: 4, size: 4, type: 'i32', View: Int32Array },\n u32: { numElements: 1, align: 4, size: 4, type: 'u32', View: Uint32Array },\n f32: { numElements: 1, align: 4, size: 4, type: 'f32', View: Float32Array },\n f16: { numElements: 1, align: 2, size: 2, type: 'u16', View: Uint16Array },\n\n vec2f: { numElements: 2, align: 8, size: 8, type: 'f32', View: Float32Array },\n vec2i: { numElements: 2, align: 8, size: 8, type: 'i32', View: Int32Array },\n vec2u: { numElements: 2, align: 8, size: 8, type: 'u32', View: Uint32Array },\n vec2h: { numElements: 2, align: 4, size: 4, type: 'u16', View: Uint16Array },\n vec3i: { numElements: 3, align: 16, size: 12, type: 'i32', View: Int32Array },\n vec3u: { numElements: 3, align: 16, size: 12, type: 'u32', View: Uint32Array },\n vec3f: { numElements: 3, align: 16, size: 12, type: 'f32', View: Float32Array },\n vec3h: { numElements: 3, align: 8, size: 6, type: 'u16', View: Uint16Array },\n vec4i: { numElements: 4, align: 16, size: 16, type: 'i32', View: Int32Array },\n vec4u: { numElements: 4, align: 16, size: 16, type: 'u32', View: Uint32Array },\n vec4f: { numElements: 4, align: 16, size: 16, type: 'f32', View: Float32Array },\n vec4h: { numElements: 4, align: 8, size: 8, type: 'u16', View: Uint16Array },\n\n // AlignOf(vecR)\tSizeOf(array)\n mat2x2f: { numElements: 4, align: 8, size: 16, type: 'f32', View: Float32Array },\n mat2x2h: { numElements: 4, align: 4, size: 8, type: 'u16', View: Uint16Array },\n mat3x2f: { numElements: 6, align: 8, size: 24, type: 'f32', View: Float32Array },\n mat3x2h: { numElements: 6, align: 4, size: 12, type: 'u16', View: Uint16Array },\n mat4x2f: { numElements: 8, align: 8, size: 32, type: 'f32', View: Float32Array },\n mat4x2h: { numElements: 8, align: 4, size: 16, type: 'u16', View: Uint16Array },\n mat2x3f: { numElements: 8, align: 16, size: 32, pad: [3, 1], type: 'f32', View: Float32Array },\n mat2x3h: { numElements: 8, align: 8, size: 16, pad: [3, 1], type: 'u16', View: Uint16Array },\n mat3x3f: { numElements: 12, align: 16, size: 48, pad: [3, 1], type: 'f32', View: Float32Array },\n mat3x3h: { numElements: 12, align: 8, size: 24, pad: [3, 1], type: 'u16', View: Uint16Array },\n mat4x3f: { numElements: 16, align: 16, size: 64, pad: [3, 1], type: 'f32', View: Float32Array },\n mat4x3h: { numElements: 16, align: 8, size: 32, pad: [3, 1], type: 'u16', View: Uint16Array },\n mat2x4f: { numElements: 8, align: 16, size: 32, type: 'f32', View: Float32Array },\n mat2x4h: { numElements: 8, align: 8, size: 16, type: 'u16', View: Uint16Array },\n mat3x4f: { numElements: 12, align: 16, size: 48, pad: [3, 1], type: 'f32', View: Float32Array },\n mat3x4h: { numElements: 12, align: 8, size: 24, pad: [3, 1], type: 'u16', View: Uint16Array },\n mat4x4f: { numElements: 16, align: 16, size: 64, type: 'f32', View: Float32Array },\n mat4x4h: { numElements: 16, align: 8, size: 32, type: 'u16', View: Uint16Array },\n\n // Note: At least as of WGSL V1 you can not create a bool for uniform or storage.\n // You can only create one in an internal struct. But, this code generates\n // views of structs and it needs to not fail if the struct has a bool\n bool: { numElements: 0, align: 1, size: 0, type: 'bool', View: Uint32Array },\n} as const;\n\nconst typeInfo: { readonly [K: string]: TypeDef } = {\n ...b,\n\n 'vec2': b.vec2i,\n 'vec2': b.vec2u,\n 'vec2': b.vec2f,\n 'vec2': b.vec2h,\n 'vec3': b.vec3i,\n 'vec3': b.vec3u,\n 'vec3': b.vec3f,\n 'vec3': b.vec3h,\n 'vec4': b.vec4i,\n 'vec4': b.vec4u,\n 'vec4': b.vec4f,\n 'vec4': b.vec4h,\n\n 'mat2x2': b.mat2x2f,\n 'mat2x2': b.mat2x2h,\n 'mat3x2': b.mat3x2f,\n 'mat3x2': b.mat3x2h,\n 'mat4x2': b.mat4x2f,\n 'mat4x2': b.mat4x2h,\n 'mat2x3': b.mat2x3f,\n 'mat2x3': b.mat2x3h,\n 'mat3x3': b.mat3x3f,\n 'mat3x3': b.mat3x3h,\n 'mat4x3': b.mat4x3f,\n 'mat4x3': b.mat4x3h,\n 'mat2x4': b.mat2x4f,\n 'mat2x4': b.mat2x4h,\n 'mat3x4': b.mat3x4f,\n 'mat3x4': b.mat3x4h,\n 'mat4x4': b.mat4x4f,\n 'mat4x4': b.mat4x4h,\n} as const;\nexport type kType = Extract;\nexport const kTypes: readonly kType[] = keysOf(typeInfo);\n\n/**\n * Set which intrinsic types to make views for.\n *\n * Example:\n *\n * Given a an array of intrinsics like this\n * `array