浏览代码

TSL: Respect types in WGSL Layouts (#28669)

* respect types in wgsl layouts

* support all wgsl types in parser

* fix webgpu_compute_texture_pingpong

* cleanup
Renaud Rohlinger 1 年之前
父节点
当前提交
903d50d045
共有 2 个文件被更改,包括 55 次插入33 次删除
  1. 47 25
      examples/jsm/renderers/webgpu/nodes/WGSLNodeFunction.js
  2. 8 8
      examples/webgpu_tsl_interoperability.html

+ 47 - 25
examples/jsm/renderers/webgpu/nodes/WGSLNodeFunction.js

@@ -2,10 +2,43 @@ import NodeFunction from '../../../nodes/core/NodeFunction.js';
 import NodeFunctionInput from '../../../nodes/core/NodeFunctionInput.js';
 
 const declarationRegexp = /^[fn]*\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*[\-\>]*\s*([a-z_0-9]+)?/i;
-const propertiesRegexp = /[a-z_0-9]+|<(.*?)>+/ig;
+const propertiesRegexp = /([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/ig;
 
 const wgslTypeLib = {
-	f32: 'float'
+	'f32': 'float',
+	'i32': 'int',
+	'u32': 'uint',
+	'bool': 'bool',
+
+	'vec2<f32>': 'vec2',
+ 	'vec2<i32>': 'ivec2',
+ 	'vec2<u32>': 'uvec2',
+ 	'vec2<bool>': 'bvec2',
+
+	'vec3<f32>': 'vec3',
+	'vec3<i32>': 'ivec3',
+	'vec3<u32>': 'uvec3',
+	'vec3<bool>': 'bvec3',
+
+	'vec4<f32>': 'vec4',
+	'vec4<i32>': 'ivec4',
+	'vec4<u32>': 'uvec4',
+	'vec4<bool>': 'bvec4',
+
+	'mat2x2<f32>': 'mat2',
+	'mat2x2<i32>': 'imat2',
+	'mat2x2<u32>': 'umat2',
+	'mat2x2<bool>': 'bmat2',
+
+	'mat3x3<f32>': 'mat3',
+	'mat3x3<i32>': 'imat3',
+	'mat3x3<u32>': 'umat3',
+	'mat3x3<bool>': 'bmat3',
+
+	'mat4x4<f32>': 'mat4',
+	'mat4x4<i32>': 'imat4',
+	'mat4x4<u32>': 'umat4',
+	'mat4x4<bool>': 'bmat4'
 };
 
 const parse = ( source ) => {
@@ -16,47 +49,36 @@ const parse = ( source ) => {
 
 	if ( declaration !== null && declaration.length === 4 ) {
 
-		// tokenizer
-
 		const inputsCode = declaration[ 2 ];
 		const propsMatches = [];
+		let match = null;
 
-		let nameMatch = null;
-
-		while ( ( nameMatch = propertiesRegexp.exec( inputsCode ) ) !== null ) {
+		while ( ( match = propertiesRegexp.exec( inputsCode ) ) !== null ) {
 
-			propsMatches.push( nameMatch );
+			propsMatches.push( { name: match[ 1 ], type: match[ 2 ] } );
 
 		}
 
-		// parser
-
+		// Process matches to correctly pair names and types
 		const inputs = [];
+		for ( let i = 0; i < propsMatches.length; i ++ ) {
 
-		let i = 0;
+			const { name, type } = propsMatches[ i ];
 
-		while ( i < propsMatches.length ) {
+			let resolvedType = type;
 
-			// default
+			if ( resolvedType.startsWith( 'texture' ) ) {
 
-			const name = propsMatches[ i ++ ][ 0 ];
-			let type = propsMatches[ i ++ ][ 0 ];
+				resolvedType = type.split( '<' )[ 0 ];
 
-			type = wgslTypeLib[ type ] || type;
+			}
 
-			// precision
+			resolvedType = wgslTypeLib[ resolvedType ] || resolvedType;
 
-			if ( i < propsMatches.length && propsMatches[ i ][ 0 ].startsWith( '<' ) === true )
-				i ++;
-
-			// add input
-
-			inputs.push( new NodeFunctionInput( type, name ) );
+			inputs.push( new NodeFunctionInput( resolvedType, name ) );
 
 		}
 
-		//
-
 		const blockCode = source.substring( declaration[ 0 ].length );
 
 		const name = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';

+ 8 - 8
examples/webgpu_tsl_interoperability.html

@@ -32,7 +32,7 @@
 			import WebGL from 'three/addons/capabilities/WebGL.js';
 
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
-			import { tslFn, attribute, varyingProperty, timerLocal, uniform, wgslFn, texture, uv, clamp, float, vec2, vec3, fract, floor, MeshBasicNodeMaterial, positionGeometry, sin } from 'three/nodes';
+			import { tslFn, sampler, attribute, varyingProperty, timerLocal, uniform, wgslFn, texture, uv, clamp, float, vec2, vec3, fract, floor, MeshBasicNodeMaterial, positionGeometry, sin } from 'three/nodes';
 
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
@@ -109,12 +109,12 @@
 							crtHeight
 						);
 						// Coordinate for each cell in the pixel map
-						var coord = pixel / cellSize;
+						let coord = pixel / cellSize;
 						// Three color values for each cell (r, g, b)
-						var subcoord = coord * vec2f( 3.0, 1.0 );
-						var offset = vec2<f32>( 0, fract( floor( coord.x ) * cellOffset ) );
+						let subcoord = coord * vec2f( 3.0, 1.0 );
+						let offset = vec2<f32>( 0, fract( floor( coord.x ) * cellOffset ) );
 
-						var maskCoord = floor( coord + offset ) * cellSize;
+						let maskCoord = floor( coord + offset ) * cellSize;
 
 						var samplePoint = maskCoord / vec2<f32>(crtWidth, crtHeight);
 						samplePoint.x += fract( time * speed / 20 );
@@ -127,7 +127,7 @@
 
 						// Current implementation does not give an even amount of space to each r, g, b unit of a cell
 						// Fix/hack this by multiplying subCoord.x by cellSize at cellSizes below 6
-						var ind = floor( subcoord.x ) % 3;
+						let ind = floor( subcoord.x ) % 3;
 
 						var maskColor = vec3<f32>(
 							f32( ind == 0.0 ), 
@@ -135,7 +135,7 @@
 							f32( ind == 2.0 )
 						) * 3.0;
 
-						var cellUV = fract( subcoord + offset ) * 2.0 - 1.0;
+						let cellUV = fract( subcoord + offset ) * 2.0 - 1.0;
 						var border: vec2<f32> = 1.0 - cellUV * cellUV * borderMask;
 
 						maskColor *= vec3f( clamp( border.x, 0.0, 1.0 ) * clamp( border.y, 0.0, 1.0) );
@@ -180,7 +180,7 @@
 				wgslShaderMaterial.fragmentNode = wgslFragmentShader( {
 					vUv: vUv,
 					tex: texture( planetTexture ),
-					texSampler: texture( planetTexture ),
+					texSampler: sampler( planetTexture ),
 					crtWidth: crtWidthUniform,
 					crtHeight: crtHeightUniform,
 					cellOffset: cellOffsetUniform,