Search code examples
vulkanimgui

How to "blend" ImGui frame with scene rendering in Vulkan


I'm not an expert in Vulkan. I want to know how do I present the Vulkan Frame (Submit an especif commandBuffer that is being recorded every frame to draw UI changes) at the top of my regular scene rendering. So in this case I have two renderPasses one for scene and other for ImGui,and also two commandBuffers. While trying to send this two commandBuffers , only the last one is being shown , since they are using the swapchain image. What am I missing? should the frameBuffer view attachment in the imgui pass be a swapchainImage?


Solution

  • If you separate scene and UI rendering into different distinct render passes you need to tell the color attachment of your first render pass to keep the contents and the second UI render pass to load the contents of the frame buffer.

    Judging from your description the second renderpass is properly set to VK_ATTACHMENT_LOAD_OP_CLEAR for the loadOp which results in the framebuffer being cleared with the current clear color as soon as you begin your second render pass.

    So in your scenario you need to store the contents in your first pass to make sure that they're not discarded due to optimizations:

    std::array<VkAttachmentDescription, 2> attachments = {};
    // Attachment 0 = Color attachment
    attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    ...
    

    And in your second render pass you need to set it to load the previous contents:

    std::array<VkAttachmentDescription, 2> attachments = {};
    // Attachment 0 = Color attachment
    attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
    ...
    

    If you submit multiple command buffers you also need to ensure correct command ordering by using appropriate synchronization primitives like semaphores or pipeline barriers (e.g. implicit via the renderpass' sub passes).

    Another, maybe simpler approach (depending on your setup) is to simply add UI rendering to the same command buffer as your scene rendering. This way you just render your UI atop of the scene geometry without having to synchronize. Though this may not be an option for all use-cases. Or you could go with sub passes intead of (heavy) render passes.