Uniform array, with each element using a different binding point?

I have an array of data for various light sources in my shader, similar to this:


struct LightSource
{
	vec3 position;
	vec4 color;
};

layout(std140,set = 0,binding = 0) uniform LightSources
{
	LightSource data;
} u_lightSources[8];

So far I’ve used a separate descriptor set for each light source. However, I’ve noticed that a lot of Nvidia cards only allow around 8 bound descriptor sets total, which is too low for my case (Since I have other descriptor sets as well).
So, instead I’d like to use a single descriptor set for the light sources, with each light source using a different binding point. However, if I do that, would there still be a way to represent it as an array inside the shader?
I could define all of them independently, like this:


layout(std140,set = 0,binding = 0) uniform LightSource u_lightSource0;
layout(std140,set = 0,binding = 1) uniform LightSource u_lightSource1;
layout(std140,set = 0,binding = 2) uniform LightSource u_lightSource2;
layout(std140,set = 0,binding = 3) uniform LightSource u_lightSource3;
layout(std140,set = 0,binding = 4) uniform LightSource u_lightSource4;
layout(std140,set = 0,binding = 5) uniform LightSource u_lightSource5;
layout(std140,set = 0,binding = 6) uniform LightSource u_lightSource6;
layout(std140,set = 0,binding = 7) uniform LightSource u_lightSource7;

LightSource get_light_source(int i)
{
	switch(i)
	{
		case 0:
			return u_lightSource0;
		case 1:
			return u_lightSource1;
		[...]
	}
}

I’d like to avoid that if possible. (And I don’t want to switch to deferred rendering either.)
Is there a better way?

So far I’ve used a separate descriptor set for each light source.

That’s not what your GLSL says you’re doing. The GLSL code says that u_lightSources comes from a single descriptor set. It will take up 8 descriptors, using the descriptor index range [0, 8). The KHR_vulkan_glsl specification makes this clear:

Arrays of uniform blocks are not arrays of resources. They instead work under the standard GLSL rule, with each array element taking up consecutive binding indices.

So it’s not clear what you’re asking here. You seem to be asking how to do what you’ve already done.

In any case, it’s a bad idea to have an array of uniform blocks solely for different lights. The maximum number of uniform buffers per stage is only required to be 12, which is what NVIDIA hardware supports. You should have an array within a single uniform block:

layout(std140,set = 0,binding = 0) uniform LightSources
{
	LightSource data[8];
} u_lightSources;

That is a single uniform buffer that takes up a single binding within the shader. It has an array of values within it.