Buckets:
| function WebGLAttributes( gl ) { | |
| const buffers = new WeakMap(); | |
| function createBuffer( attribute, bufferType ) { | |
| const array = attribute.array; | |
| const usage = attribute.usage; | |
| const size = array.byteLength; | |
| const buffer = gl.createBuffer(); | |
| gl.bindBuffer( bufferType, buffer ); | |
| gl.bufferData( bufferType, array, usage ); | |
| attribute.onUploadCallback(); | |
| let type; | |
| if ( array instanceof Float32Array ) { | |
| type = gl.FLOAT; | |
| } else if ( array instanceof Uint16Array ) { | |
| if ( attribute.isFloat16BufferAttribute ) { | |
| type = gl.HALF_FLOAT; | |
| } else { | |
| type = gl.UNSIGNED_SHORT; | |
| } | |
| } else if ( array instanceof Int16Array ) { | |
| type = gl.SHORT; | |
| } else if ( array instanceof Uint32Array ) { | |
| type = gl.UNSIGNED_INT; | |
| } else if ( array instanceof Int32Array ) { | |
| type = gl.INT; | |
| } else if ( array instanceof Int8Array ) { | |
| type = gl.BYTE; | |
| } else if ( array instanceof Uint8Array ) { | |
| type = gl.UNSIGNED_BYTE; | |
| } else if ( array instanceof Uint8ClampedArray ) { | |
| type = gl.UNSIGNED_BYTE; | |
| } else { | |
| throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); | |
| } | |
| return { | |
| buffer: buffer, | |
| type: type, | |
| bytesPerElement: array.BYTES_PER_ELEMENT, | |
| version: attribute.version, | |
| size: size | |
| }; | |
| } | |
| function updateBuffer( buffer, attribute, bufferType ) { | |
| const array = attribute.array; | |
| const updateRanges = attribute.updateRanges; | |
| gl.bindBuffer( bufferType, buffer ); | |
| if ( updateRanges.length === 0 ) { | |
| // Not using update ranges | |
| gl.bufferSubData( bufferType, 0, array ); | |
| } else { | |
| // Before applying update ranges, we merge any adjacent / overlapping | |
| // ranges to reduce load on `gl.bufferSubData`. Empirically, this has led | |
| // to performance improvements for applications which make heavy use of | |
| // update ranges. Likely due to GPU command overhead. | |
| // | |
| // Note that to reduce garbage collection between frames, we merge the | |
| // update ranges in-place. This is safe because this method will clear the | |
| // update ranges once updated. | |
| updateRanges.sort( ( a, b ) => a.start - b.start ); | |
| // To merge the update ranges in-place, we work from left to right in the | |
| // existing updateRanges array, merging ranges. This may result in a final | |
| // array which is smaller than the original. This index tracks the last | |
| // index representing a merged range, any data after this index can be | |
| // trimmed once the merge algorithm is completed. | |
| let mergeIndex = 0; | |
| for ( let i = 1; i < updateRanges.length; i ++ ) { | |
| const previousRange = updateRanges[ mergeIndex ]; | |
| const range = updateRanges[ i ]; | |
| // We add one here to merge adjacent ranges. This is safe because ranges | |
| // operate over positive integers. | |
| if ( range.start <= previousRange.start + previousRange.count + 1 ) { | |
| previousRange.count = Math.max( | |
| previousRange.count, | |
| range.start + range.count - previousRange.start | |
| ); | |
| } else { | |
| ++ mergeIndex; | |
| updateRanges[ mergeIndex ] = range; | |
| } | |
| } | |
| // Trim the array to only contain the merged ranges. | |
| updateRanges.length = mergeIndex + 1; | |
| for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { | |
| const range = updateRanges[ i ]; | |
| gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, | |
| array, range.start, range.count ); | |
| } | |
| attribute.clearUpdateRanges(); | |
| } | |
| attribute.onUploadCallback(); | |
| } | |
| // | |
| function get( attribute ) { | |
| if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; | |
| return buffers.get( attribute ); | |
| } | |
| function remove( attribute ) { | |
| if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; | |
| const data = buffers.get( attribute ); | |
| if ( data ) { | |
| gl.deleteBuffer( data.buffer ); | |
| buffers.delete( attribute ); | |
| } | |
| } | |
| function update( attribute, bufferType ) { | |
| if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; | |
| if ( attribute.isGLBufferAttribute ) { | |
| const cached = buffers.get( attribute ); | |
| if ( ! cached || cached.version < attribute.version ) { | |
| buffers.set( attribute, { | |
| buffer: attribute.buffer, | |
| type: attribute.type, | |
| bytesPerElement: attribute.elementSize, | |
| version: attribute.version | |
| } ); | |
| } | |
| return; | |
| } | |
| const data = buffers.get( attribute ); | |
| if ( data === undefined ) { | |
| buffers.set( attribute, createBuffer( attribute, bufferType ) ); | |
| } else if ( data.version < attribute.version ) { | |
| if ( data.size !== attribute.array.byteLength ) { | |
| throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' ); | |
| } | |
| updateBuffer( data.buffer, attribute, bufferType ); | |
| data.version = attribute.version; | |
| } | |
| } | |
| return { | |
| get: get, | |
| remove: remove, | |
| update: update | |
| }; | |
| } | |
| export { WebGLAttributes }; | |
Xet Storage Details
- Size:
- 4.97 kB
- Xet hash:
- b44393bf249a6b2f5d78986a645cc044e5bd7e92328a30ebcbd51bdc0b8a0b9d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.