Skip to content

Add first-class DescriptorSet types - #115

Draft
attackgoat wants to merge 3 commits into
mainfrom
descriptor-set
Draft

Add first-class DescriptorSet types#115
attackgoat wants to merge 3 commits into
mainfrom
descriptor-set

Conversation

@attackgoat

Copy link
Copy Markdown
Owner

Additive change to allow manually-specified descriptor set writes and copies. This should reduce CPU/driver usage during graph submission for most common workloads. Regular automatic descriptor set usage remains unchanged.

See examples/bindless.rs for the change, which is quite minimal. This builds set 0 with a bunch of images bound to descriptor 1:

let descriptor_set = DescriptorSet::alloc_and_update(
    &pipeline,
    DescriptorSetInfo::builder().set(0).build(),
    images
        .iter()
        .enumerate()
        .map(|(idx, image)| DescriptorSetUpdateInfo::image((1, [idx as u32]), image)),
)?;

...

graph
    .begin_cmd()
    .bind_pipeline(&pipeline)
    .bind_descriptor_set(&descriptor_set)

The rest, including declaring access, remains unchanged. I think that could be relaxed in practice, but each program can decide that.

@Flopgop

Flopgop commented Aug 12, 2026

Copy link
Copy Markdown

I don't see a super clear way to update already allocated descriptor sets, is it possible to add API for that?

@attackgoat

Copy link
Copy Markdown
Owner Author

This was intentionally skipped in the safe API; because the sets cannot be updated while in use by any submission. I thought about encoding this as either DescriptorSet<Immutable> or DescriptorSet<Mutable>, or a wrapper type, but it was then awkward to hold one and you end up with some box and suddenly the user has more burden than I'd prefer.

The easy path out of that was to offer DescriptorSet::alloc_and_update as one path, but you'll need to drop to unsafe code to do this:

let write = vk::WriteDescriptorSet::default().dst_set(set.handle())
        .dst_binding(binding)
        .dst_array_element(0)
        .descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
        .buffer_info(...);

unsafe {
    // SAFETY: This is UB unless we have observed all submissions which used this set to have completed
    set.device().update_descriptor_sets(&[write], &[]);
}

This pattern could be wrapped up into a type-level update safety through a very tiny custom tracker/wrapper.

Due to the nature of having to wait for availability, and it being very annoying to track that concept, it would be easier if possible to separate out the descriptors that change from the static ones and keep those bound in a regular dynamic/automatic descriptor set index.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants