Is synchronization needed between multiple draw calls with transparency in Vulkan?
Asked Answered
I

1

5

I'm in the processing of learning Vulkan, and I have just integrated ImGui into my code using the Vulkan-GLFW example in the original ImGui repo, and it works fine.

Now I want to render both the GUI and my 3D model on the screen at the same time, and since the GUI and the model definitely needs different shaders, I need to use multiple pipelines and submit multiples commands. The GUI is partly transparent, so I would like it to be rendered after the model. The Vulkan specs states that the execution order of commands are not likely to be the order that I record the commands, thus I need synchronization of some kind. In this Reddit post several methods of exactly achieving my goals was proposed, and I once believed that I must use multiple subpasses (together with subpass dependency) or barriers or other synchronization methods like that to solve this problem.

Then I had a look at SaschaWillems' Vulkan examples, in the ImGui example though, I see no synchronization between the two draw calls, it just record the command to draw the model first, and then the command to draw the GUI.

I am confused. Is synchronization really needed in this case, or did I misunderstand something about command re-ordering or blending? Thanks.

Intoxicate answered 5/11, 2019 at 16:59 Comment(0)
S
7

Think about what you're doing for a second. Why do you think there needs to be synchronization between the two sets of commands? Because the second set of commands needs to blend with the data in the first set, right? And therefore, it needs to do a read/modify/write (RMW), which must be able to read data written by the previous set of commands. The data being read has to have been written, and that typically requires synchronization.

But think a bit more about what that means. Blending has to read from the framebuffer to do its job. But... so does the depth test, right? It has to read the existing sample's depth value, compare it with the incoming fragment, and then discard the fragment or not based on the depth test. So basically every draw call that uses a depth test contains a framebuffer read/modify/wright.

And yet... your depth tests work. Not only do they work between draw calls without explicit synchronization, they also work within a draw call. If two triangles in a draw call overlap, you don't have any problem with seeing the bottom one through the top one, right? You don't have to do inter-triangle synchronization to make sure that the previous triangles' writes are finished before the reads.

So somehow, the depth test's RMW works without any explicit synchronization. So... why do you think that this is untrue of the blend stage's RMW?

The Vulkan specification states that commands, and stages within commands, will execute in a largely unordered way, with several exceptions. The most obvious being the presence of explicit execution barriers/dependencies. But it also says that the fixed-function per-sample testing and blending stages will always execute (as if) in submission order (within a subpass). Not only that, it requires that the triangles generated within a command also execute these stages (as if) in a specific, well-defined order.

That's why your depth test doesn't need synchronization; Vulkan requires that this is handled. This is also why your blending will not need synchronization (within a subpass).

So you have plenty of options (in order from fastest to slowest):

  • Render your UI in the same subpass as the non-UI. Just change pipelines as appropriate.
  • Render your UI in a subpass with an explicit dependency on the framebuffer images of the non-UI subpass. While this is technically slower, it probably won't be slower by much if at all. Also, this is useful for deferred rendering, since your UI needs to happen after your lighting pass, which will undoubtedly be its own subpass.
  • Render your UI in a different render pass. This would only really be needed for cases where you need to do some full-screen work (SSAO) that would force your non-UI render pass to terminate anyway.
Stagnate answered 5/11, 2019 at 18:7 Comment(5)
Thanks for your great answer. But actually I think between depth testing and blending there's a difference, that depth testing just compares and no matter what the order is it always discards the fragment further away, but blending do care about what is the source and what is the destination. Am I correct on this?Intoxicate
@Chlorie: But we're talking about a memory synchronization perspective here. Both operations need to do a RMW operation, and both such operations need to be able to do their stuff based on previously written data. Whether per-triangle or per-draw call, you still need to be able to read the previous stuff. Also, combining depth tests with stencil tests can lead to circumstances where evaluating the operations in different triangle orders will lead to different outcomes, so they too must be in order.Stagnate
You said that the depth from drawing cmd 1 will have been written before the depth is written or tested by cmd 2. So you can act as if the cmd1 happens before cmd1 (even though that's not specified) for at least the depth writing and testing stage. Because that goes only for that specific stage (the depth testing and writing) you can't assume that the color buffer will be written to by cmd 1 before cmd2. Couldn't you just assume that drawing cmd 1 happens before cmd2? In what cases doesn't it behave like that? For example cmd1 draws and cmd2 reads? That would have to be in the same render ...Idou
pass or subpass? Can you write to and read from the same framebuffer in the same render (sub)pass (I mean aside from blending)Idou
@Zebrafish: "Can you write to and read from the same framebuffer in the same render (sub)pass (I mean aside from blending)" No. The only way to write to an attachment is through the outputs of a fragment shader. You can read from an input attachment, and you can write to it as a color attachment in the same subpass, but there are specific limitations on how you can do that and when you need a barrier.Stagnate

© 2022 - 2024 — McMap. All rights reserved.