Skip to content

descriptor indexing example #1441

@lch32111

Description

@lch32111

I have a question on the descriptor indexing example.
As far as I know, DescriptorIndexing::render is called every from to record commands on a command buffer and submit the buffer for rendering. To show how to use the descriptor indexing extension, it binds descriptors.descriptor_set_update_after_bind, and then update it in the loop.

// The update-after-bind style, i.e. "streamed" descriptors. We bind the descriptor set once, and update descriptors as we go.
// With update-after-bind we can update the descriptor set from multiple threads, and we can update descriptors while the descriptor set is bound.
// We can update descriptors at any time, as long as the GPU is not actually accessing the descriptor.
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.update_after_bind);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.pipeline_layout, 0, 1, &descriptors.descriptor_set_update_after_bind, 0, nullptr);
for (unsigned i = 0; i < NumDescriptorsNonUniform; i++)
{
VkDescriptorImageInfo image_info = vkb::initializers::descriptor_image_info(VK_NULL_HANDLE, test_images[i].image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VkWriteDescriptorSet write = vkb::initializers::write_descriptor_set(descriptors.descriptor_set_update_after_bind, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0, &image_info);
// One way we can use VK_EXT_descriptor_indexing is to treat the update-after-bind descriptor set as a ring buffer where we write descriptors,
// and we use push constants as a way to index into the "bindless" descriptor set.
write.dstArrayElement = descriptor_offset;
vkCmdPushConstants(cmd, pipelines.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(uint32_t), sizeof(uint32_t), &descriptor_offset);
descriptor_offset = (descriptor_offset + 1) % NumDescriptorsStreaming;
vkUpdateDescriptorSets(get_device().get_handle(), 1, &write, 0, nullptr);
// We can use base instance as a way to offset gl_InstanceIndex in a shader.
// This can also be a nice way to pass down an offset for bindless purposes in vertex shaders that does not consume a push constant.
// In this case however, we only use the instance offset to place the textures where we expect
// and we cannot directly access gl_InstanceIndex in fragment shaders.
vkCmdDraw(cmd, 4, 1, 0, i);

However as its comment says "We can update descriptors at any time, as long as the GPU is not actually accessing the descriptor.", it is updating while the GPU is accessing it. In my debugging, current_buffer variable changes like this: 0, 1, 2, 0, 1, 2. This means we get the current_buffer 0 and record and submit with it for frame 0, and then for frame 1, we don't wait for frame 0 and just update the descriptorset and submit it. While updating the desciptor set for frame 1, the frame 0 is not done yet, which means the GPU could be accessing the descriptorset.

In this case, I think the example is doing what the comment says you should not do. Please correct me If I'm wrong. Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions