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: Uniform Group #27134

Merged
merged 2 commits into from Nov 8, 2023
Merged

WebGPURenderer: Uniform Group #27134

merged 2 commits into from Nov 8, 2023

Conversation

sunag
Copy link
Collaborator

@sunag sunag commented Nov 7, 2023

Related issue: #27101, #26673

GOAL

This PR implements shared and unique Uniform Groups in WebGPURenderer.

NODE UPDATE

Node System has 3 root update systems, FRAME, RENDER, OBJECT.

  • FRAME: The Node is updated once per frame.
  • RENDER: The Node is updated whenever .render() or .compute() is called.
  • OBJECT: The Node is updated in each Mesh or derivative (RenderObject).

Normally, Nodes belonging to projectionMatrix (Camera) and materialColor (Material) are classified as updating type RENDER, and the buffer can be shared with others.

While modelViewMatrix (Mesh), for example, is classified as OBJECT, and is updated every time the object is rendered, its buffer is not shared.

Global nodes like timerGlobal() are classified as FRAME, and are updated once for each requestAnimationFrame(), unlike RENDER it is not updated if there are other RTT in the same frame, the buffer of a FRAME is shared.

UNIFORM GROUP

To implement a uniform group, you just need to tell the uniform which group it will be linked to. Groups will be automatically created in the code, if the group is shared it will look for other equivalent blocks in the active shaders already created to share the buffer. Defining the children of a group should not be a concern for the end user.

import { frameGroup, renderGroup, objectGroup, uniform } from 'three/nodes';

const myUniform = uniform( new THRE.Color( 0x0066FF ) );

// frameGroup, renderGroup, objectGroup are the system groups
myUniform.setGroup( renderGroup );

...
material.colorNode = myUniform;

CUSTOM UNIFORM GROUP

import { uniformGroup, sharedUniformGroup, uniform } from 'three/nodes';

const myUniform = uniform( new THRE.Color( 0x0066FF ) );
const myGroup = sharedUniformGroup( 'myGroup' );

myUniform.setGroup( myGroup );

...
material.colorNode = myUniform;

// For update your group...
// The uniform updates will be sent to the GPU if the version is different from the CPU, 
// in this case use `.needsUpdate=true` to update the version.

myGroup.needsUpdate = true;

NEXT STEP

This PR offers the necessary support for optimization that must be done in separate PRs, so that each Node is in its equivalent group as proposed in the design.

WGSL TEST RESULT

...
// uniforms

struct cameraStruct {
	projectionMatrix : mat4x4<f32>
};
@binding( 0 ) @group( 0 )
var<uniform> camera : cameraStruct;

struct objectStruct {
	modelViewMatrix : mat4x4<f32>
};
@binding( 1 ) @group( 0 )
var<uniform> object : objectStruct;

...
// You need to remove comments left on `CameraNode` to view this example.

@sunag sunag added this to the r159 milestone Nov 7, 2023
@sunag sunag marked this pull request as ready for review November 7, 2023 07:00
@sunag sunag merged commit 025b563 into mrdoob:dev Nov 8, 2023
19 checks passed
@sunag sunag deleted the dev-uniform-group branch November 8, 2023 04:20
import Node from './Node.js';
import { addNodeClass } from './Node.js';

class UniformGroupNode extends Node {
Copy link
Contributor

@LeviPesin LeviPesin Jan 11, 2024

Choose a reason for hiding this comment

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

Should this be a node, actually? Can't we unify this with the UniformGroup class (and maybe name it NodeUniformGroup)? /ping @sunag


// objectGroup is every updated

if ( name === objectGroup.name ) return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why we can't just compare groupNode === objectGroup instead of comparing names?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is possible that more than one sharedUniformGroup node was created with the same name, this would unify them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants