How to access a descriptor array within shaders?


the struct VkDescriptorSetLayoutBinding has a member descriptorCount describing the amount of elements of a descriptor array,

my question is how to access this descriptor array from shader side?

Here’s the code corresponds to my picture:

struct of my uniform buffer:

struct UniformBufferObject {
		glm::mat4 model;
		glm::mat4 view;
		glm::mat4 proj;
};



struct UniformBufferObjectTest {
		glm::mat4 model;
		glm::mat4 view;
};

Descriptor buffer infos:

VkDescriptorBufferInfo bufferInfo0{};
bufferInfo0.buffer = uniformBuffers[i];
bufferInfo0.offset = 0;
bufferInfo0.range = sizeof(UniformBufferObject::model) + sizeof(UniformBufferObject::view);


VkDescriptorBufferInfo bufferInfo1{};
bufferInfo1.buffer = uniformBuffers[i];
bufferInfo1.offset = offsetof(UniformBufferObject, proj);
bufferInfo1.range = sizeof(UniformBufferObject::proj);



std::vector< VkDescriptorBufferInfo> bufferInfos = { bufferInfo0, bufferInfo1 };

VkDescriptorBufferInfo bufferInfo2{};
bufferInfo2.buffer = uniformBuffersTest[i];
bufferInfo2.offset = 0;
bufferInfo2.range = sizeof(UniformBufferObjectTest);

Write descriptor sets:

	    std::array<VkWriteDescriptorSet, 3> writeDescriptorSets{};

		/*
			Binding 0: Object matrices Uniform buffer
		*/
		writeDescriptorSets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
		writeDescriptorSets[0].dstSet = descriptorSetsWrite[i];
		writeDescriptorSets[0].dstBinding = 0;
		writeDescriptorSets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;

		writeDescriptorSets[0].pBufferInfo = bufferInfos.data();
		writeDescriptorSets[0].descriptorCount = 2;
		writeDescriptorSets[0].dstArrayElement = 0;


		/*
			Binding 1: test purposes uniform buffer
		*/

		writeDescriptorSets[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
		writeDescriptorSets[1].dstSet = descriptorSetsWrite[i];
		writeDescriptorSets[1].dstBinding = 1;
		writeDescriptorSets[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
		// Images use a different descriptor structure, so we use pImageInfo instead of pBufferInfo
		writeDescriptorSets[1].pBufferInfo = &bufferInfo2;
		writeDescriptorSets[1].descriptorCount = 1;
		writeDescriptorSets[1].dstArrayElement = 0;

And my vertex shader:

#version 460
#extension GL_ARB_separate_shader_objects : enable
#extension GL_EXT_debug_printf : enable

//#extension GL_KHR_vulkan_glsl : enable


layout(set = 0,binding = 0) uniform  UniformBufferObject{

    mat4 model;
    mat4 view;
    mat4 proj;
} ubo1;

layout(set = 0,binding = 1) uniform UniformBufferObjectTest {
    mat4 model;
    mat4 view;

} uboTest;





//Input
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in mat4 instanceMatrix;
//Output
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;


void main() 
{

  
    gl_Position = ubo1.proj * uboTest.view  * uboTest.model* instanceMatrix * vec4(inPosition, 1.0);



    fragColor = inColor;
    fragTexCoord = inTexCoord;

}

I don’t really know what that diagram is supposed to show. Posting the actual shader code is better than a picture.

But descriptor arrays are just arrays. The only special thing about them is the class of expression you’re allowed to use with them.

The minimum you can use are constant expression indices. If the Vulkan implementation has certain features, you can use dynamically uniform expressions as indices. However, such features are specific to the type of descriptor; it’s possible for arrays of samplers to be dynamcally indexed while arrays of UBO descriptors only allow constant expressions.

How we access descriptor arrays in glsl shaders?what is the syntax for doning that?Thank you sir.

It’s an array. You use array indexing syntax.

But this layout(set = 0,binding = 0) statement only indexes descriptor set layout binding 0,can’t index the descriptor array contained in descriptor set layout binding.

There is no “descriptor array contained in descriptor set layout binding” in the code you posted. You seem to be thinking that the word “array” only exists in the Vulkan layout binding and not in the actual shader. Descriptor layouts are supposed to match the declarations in your shader (with the static vs. dynamic offset being one of the few exceptions).

If you want a “descriptor array” of UBOs, your shader must declare such a thing. Just like if you want a descriptor which is a UBO, your shader has to declare a UBO.

This is a UBO array:

layout(set = 0,binding = 0) uniform  UniformBufferObject
{
    mat4 model;
    mat4 view;
    mat4 proj;
} ubo1[10];

Granted, I’m not sure why you would want an array of UBOs like this. It makes far more sense to have a UBO containing an array:

struct matrices
{
    mat4 model;
    mat4 view;
    mat4 proj;
};

layout(set = 0,binding = 0) uniform  UniformBufferObject
{
   matrices mats[10];
} ubo1;

You’re subject to the size limits of a UBO, but at least you won’t have dozens of UBOs (and there are limits to those too, which can be quite severe). Also, a UBO containing an array can be indexed by any expression, while a UBO array indices are restricted by the implementation.

I’m just testing out functionalities of VkDescriptorSetLayoutBinding.Is it possible to have descriptors within a VkDescriptorSetLayoutBinding to have different structures?Just like what I did in my code,one descriptor for first two matrix in UBO and another descriptor for last matrix in UBO.

They’re arrays. The array elements in an array are all the same type. This isn’t something you should be looking at from the perspective of the Vulkan API; it’s SPIR-V/GLSL that you need to be paying attention to. The descriptor set layout matches the definitions in the shader, not the other way around.