Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGPURenderer: Performance revision #26556

Merged
merged 1 commit into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions examples/jsm/nodes/accessors/ExtendedMaterialNode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @TODO: Is this needed? Can it be moved in MaterialNode?

import MaterialNode from './MaterialNode.js';
import { materialReference } from './MaterialReferenceNode.js';
import { normalView } from './NormalNode.js';
Expand Down Expand Up @@ -42,7 +40,7 @@ class ExtendedMaterialNode extends MaterialNode {

if ( material.normalMap ) {

node = normalMap( this.getTexture( 'normalMap' ), materialReference( 'normalScale', 'vec2' ) );
node = normalMap( this.getTexture( builder, 'normalMap' ), materialReference( 'normalScale', 'vec2' ) );

} else if ( material.bumpMap ) {

Expand All @@ -56,7 +54,7 @@ class ExtendedMaterialNode extends MaterialNode {

} else if ( scope === ExtendedMaterialNode.CLEARCOAT_NORMAL ) {

node = material.clearcoatNormalMap ? normalMap( this.getTexture( 'clearcoatNormalMap' ), materialReference( 'clearcoatNormalScale', 'vec2' ) ) : normalView;
node = material.clearcoatNormalMap ? normalMap( this.getTexture( builder, 'clearcoatNormalMap' ), materialReference( 'clearcoatNormalScale', 'vec2' ) ) : normalView;

}

Expand Down
4 changes: 2 additions & 2 deletions examples/jsm/nodes/accessors/LineMaterialNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class LineMaterialNode extends MaterialNode {

}

construct( /* builder */ ) {
construct( builder ) {

return this.getFloat( this.scope );
return this.getFloat( builder, this.scope );

}

Expand Down
88 changes: 55 additions & 33 deletions examples/jsm/nodes/accessors/MaterialNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { reference } from './ReferenceNode.js';
import { materialReference } from './MaterialReferenceNode.js';
import { nodeImmutable, float } from '../shadernode/ShaderNode.js';

const cache = new WeakMap();

class MaterialNode extends Node {

constructor( scope ) {
Expand All @@ -13,29 +15,49 @@ class MaterialNode extends Node {

}

getFloat( property ) {
getCache( builder, property, type ) {

//@TODO: Check if it can be cached by property name.
const material = builder.context.material;

return materialReference( property, 'float' );
let cacheMaterial = cache.get( material );

}
if ( cacheMaterial === undefined ) {

cacheMaterial = {};

cache.set( material, cacheMaterial );

}

let node = cacheMaterial[ property ];

if ( node === undefined ) {

getColor( property ) {
node = materialReference( property, type );

//@TODO: Check if it can be cached by property name.
cacheMaterial[ property ] = node;

return materialReference( property, 'color' );
}

return node;

}

getTexture( property ) {
getFloat( builder, property ) {

//@TODO: Check if it can be cached by property name.
return this.getCache( builder, property, 'float' );

}

getColor( builder, property ) {

return this.getCache( builder, property, 'color' );

}

const textureRefNode = materialReference( property, 'texture' );
getTexture( builder, property ) {

return textureRefNode;
return this.getCache( builder, property, 'texture' );

}

Expand All @@ -48,19 +70,19 @@ class MaterialNode extends Node {

if ( scope === MaterialNode.ALPHA_TEST || scope === MaterialNode.SHININESS || scope === MaterialNode.REFLECTIVITY || scope === MaterialNode.ROTATION || scope === MaterialNode.IRIDESCENCE || scope === MaterialNode.IRIDESCENCE_IOR ) {

node = this.getFloat( scope );
node = this.getFloat( builder, scope );

} else if ( scope === MaterialNode.SPECULAR_COLOR ) {

node = this.getColor( 'specular' );
node = this.getColor( builder, 'specular' );

} else if ( scope === MaterialNode.COLOR ) {

const colorNode = this.getColor( 'color' );
const colorNode = this.getColor( builder, 'color' );

if ( material.map && material.map.isTexture === true ) {

node = colorNode.mul( this.getTexture( 'map' ) );
node = colorNode.mul( this.getTexture( builder, 'map' ) );

} else {

Expand All @@ -70,11 +92,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.OPACITY ) {

const opacityNode = this.getFloat( 'opacity' );
const opacityNode = this.getFloat( builder, 'opacity' );

if ( material.alphaMap && material.alphaMap.isTexture === true ) {

node = opacityNode.mul( this.getTexture( 'alphaMap' ) );
node = opacityNode.mul( this.getTexture( builder, 'alphaMap' ) );

} else {

Expand All @@ -86,7 +108,7 @@ class MaterialNode extends Node {

if ( material.specularMap && material.specularMap.isTexture === true ) {

node = this.getTexture( 'specularMap' ).r;
node = this.getTexture( builder, 'specularMap' ).r;

} else {

Expand All @@ -96,11 +118,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.ROUGHNESS ) {

const roughnessNode = this.getFloat( 'roughness' );
const roughnessNode = this.getFloat( builder, 'roughness' );

if ( material.roughnessMap && material.roughnessMap.isTexture === true ) {

node = roughnessNode.mul( this.getTexture( 'roughnessMap' ).g );
node = roughnessNode.mul( this.getTexture( builder, 'roughnessMap' ).g );

} else {

Expand All @@ -110,11 +132,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.METALNESS ) {

const metalnessNode = this.getFloat( 'metalness' );
const metalnessNode = this.getFloat( builder, 'metalness' );

if ( material.metalnessMap && material.metalnessMap.isTexture === true ) {

node = metalnessNode.mul( this.getTexture( 'metalnessMap' ).b );
node = metalnessNode.mul( this.getTexture( builder, 'metalnessMap' ).b );

} else {

Expand All @@ -124,11 +146,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.EMISSIVE ) {

const emissiveNode = this.getColor( 'emissive' );
const emissiveNode = this.getColor( builder, 'emissive' );

if ( material.emissiveMap && material.emissiveMap.isTexture === true ) {

node = emissiveNode.mul( this.getTexture( 'emissiveMap' ) );
node = emissiveNode.mul( this.getTexture( builder, 'emissiveMap' ) );

} else {

Expand All @@ -138,11 +160,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.CLEARCOAT ) {

const clearcoatNode = this.getFloat( 'clearcoat' );
const clearcoatNode = this.getFloat( builder, 'clearcoat' );

if ( material.clearcoatMap && material.clearcoatMap.isTexture === true ) {

node = clearcoatNode.mul( this.getTexture( 'clearcoatMap' ).r );
node = clearcoatNode.mul( this.getTexture( builder, 'clearcoatMap' ).r );

} else {

Expand All @@ -152,11 +174,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.CLEARCOAT_ROUGHNESS ) {

const clearcoatRoughnessNode = this.getFloat( 'clearcoatRoughness' );
const clearcoatRoughnessNode = this.getFloat( builder, 'clearcoatRoughness' );

if ( material.clearcoatRoughnessMap && material.clearcoatRoughnessMap.isTexture === true ) {

node = clearcoatRoughnessNode.mul( this.getTexture( 'clearcoatRoughnessMap' ).r );
node = clearcoatRoughnessNode.mul( this.getTexture( builder, 'clearcoatRoughnessMap' ).r );

} else {

Expand All @@ -166,11 +188,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.SHEEN ) {

const sheenNode = this.getColor( 'sheenColor' ).mul( this.getFloat( 'sheen' ) ); // Move this mul() to CPU
const sheenNode = this.getColor( builder, 'sheenColor' ).mul( this.getFloat( builder, 'sheen' ) ); // Move this mul() to CPU

if ( material.sheenColorMap && material.sheenColorMap.isTexture === true ) {

node = sheenNode.mul( this.getTexture( 'sheenColorMap' ).rgb );
node = sheenNode.mul( this.getTexture( builder, 'sheenColorMap' ).rgb );

} else {

Expand All @@ -180,11 +202,11 @@ class MaterialNode extends Node {

} else if ( scope === MaterialNode.SHEEN_ROUGHNESS ) {

const sheenRoughnessNode = this.getFloat( 'sheenRoughness' );
const sheenRoughnessNode = this.getFloat( builder, 'sheenRoughness' );

if ( material.sheenRoughnessMap && material.sheenRoughnessMap.isTexture === true ) {

node = sheenRoughnessNode.mul( this.getTexture( 'sheenRoughnessMap' ).a );
node = sheenRoughnessNode.mul( this.getTexture( builder, 'sheenRoughnessMap' ).a );

} else {

Expand All @@ -202,7 +224,7 @@ class MaterialNode extends Node {

const iridescenceThicknessMinimum = reference( 0, 'float', material.iridescenceThicknessRange );

node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( 'iridescenceThicknessMap' ).g ).add( iridescenceThicknessMinimum );
node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( builder, 'iridescenceThicknessMap' ).g ).add( iridescenceThicknessMinimum );

} else {

Expand Down
3 changes: 3 additions & 0 deletions examples/jsm/nodes/accessors/MaterialReferenceNode.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ReferenceNode from './ReferenceNode.js';
import { NodeUpdateType } from '../core/constants.js';
import { addNodeClass } from '../core/Node.js';
import { nodeObject } from '../shadernode/ShaderNode.js';

Expand All @@ -10,6 +11,8 @@ class MaterialReferenceNode extends ReferenceNode {

this.material = material;

this.updateType = NodeUpdateType.RENDER;

}

construct( builder ) {
Expand Down
4 changes: 2 additions & 2 deletions examples/jsm/nodes/accessors/Object3DNode.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Node, { addNodeClass } from '../core/Node.js';
import { NodeUpdateType } from '../core/constants.js';
import { uniform } from '../core/UniformNode.js';
import UniformNode from '../core/UniformNode.js';
import { nodeProxy } from '../shadernode/ShaderNode.js';

import { Vector3 } from 'three';
Expand All @@ -16,7 +16,7 @@ class Object3DNode extends Node {

this.updateType = NodeUpdateType.OBJECT;

this._uniformNode = uniform( null );
this._uniformNode = new UniformNode( null );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference here?

Copy link
Collaborator Author

@sunag sunag Sep 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was part of what I described about avoiding NodeObject (Use Non-NodeObject for uniforms.), in general Nodes that need to be updated for every frame.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what is the benefit then? UniformNode is still a node.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what is the benefit then?

Better performance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a significant difference in performance between a node and a node wrapped in nodeObject?


}

Expand Down
8 changes: 8 additions & 0 deletions examples/jsm/nodes/core/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ class Node extends EventDispatcher {

}

getSelf() {

// Returns non-node object.

return this.self || this;

}

isGlobal( /*builder*/ ) {

return false;
Expand Down
35 changes: 29 additions & 6 deletions examples/jsm/nodes/core/NodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,20 @@ class NodeBuilder {

}

createBindings() {

const bindingsArray = [];

for ( const binding of this.getBindings() ) {

bindingsArray.push( binding.clone() );

}

return bindingsArray;

}

getBindings() {

let bindingsArray = this.bindingsArray;
Expand All @@ -128,14 +142,26 @@ class NodeBuilder {

addNode( node ) {

if ( this.nodes.indexOf( node ) === - 1 ) {
if ( this.nodes.includes( node ) === false ) {

this.nodes.push( node );

this.setHashNode( node, node.getHash( this ) );

}

}

buildUpdateNodes() {

for ( const node of this.nodes ) {

const updateType = node.getUpdateType();
const updateBeforeType = node.getUpdateBeforeType();

if ( updateType !== NodeUpdateType.NONE ) {

this.updateNodes.push( node );
this.updateNodes.push( node.getSelf() );

}

Expand All @@ -145,10 +171,6 @@ class NodeBuilder {

}

this.nodes.push( node );

this.setHashNode( node, node.getHash( this ) );

}

}
Expand Down Expand Up @@ -940,6 +962,7 @@ class NodeBuilder {
// stage 4: build code for a specific output

this.buildCode();
this.buildUpdateNodes();

return this;

Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/core/NodeUniform.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class NodeUniform {

this.name = name;
this.type = type;
this.node = node;
this.node = node.getSelf();
this.needsUpdate = needsUpdate;

}
Expand Down
Loading