<p>To the uniform query API, there is no such thing as an &quot;array of non-basic types&quot;. There are just a bunch of uniforms that just so happen to have names that include array notation like &quot;pointLights[1].constant&quot;.</p>
<p>Put another way, <code>pointLights</code> is not a uniform. Nor is <code>pointLights[1]</code>. Only the elements the aggregate are themselves uniforms. And as far as the API is concerned, &quot;pointLights[1].constant&quot; is a completely separate uniform from the one named &quot;pointLights[3].constant&quot; with no relationship between them.</p>
<p>This is in part because you cannot <em>set</em> arrays of non-basic types with a single call. That is, there's no equivalent to <code>glProgramUniform4fv</code>, which has the ability to set a <code>vec4[N]</code> array uniform in a single function call.</p>
<p>So if you want to know how big some array of aggregates is, you're going to have to deduce it by iterating through all of the uniform names and comparing them to see which has the largest index.</p>

CC BY-SA 4.0
2023-02-26T02:09:34.873Z
2023-02-26T02:09:34.873Z
Nicol Bolas
<p>Consider the following code in an OpenGL shader:</p>
<pre><code>struct PointLight {
    vec3 position;

    float constant;
    float linear;
    float quadratic;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};
uniform PointLight pointLights[4];
</code></pre>
<p>How can I query the size of <code>pointLights</code> using interface query?
I tried this:</p>
<pre class="lang-cpp prettyprint-override"><code>auto idx = glGetProgramResourceIndex(prog, GL_UNIFORM, &quot;pointLights&quot;);
auto blockProperty = (GLenum)GL_ARRAY_SIZE;
auto arraySize = GLint{};
glGetProgramResourceiv(prog, GL_UNIFORM, idx, 1, &amp;blockProperty, 1, nullptr, &amp;arraySize);
</code></pre>
<p>It returns 0, which corresponds to the documentation of <code>glGetProgramResourceiv</code>:</p>
<blockquote>
<p>For active variables not corresponding to an array of basic types, the value zero is written to params.</p>
</blockquote>
<p>Well, what should I do for non-basic types?</p>

CC BY-SA 4.0
2023-02-26T02:10:23.743Z
Generally speaking, you shouldn't allow shaders to dictate information like how many lights it allows. This is something the shader and the code using it need to agree on, not something that should be deduced from how the shader is written.
Nicol Bolas
CC BY-SA 4.0
2023-02-26T03:19:15.533Z
And what is the proper way to agree on it? The array size in the shader is a GLSL compile time constant, I cannot set it from my C++ code.
facetus
CC BY-SA 4.0
2023-02-26T03:46:25.937Z
A person wrote the shader. A person wrote the code that consumes the shader. If these aren't the same people, then they need to talk to each other and get on the same page about what's going on in the shader. This could be an actual meeting or documentation on how to use the engine or whatever. Alternatively, you could use UBOs.
Nicol Bolas
CC BY-SA 4.0
2023-02-26T04:01:51.140Z
It's not how usually modules of software agree on things, if they want to avoid a disaster. There is a constant set somewhere in one module, then it gets advertised to other modules. Otherwise, one day Vasya Pupkin decides to change a constant, and everything explodes. See the maiden flight of Ariane 5 on June 4, 1996.
facetus
CC BY-SA 4.0
2023-02-26T06:02:38.863Z
"*There is a constant set somewhere in one module, then it gets advertised to other modules.*" That's great... when you're working in a single language. If you're working across non-interoperable languages, you can't do that easily. Eventually, it has to come down to some sort of convention. After all, you both had to agree that `pointLights` is an array of `PointLight` structures which contain certain fields with certain names, right? Adding one number to this list is hardly out of left field.
Nicol Bolas
CC BY-SA 4.0
2023-02-26T07:23:27.673Z
It's a moot point. There is no reason to prevent the introspection layer querying the size of an array perfectly syntactically defined in GLSL, besides poor design.
facetus
<opengl><shader>
Query the size of an array of non-basic types using interface query in OpenGL
facetus
# Query the size of an array of non-basic types using interface query in OpenGL

(Asked by: username_0 on 2023-02-25)

Consider the following code in an OpenGL shader:

```
struct PointLight {
    vec3 position;

    float constant;
    float linear;
    float quadratic;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};
uniform PointLight pointLights[4];

```

How can I query the size of `pointLights` using interface query?
I tried this:

```cpp
auto idx = glGetProgramResourceIndex(prog, GL_UNIFORM, "pointLights");
auto blockProperty = (GLenum)GL_ARRAY_SIZE;
auto arraySize = GLint{};
glGetProgramResourceiv(prog, GL_UNIFORM, idx, 1, &blockProperty, 1, nullptr, &arraySize);

```

It returns 0, which corresponds to the documentation of `glGetProgramResourceiv`:

> For active variables not corresponding to an array of basic types, the value zero is written to params.

Well, what should I do for non-basic types?

**Tags:** opengl, shader

> **Comments:**
> **username_1**: Generally speaking, you shouldn't allow shaders to dictate information like how many lights it allows. This is something the shader and the code using it need to agree on, not something that should be deduced from how the shader is written.  
> **username_0**: And what is the proper way to agree on it? The array size in the shader is a GLSL compile time constant, I cannot set it from my C++ code.  
> **username_1**: A person wrote the shader. A person wrote the code that consumes the shader. If these aren't the same people, then they need to talk to each other and get on the same page about what's going on in the shader. This could be an actual meeting or documentation on how to use the engine or whatever. Alternatively, you could use UBOs.  
> **username_0**: It's not how usually modules of software agree on things, if they want to avoid a disaster. There is a constant set somewhere in one module, then it gets advertised to other modules. Otherwise, one day Vasya Pupkin decides to change a constant, and everything explodes. See the maiden flight of Ariane 5 on June 4, 1996.  
> **username_1**: "*There is a constant set somewhere in one module, then it gets advertised to other modules.*" That's great... when you're working in a single language. If you're working across non-interoperable languages, you can't do that easily. Eventually, it has to come down to some sort of convention. After all, you both had to agree that `pointLights` is an array of `PointLight` structures which contain certain fields with certain names, right? Adding one number to this list is hardly out of left field.  
> **username_0**: It's a moot point. There is no reason to prevent the introspection layer querying the size of an array perfectly syntactically defined in GLSL, besides poor design.  

---

## 1 answers

### Answer by username_1 on 2023-02-26. Score: 1 | Accepted answer

To the uniform query API, there is no such thing as an "array of non-basic types". There are just a bunch of uniforms that just so happen to have names that include array notation like "pointLights[1].constant".

Put another way, `pointLights` is not a uniform. Nor is `pointLights[1]`. Only the elements the aggregate are themselves uniforms. And as far as the API is concerned, "pointLights[1].constant" is a completely separate uniform from the one named "pointLights[3].constant" with no relationship between them.

This is in part because you cannot *set* arrays of non-basic types with a single call. That is, there's no equivalent to `glProgramUniform4fv`, which has the ability to set a `vec4[N]` array uniform in a single function call.

So if you want to know how big some array of aggregates is, you're going to have to deduce it by iterating through all of the uniform names and comparing them to see which has the largest index.


---

