Skip to content

Vulkan Dynamic Uniform Descriptors

github-actions[bot] edited this page Sep 18, 2026 · 4 revisions

Vulkan Dynamic Uniform Descriptors

Lifecycle: Performance - Unproven · Type: Descriptor architecture
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579
State: Descriptor coupling is source-confirmed. Runtime value is unmeasured.

Vulkan throughput pages: Overview · Submission & retirement · Native presentation · Dynamic uniforms · PVIDEO lifetime · GPU-resident consumers · Buffer placement

Status

Ordinary vertex and fragment uniforms use non-dynamic uniform-buffer descriptors. A new uniform-buffer offset can require another descriptor set, and that update also rewrites the four texture/sampler bindings. Exhausting the set array can force pgraph_vk_finish().

Ubershader controls already use VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, and a control-only upload can reuse the prior set. That is a local precedent, not proof that the same design is best for all uniforms.

Source seams:

Why it matters

Changing shader constants should require new constant data. It should not automatically require rewriting texture descriptors that did not change.

Current path

flowchart TD
    A[Uniform data changes] --> B[Append new UBO bytes]
    B --> C[New uniform-buffer offsets]
    C --> D[Allocate next descriptor set]
    D --> E[Write VSH UBO descriptor]
    E --> F[Write PSH UBO descriptor]
    F --> G[Rewrite four texture/sampler descriptors]
    G --> H[Advance descriptor-set index]
    H --> I{Set array exhausted?}
    I -->|Yes| J[pgraph_vk_finish and reset]
    I -->|No| K[Draw]
    J --> K
Loading

Candidate path

Use dynamic offsets for ordinary vertex/fragment uniform buffers. Keep texture descriptors stable until texture state actually changes.

flowchart TD
    A[Uniform data changes] --> B[Append new UBO bytes]
    B --> C[Keep stable descriptor set]
    C --> D[Bind VSH and PSH dynamic offsets]
    D --> E[Draw]
    F[Texture binding changes] --> G[Update texture descriptor state]
    G --> C
Loading

What changes

  • VSH and PSH bindings become dynamic uniform-buffer descriptors.
  • Descriptor identity no longer depends on each uniform offset.
  • Texture descriptor updates are driven by texture changes, not ordinary constant changes.
  • Uniform upload bytes remain; only descriptor reconstruction and pressure are targeted.

Required guard

  • Dynamic offsets satisfy minUniformBufferOffsetAlignment.
  • Descriptor ranges remain valid at every offset.
  • The backing buffer and uploaded bytes remain alive until the draw completes.
  • Ring wrap or buffer replacement cannot overwrite in-flight constants.
  • Pipeline layouts match the new descriptor types.
  • Texture/sampler lifetimes remain independently tracked.

Risks

  • Using VK_WHOLE_SIZE or an oversized range with a nonzero dynamic offset.
  • Reusing a descriptor set while a referenced texture was replaced or destroyed.
  • Hiding descriptor pressure but moving the stall to uniform-buffer wrap.
  • Increasing bind-time work enough to offset fewer descriptor writes.
  • Mixing specialized and ubershader layouts incorrectly.

Evidence

uniform_uploads
uniform_upload_bytes
descriptor_sets_consumed
descriptor_writes_total
texture_descriptor_writes
texture_descriptor_writes_due_only_to_uniform_change
descriptor_pressure_finishes
dynamic_offset_binds
CPU draw-preparation time

The decisive signal is that texture-descriptor writes stop following uniform-only changes.

How to test

  1. Draw many objects with stable textures and changing vertex/fragment constants.
  2. Verify output against the current descriptor route.
  3. Force ring wrap, descriptor pressure, and backing-buffer replacement while earlier draws remain in flight.
  4. Change textures, samplers, shader layouts, UBO sizes, and fragment route independently.
  5. Run Vulkan validation and an uninstrumented Release A/B using fixed guest progress.

Related

Full technical reference

Primary reference: This subject page is the design and research reference for Dynamic Uniform Descriptors. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Descriptor architecture
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579 · Acceptance class: intended exact or behavior-preserving for its admitted scope

1. Scope

Use dynamic offsets for ordinary VSH/PSH uniform buffers so changing constant offsets does not require rewriting unchanged texture descriptors or consuming another set.

This entry remains Unproven: the source path and opportunity are concrete, but no accepted xemu runtime result has established that the candidate improves representative workloads. The page defines what must be bypassed, what remains mandatory, and how the hypothesis can be rejected.

2. Source seams

File / function Role
hw/xbox/nv2a/pgraph/vk/shaders.c descriptor layout, pgraph_vk_update_descriptor_sets(), set index and UBO staging
hw/xbox/nv2a/pgraph/vk/renderer.h descriptor arrays and uniform offsets

3. Current execution path

