Просмотр исходного кода

WebGPURenderer: sort bind groups and minimise setBindGroup() commands (#29256)

* sort and minimixe setbindgroup()

* lint

---------

Co-authored-by: aardgoose <angus.sawyer@email.com>
aardgoose 1 год назад
Родитель
Сommit
6b74981b67

+ 17 - 0
src/nodes/core/NodeBuilder.js

@@ -277,6 +277,23 @@ class NodeBuilder {
 
 	}
 
+	sortBindingGroups() {
+
+		const bindingsGroups = this.getBindings();
+
+		bindingsGroups.sort( ( a, b ) => ( a.bindings[ 0 ].groupNode.order - b.bindings[ 0 ].groupNode.order ) );
+
+		for ( let i = 0; i < bindingsGroups.length; i ++ ) {
+
+			const bindingGroup = bindingsGroups[ i ];
+			this.bindingsIndexes[ bindingGroup.name ].group = i;
+
+			bindingGroup.index = i;
+
+		}
+
+	}
+
 	setHashNode( node, hash ) {
 
 		this.hashNodes[ hash ] = node;

+ 3 - 3
src/nodes/core/UniformGroupNode.js

@@ -8,7 +8,7 @@ class UniformGroupNode extends Node {
 
 	}
 
-	constructor( name, shared = false ) {
+	constructor( name, shared = false, order = 1 ) {
 
 		super( 'string' );
 
@@ -16,7 +16,7 @@ class UniformGroupNode extends Node {
 		this.version = 0;
 
 		this.shared = shared;
-
+		this.order = order;
 		this.isUniformGroup = true;
 
 	}
@@ -52,7 +52,7 @@ class UniformGroupNode extends Node {
 export default UniformGroupNode;
 
 export const uniformGroup = ( name ) => new UniformGroupNode( name );
-export const sharedUniformGroup = ( name ) => new UniformGroupNode( name, true );
+export const sharedUniformGroup = ( name, order = 0 ) => new UniformGroupNode( name, true, order );
 
 export const frameGroup = /*@__PURE__*/ sharedUniformGroup( 'frame' );
 export const renderGroup = /*@__PURE__*/ sharedUniformGroup( 'render' );

+ 11 - 4
src/renderers/webgpu/WebGPUBackend.js

@@ -425,7 +425,7 @@ class WebGPUBackend extends Backend {
 		renderContextData.descriptor = descriptor;
 		renderContextData.encoder = encoder;
 		renderContextData.currentPass = currentPass;
-		renderContextData.currentSets = { attributes: {}, pipeline: null, index: null };
+		renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null };
 		renderContextData.renderBundles = [];
 
 		//
@@ -848,12 +848,19 @@ class WebGPUBackend extends Backend {
 
 		// bind groups
 
+		const currentBindingGroups = currentSets.bindingGroups;
+
 		for ( let i = 0, l = bindings.length; i < l; i ++ ) {
 
 			const bindGroup = bindings[ i ];
 			const bindingsData = this.get( bindGroup );
 
-			passEncoderGPU.setBindGroup( bindGroup.index, bindingsData.group );
+			if ( currentBindingGroups[ bindGroup.index ] !== bindGroup.id ) {
+
+				passEncoderGPU.setBindGroup( bindGroup.index, bindingsData.group );
+				currentBindingGroups[ bindGroup.index ] = bindGroup.id;
+
+			}
 
 		}
 
@@ -1286,7 +1293,7 @@ class WebGPUBackend extends Backend {
 		renderContextData._currentPass = renderContextData.currentPass;
 		renderContextData._currentSets = renderContextData.currentSets;
 
-		renderContextData.currentSets = { attributes: {}, pipeline: null, index: null };
+		renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null };
 		renderContextData.currentPass = this.pipelineUtils.createBundleEncoder( renderContext );
 
 	}
@@ -1515,7 +1522,7 @@ class WebGPUBackend extends Backend {
 		if ( renderContext.stencil ) descriptor.depthStencilAttachment.stencilLoadOp = GPULoadOp.Load;
 
 		renderContextData.currentPass = encoder.beginRenderPass( descriptor );
-		renderContextData.currentSets = { attributes: {}, pipeline: null, index: null };
+		renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null };
 
 	}
 

+ 2 - 0
src/renderers/webgpu/nodes/WGSLNodeBuilder.js

@@ -1043,6 +1043,8 @@ ${ flowData.code }
 
 		const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} };
 
+		this.sortBindingGroups();
+
 		for ( const shaderStage in shadersData ) {
 
 			const stageData = shadersData[ shaderStage ];

粤ICP备19079148号