Browse Source

WebGPUUniformBuffer: Chunk size following STD140 layout (#22489)

* WebGPUUniformBuffer: Chunk size following STD140 layout

* WebGPUUniformBuffer: Chunk size following STD140 layout

This reverts commit 0db22e1d86e90a1810c765b7836904c11b2e473d.

* WebGPUBufferUtils.getFloatLength()

* WebGPUBufferUtils: update tree-shaking style

* add WebGPUBufferUtils.getVectorLength()

* two vector3 for chunk size validation

* update mrdoob code style
sunag 3 years ago
parent
commit
105bd07ffc

+ 26 - 0
examples/jsm/renderers/webgpu/WebGPUBufferUtils.js

@@ -0,0 +1,26 @@
+import { GPUChunkSize } from './constants.js';
+
+function getFloatLength( floatLength ) {
+
+	// ensure chunk size alignment (STD140 layout)
+
+	return floatLength + ( ( GPUChunkSize - ( floatLength % GPUChunkSize ) ) % GPUChunkSize );
+
+}
+
+function getVectorLength( count, vectorLength ) {
+
+	const strideLength = 4;
+
+	vectorLength = vectorLength + ( ( strideLength - ( vectorLength % strideLength ) ) % strideLength );
+
+	const floatLength = vectorLength * count;
+
+	return getFloatLength( floatLength );
+
+}
+
+export {
+	getFloatLength,
+	getVectorLength
+};

+ 3 - 3
examples/jsm/renderers/webgpu/WebGPUUniformBuffer.js

@@ -1,4 +1,6 @@
 import WebGPUBinding from './WebGPUBinding.js';
 import WebGPUBinding from './WebGPUBinding.js';
+import { getFloatLength } from './WebGPUBufferUtils.js';
+
 import { GPUBindingType } from './constants.js';
 import { GPUBindingType } from './constants.js';
 
 
 class WebGPUUniformBuffer extends WebGPUBinding {
 class WebGPUUniformBuffer extends WebGPUBinding {
@@ -20,9 +22,7 @@ class WebGPUUniformBuffer extends WebGPUBinding {
 
 
 	getByteLength() {
 	getByteLength() {
 
 
-		const buffer = 	this.buffer;
-
-		return buffer.byteLength + ( ( 4 - ( buffer.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
+		return getFloatLength( this.buffer.byteLength );
 
 
 	}
 	}
 
 

+ 4 - 4
examples/jsm/renderers/webgpu/WebGPUUniformsGroup.js

@@ -1,4 +1,5 @@
 import WebGPUUniformBuffer from './WebGPUUniformBuffer.js';
 import WebGPUUniformBuffer from './WebGPUUniformBuffer.js';
+import { GPUChunkSize } from './constants.js';
 
 
 class WebGPUUniformsGroup extends WebGPUUniformBuffer {
 class WebGPUUniformsGroup extends WebGPUUniformBuffer {
 
 
@@ -55,7 +56,6 @@ class WebGPUUniformsGroup extends WebGPUUniformBuffer {
 	getByteLength() {
 	getByteLength() {
 
 
 		let offset = 0; // global buffer offset in bytes
 		let offset = 0; // global buffer offset in bytes
-		const chunkSize = 16; // size of a chunk in bytes (STD140 layout)
 
 
 		for ( let i = 0, l = this.uniforms.length; i < l; i ++ ) {
 		for ( let i = 0, l = this.uniforms.length; i < l; i ++ ) {
 
 
@@ -63,8 +63,8 @@ class WebGPUUniformsGroup extends WebGPUUniformBuffer {
 
 
 			// offset within a single chunk in bytes
 			// offset within a single chunk in bytes
 
 
-			const chunkOffset = offset % chunkSize;
-			const remainingSizeInChunk = chunkSize - chunkOffset;
+			const chunkOffset = offset % GPUChunkSize;
+			const remainingSizeInChunk = GPUChunkSize - chunkOffset;
 
 
 			// conformance tests
 			// conformance tests
 
 
@@ -72,7 +72,7 @@ class WebGPUUniformsGroup extends WebGPUUniformBuffer {
 
 
 				// check for chunk overflow
 				// check for chunk overflow
 
 
-				offset += ( chunkSize - chunkOffset );
+				offset += ( GPUChunkSize - chunkOffset );
 
 
 			} else if ( chunkOffset % uniform.boundary !== 0 ) {
 			} else if ( chunkOffset % uniform.boundary !== 0 ) {
 
 

+ 2 - 0
examples/jsm/renderers/webgpu/constants.js

@@ -252,6 +252,8 @@ export const GPUInputStepMode = {
 	Instance: 'instance'
 	Instance: 'instance'
 };
 };
 
 
+export const GPUChunkSize = 16; // size of a chunk in bytes (STD140 layout)
+
 // @TODO: Move to src/constants.js
 // @TODO: Move to src/constants.js
 
 
 export const BlendColorFactor = 211;
 export const BlendColorFactor = 211;

+ 8 - 5
examples/webgpu_compute.html

@@ -30,6 +30,7 @@
 
 
 			import WebGPUStorageBuffer from './jsm/renderers/webgpu/WebGPUStorageBuffer.js';
 			import WebGPUStorageBuffer from './jsm/renderers/webgpu/WebGPUStorageBuffer.js';
 			import WebGPUUniformBuffer from './jsm/renderers/webgpu/WebGPUUniformBuffer.js';
 			import WebGPUUniformBuffer from './jsm/renderers/webgpu/WebGPUUniformBuffer.js';
+			import * as WebGPUBufferUtils from './jsm/renderers/webgpu/WebGPUBufferUtils.js';
 			import WebGPUUniformsGroup from './jsm/renderers/webgpu/WebGPUUniformsGroup.js';
 			import WebGPUUniformsGroup from './jsm/renderers/webgpu/WebGPUUniformsGroup.js';
 			import { Vector2Uniform } from './jsm/renderers/webgpu/WebGPUUniform.js';
 			import { Vector2Uniform } from './jsm/renderers/webgpu/WebGPUUniform.js';
 
 
@@ -80,7 +81,9 @@
 				const particleBuffer = new WebGPUStorageBuffer( 'particle', new THREE.BufferAttribute( particleArray, 3 ) );
 				const particleBuffer = new WebGPUStorageBuffer( 'particle', new THREE.BufferAttribute( particleArray, 3 ) );
 				const velocityBuffer = new WebGPUStorageBuffer( 'velocity', new THREE.BufferAttribute( velocityArray, 3 ) );
 				const velocityBuffer = new WebGPUStorageBuffer( 'velocity', new THREE.BufferAttribute( velocityArray, 3 ) );
 
 
-				scaleUniformBuffer = new WebGPUUniformBuffer( 'scaleUniform', new Float32Array( 3 ) ); // single vector3
+				const scaleUniformLength = WebGPUBufferUtils.getVectorLength( 2, 3 ); // two vector3 for array
+
+				scaleUniformBuffer = new WebGPUUniformBuffer( 'scaleUniform', new Float32Array( scaleUniformLength ) ); 
 
 
 				pointer = new THREE.Vector2( - 10.0, - 10.0 ); // Out of bounds first
 				pointer = new THREE.Vector2( - 10.0, - 10.0 ); // Out of bounds first
 
 
@@ -114,7 +117,7 @@
 					} velocity;
 					} velocity;
 
 
 					layout(set = 0, binding = 2) uniform Scale {
 					layout(set = 0, binding = 2) uniform Scale {
-						vec3 value;
+						vec3 value[2];
 					} scaleUniform;
 					} scaleUniform;
 
 
 					layout(set = 0, binding = 3) uniform MouseUniforms {
 					layout(set = 0, binding = 3) uniform MouseUniforms {
@@ -161,9 +164,9 @@
 
 
 						}
 						}
 
 
-						particle.particle[ index * 3 + 0 ] = position.x * scaleUniform.value.x;
-						particle.particle[ index * 3 + 1 ] = position.y * scaleUniform.value.y;
-						particle.particle[ index * 3 + 2 ] = position.z * scaleUniform.value.z;
+						particle.particle[ index * 3 + 0 ] = position.x * scaleUniform.value[0].x;
+						particle.particle[ index * 3 + 1 ] = position.y * scaleUniform.value[0].y;
+						particle.particle[ index * 3 + 2 ] = position.z * scaleUniform.value[0].z;
 
 
 					}
 					}
 				`;
 				`;