PDA

View Full Version : Dynamic array of uniforms



DarkRaven
01-17-2011, 07:21 AM
Is it possible to declare something dynamic sized inside shader? For example uniform blocks? I would specify size (or better, send it to shader) by another uniform so I know what are the boundaries. As GLSL miss pointers in it, I have feeling that this can't be done.

What is common approach to send non-specified (in shader) number of uniform blocks (I will use these but also in general) to shader?

For example I would like to send multiple lights into shader, so it's position, intensity, color packed into block, and I can add more and more of these blocks and compute for them with increasing number of iterrations as I specify later in host application. Btw. lights are just examples of something that need more then one parameter but it could be really anything.

Thanks in advance.

aqnuep
01-17-2011, 07:27 AM
Usually, you cannot create any dynamic arrays in GLSL. However, with uniform buffer objects you can pass in various sized buffers as the back-end storage of your uniform blocks. I don't think that there is any validation about whether the buffer has enough storage, but maybe I'm wrong.

Anyway, uniform buffer objects and as such uniform blocks have their size limitation, but if you allocate in the shader the largest possible size for your array of structs then maybe you can pass in various uniform buffer objects that have less actual storage.

Alfonse Reinheart
01-17-2011, 10:15 AM
Is it possible to declare something dynamic sized inside shader? For example uniform blocks? I would specify size (or better, send it to shader) by another uniform so I know what are the boundaries

You can't do that precisely with GLSL. But there's nothing that says you can't create an array of, say, 20 elements in the shader but only fill in 4 elements from OpenGL. You can pass a uniform specifying how many of the 20 elements actually have data.

GLSL must have a maximum size for uniforms (whether in blocks or not), because there are limits to the size of uniform data that the implementation allows. But that doesn't mean you have to use all of that size every time.

However, if that doesn't work to your liking, you can always use buffer textures. Though they will be a bit slower to access, and they don't come in GLSL-friendly arrays-of-structs.

DarkRaven
01-17-2011, 11:11 AM
I'm interrested about this one Reinheart. I thought about it that way, but if you create say 10k array size, does it immediatly occupy space 10000*sizeof(struct)? Or does it only occupy the number you actually suply. This way it would be just what I need with some max-size (which is anyway there). But If it creates that huge space every time, I'd go for UBO or textures.

Alfonse Reinheart
01-17-2011, 11:34 AM
I'm interrested about this one Reinheart. I thought about it that way, but if you create say 10k array size, does it immediatly occupy space 10000*sizeof(struct)?

Yes.

Though uniform blocks tend to max out at around ~16384 vec4's, so I don't think you'll be creating arrays with 10,000 elements anytime soon.

aqnuep
01-17-2011, 12:17 PM
Anyway, if you would really want to use this static allocation method of uniforms, I would still better go with uniform buffer objects rather than uniforms.

Texture buffer objects would be a good alternative as well, but as Alfonse mentioned, they perform worse than uniforms, however they don't have the strict size constraints that uniform buffers have (usually 64K).

Sorry, I don't really want to advertise myself here, but I wrote some articles about texture buffers and uniform buffers that may help in deciding which direction to go:

Uniform Buffers VS Texture Buffers (http://rastergrid.com/blog/2010/01/uniform-buffers-vs-texture-buffers/)
Texture and buffer access performance (http://rastergrid.com/blog/2010/11/texture-and-buffer-access-performance/)

DarkRaven
01-17-2011, 12:26 PM
Ok and what about these texture buffer objects? I can't find any real examples or even documentations (other then official quite long one). And how do you map structure to this? I read somewhere there it actually acts like 1D array of data with random acces, so you have to manualy unpack in host and again pack in shader to get your struct?

malexander
01-17-2011, 03:25 PM
A texture buffer object is just a texture wrapper around a buffer object. It requires GL 3.1 or GL_ARB_texture_buffer_object, meaning you won't be able to use it on older OGL2 hardware or OSX (at the moment).

First, you create a buffer object and map it, filling it with your data just as you would a VBO. Next, create a texture object and link the buffer object to it:


glTexBuffer(GL_TEXTURE_BUFFER_ARB, <buffer_data_type>, <buffer_id>);

When you're ready to access it via the shader, bind this texture to a unit as you would a normal texture. Then, in the shader, you can access your data via a texelFetch() on its uniform samplerBuffer:



uniform samplerBuffer varyingData;
...
value = texelFetch(varyingData, int_index);


I've been using texture buffers a lot for out-of-step vertex data and found them to be quite fast. The only downside is the restriction on the formats that are supported (like vec3).

DarkRaven
01-18-2011, 06:35 AM
Oh thanks for that very much malexander! I think internal format won't be problem, as I have just these 4 floats which can be packed to rgba32f and vec2 to rg32f.. so 2 texture buffers should make everything ok and easy.

Those articles by aqnuep are nice, good to have some benchmarking and comparison in hand.

I think I'll give a chance to every solution mentioned here and decide which suits my needs best. Thank you!