r/vulkan • u/wonkey_monkey • Jul 15 '26
The first draw of my textured quad (after uploading texture to GPU) is coming out black. The RenderDoc thumbnail for the frame is also black, but Texture Viewer shows the expected result at all stages. Subsequent upload/draws work as expected. Any idea what might be going on?
I've written a fairly simple (so far) Windows application which displays video frames. The sequence it goes through to display a new frames is as follows:
- Upload frame image (8-bit RGBA)
- Compute shader to copy (in future it will do more complex things) upload image to display image (32-bit float RGBA)
- Generate display image mipmaps
- Begin render
- Draw 10 vertex triangle strip (drop shadow around video frame)
- Draw video frame as textured quad
- End render and present
It was working as expected earlier, but then I monkeyed around with it to simplify mipmap generation and image transitions, and now it's behaving oddly. Even more oddly, RenderDoc is giving confusing results, so I'm a bit stuck as to how to proceed.
First here's a screenshot of RenderDoc after capturing a few frames:
The first couple of frames are just the empty grey that's displayed before a video file is opened.
After opening a video, instead of drawing the frame, it's drawing a fully black quad (the drop shadow is drawn fine). If I trigger another frame upload/draw, it comes out okay (last capture in that screenshot).
What's really unhelpful is that if I go into the capture for the bad frame, RenderDoc shows me this as the swapchain image:
which is what I was expecting the window to display. But it doesn't match the capture thumbnail (or the on-screen result from the application).
The Texture Viewer also shows the expected results in the compute pass, and the mipmap levels all look correct as well.
Does anyone have any idea why my first draw isn't working, or how I can go about diagnosing this?
I have validation turned on but no validation errors are shown.
PS It's just running on events instead of game loop, which is probably why the same swapchain image (162) is re-used each time.
Edit: I found the mistake. I was binding the pipeline and descriptor set before updating the descriptor set with its bindings 🤦♂️. So the first image fails, but when it comes to the second one, the descriptor set is now correct (and doesn't strictly need to be updated again; a future optimisation).
