UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

3 lines (2 loc) 8.54 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */ import{nextHighestPowerOfTwo as t}from"../../../../../core/mathUtils.js";import{disposeMaybe as e}from"../../../../../core/maybe.js";import{copy as r,invert as o,transpose as s}from"../../../../../core/libs/gl-matrix-2/math/mat4.js";import{create as n}from"../../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{glLayout as a}from"../../../support/buffer/glUtil.js";import{VertexArrayObject as f}from"../../lib/VertexArrayObject.js";import{getMaxItemCount as i,getMaxByteSize as u}from"../../lib/TextureBackedBuffer/TextureBackedBufferUtils.js";import{TextureBuffer as c}from"../../lib/TextureBackedBuffer/TextureBuffer.js";import{bufferRangePool as m}from"./BufferRange.js";import{DrawCommand as l}from"./DrawCommand.js";import{BaseInstanceData as g}from"./PerBaseInstanceData.js";import{VertexBuffer as h}from"../../../../webgl/VertexBuffer.js";class y{constructor(t,e){this._rctx=e;const r=t.createBufferWriter();this._bufferWriter=r,this._vaoCache=e.getVaoCache(a(r.layout));const o=["geometry"];"textureBufferLayout"in r&&null!=r.textureBufferLayout&&o.push("texture"),this.targetBuffers=o}maxElements(t){if("texture"===t){const t=this._targetLayout("texture");return null==t?0:i(this._rctx,t)}return Math.floor(x/this._targetStrideBytes(t))}_targetStrideBytes(t){return this._targetLayout(t)?.stride??0}_targetLayout(t){return"geometry"===t?this._bufferWriter.layout:"baseInstance"===t?this._bufferWriter.baseInstanceLayout:this._bufferWriter.textureBufferLayout}evaluateBufferAllocation(t,e,r,o){const s=this._targetStrideBytes("geometry"),n=e.reduce((t,{geometry:e})=>t+this.vertexElementCount(e),0),a=r.reduce((t,{geometry:e})=>t+this.vertexElementCount(e),0),f=Math.min((t+n-a)*s,x),i=o.vao?.buffer("geometry"),u=i?.sizeBytes??0;return f>b&&f<u/2?0:f>u?1:2}deleteBuffer(t){if(t.isInstanced)return t.instancedCommandVAOs?.dispose(),t.vao?.buffer("geometry")?.dispose(),t.vao?.disposeVAOOnly(),void(t.vao=null);this._vaoCache.deleteVao(t.vao),t.vaoEndElement=0,t.textureBuffer=e(t.textureBuffer),t.textureEndElement=0}createBaseInstanceData(t){const{_bufferWriter:e}=this;if(null==t||null==e.baseInstanceLayout||null==e.writeBaseInstance||null==e.elementCountBaseInstance)return null;const r=this._targetLayout("baseInstance"),o=e.elementCountBaseInstance(t.attributes),s=o*r.stride,n=new h(this._rctx,a(r));n.setSize(Math.ceil(s));const f=S(s),i=r.createView(f.buffer);e.writeBaseInstance(t.attributes,i),n.setSubData(f,0,0,s);const u=new l;return u.first=0,u.count=o,new g(t,n,u)}_allocateInstanceBuffer(t){const e=this._bufferWriter.layout,r=t*this._targetStrideBytes("geometry"),o=new h(this._rctx,a(e,1));return o.setSize(I(r)),o}_createInstancedVao(t,e){return new f(this._rctx,new Map([["baseInstance",t],["geometry",e]]))}reallocateBuffer(t,e,r){if(this.deleteBuffer(e),null!=t){const o=t.baseInstanceBuffer,s=this._allocateInstanceBuffer(r.geometry);e.vao=this._createInstancedVao(o,s)}else{const t=r.geometry*this._targetStrideBytes("geometry");e.vao=this._vaoCache.newVao(I(t))}const o=this._targetLayout("texture");if(null!=o){const t=I(r.texture*o.stride),s=Math.ceil(t/o.stride);e.textureBuffer=new c(this._rctx,o,s)}e.vaoEndElement=Math.floor((e.vao?.getByteLength("geometry")??0)/this._targetStrideBytes("geometry")),e.textureEndElement=e.textureBuffer?.itemCount??0}elementCount(t,e){const{attributes:r}=t;return"geometry"===e?this._bufferWriter.elementCount(r):"baseInstance"===e?this._bufferWriter.elementCountBaseInstance?.(r)??0:this._bufferWriter.elementCountTextureBuffer?.(r)??0}vertexElementCount(t){return this._bufferWriter.elementCount(t.attributes)}textureElementCount(t){return this._bufferWriter.elementCountTextureBuffer?.(t.attributes)??0}canGrow(t,e){const r=this.targetBuffers.map(r=>this._evaluateTargetBufferGrowth(r,t,e));return r.every(({canGrow:t})=>t)&&r.some(({needsToGrow:t})=>t)}_evaluateTargetBufferGrowth(t,e,r){const o=this._targetLayout(t),s=e.getTargetBuffer(t);if(null==o||null==s)return{needsToGrow:null!=o,canGrow:!0};return{needsToGrow:r[t]*o.stride>s.sizeBytes,canGrow:"geometry"===t?s.sizeBytes<I(x-b):s.sizeBytes<u(this._rctx,o)}}clearHoles(t,e){for(const r of this.targetBuffers){const o=this._targetStrideBytes(r),s=t[r],n=s.reduce((t,e)=>Math.max(t,e.numElements),0)*o,a=S(n);a.fill(0,0,n);for(const t of s)this._setTargetSubData(r,e,o,t,a)}}clearHolesMetal(t,e,r){const{targetBuffers:o}=this,s={};let n=0;for(const i of o){const t=e[i].numElements*this._targetStrideBytes(i);s[i]=n,n+=v(t)}const a=S(n);a.fill(0,0,n);const f={};for(const i of o)f[i]=this._targetLayout(i)?.createView(a.buffer,s[i]);for(const i of t){const t=i.targetRanges.geometry;if(!(t.from>=e.geometry.from&&t.to<=e.geometry.to))continue;const r={};for(const s of o)r[s]=i.targetRanges[s].from-e[s].from;this._writeGeometry(i.geometry,f,r,i.targetRanges)}for(const i of o)this._setTargetSubData(i,r,this._targetStrideBytes(i),e[i],a,s[i])}writeRandomInstances(t,e,r){const{targetBuffers:o}=this,s={},n={},a={},f={};let i=0;for(const l of o)s[l]=t[l]*this._targetStrideBytes(l),n[l]=i,a[l]=0,f[l]=m.acquire(0,0),i+=v(s[l]);const u=S(i),c={};for(const m of o)c[m]=this._targetLayout(m)?.createView(u.buffer,n[m]);for(const m of e){for(const t of o){const e=m.targetRanges[t],o=f[t];o.to===e.from||(o.numElements>0&&this._setTargetSubData(t,r,this._targetStrideBytes(t),f[t],u,n[t]),o.from=e.from,a[t]=0)}this._writeGeometry(m.geometry,c,a,m.targetRanges);for(const t of o){const e=m.targetRanges[t];a[t]+=e.numElements,f[t].to=e.to}}for(const l of o){const t=f[l];t.numElements>0&&this._setTargetSubData(l,r,this._targetStrideBytes(l),t,u,n[l]),m.release(f[l])}}writeInstanceRangeMetal(t,e,r){const{targetBuffers:o}=this,s={},n={};let a=0;for(const u of o)s[u]=t[u].numElements*this._targetStrideBytes(u),n[u]=a,a+=v(s[u]);const f=S(a),i={};for(const u of o)i[u]=this._targetLayout(u)?.createView(f.buffer,n[u]);f.fill(0,0,a);for(const u of e){const e=u.targetRanges.geometry;if(!(e.from>=t.geometry.from&&e.to<=t.geometry.to))continue;const r={},s={};for(const n of o){const e=u.targetRanges[n];r[n]=e.from-t[n].from,s[n]=e}this._writeGeometry(u.geometry,i,r,s)}for(const u of o)t[u].numElements>0&&this._setTargetSubData(u,r,this._targetStrideBytes(u),t[u],f,n[u])}rebuildInstances(t,e,r){const{targetBuffers:o}=this,s={},n={},a={};let f=0;for(const c of o)s[c]=t[c]*this._targetStrideBytes(c),n[c]=f,f+=v(s[c]),a[c]=0;const i=S(f),u={};for(const c of o)u[c]=this._targetLayout(c)?.createView(i.buffer,n[c]);for(const c of e){const t={},e={};for(const r of o){t[r]=a[r],a[r]+=this.elementCount(c.geometry.geometry,r);const o=c.targetRanges[r];o.from=t[r],o.to=a[r],e[r]=o}this._writeGeometry(c.geometry,u,t,e)}for(const c of o){const t=m.acquire(0,a[c]);this._setTargetSubData(c,r,this._targetStrideBytes(c),t,i,n[c]),m.release(t)}return a}updateInstance(t,e){const{targetBuffers:r}=this,o={},s={};let n=0;for(const u of r){const e=this._targetStrideBytes(u);o[u]=this.elementCount(t.geometry.geometry,u)*e,s[u]=n,n+=v(o[u])}const a=S(n),f={},i={};for(const u of r)i[u]=0,f[u]=this._targetLayout(u)?.createView(a.buffer,s[u]);this._writeGeometry(t.geometry,f,i,t.targetRanges);for(const u of r)this._setTargetSubData(u,e,this._targetStrideBytes(u),t.targetRanges[u],a,s[u])}updateInstancesMetal(t){const{targetBuffers:e}=this;for(const[r,o]of t){const t={};for(const r of e)t[r]=m.acquire(1/0,-1/0);for(const r of o)for(const o of e){const e=t[o],s=r.targetRanges[o];e.from=Math.min(e.from,s.from),e.to=Math.max(e.to,s.to)}this.writeInstanceRangeMetal(t,r.instances.values(),r);for(const r of e)m.release(t[r])}}_writeGeometry(t,e,n,a){const{_bufferWriter:f}=this;null!=f&&(r(B,t.transformation),B[12]-=t.localOrigin.vec3[0],B[13]-=t.localOrigin.vec3[1],B[14]-=t.localOrigin.vec3[2],o(_,B),s(_,_),f.write(B,_,t.geometry.attributes,t.geometry.olidColor,e.geometry,n.geometry,a.texture),null!=e.texture&&f.writeTextureBuffer&&f.writeTextureBuffer(B,_,t.geometry.attributes,e.texture,n.texture))}_setTargetSubData(t,e,r,o,s,n=0){if("geometry"===t){const a=e.getTargetBuffer(t);a?.setSubData(s,o.from*r,n,o.numElements*r)}else if("texture"===t){const r=e.getTargetBuffer(t);r?.setSubData(s.buffer,o.from,n,o.numElements)}}static prune(){w=new Uint8Array(b)}}const B=n(),_=n(),b=262144,d=1024,x=16777216;let w=new Uint8Array(b);function S(t){return w.byteLength<t&&(w=new Uint8Array(t)),w}function v(t){return 4*Math.ceil(t/4)}function I(e){return e<=d?d:e<b?t(e):Math.max(Math.min(Math.ceil(1.5*e/b)*b,x),e)}export{y as VaoWriter};