flowchart TD
    N0["Uniform changes"]
    N1["Append UBO bytes"]
    N0 --> N1
    N2["Create next descriptor-set contents"]
    N1 --> N2
    N3["Rewrite two UBO descriptors"]
    N2 --> N3
    N4["Rewrite four texture/sampler descriptors"]
    N3 --> N4
    N5["Advance set index"]
    N4 --> N5
    N6["Finish on exhaustion"]
    N5 --> N6
Loading

4. Candidate execution path

flowchart TD
    N0["Uniform changes"]
    N1["Append UBO bytes"]
    N0 --> N1
    N2["Keep stable descriptor set"]
    N1 --> N2
    N3["Bind VSH/PSH dynamic offsets"]
    N2 --> N3
    N4["Rewrite texture descriptors only on texture change"]
    N3 --> N4
Loading

5. Why it may help

The ubershader control binding already demonstrates a dynamic UBO path. Ordinary constants are coupled to texture descriptors because descriptor identity includes new buffer offsets. The candidate targets descriptor reconstruction and capacity pressure, not uniform value preparation itself.

6. Work removed

  • Texture descriptor rewrites caused only by uniform offsets
  • Descriptor-set consumption for uniform-only changes
  • Some finishes caused by descriptor exhaustion

7. Work that remains mandatory

  • Uniform uploads
  • Dynamic offset binding
  • Texture descriptor updates when textures actually change
  • Buffer lifetime/alignment
  • Fallback for unsupported layout

8. Implementation sketch

uint32_t offsets[] = {
    (uint32_t)r->uniform_buffer_offsets[VSH_STAGE],
    (uint32_t)r->uniform_buffer_offsets[PSH_STAGE],
};
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
                        pipeline_layout, 0, 1, &stable_set,
                        ARRAY_SIZE(offsets), offsets);

The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.

9. Correctness contract

  • Offsets satisfy minUniformBufferOffsetAlignment and fit uint32_t.
  • Descriptor range plus dynamic offset remains inside the backing buffer.
  • Uploaded bytes and buffer remain alive until draw completion.
  • Texture object lifetime is independent and correctly invalidates stable sets.

10. State, ownership, invalidation, and fallback

Stable sets may be cached by texture/sampler binding plus layout generation. Uniform offsets are draw/batch state. Ring wrap and buffer replacement require new storage or retirement before overwrite.

The maintained reference path remains the fallback whenever admission, capability, lifetime, or validation is uncertain. A fast result with an unproven dependency is not acceptable as an exact optimization.

11. Advantages

  • Fewer vkUpdateDescriptorSets calls
  • Decouples constants from textures
  • Reduces descriptor pressure/finish triggers
  • Uses an established Vulkan mechanism

12. Costs and failure modes

  • Pipeline layout migration
  • Stable set still needs texture lifetime tracking
  • Dynamic bind overhead
  • Uniform ring wrap can become the new stall
  • Validation traps around range/offset

13. Evidence counters

Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:

  • uniform_updates
  • descriptor_sets_consumed
  • descriptor_writes_total
  • texture_descriptor_writes_due_to_uniforms
  • dynamic_offset_binds
  • descriptor_pressure_finishes
  • draw_prepare_cpu_us

A local reduction is not enough. Evidence must connect route reachability and removed work to fixed guest progress, CPU/GPU time where applicable, and p95/p99 behavior.

14. Qualification matrix

  • Thousands of draws with stable textures/changing constants
  • Texture-only changes
  • Shader/layout changes
  • Different UBO sizes
  • Ring wrap with in-flight draws
  • Buffer replacement
  • Ubershader/specialized routes
  • Vulkan validation

Correctness runs may use validation layers, detailed comparisons, and fault injection. Performance acceptance must use optimized Release builds with matching symbols and minimal instrumentation.

15. Acceptance rule

Promote when texture writes and descriptor-pressure finishes fall materially, validation passes, and Release draw-preparation/frame tails improve.

16. Rejection rule

Reject if dynamic binds/ring management erase gains, stable texture-set invalidation is unreliable, or the bottleneck lies elsewhere.

17. Related architecture and history

Vulkan-Renderer · Performance-Unproven · Hot-Path-Vulkan-Uniform-Update-Plans · Vulkan-Submission-and-Resource-Retirement

PR pages may be linked as supporting evidence, but they are not substitutes for this reference.

Recent descriptor/uniform evidence

Draft PRs #134 and #135 provide narrower evidence for this broader design.

#134 shows that descriptor capacity can be consumed after a slow texture traversal even when the final image/sampler identity is unchanged. Its model retains a publication-required obligation until actual descriptor publication.

#135 shows a separate dependency: effective texture scale may need shader-uniform reconciliation even when descriptor identity is otherwise stable.

image/sampler descriptor identity
uniform-buffer location/offset identity
shader-derived texture values such as texScale

A dynamic-offset design should not collapse these into one “textures changed” bit. Measure descriptor identity changes, publication calls, descriptor writes, uniform-offset changes, scale reconciliations, actual uniform writes, and capacity rollovers separately.

These drafts do not yet prove ordinary dynamic UBO descriptors are a net win; they improve the dependency model needed to test that proposal.

Clone this wiki locally