<p>I am suprised that it was only mentioned in comments but yes you can use variable length arrays through SSBO.
Here is the excerpt from <a href="https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" rel="nofollow noreferrer">wiki</a>:</p>
<p>On the host side:</p>
<pre class="lang-cpp prettyprint-override"><code>int data[SOME_SIZE];
...
GLuint ssbo;
glGenBuffers(1, &amp;ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data​, GLenum usage); //sizeof(data) only works for statically sized C/C++ arrays.
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); // unbind
</code></pre>
<p>On the glsl side:</p>
<pre class="lang-c prettyprint-override"><code>layout(std430, binding = 3) buffer layoutName
{
    int data_SSBO[];
};
</code></pre>
<p>Note that it has to be the last element in an SSBO:</p>
<pre class="lang-c prettyprint-override"><code>layout(std430, binding = 2) buffer anotherLayoutName
{
    int some_int;
    float fixed_array[42];
    float variable_array[];
};
</code></pre>
<p>The only limitation is that you can use one variable array per SSBO. You can use multiple SSBO's in a shader though.</p>

CC BY-SA 4.0
2021-01-09T10:14:39.737Z
2021-01-10T13:05:58.397Z
2021-01-10T13:05:58.397Z
Kaan E.
<p>You could add the variable as code when you upload the shader code.</p>
<pre><code>char header[64];
sprintf (header, &quot;const int size = %u;\n&quot;, pointLights.size());
</code></pre>
<p>Then add the header (assuming your code is in <code>char code[]</code>):</p>
<pre><code>GLchar  *source[2] = {(GLchar  *)header, (GLchar  *)code};
glShaderSource(shader, 2, (const GLchar **)source, NULL);
..
</code></pre>
<p>That way you can vary the size and add it to the shader on the fly.
Bit of a hack, but it's the way I did it.</p>

CC BY-SA 4.0
2020-12-23T13:29:02.830Z
2020-12-23T13:59:22.590Z
2020-12-23T13:59:22.590Z
Graham
<p>I don't think uniform arrays can be dynamically sized. In your case you should define the array as the maximum number of lights you will process and then use a uniform to control the number of iterations you do on this array. On the CPU side you can set a subset of the lights[] array according to the 'size' variable.</p>

<p>e.g.</p>

<pre><code>#define MAX_LIGHTS 128

uniform int size;
uniform SceneLights lights[MAX_LIGHTS];

void main()
{
    for(int i = 0; i &lt; size; i++) {
        /* Do Some Calculation */
    }
}
</code></pre>

<p>I think (speculate) the likely reason for this is that it would be impossible to determine the location of a uniform if there are variable sized arrays in your uniform list which depend on the value of another uniform.. e.g.</p>

<pre><code>uniform int arraySize;               // offset 0
uniform int myArray[arraySize];      // offset 4
uniform int anotherVar;              // offset ???? 
</code></pre>

<p>GLSL would not know were to place anotherVar, because it would need arraySize to be set with a value before it can compute the offset of 'anotherVar'. I suppose the compiler could be clever and re-arrange the order of uniforms to get around this, but this will fail again if you have 2 or more variable sized arrays..</p>

CC BY-SA 4.0
2021-11-27T22:21:32.547Z
+1 especially for stating the reason you think it's not possible, and of course for offering an alternative strategy. Very helpful answer.
Alexandre
CC BY-SA 3.0
2017-07-05T08:11:40.990Z
2017-07-11T02:49:43.297Z
2017-07-11T02:49:43.297Z
PaulHK
<p>Is it possible to have a dynamic array in a GLSL shader? For instance, what if I have something like this in my GLSL Shader:</p>

<pre><code>uniform int size;
uniform SceneLights lights[size];

void main()
{
    for(int i = 0; i &lt; size; i++) {
        /* Do Some Calculation */
    }
}
</code></pre>

<p>And this would be my C++ file:</p>

<pre><code>for (GLuint i = 0; i &lt; pointLights.size(); i++) {
    glUniform3f(glGetUniformLocation(shader, ("pointLights[" + std::to_string(i) + "].position").c_str()), lights[i].someValue);
}
</code></pre>

<p>I would like to do this because I have a file with the positions of all the light sources in my scene (this may vary for each scene) so I would like to have a dynamic array which will allow me to send different numbers of lights to my shader.</p>

