Shaders: transmitting a fair bit of data

I’m hoping for some shader-advice, if I may:

I want to give a fragment shader access to a largish set of data-points–perhaps thousands, perhaps even tens of thousands of data-points; I haven’t yet determined the final scale of this. (Although a given fragment would likely access only a single data-point.) The data-points would each consist of a time-stamp, a state (either boolean or integer), and possibly a 2D vector.

(Okay, I don’t know whether this is a largish data-set by most standards; it is by my limited shader-experience, at least. ^^; )

This data would be updated at run-time. The exact rate of updates would likely depend on what the player was doing–there might be periods in which it’s updated every frame, and periods in which it’s not updated at all, and periods in-between.

Either way, I would expect only a few entries to be updated in any given frame.

Handling this on the Python side shouldn’t be too difficult, I think.

My uncertainty, then, is how to communicate and handle this data on the shader-side.

Would an array of some sort be a good idea? But then, each fragment would have to index into this array–would that cause problematic branching…?

It’s tempting to consider storing the data in a texture and then just using a standard texture-read.

But I’m not sure of how well that works with the time-stamp data–would values higher than one be passed through intact? Would some other means of representing time-stamps be called for?

Furthermore, storing the data in a texture would seem to imply that I’d have to transmit the entire texture every time anything changes–even if only one data-point has changed. Is that likely to perform well, especially in those periods in which there might be an update per frame?

Is there perhaps another way…?

So, as you may see, I am somewhat unclear on how I might proceed.

Any suggestions?

You can use a buffer texture to pass large amounts of data that you want to be able to access using arbitrary indexing. You can use a floating-point or integer format to support values larger than 1.

However, Panda will retransmit the entire texture every frame. We can look into ways to optimize that if that proves to be inefficient. One way might be to add a feature for partial updates to Panda, another might be to use a compute shader to make your updates.

Come to think of it, an SSBO (ShaderBuffer) really is a better way to do this, but we don’t currently support updating them after they are created. I’ll get back to you.

Hmm… It looks like Shader Buffers wee introduced more recently than Buffer Textures. I’m less familiar with the more-recent version of GLSL, I think, and on top of that generally prefer to keep my GLSL version down.

And indeed, it occurs to me that even with only a 128x128 buffer I should still be able to store more than ten thousand data-points; far more if I increase that to 256x256.

So, I think that I’ll try the Buffer Texture approach first; if that proves to perform too poorly, then I can reconsider the Shader Buffer approach!

Thank you for the guidance! :slight_smile:

A buffer texture has only one dimension.

Fair enough–and that might be more convenient, anyway–but the points stands that it needn’t be all that big.

But then–as you may gather–I’ve never used them before (much less Shader Buffers), and so don’t know how well they might work. We’ll see, I suppose!

That said… do we have any resources on working with Buffer Textures in Panda? Forum searching has turned up somewhat, but I don’t know how to be confident that I’m not just looking at references to standard offscreen buffers…

Anything that uses setupBufferTexture (and something like (u/i)samplerBuffer in the shader) is using buffer textures. It’s really just a different type of texture.

Apparently I attached a bit of sample code here:

1 Like

Great! Thank you for all of that! :slight_smile: