StorageBuffer Questions

Hookay, Im trying to connect all the dots in my lack of knowledge with wgsl and BJS.

Currently I have a simple sand simulation running that its buffer ends up getting passed to a shader later and visualizes the cube instances.

Now that I want to actually add some metadata I realized that there are two different number types Ill need u32 and f32. Im assuming that means I need to create two separate buffers of the correct type and make sure I track my stride sizes for all the “metadata” I want to track.

I came up with a structure like this:

export enum SandType {
    Void = 0,
    Fixed = 1,
    Sand = 2,
    Water = 3,
}

export enum PhysicsKind {
    None = 0,
    Static = 1,
    Dynamic = 2,
}

interface ISand {
    type: SandType;
    u32Buffers: {     
        type: IU32BufferValue;
        color: IU32BufferValue;
        physicsKind: IU32BufferValue;
    }
    f32Buffers: {
        age: IF32BufferValue;
        velocity: IF32BufferValue;
    }
}

enum U32BufferValueKind {
    Number = 0,
    Color = 1,
}

interface IU32BufferValue{
    kind: U32BufferValueKind;
    value: number | [number, number, number];
    stride: 1 | 3;
}

enum F32BufferValueKind {
    Number = 0,
    Vector3 = 1,
}

interface IF32BufferValue{
    kind: F32BufferValueKind;
    value: number | [number, number, number];
    stride: 1 | 3;
}

So I can define what the buffers look like and the different “slot” offsets for values. This also makes it so I can build the default buffer chunks automatically.

My question is do I need to do this as a two storage buffers? Is there a way to define a mixed kind buffer? Is there a better way to be doing this?

A storage buffer can be defined as an array of structs, so you can mix things in a storage buffer. See the linkedList buffer in this example:

1 Like

How would I tell it things like its stride and stuff when trying to define one with babylon js shader material?

On Babylon side, you will have to put the data in a DataArray (== number[] | ArrayBuffer | ArrayBufferView) and use the StorageBuffer.update() method to update the buffer on the GPU. If you must mix different types (like byte, float, etc), you will have to use a DataView to fill an ArrayBuffer that you can use with StorageBuffer.update().

Yup those are words. XD hahaha ok, let me figure out what you are saying.

I’ve noticed a lot of the time here I know how to do it some what with just webGPU but once I mix in Babylon there is a lot of disconnect on how to access certain things but that’s probably on me. Im slowly digesting it, thanks for your help.

You have an example in the Ocean demo, albeit simplified:

  • lines 2037, 2038: buffer (an array of numbers) is filled with two instances of a SpectrumSettings type. It’s the _linearizeSpectrumSetting method (line 2043) which actually puts the data in the buffer.
  • buffer is used to update the storage buffer line 2040

It’s a simplified example because the SpectrumSettings struct is made only of floats, so there’s no need for a DataView to create the JS buffer, you can simply push the data in an array of numbers.

1 Like

Oh Ok, Im kinda already doing this nice.

Now I need to figure out the dataView stuff and ill be trucking.

Thanks for your help, this is going to give me a ton to think about when I get off work today.

So something like this?

Then I pass that to the storage buffer and define my struct and I should be able to then access the named structure prop per instance on the wgsl shader correct?

Yes, but there are some alignment rules you must follow in the struct. See:

https://gpuweb.github.io/gpuweb/wgsl/#alignment-and-size

You will have to add some padding (or simply increment offset), depending on the current value of offset and the property you want to write at that offset.

1 Like

Ok, I read that document you sent like three times last night and looked over their example.

I feel dense and do not understand what’s going on with that part. Can you put it into terms and oaf like me can comprehend please? :point_right: :point_left:

This website you linked though just in general is amazing btw.
https://gpuweb.github.io/gpuweb/wgsl/#intro

So my age part seems to be working, but why can I not get the position to work now?

Also how can I setup the offset stuff to make sure my buffer is the right size, I had to do some hacky stuff to get it to “work”, I bet the vectors are not working because I have the offset wrong.

UPDATE
Thanks to your links, and guidance my monkey brain was able to grok it finally.

This is going to be big for me, I’ve been wanting to ditch simulated compute shaders with texture buffer tricks for a long long time now. Thank you.

1 Like