|
@@ -34,23 +34,30 @@ class WebGPUAttributeUtils {
|
|
|
const bufferAttribute = this._getBufferAttribute( attribute );
|
|
|
|
|
|
const backend = this.backend;
|
|
|
- const device = backend.device;
|
|
|
+ const bufferData = backend.get( bufferAttribute );
|
|
|
|
|
|
- const array = bufferAttribute.array;
|
|
|
- const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
|
|
|
+ let buffer = bufferData.buffer;
|
|
|
+
|
|
|
+ if ( buffer === undefined ) {
|
|
|
|
|
|
- const buffer = device.createBuffer( {
|
|
|
- label: bufferAttribute.name,
|
|
|
- size: size,
|
|
|
- usage: usage,
|
|
|
- mappedAtCreation: true
|
|
|
- } );
|
|
|
+ const device = backend.device;
|
|
|
|
|
|
- new array.constructor( buffer.getMappedRange() ).set( array );
|
|
|
+ const array = bufferAttribute.array;
|
|
|
+ const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
|
|
|
+
|
|
|
+ buffer = device.createBuffer( {
|
|
|
+ label: bufferAttribute.name,
|
|
|
+ size: size,
|
|
|
+ usage: usage,
|
|
|
+ mappedAtCreation: true
|
|
|
+ } );
|
|
|
|
|
|
- buffer.unmap();
|
|
|
+ new array.constructor( buffer.getMappedRange() ).set( array );
|
|
|
|
|
|
- backend.get( attribute ).buffer = buffer;
|
|
|
+ buffer.unmap();
|
|
|
+
|
|
|
+ bufferData.buffer = buffer;
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
@@ -61,7 +68,7 @@ class WebGPUAttributeUtils {
|
|
|
const backend = this.backend;
|
|
|
const device = backend.device;
|
|
|
|
|
|
- const buffer = backend.get( attribute ).buffer;
|
|
|
+ const buffer = backend.get( bufferAttribute ).buffer;
|
|
|
|
|
|
const array = bufferAttribute.array;
|
|
|
const updateRange = bufferAttribute.updateRange;
|
|
@@ -93,51 +100,64 @@ class WebGPUAttributeUtils {
|
|
|
|
|
|
}
|
|
|
|
|
|
- createShaderAttributes( renderObject ) {
|
|
|
+ createShaderVertexBuffers( renderObject ) {
|
|
|
|
|
|
const attributes = renderObject.getAttributes();
|
|
|
- const shaderAttributes = [];
|
|
|
+ const vertexBuffers = new Map();
|
|
|
|
|
|
for ( let slot = 0; slot < attributes.length; slot ++ ) {
|
|
|
|
|
|
const geometryAttribute = attributes[ slot ];
|
|
|
const bytesPerElement = geometryAttribute.array.BYTES_PER_ELEMENT;
|
|
|
+ const bufferAttribute = this._getBufferAttribute( geometryAttribute );
|
|
|
|
|
|
- const format = this._getVertexFormat( geometryAttribute );
|
|
|
+ let vertexBufferLayout = vertexBuffers.get( bufferAttribute );
|
|
|
+
|
|
|
+ if ( vertexBufferLayout === undefined ) {
|
|
|
|
|
|
- let arrayStride = geometryAttribute.itemSize * bytesPerElement;
|
|
|
- let offset = 0;
|
|
|
- let stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
|
|
|
+ let arrayStride, stepMode;
|
|
|
|
|
|
- if ( geometryAttribute.isInterleavedBufferAttribute === true ) {
|
|
|
+ if ( geometryAttribute.isInterleavedBufferAttribute === true ) {
|
|
|
|
|
|
- // @TODO: It can be optimized for "vertexBuffers" on RenderPipeline
|
|
|
+ arrayStride = geometryAttribute.data.stride * bytesPerElement;
|
|
|
+ stepMode = geometryAttribute.data.isInstancedInterleavedBuffer ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
|
|
|
|
|
|
- arrayStride = geometryAttribute.data.stride * bytesPerElement;
|
|
|
- offset = geometryAttribute.offset * bytesPerElement;
|
|
|
- if ( geometryAttribute.data.isInstancedInterleavedBuffer ) stepMode = GPUInputStepMode.Instance;
|
|
|
+ } else {
|
|
|
+
|
|
|
+ arrayStride = geometryAttribute.itemSize * bytesPerElement;
|
|
|
+ stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ vertexBufferLayout = {
|
|
|
+ arrayStride,
|
|
|
+ attributes: [],
|
|
|
+ stepMode
|
|
|
+ };
|
|
|
+
|
|
|
+ vertexBuffers.set( bufferAttribute, vertexBufferLayout );
|
|
|
|
|
|
}
|
|
|
|
|
|
- shaderAttributes.push( {
|
|
|
- geometryAttribute,
|
|
|
- arrayStride,
|
|
|
- stepMode,
|
|
|
+ const format = this._getVertexFormat( geometryAttribute );
|
|
|
+ const offset = ( geometryAttribute.isInterleavedBufferAttribute === true ) ? geometryAttribute.offset * bytesPerElement : 0;
|
|
|
+
|
|
|
+ vertexBufferLayout.attributes.push( {
|
|
|
+ shaderLocation: slot,
|
|
|
offset,
|
|
|
- format,
|
|
|
- slot
|
|
|
+ format
|
|
|
} );
|
|
|
|
|
|
}
|
|
|
|
|
|
- return shaderAttributes;
|
|
|
+ return Array.from( vertexBuffers.values() );
|
|
|
|
|
|
}
|
|
|
|
|
|
destroyAttribute( attribute ) {
|
|
|
|
|
|
const backend = this.backend;
|
|
|
- const data = backend.get( attribute );
|
|
|
+ const data = backend.get( this._getBufferAttribute( attribute ) );
|
|
|
|
|
|
data.buffer.destroy();
|
|
|
|
|
@@ -150,9 +170,7 @@ class WebGPUAttributeUtils {
|
|
|
const backend = this.backend;
|
|
|
const device = backend.device;
|
|
|
|
|
|
- const data = backend.get( attribute );
|
|
|
-
|
|
|
- //const bufferAttribute = this._getBufferAttribute( attribute );
|
|
|
+ const data = backend.get( this._getBufferAttribute( attribute ) );
|
|
|
|
|
|
const bufferGPU = data.buffer;
|
|
|
const size = bufferGPU.size;
|