Skip to content

Nodes: Struct extension proposal #29760

@Spiri0

Description

@Spiri0

Description

I'm ready to get to work on this myself, but I'd like to hear your opinion on my ideas. Better I ask before I Investing energy and time in a way that you don't consider good.

After the initial euphoria about Aardgoose's bundler expansion, disillusionment followed in the days that followed.
The extension is great because it takes care of all the uniforms that I as a user don't want to take care of myself.
But it is not intended for storageBuffers. So far we only use the storageBuffers in analogy to attributes. In WebGPU you would like to use entire parameter sets with storage buffers in compute shaders. If uniform had an additional flag that we would call struct, then that would be a clean distinctive feature. Then at this point the WGSLNodeBuilder would make a case distinction as to whether it is a struct or not and at if false, the previous code is executed and if true, we can run a structbuilder without any risks.

} else if ( uniform.type === 'buffer' || uniform.type === 'storageBuffer' || uniform.type === 'indirectStorageBuffer' ) {

    if ( uniform.struct ) {

    }
    else {

        const bufferNode = uniform.node;
        const bufferType = this.getType( bufferNode.bufferType );
        const bufferCount = bufferNode.bufferCount;

        const bufferCountSnippet = bufferCount > 0 && uniform.type === 'buffer' ? ', ' + bufferCount : '';
        const bufferTypeSnippet = bufferNode.isAtomic ? `atomic<${bufferType}>` : `${bufferType}`;
        const bufferSnippet = `\t${ uniform.name } : array< ${ bufferTypeSnippet }${ bufferCountSnippet } >\n`;
        const bufferAccessMode = bufferNode.isStorageBufferNode ? `storage, ${ this.getStorageAccess( bufferNode ) }` : 'uniform';

        bufferSnippets.push( this._getWGSLStructBinding( 'NodeBuffer_' + bufferNode.id, bufferSnippet, bufferAccessMode, uniformIndexes.binding ++, uniformIndexes.group ) );
    
    }
}

What I don't yet see clearly is how the struct content is best transported into the WGSLNodeBuilder using the uniform.
But with this you could store worldMatrices, boundingSphere, ... of every instance of a mesh in a storageBuffer.
This means that almost anything can be brought into the compute shader for processing in order to exploit the big potential of WebGPU.

A new node is necessary for this, e.g. struct and I imagine it like this.

const StructExample = struct({
    someVector4: someVector4, 
    someVector3: someVector3,
    someScalar: someScalar
});
or struct.push() to add many of such datasets for different meshes or instances.

//in case of wgsl, not neccessary for Fn
const computeShader = wgslFn(`
    fn compute( 
        structBuffer: ptr<storage, StructExample, read_write>,   //StructExample is the name from the struct
    ) -> void {

    }
`);       

this.compute = computeShader({
    structBuffer: StructExample.buffer 
}).compute(length);

Maybe just assign the struct and the shader builder will recognize from the struct flag that it should use the buffer and all the names?

The struct built by the WGSLNodeBuilder would then look like this:

struct StructExample {
    someVector4: vec4<f32>
    someVector3: vec3<f32>
    someScalar: f32
};

If you see it as a good way, I'm willing to invest a lot of time and energy myself.

Solution

Described in the description

Alternatives

Lots of individual storage buffers and in the case of matrices no sensible solution.

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions