-->

Debugging a black image in Vulkan

2019-08-02 15:00发布

问题:

I'm trying to render a scene into an image in Vulkan which I want to sample on a quad that's floating around somewhere in that scene.

My approach was to basically do the same steps I used to render the scene into presentation images, except that I would only have a single image in RGBA8 format instead of a presentation-specific format. All I'm seeing, though, is blackness. The validation layers are on and do not report anything. When debugging with RenderDoc, the data seems to be correct. It shows an image of the scene as input to the draw command (see screenshot below).

However, as you can see, the image on the surface is simply black (center of the image on the right-hand side). So how would I go about to debugging this kind of problem? RenderDoc data seems to be what I expect but the result is not. The validation layers are not reporting anything, so I must do something vaguely valid at least.


If you want to dig in, full source code for this particular example can be found on GitHub in Main.cpp and VulkanHelpers.cpp. Look for Vulkan.RenderTarget2.

回答1:

I don't get quite the same result as you when capturing in RenderDoc - I only have one colour pass, writing to the backbuffer, but also with a black quad (What I get when I capture).

This seems to be consistent with the code on github. The draw command buffer in Vulkan.RenderTarget2.DrawCommandBuffer is recorded to in the VulkanBuildDrawCommands function, but then it never gets submitted. The only calls to vkQueueSubmit are for the the per-backbuffer command buffers and the pre/post- present command buffers transitioning to and from VK_PRESENT_SRC_KHR.

On the assumption that maybe you have local changes which do submit that command buffer, from what I can tell the remaining problem is actually reported by the validation layers even with no modification to the code other than to turn them on:

Err: [DS] Code 52: DS 0x4a encountered the following validation error at
vkCmdDrawIndexed() time: Descriptor in binding #10 at global descriptor
index 2 requires an image view of type VK_IMAGE_VIEW_TYPE_2D but got VK_IMAGE_VIEW_TYPE_1D.

Which is because the image view created for RenderTarget2 (I can't link to that specific code because I don't have "10 reputation"? No idea what that BS is) doesn't set the image view type, and 1D is value '0' from default initialisation.

If you're not getting that message, you should check you are on the latest SDK. I also get several other messages including one mentioning layout issues. This is is because your recording function linked above seems to have the layouts switched for the off-screen target, it transitions away from COLOR_ATTACHMENT_OPTIMAL into SHADER_READ_ONLY_OPTIMAL before rendering (the OldImageLayout is the first parameter), then back to COLOR_ATTACHMENT_OPTIMAL. I think that should be reversed, or better yet transition from UNDEFINED to COLOR_ATTACHMENT_OPTIMAL, then back to SHADER_READ_ONLY_OPTIMAL.

Because you're using the same recording helper too when rendering into the offscreen-target, it means that it tries to read from the offscreen-target to draw the quad. This probably isn't what you want so you might need to detect this case and skip the quad, or bind another texture, or something.