baldurk / renderdoc

RenderDoc is a stand-alone graphics debugging tool.
https://renderdoc.org
MIT License
8.62k stars 1.3k forks source link

Vulkan dynamic uniform buffer offsets are interpreted incorrectly #3291

Closed Devenec closed 3 months ago

Devenec commented 3 months ago

Description

I use a descriptor set layout that defines multiple dynamic uniform buffer descriptors in consecutive bindings. I use the same descriptor set layout with multiple pipelines, but not all pipelines reference all the descriptors. Sometimes the used descriptor set has some undefined descriptors that are not referenced. When a descriptor is undefined, RenderDoc seems to use its offset for the next defined descriptor.

Consider the following descriptor set layout:

Binding | Type
--------+------------------------
0       | Dynamic uniform buffer
1       | Dynamic uniform buffer
2       | Dynamic uniform buffer
3       | Dynamic uniform buffer

Consider the following descriptor set:

Binding | Defined?
--------+------------------------
0       | No
1       | Yes
2       | No
3       | Yes

Calling vkCmdBindDescriptorSets() with dynamic offsets { 0, 16, 208, 240 }:

some_descriptors_bound

Notice that the Byte Range offsets are incorrect. Also clicking a Go arrow shows incorrect data.

With a descriptor set with all descriptors defined, and the same dynamic offsets:

all_descriptors_bound

The latter is the excepted behaviour, even when the non-referenced descriptors are undefined.

Steps to reproduce

I have attached the captures, and a modified source code and a vertex shader of Sascha Willems' triangle example (https://github.com/SaschaWillems/Vulkan/tree/2f8b5c92ad32b0e6c81df1dc2b07be56fa540807) below. Building and running the example reproduces the issue. Uncommenting #define BIND_ALL_UNIFORM_BUFFERS at line 14 defines all the descriptors.

repro.zip

Environment

baldurk commented 3 months ago

Yes this is an issue I noticed while doing a refactor on descriptor handling, which seems to have been around for a while since support for mutable descriptors was added.

The trigger is not whether descriptors are referenced but whether they are written to - though those are likely correlated. The code was relying on dynamic descriptors being written to in order to have a proper type marked, otherwise it skipped over them when looking for dynamic offsets to consume.

If you want a workaround in the meantime until this is fixed you can write any buffer into the descriptor to mark it as dynamic.

baldurk commented 3 months ago

The refactor is now pushed so this bug should be fixed in the next nightly build.