Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/flo-bit/shapecraft. flo-bit.dev/shapecraft
Something went wrong. Try again.
5.7 kB · 264 lines
JavaScript
at commit 049ef598
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265import { IntType } from '../../../constants.js';
let _id = 0;
class DualAttributeData {
constructor( attributeData, dualBuffer ) {
this.buffers = [ attributeData.bufferGPU, dualBuffer ]; this.type = attributeData.type; this.bufferType = attributeData.bufferType; this.pbo = attributeData.pbo; this.byteLength = attributeData.byteLength; this.bytesPerElement = attributeData.BYTES_PER_ELEMENT; this.version = attributeData.version; this.isInteger = attributeData.isInteger; this.activeBufferIndex = 0; this.baseId = attributeData.id;
}
get id() {
return `${ this.baseId }|${ this.activeBufferIndex }`;
}
get bufferGPU() {
return this.buffers[ this.activeBufferIndex ];
}
get transformBuffer() {
return this.buffers[ this.activeBufferIndex ^ 1 ];
}
switchBuffers() {
this.activeBufferIndex ^= 1;
}
}
class WebGLAttributeUtils {
constructor( backend ) {
this.backend = backend;
}
createAttribute( attribute, bufferType ) {
const backend = this.backend; const { gl } = backend;
const array = attribute.array; const usage = attribute.usage || gl.STATIC_DRAW;
const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; const bufferData = backend.get( bufferAttribute );
let bufferGPU = bufferData.bufferGPU;
if ( bufferGPU === undefined ) {
bufferGPU = this._createBuffer( gl, bufferType, array, usage );
bufferData.bufferGPU = bufferGPU; bufferData.bufferType = bufferType; bufferData.version = bufferAttribute.version;
}
//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.WebGLBackend: Unsupported buffer data format: ' + array );
}
let attributeData = { bufferGPU, bufferType, type, byteLength: array.byteLength, bytesPerElement: array.BYTES_PER_ELEMENT, version: attribute.version, pbo: attribute.pbo, isInteger: type === gl.INT || type === gl.UNSIGNED_INT || attribute.gpuType === IntType, id: _id ++ };
if ( attribute.isStorageBufferAttribute || attribute.isStorageInstancedBufferAttribute ) {
// create buffer for tranform feedback use const bufferGPUDual = this._createBuffer( gl, bufferType, array, usage ); attributeData = new DualAttributeData( attributeData, bufferGPUDual );
}
backend.set( attribute, attributeData );
}
updateAttribute( attribute ) {
const backend = this.backend; const { gl } = backend;
const array = attribute.array; const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; const bufferData = backend.get( bufferAttribute ); const bufferType = bufferData.bufferType; const updateRanges = attribute.isInterleavedBufferAttribute ? attribute.data.updateRanges : attribute.updateRanges;
gl.bindBuffer( bufferType, bufferData.bufferGPU );
if ( updateRanges.length === 0 ) {
// Not using update ranges
gl.bufferSubData( bufferType, 0, array );
} else {
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 );
}
bufferAttribute.clearUpdateRanges();
}
gl.bindBuffer( bufferType, null );
bufferData.version = bufferAttribute.version;
}
destroyAttribute( attribute ) {
const backend = this.backend; const { gl } = backend;
if ( attribute.isInterleavedBufferAttribute ) {
backend.delete( attribute.data );
}
const attributeData = backend.get( attribute );
gl.deleteBuffer( attributeData.bufferGPU );
backend.delete( attribute );
}
async getArrayBufferAsync( attribute ) {
const backend = this.backend; const { gl } = backend;
const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; const { bufferGPU } = backend.get( bufferAttribute );
const array = attribute.array; const byteLength = array.byteLength;
gl.bindBuffer( gl.COPY_READ_BUFFER, bufferGPU );
const writeBuffer = gl.createBuffer();
gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer ); gl.bufferData( gl.COPY_WRITE_BUFFER, byteLength, gl.STREAM_READ );
gl.copyBufferSubData( gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, byteLength );
await backend.utils._clientWaitAsync();
const dstBuffer = new attribute.array.constructor( array.length );
// Ensure the buffer is bound before reading gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer );
gl.getBufferSubData( gl.COPY_WRITE_BUFFER, 0, dstBuffer );
gl.deleteBuffer( writeBuffer );
gl.bindBuffer( gl.COPY_READ_BUFFER, null ); gl.bindBuffer( gl.COPY_WRITE_BUFFER, null );
return dstBuffer.buffer;
}
_createBuffer( gl, bufferType, array, usage ) {
const bufferGPU = gl.createBuffer();
gl.bindBuffer( bufferType, bufferGPU ); gl.bufferData( bufferType, array, usage ); gl.bindBuffer( bufferType, null );
return bufferGPU;
}
}
export default WebGLAttributeUtils;