You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
2.0 KiB
123 lines
2.0 KiB
class WebGPUAttributes {
|
|
|
|
constructor( device ) {
|
|
|
|
this.buffers = new WeakMap();
|
|
this.device = device;
|
|
|
|
}
|
|
|
|
get( attribute ) {
|
|
|
|
return this.buffers.get( attribute );
|
|
|
|
}
|
|
|
|
remove( attribute ) {
|
|
|
|
const data = this.buffers.get( attribute );
|
|
|
|
if ( data ) {
|
|
|
|
data.buffer.destroy();
|
|
|
|
this.buffers.delete( attribute );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
update( attribute, isIndex = false, usage = null ) {
|
|
|
|
let data = this.buffers.get( attribute );
|
|
|
|
if ( data === undefined ) {
|
|
|
|
if ( usage === null ) {
|
|
|
|
usage = ( isIndex === true ) ? GPUBufferUsage.INDEX : GPUBufferUsage.VERTEX;
|
|
|
|
}
|
|
|
|
data = this._createBuffer( attribute, usage );
|
|
|
|
this.buffers.set( attribute, data );
|
|
|
|
} else if ( usage && usage !== data.usage ) {
|
|
|
|
data.buffer.destroy();
|
|
|
|
data = this._createBuffer( attribute, usage );
|
|
|
|
this.buffers.set( attribute, data );
|
|
|
|
} else if ( data.version < attribute.version ) {
|
|
|
|
this._writeBuffer( data.buffer, attribute );
|
|
|
|
data.version = attribute.version;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_createBuffer( attribute, usage ) {
|
|
|
|
const array = attribute.array;
|
|
const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
|
|
|
|
const buffer = this.device.createBuffer( {
|
|
size: size,
|
|
usage: usage | GPUBufferUsage.COPY_DST,
|
|
mappedAtCreation: true,
|
|
} );
|
|
|
|
new array.constructor( buffer.getMappedRange() ).set( array );
|
|
|
|
buffer.unmap();
|
|
|
|
attribute.onUploadCallback();
|
|
|
|
return {
|
|
version: attribute.version,
|
|
buffer: buffer,
|
|
usage: usage
|
|
};
|
|
|
|
}
|
|
|
|
_writeBuffer( buffer, attribute ) {
|
|
|
|
const array = attribute.array;
|
|
const updateRange = attribute.updateRange;
|
|
|
|
if ( updateRange.count === - 1 ) {
|
|
|
|
// Not using update ranges
|
|
|
|
this.device.queue.writeBuffer(
|
|
buffer,
|
|
0,
|
|
array,
|
|
0
|
|
);
|
|
|
|
} else {
|
|
|
|
this.device.queue.writeBuffer(
|
|
buffer,
|
|
0,
|
|
array,
|
|
updateRange.offset * array.BYTES_PER_ELEMENT,
|
|
updateRange.count * array.BYTES_PER_ELEMENT
|
|
);
|
|
|
|
updateRange.count = - 1; // reset range
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export default WebGPUAttributes;
|
|
|