Vulkan: Shaders reading wrong uniform buffer contents after dispatching compute with descriptor set containing indirect buffers which where previously used
Describe the issue
I have been running into an issue in my Vulkan rendering engine, and I'm so sorry if this is something I'm doing wrong, but I believe this could be an issue with the Vulkan drivers. To hazard a guess, it seems that somehow binding buffers which have been used as a parameter to vkCmdDrawIndirect
(or any of the other indirect draw commands) in a shader is messing up binding the uniform buffer in the next shader. I don't really have the time right now to figure out all the details of what makes this issue occur, but I've done my best to make these reproduction steps as short as I can. I have also attached a RenderDoc export and a gfxr reconstruct file of these steps.
- Uniform Buffer A contains some uniform data. It doesn't seem to matter if it's host visible and mapped or written through staging memory with
vkCmdCopyBuffer
. - Dynamic Render Pipeline A is started, a descriptor set containing Uniform Buffer A is bound and
vkCmdDrawIndirect
is called with Indirect Buffer B as its parameter. I can confirm this issue still happens withvkCmdDrawIndirectCount
. In the exports provided I am using a count of 1 and Indirect Buffer B contains all 0s, but these things don't seem to matter. If something is actually drawn here, Uniform Buffer A is read correctly by the shaders. - I use
vkCmdPipelineBarrier2
with a buffer memory barrier which has source stage and access ofVK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
andVK_ACCESS_2_INDIRECT_COMMAND_READ_BIT
and a destination ofVK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT
andVK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT
. - A compute shader is bound, a descriptor set containing Indirect Buffer B as a storage buffer is bound and the compute shader is dispatched. In the exports the compute shader does nothing (
void main() {}
), but has thelayout(set 0, binding = 0) buffer [...]
. If the dispatch of the empty compute shader is omitted, the issue does not occur. - There is a pipeline barrier on the color attachment output from step 2.
- Dynamic Render Pipeline A is started again, the same descriptor set containing Uniform Buffer A is bound again and
vkCmdDraw
is called. This is where the problem occurs. For some reason now the contents of Uniform Buffer A appear to the shader as all 0s. It does not matter if it's invoked withvkCmdDraw
orvkCmdDrawIndirect
, it always reads the buffer's contents as 0s.
I have synchronization validation turned on in my validation layers and there is no errors reported. I have tested this on 3 different NVIDIA cards and a different Intel Integrated card under Windows and the issue does not occur. This seems like a driver bug to me because in step 2 the uniform buffer is read correctly, but in step 6 it is read as all 0s despite nothing ever writing anything to any buffers, it being the exact same descriptor set and pipeline. The bug does not happen if either the `vkCmdDrawIndirect` command (which should do nothing) is omitted or the vkCmdDispatch
command which invokes a compute shader which should do nothing is omitted. I don't know if this happens when using using regular render passes and pipelines instead of dynamic rendering.
Here is a gfx reconstruct capture and a RenderDoc export of the issue occurring. In this example, "Dynamic Render Pipeline A" draws a triangle onto the screen with the red and green color coming from a float in "Uniform Buffer A", and the blue channel set to 1. "Uniform Buffer A" contains a 1, so the triangle on other hardware and systems is white, but on my system it is blue because the shader is failing to read the 1 from the uniform buffer and reads a 0 instead. You can see in RenderDoc the capture of the final frame from `vkQueueSubmit2` is a blue triangle, yet it thinks that vkCmdDraw
should have drawn a white triangle.
gfxrecon_capture_20240221T141115.gfxr
Please let me know if you need any additional details, I'm more than happy to provide them. This is my first issue here and I hope it is the right place to report this. If not, please direct me to where I should report it instead. This is such a weird problem and I can't help but shake the feeling that I am doing something wrong, so I am very sorry for wasting your time if it turns out to be an issue with my shoddy Vulkan engine.
System information
- OS: Arch Linux
- GPU: Intel Corporation TigerLake-H GT1 [UHD Graphics]
- Kernel version: 6.7.5-arch1-1
- Mesa version: 4.6 (Compatibility Profile) Mesa 24.0.1-arch1.1
- Xserver version (if applicable): 1.21.1.11
System:
Host: xps Kernel: 6.7.5-arch1-1 arch: x86_64 bits: 64 compiler: gcc
v: 13.2.1
Desktop: i3 v: 4.23 dm: LightDM Distro: Arch Linux
CPU:
Info: 8-core model: 11th Gen Intel Core i7-11800H bits: 64 type: MT MCP
arch: Tiger Lake rev: 1 cache: L1: 640 KiB L2: 10 MiB L3: 24 MiB
Speed (MHz): avg: 2500 high: 4200 min/max: 800/4600 cores: 1: 3323 2: 1829
3: 3574 4: 2869 5: 4200 6: 982 7: 1326 8: 1432 9: 3431 10: 2204 11: 2851
12: 1165 13: 4200 14: 3555 15: 1055 16: 2011 bogomips: 73744
Flags: avx avx2 ht lm nx pae sse sse2 sse3 sse4_1 sse4_2 ssse3 vmx
Graphics:
Device-1: Intel TigerLake-H GT1 [UHD Graphics] vendor: Dell driver: i915
v: kernel arch: Gen-12.1 ports: active: DP-5,eDP-1 empty: DP-1, DP-2, DP-3,
DP-4, DP-6 bus-ID: 0000:00:02.0 chip-ID: 8086:9a60
Device-2: NVIDIA GA107M [GeForce RTX 3050 Ti Mobile] vendor: Dell
driver: vfio-pci v: N/A arch: Ampere bus-ID: 0000:01:00.0 chip-ID: 10de:25a0
Device-3: Microdia Integrated_Webcam_HD driver: uvcvideo type: USB
rev: 2.0 speed: 480 Mb/s lanes: 1 bus-ID: 3-11:5 chip-ID: 0c45:6d1b
Display: x11 server: X.Org v: 21.1.11 with: Xwayland v: 23.2.4 driver: X:
loaded: modesetting dri: iris gpu: i915 display-ID: :0 screens: 1
Screen-1: 0 s-res: 3840x1200 s-dpi: 96
Monitor-1: DP-5 mapped: DP-1-2 pos: right model: Samsung LS24AG30x
res: 1920x1080 dpi: 93 diag: 604mm (23.8")
Monitor-2: eDP-1 pos: primary,left model: Sharp 0x14d1 res: 1920x1200
dpi: 145 diag: 396mm (15.6")
API: EGL v: 1.5 platforms: device: 0 drv: iris device: 1 drv: swrast
surfaceless: drv: iris x11: drv: iris inactive: gbm,wayland
API: OpenGL v: 4.6 compat-v: 4.5 vendor: intel mesa v: 24.0.1-arch1.1
glx-v: 1.4 direct-render: yes renderer: Mesa Intel UHD Graphics (TGL GT1)
device-ID: 8086:9a60
API: Vulkan v: 1.3.276 surfaces: xcb,xlib device: 0 type: integrated-gpu
driver: mesa intel device-ID: 8086:9a60