CC BY-SA 4.0
2020-12-23T23:24:11.997Z
There are also Shader Storage Buffer Objects that you can read about here: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object    And in vulkan there are "unbounded arrays" that are declared in GLSL like this: layout(binding=10) uniform sampler2D TextureUBA[];"  (sampler2D is just an example) I'm not sure how that is set up in OpenGL though. The last version has very large limits but both of these have a performance penalty which varies depending on how the memory is accessed.
pmw1234
<opengl><glsl>
Dynamic Array in GLSL
Archmede
# Dynamic Array in GLSL

(Asked by: username_0 on 2017-07-05)

Is it possible to have a dynamic array in a GLSL shader? For instance, what if I have something like this in my GLSL Shader:

```
uniform int size;
uniform SceneLights lights[size];

void main()
{
    for(int i = 0; i < size; i++) {
        /* Do Some Calculation */
    }
}

```

And this would be my C++ file:

```
for (GLuint i = 0; i < pointLights.size(); i++) {
    glUniform3f(glGetUniformLocation(shader, ("pointLights[" + std::to_string(i) + "].position").c_str()), lights[i].someValue);
}

```

I would like to do this because I have a file with the positions of all the light sources in my scene (this may vary for each scene) so I would like to have a dynamic array which will allow me to send different numbers of lights to my shader.

**Tags:** opengl, glsl

> **Comments:**
> **username_1**: There are also Shader Storage Buffer Objects that you can read about here: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object    And in vulkan there are "unbounded arrays" that are declared in GLSL like this: layout(binding=10) uniform sampler2D TextureUBA[];"  (sampler2D is just an example) I'm not sure how that is set up in OpenGL though. The last version has very large limits but both of these have a performance penalty which varies depending on how the memory is accessed.  

---

## 3 answers

### Answer by username_4 on 2017-07-05. Score: 21 | Accepted answer

I don't think uniform arrays can be dynamically sized. In your case you should define the array as the maximum number of lights you will process and then use a uniform to control the number of iterations you do on this array. On the CPU side you can set a subset of the lights[] array according to the 'size' variable.

e.g.

```
#define MAX_LIGHTS 128

uniform int size;
uniform SceneLights lights[MAX_LIGHTS];

void main()
{
    for(int i = 0; i < size; i++) {
        /* Do Some Calculation */
    }
}

```

I think (speculate) the likely reason for this is that it would be impossible to determine the location of a uniform if there are variable sized arrays in your uniform list which depend on the value of another uniform.. e.g.

```
uniform int arraySize;               // offset 0
uniform int myArray[arraySize];      // offset 4
uniform int anotherVar;              // offset ???? 

```

GLSL would not know were to place anotherVar, because it would need arraySize to be set with a value before it can compute the offset of 'anotherVar'. I suppose the compiler could be clever and re-arrange the order of uniforms to get around this, but this will fail again if you have 2 or more variable sized arrays..

> **Comments:**
> **username_5**: +1 especially for stating the reason you think it's not possible, and of course for offering an alternative strategy. Very helpful answer.  

---

### Answer by username_2 on 2021-01-09. Score: 4

I am suprised that it was only mentioned in comments but yes you can use variable length arrays through SSBO.
Here is the excerpt from [wiki](https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object):

On the host side:

```cpp
int data[SOME_SIZE];
...
GLuint ssbo;
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data​, GLenum usage); //sizeof(data) only works for statically sized C/C++ arrays.
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); // unbind

```

On the glsl side:

```c
layout(std430, binding = 3) buffer layoutName
{
    int data_SSBO[];
};

```

Note that it has to be the last element in an SSBO:

```c
layout(std430, binding = 2) buffer anotherLayoutName
{
    int some_int;
    float fixed_array[42];
    float variable_array[];
};

```

The only limitation is that you can use one variable array per SSBO. You can use multiple SSBO's in a shader though.


---

### Answer by username_3 on 2020-12-23. Score: 3

You could add the variable as code when you upload the shader code.

```
char header[64];
sprintf (header, "const int size = %u;\n", pointLights.size());

```

Then add the header (assuming your code is in `char code[]`):

```
GLchar  *source[2] = {(GLchar  *)header, (GLchar  *)code};
glShaderSource(shader, 2, (const GLchar **)source, NULL);
..

```

That way you can vary the size and add it to the shader on the fly.
Bit of a hack, but it's the way I did it.


---

