Gary C.
Gary C.

Reputation: 35

Rendering to different framebuffers with multithreading rendering in Vulkan

I was trying to reproduce a result that is similar to this video: https://www.youtube.com/watch?v=21UsMuFTN0k Specifically, I want to render the whole scene to a different texture, and put the texture inside the UI like this screenshot of the video:OpenGL rendering to a different framebuffer

The author of the video was using OpenGL to do this, and I was trying to achieve it in Vulkan instead. However, since my current program is using the third attachment to enable MSAA and rendering the whole scene using secondary command buffers, I have difficulty translating the way to do this in the video to Vulkan. I figured that I probably not only need more framebuffers, but also multiple renderpasses. Simply put, so far this is what I tried:

  1. Begin the first renderpass, with the renderpass begin info set to a smaller render area, an offscreen renderpass, and a separate framebuffer.
  2. Pass the offscreen renderpass and the framebuffer to an inheritance info, and pass it to secondary command buffers to do the drawing.
  3. End the first renderpass.
  4. Begin the second renderpass, with the renderpass begin info set to the actual size of the screen, the primary renderpass, and the primary framebuffer.
  5. Pass the second renderpass and the framebuffer to an inheritance info, and pass it to secondary command buffers to do the drawing.
  6. Do vkCmdExecuteCommands.
  7. End the second renderpass.
  8. End command buffer.

Nonetheless, when the program is executed, the validation layer shows that:

vkCmdExecuteCommands(): Cannot duplicate VkCommandBuffer 0x1c26226d2e8[] in pCommandBuffers without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. The Vulkan spec states: If any element of pCommandBuffers was not recorded with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT flag, it
must not appear more than once in pCommandBuffers

Does this mean I have to set VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT for all secondary command buffers? Or there are other ways to correct do it? Because as far as I know, setting VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT has a performance cost. Also, if I instead try to do vkExecuteCommands in each renderpass, the validation layer will show that the command buffer has been destroyed.

I wonder what the correct way to reproduce a similar result in Vulkan is, and whether I have to separate them so that I will have to do vkQueueSubmit multiple times.

Upvotes: 1

Views: 1675

Answers (1)

Janakiraman Kannan
Janakiraman Kannan

Reputation: 46

You are trying to do two RenderPasses with different Framebuffers in a single CommandBuffer.

RenderPass Execution

Execution of RenderPasses inside Graphics Queue can be Out-of-order, ie) no guarantee that the RenderPasses will be executed based on the submission order. Since, you are recording multi-passes in the same Command Buffer, it can be a problem

Synchronization Using Semaphores

Record the First RenderPass and Second RenderPass in different Command Buffers and use Semaphores to synchronize when you submit it to the queue.

Use a Semaphore to signal in vkQueueSubmit for the First RenderPass. When you submit the Second RenderPass use the semaphore in the wait slot.

Check for VKSubmitInfo in VKQueueSubmit. This is used in internal synchronization in the queue.

ImageLayout Transition

You also have to ensure that the Texture you write and read are in the correct Layouts at the appropriate RenderPasses.

  • First RenderPass, the texture has to in COLOR_ATTACHMENT_OPTIMAL
  • Second RenderPass, the texture has to in SHADER_READ_ONLY_OPTIMAL

You can use use a ImageBarrier or make the first renderpass output to transition the attachment Layout to Read_Only thus preparing early.

General Instructions

  • Record First Pass with a CommandBuffer, Change Final ImageLayout of Texture to SHADER_READ_ONLY_OPTIMAL(if not using ImageBarrier)
  • Record Second Pass with a CommandBuffer
  • Submit First Pass with a wait Semaphore
  • Submit Second Pass with a signal Semaphore

If you use ImageBarrier, you need one more semaphore and one more Command Buffer to insert into middle of the First and Second Pass.

Command_Buffer_Simultaneous_Use_Bit

Simultaneous Bit is used when you need store some commands which needs to be submitted multiple times into different queues or recorded into different primary buffers.

This is commonly used in secondary buffers to store few commands (perhaps a common procedure in many process) and to record in primary buffers as needed.

In your case it's not needed.

Upvotes: 0

Related Questions