diff --git a/src/nodes/core/NodeBuilder.js b/src/nodes/core/NodeBuilder.js index f53619c682f7c6..822e74871ee1e4 100644 --- a/src/nodes/core/NodeBuilder.js +++ b/src/nodes/core/NodeBuilder.js @@ -35,6 +35,8 @@ import { warn, error } from '../../utils.js'; let _id = 0; +const sharedNodeData = new WeakMap(); + const rendererCache = new WeakMap(); const typeFromArray = new Map( [ @@ -2951,6 +2953,26 @@ class NodeBuilder { } + /** + * Returns shared data object for the given node. + * + * @param {Node} node - The node to get shared data from. + * @return {Object} The shared data. + */ + getSharedDataFromNode( node ) { + + let data = sharedNodeData.get( node ); + + if ( data === undefined ) { + + data = {}; + + } + + return data; + + } + /** * Returns a uniform representation which is later used for UBO generation and rendering. * @@ -2960,16 +2982,31 @@ class NodeBuilder { */ getNodeUniform( uniformNode, type ) { - if ( type === 'float' || type === 'int' || type === 'uint' ) return new NumberNodeUniform( uniformNode ); - if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) return new Vector2NodeUniform( uniformNode ); - if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) return new Vector3NodeUniform( uniformNode ); - if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) return new Vector4NodeUniform( uniformNode ); - if ( type === 'color' ) return new ColorNodeUniform( uniformNode ); - if ( type === 'mat2' ) return new Matrix2NodeUniform( uniformNode ); - if ( type === 'mat3' ) return new Matrix3NodeUniform( uniformNode ); - if ( type === 'mat4' ) return new Matrix4NodeUniform( uniformNode ); + const nodeData = this.getSharedDataFromNode( uniformNode ); + + let node = nodeData.cache; + + if ( node === undefined ) { + + if ( type === 'float' || type === 'int' || type === 'uint' ) node = new NumberNodeUniform( uniformNode ); + else if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) node = new Vector2NodeUniform( uniformNode ); + else if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) node = new Vector3NodeUniform( uniformNode ); + else if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) node = new Vector4NodeUniform( uniformNode ); + else if ( type === 'color' ) node = new ColorNodeUniform( uniformNode ); + else if ( type === 'mat2' ) node = new Matrix2NodeUniform( uniformNode ); + else if ( type === 'mat3' ) node = new Matrix3NodeUniform( uniformNode ); + else if ( type === 'mat4' ) node = new Matrix4NodeUniform( uniformNode ); + else { + + throw new Error( `Uniform "${ type }" not implemented.` ); - throw new Error( `Uniform "${type}" not declared.` ); + } + + nodeData.cache = node; + + } + + return node; } diff --git a/src/renderers/common/Binding.js b/src/renderers/common/Binding.js index 3afbd105138a44..9b4401571eece6 100644 --- a/src/renderers/common/Binding.js +++ b/src/renderers/common/Binding.js @@ -44,6 +44,17 @@ class Binding { } + /** + * The shader stages in which the binding's resource is visible. + * + * @return {number} The visibility bitmask. + */ + getVisibility() { + + return this.visibility; + + } + /** * Clones the binding. * diff --git a/src/renderers/common/Bindings.js b/src/renderers/common/Bindings.js index f21b1ca0be4e09..89339b20f078f5 100644 --- a/src/renderers/common/Bindings.js +++ b/src/renderers/common/Bindings.js @@ -251,16 +251,14 @@ class Bindings extends DataMap { for ( const binding of bindGroup.bindings ) { - if ( binding.isNodeUniformsGroup ) { + const updatedGroup = this.nodes.updateGroup( binding ); - const updated = this.nodes.updateGroup( binding ); + // every uniforms group is a uniform buffer. So if no update is required, + // we move one with the next binding. Otherwise the next if block will update the group. - // every uniforms group is a uniform buffer. So if no update is required, - // we move one with the next binding. Otherwise the next if block will update the group. + if ( updatedGroup === false ) continue; - if ( updated === false ) continue; - - } + // if ( binding.isStorageBuffer ) { diff --git a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js index 33462c8fea4b39..73667df5577f98 100644 --- a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +++ b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js @@ -1531,11 +1531,22 @@ void main() { } else if ( type === 'buffer' ) { - node.name = `NodeBuffer_${ node.id }`; uniformNode.name = `buffer${ node.id }`; - const buffer = new NodeUniformBuffer( node, group ); - buffer.name = node.name; + const sharedData = this.getSharedDataFromNode( node ); + + let buffer = sharedData.buffer; + + if ( buffer === undefined ) { + + node.name = `NodeBuffer_${ node.id }`; + + buffer = new NodeUniformBuffer( node, group ); + buffer.name = node.name; + + sharedData.buffer = buffer; + + } bindings.push( buffer ); diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index d5ec346aa81288..5d46f37d2e2157 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -974,10 +974,21 @@ class WGSLNodeBuilder extends NodeBuilder { } else if ( type === 'buffer' || type === 'storageBuffer' || type === 'indirectStorageBuffer' ) { - const bufferClass = type === 'buffer' ? NodeUniformBuffer : NodeStorageBuffer; + const sharedData = this.getSharedDataFromNode( node ); - const buffer = new bufferClass( node, group ); - buffer.setVisibility( gpuShaderStageLib[ shaderStage ] ); + let buffer = sharedData.buffer; + + if ( buffer === undefined ) { + + const bufferClass = type === 'buffer' ? NodeUniformBuffer : NodeStorageBuffer; + + buffer = new bufferClass( node, group ); + + sharedData.buffer = buffer; + + } + + buffer.setVisibility( buffer.getVisibility() | gpuShaderStageLib[ shaderStage ] ); bindings.push( buffer );