Skip to content

Performance improvements - #117

Draft
attackgoat wants to merge 8 commits into
mainfrom
performance
Draft

Performance improvements#117
attackgoat wants to merge 8 commits into
mainfrom
performance

Conversation

@attackgoat

@attackgoat attackgoat commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Various internal pattern changes and optimizations found while testing. Not yet fully scoped, will expand.

  • Support coarse image ownership tracking (whole/dual/dense, like access has single/dual/dense)
  • Optimize both ownership and access patterns now that they have similar APIs
  • Optimize solver with "same resource list" detection/re-use
  • Skip barriers if possible (tried twice before, this needs many tests)
  • Add resource-set API to make "bind my materials" faster
  • Add threaded command buffer finalizer (disposer)

@attackgoat

Copy link
Copy Markdown
Owner Author

The "same resource list" optimization makes a big difference if the workload is "lots of materials and a smaller collection of program-related resources". This is a micro-bench of a very small section of the submission process but a good first target:

New Bench Before After
10 commands 55.9 us 5.6 us
11 commands 67.6 us 5.7 us
25 commands 158.2 us 9.1 us

@attackgoat

Copy link
Copy Markdown
Owner Author

The new resource set API is additive and allows repeated arrays of images and acceleration structures to have a single bind/access operation as a group instead of one by one for each resource+command. This optimization can be combined with prepared command streams and descriptor sets.

This per-resource tax became quite a burden in real-world use:

  • Images used as materials often need to be bound and used in many additional commands
  • Acceleration structures built into a TLAS require read access in many later commands

There are probably also reasonable "I have a lot of buffers here" issues that come up, but I don't have any of those workloads right now so nothing has been designed for them.

There are probably also more reasonable access types to add (transfers, writes) for images and acceleration structures which could be helpful - those should be explored when the need arises because they might upset some of the sampled-only optimizations. Additions may wait until bugs are found/fixed.

I applied these changes in a test program and found significant performance gains by reducing the CPU overhead, example:

// Construct; each Arc<Image> is one descriptor slot.
let image_set = ImageSet::new(images.iter())?;

// Bind to the graph and declare sampled-read access.
let image_set_node = graph.bind_resource(&image_set);
graph
    .begin_cmd()
    .resource_access(image_set_node, ImageAccessType::SampledRead)
    .record_cmd(|cmd| {
        // Bind/use your descriptor set and issue commands here.
    })
    .end_cmd();

For subresources, pass (Arc<Image>, vk::ImageSubresourceRange) entries. ImageSet tracks synchronization.

Note:
Each new set type has a new type-specific AccessType which contains all the supported accesses for each resource set.

Note:
Do not bind an individual resource set member in the same graph - it will panic. We have the option of folding these accesses together, but you can avoid this by binding individual members on the conflicting frames and the whole set on other frames.

Note:
Descriptor-set binding remains separate and for the most performance implement both:

  • AccelerationStructureSet/ImageSet: access and graph optimization
  • DescriptorSet: Vulkan driver optimization

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.

1 participant