2
0
Эх сурвалжийг харах

WebGPUUniformsGroup: Manage buffer according to STD140 layout.

Mugen87 4 жил өмнө
parent
commit
1cf4431f75

+ 10 - 8
examples/jsm/renderers/webgpu/WebGPUUniform.js

@@ -7,9 +7,11 @@ class WebGPUUniform {
 		this.name = name;
 		this.value = value;
 
-		this.byteLength = 0;
+		this.boundary = 0; // used to build the uniform buffer according to the STD140 layout
 		this.itemSize = 0;
 
+		this.offset = 0; // this property is set by WebGPUUniformsGroup and marks the start position in the uniform buffer
+
 	}
 
 	setValue( value ) {
@@ -26,7 +28,7 @@ class FloatUniform extends WebGPUUniform {
 
 		super( name, value );
 
-		this.byteLength = 4;
+		this.boundary = 4;
 		this.itemSize = 1;
 
 		Object.defineProperty( this, 'isFloatUniform', { value: true } );
@@ -41,7 +43,7 @@ class Vector2Uniform extends WebGPUUniform {
 
 		super( name, value );
 
-		this.byteLength = 8;
+		this.boundary = 8;
 		this.itemSize = 2;
 
 		Object.defineProperty( this, 'isVector2Uniform', { value: true } );
@@ -56,7 +58,7 @@ class Vector3Uniform extends WebGPUUniform {
 
 		super( name, value );
 
-		this.byteLength = 12;
+		this.boundary = 16;
 		this.itemSize = 3;
 
 		Object.defineProperty( this, 'isVector3Uniform', { value: true } );
@@ -71,7 +73,7 @@ class Vector4Uniform extends WebGPUUniform {
 
 		super( name, value );
 
-		this.byteLength = 16;
+		this.boundary = 16;
 		this.itemSize = 4;
 
 		Object.defineProperty( this, 'isVector4Uniform', { value: true } );
@@ -86,7 +88,7 @@ class ColorUniform extends WebGPUUniform {
 
 		super( name, value );
 
-		this.byteLength = 12;
+		this.boundary = 16;
 		this.itemSize = 3;
 
 		Object.defineProperty( this, 'isColorUniform', { value: true } );
@@ -101,7 +103,7 @@ class Matrix3Uniform extends WebGPUUniform {
 
 		super( name, value );
 
-		this.byteLength = 48; // (3 * 4) * 4 bytes
+		this.boundary = 48;
 		this.itemSize = 12;
 
 		Object.defineProperty( this, 'isMatrix3Uniform', { value: true } );
@@ -116,7 +118,7 @@ class Matrix4Uniform extends WebGPUUniform {
 
 		super( name, value );
 
-		this.byteLength = 64;
+		this.boundary = 64;
 		this.itemSize = 16;
 
 		Object.defineProperty( this, 'isMatrix4Uniform', { value: true } );

+ 48 - 23
examples/jsm/renderers/webgpu/WebGPUUniformsGroup.js

@@ -13,6 +13,7 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 		this.onBeforeUpdate = function () {};
 
+		this.bytesPerElement = Float32Array.BYTES_PER_ELEMENT;
 		this.type = GPUBindingType.UniformBuffer;
 		this.visibility = GPUShaderStage.VERTEX;
 
@@ -57,59 +58,77 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 	getByteLength() {
 
-		let byteLength = 0;
+		let offset = 0; // global buffer offset in bytes
+		const chunkSize = 16; // size of a chunk in bytes (STD140 layout)
 
-		for ( const uniform of this.uniforms ) {
+		for ( let i = 0, l = this.uniforms.length; i < l; i ++ ) {
+
+			const uniform = this.uniforms[ i ];
+
+			// offset within a single chunk in bytes
+
+			const chunkOffset = offset % chunkSize;
+			const remainingSizeInChunk = chunkSize - chunkOffset;
+
+			// check for chunk overflow
+
+			if ( chunkOffset !== 0 && ( remainingSizeInChunk - uniform.boundary ) < 0 ) {
 
-			byteLength += uniform.byteLength;
+				// add padding and adjust offset
+
+				offset += ( chunkSize - chunkOffset );
+
+			}
+
+			uniform.offset = ( offset / this.bytesPerElement );
+
+			offset += ( uniform.itemSize * this.bytesPerElement );
 
 		}
 
-		return byteLength;
+		return offset;
 
 	}
 
 	update() {
 
 		let updated = false;
-		let offset = 0;
 
 		for ( const uniform of this.uniforms ) {
 
-			if ( this.updateByType( uniform, offset ) === true ) {
+			if ( this.updateByType( uniform ) === true ) {
 
 				updated = true;
 
 			}
 
-			offset += uniform.itemSize;
-
 		}
 
 		return updated;
 
 	}
 
-	updateByType( uniform, offset ) {
+	updateByType( uniform ) {
 
-		if ( uniform.isFloatUniform ) return this.updateNumber( uniform, offset );
-		if ( uniform.isVector2Uniform ) return this.updateVector2( uniform, offset );
-		if ( uniform.isVector3Uniform ) return this.updateVector3( uniform, offset );
-		if ( uniform.isVector4Uniform ) return this.updateVector4( uniform, offset );
-		if ( uniform.isColorUniform ) return this.updateColor( uniform, offset );
-		if ( uniform.isMatrix3Uniform ) return this.updateMatrix3( uniform, offset );
-		if ( uniform.isMatrix4Uniform ) return this.updateMatrix4( uniform, offset );
+		if ( uniform.isFloatUniform ) return this.updateNumber( uniform );
+		if ( uniform.isVector2Uniform ) return this.updateVector2( uniform );
+		if ( uniform.isVector3Uniform ) return this.updateVector3( uniform );
+		if ( uniform.isVector4Uniform ) return this.updateVector4( uniform );
+		if ( uniform.isColorUniform ) return this.updateColor( uniform );
+		if ( uniform.isMatrix3Uniform ) return this.updateMatrix3( uniform );
+		if ( uniform.isMatrix4Uniform ) return this.updateMatrix4( uniform );
 
 		console.error( 'THREE.WebGPUUniformsGroup: Unsupported uniform type.', uniform );
 
 	}
 
-	updateNumber( uniform, offset ) {
+	updateNumber( uniform ) {
 
 		let updated = false;
 
 		const a = this.array;
 		const v = uniform.value;
+		const offset = uniform.offset;
 
 		if ( a[ offset ] !== v ) {
 
@@ -122,12 +141,13 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 	}
 
-	updateVector2( uniform, offset ) {
+	updateVector2( uniform ) {
 
 		let updated = false;
 
 		const a = this.array;
 		const v = uniform.value;
+		const offset = uniform.offset;
 
 		if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y ) {
 
@@ -142,12 +162,13 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 	}
 
-	updateVector3( uniform, offset ) {
+	updateVector3( uniform ) {
 
 		let updated = false;
 
 		const a = this.array;
 		const v = uniform.value;
+		const offset = uniform.offset;
 
 		if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y || a[ offset + 2 ] !== v.z ) {
 
@@ -163,12 +184,13 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 	}
 
-	updateVector4( uniform, offset ) {
+	updateVector4( uniform ) {
 
 		let updated = false;
 
 		const a = this.array;
 		const v = uniform.value;
+		const offset = uniform.offset;
 
 		if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y || a[ offset + 2 ] !== v.z || a[ offset + 4 ] !== v.w ) {
 
@@ -185,12 +207,13 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 	}
 
-	updateColor( uniform, offset ) {
+	updateColor( uniform ) {
 
 		let updated = false;
 
 		const a = this.array;
 		const c = uniform.value;
+		const offset = uniform.offset;
 
 		if ( a[ offset + 0 ] !== c.r || a[ offset + 1 ] !== c.g || a[ offset + 2 ] !== c.b ) {
 
@@ -206,12 +229,13 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 	}
 
-	updateMatrix3( uniform, offset ) {
+	updateMatrix3( uniform ) {
 
 		let updated = false;
 
 		const a = this.array;
 		const e = uniform.value.elements;
+		const offset = uniform.offset;
 
 		if ( a[ offset + 0 ] !== e[ 0 ] || a[ offset + 1 ] !== e[ 1 ] || a[ offset + 2 ] !== e[ 2 ] ||
 			a[ offset + 4 ] !== e[ 3 ] || a[ offset + 5 ] !== e[ 4 ] || a[ offset + 6 ] !== e[ 5 ] ||
@@ -235,12 +259,13 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 
 	}
 
-	updateMatrix4( uniform, offset ) {
+	updateMatrix4( uniform ) {
 
 		let updated = false;
 
 		const a = this.array;
 		const e = uniform.value.elements;
+		const offset = uniform.offset;
 
 		if ( arraysEqual( a, e, offset ) === false ) {