1

I have the following uniform in a shader pipeline:

layout (set = 1, binding = 0) uniform window_uniform_data_uniform {};

Now I want to bind this set, so I do:

vkCmdBindDescriptorSets(cmd_buffer->vk_buffer_handle, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS,
        PipelineLayouts::GUI,
        1, // THE UNIFORM BUFFER IS SET 1
        1,
        &DescriptorSets::GUI, 0, nullptr);

When I call that function I get the validation error:

Vulkan validation layer callback: Validation Error: [ VUID-VkPipelineLayoutCreateInfo-pSetLayouts-parameter ] Object 0: handle = 0x1acf6211460, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0xb3f957d3 | Invalid VkDescriptorSetLayout Object 0x0. The Vulkan spec states: If setLayoutCount is not 0, pSetLayouts must be a valid pointer to an array of setLayoutCount valid VkDescriptorSetLayout handles

The reason I think this is happening is because in the pipeline layout description I say that there is one set layout count:

pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &DescriptorSetLayouts::GUI; 

Which makes sense to me because in the shader I have only set = 1, and no 0. However what I think is happening is in the vkCmdBindDescriptorSets I pass (firstSet (1), descriptorSetCount(1) ) because I only want to update set 1. Vulkan probably looks up element/position 1 of the pipeline layouts and sees that it's empty or has invalid arguments. Is this correct?

If this is the case, does this mean that if I have a description in a shader that's set = 11 that the pipeline needs to be created with 10 dummy layouts, even if I never update them?

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • "*if I have a description in a shader that's set = 11*" Ignoring the fact that pretty much no Vulkan implementation supports 12 descriptor sets at a time, why would you even do that? What do you think different sets of descriptors are *for*, exactly? – Nicol Bolas Mar 18 '22 at 20:37
  • And [here's a question about what descriptor sets are for](https://stackoverflow.com/q/56928041/734069). – Nicol Bolas Mar 18 '22 at 20:45
  • @NicolBolas I believe I'm using the sets properly, set 0 I'll use for certain data, set 1 for another type of data. But then I have a fragment shader that only uses 1, not 0, so it makes sense that the layout count would be 1 as that shader only uses one. It seems in this case I do need a dummy set layout. Does that sound strange to you? I mean am I doing something wrong? – Zebrafish Mar 19 '22 at 00:06
  • Again, the question arises: why does it only use set 1? What do these sets *mean*? You say they're for a certain type of data, but you don't really explain what that's all about. The question I linked to goes over the design of the feature; how does that fit into the goals you're trying to achieve here? – Nicol Bolas Mar 19 '22 at 00:18
  • @NicolBolas Will we get to the stage soon where selecting textures will be in a more bindless form, like what the buffer reference and address extensions do? So you can essentially store a pointer to an image in a uniform buffer, and pick that image from the shader? This would bypass descriptors altogether. This is, I believe, what those extensions I mentioned do, but it doesn't work with images, does it? – Zebrafish Mar 19 '22 at 00:41
  • You can use [an array of samplers](https://stackoverflow.com/a/36781650/734069). They've been core since Vulkan 1.0. – Nicol Bolas Mar 19 '22 at 02:15

2 Answers2

2

VkPipelineLayoutCreateInfo has the member setLayoutCount, but there's no "set offset" member. A pipeline layout has setLayoutCount descriptor sets, with indices on the range [0, setLayoutCount).

Your pipeline has a set 0 even if the shaders in that pipeline never use it. It's still there.

Note that the validation error you get is not from vkBindDescriptorSets; it's from VkPipelineLayoutCreateInfo, likely in the call to vkCreatePipelineLayout.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
1

In your case, you can apply descriptor set 0 with an "empty" descriptor set layout:

VkDescriptorSetLayoutCreateInfo emptyLayoutInfo = {};
emptyLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
emptyLayoutInfo.flags = 0;
emptyLayoutInfo.pNext = NULL;
emptyLayoutInfo.bindingCount = 0;
emptyLayoutInfo.pBindings = NULL;

VkDescriptorSetLayout emptyLayout;
vkCreateDescriptorSetLayout(device, &emptyLayoutInfo, NULL, &emptyLayout);
// ...
VkDescriptorSetLayout descriptorSetLayouts[2] = { emptyLayout, layout };
// ...
pipelineLayoutInfo.setLayoutCount = 2;
pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts;
// ...
vkCmdBindDescriptorSets(cmd_buffer->vk_buffer_handle, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS,
        PipelineLayouts::GUI,
        1,
        1,
        &DescriptorSets::GUI, 0, nullptr);
chirsz
  • 11
  • 2