Vulkan:如何在交换链重新创建后处理两个渲染通道之间的图像布局转换?

问题描述 投票:0回答:1

我正在努力将 ImGui 安装到我的项目中。因此,我为主渲染和 UI(ImGui) 渲染创建了两个渲染通道。另外,正如 ImGui 的建议一样,我制作了不同的命令缓冲区和帧缓冲区。 当重新创建时,将重新创建主命令缓冲区、帧缓冲区、图像、imageView,并相应地重新创建 UI 的命令缓冲区和帧缓冲区。 UI 重新创建发生在主重新创建之后。之后会出现错误有时

VulkanCore: [VULKAN ERROR]: Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout ] Object 0: handle = 0x2aab4061990, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x4dae5635 | vkQueueSubmit(): pSubmits[0].pCommandBuffers[1] command buffer VkCommandBuffer 0x2aab4061990[] expects VkImage 0xd0e29300000000aa[] (subresource: aspectMask 0x1 array layer 0, mip level 0) to be in layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL--instead, current layout is VK_IMAGE_LAYOUT_UNDEFINED.
VulkanCore: [VULKAN ERROR]: Validation Error: [ VUID-VkPresentInfoKHR-pImageIndices-01296 ] Object 0: handle = 0x2aab3d21540, type = VK_OBJECT_TYPE_QUEUE; | MessageID = 0xc7aabc16 | vkQueuePresentKHR(): pSwapchains[0] images passed to present must be in layout VK_IMAGE_LAYOUT_PRESENT_SRC_KHR or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR but is in VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. The Vulkan spec states: Each element of pImageIndices must be the index of a presentable image acquired from the swapchain specified by the corresponding element of the pSwapchains array, and the presented image subresource must be in the VK_IMAGE_LAYOUT_PRESENT_SRC_KHR layout at the time the operation is executed on a VkDevice (https://github.com/KhronosGroup/Vulkan-Docs/search?q=)VUID-VkPresentInfoKHR-pImageIndices-01296)

我听说过图像内存障碍,但我不理解如何实现它们,并且我认为可以避免它们。我不明白如何首先将图像转换为最佳颜色然后再呈现。 所以有创建两个渲染通道的代码:

//the main one
// Color attachment setup
const vk::AttachmentDescription colorAttachment(
    vk::AttachmentDescriptionFlags(),           // Flags (default)
    swapchainImageFormat,                       // Format of the swapchain images
    vk::SampleCountFlagBits::e1,                // Sample count (1 sample per pixel)
    vk::AttachmentLoadOp::eClear,               // Clear attachment at the start of the render pass
    vk::AttachmentStoreOp::eStore,              // Store the attachment after the render pass finishes
    vk::AttachmentLoadOp::eDontCare,            // Stencil load operation (not used here)
    vk::AttachmentStoreOp::eDontCare,           // Stencil store operation (not used here)
    vk::ImageLayout::eUndefined,                // Initial layout before rendering
    vk::ImageLayout::eColorAttachmentOptimal    // Final layout for color attachment after rendering
);

// Depth attachment setup
const vk::AttachmentDescription depthAttachment(
    vk::AttachmentDescriptionFlags(),           // Flags (default)
    DeviceManager::FindSupportedFormat(physicalDevice,  // Find a suitable depth format
        {vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint}, 
        vk::ImageTiling::eOptimal, vk::FormatFeatureFlagBits::eDepthStencilAttachment),
    vk::SampleCountFlagBits::e1,                // 1 sample per pixel
    vk::AttachmentLoadOp::eClear,               // Clear depth attachment at the start
    vk::AttachmentStoreOp::eDontCare,           // Don't store depth data after rendering
    vk::AttachmentLoadOp::eDontCare,            // No stencil load operation
    vk::AttachmentStoreOp::eDontCare,           // No stencil store operation
    vk::ImageLayout::eUndefined,                // Initial layout (undefined)
    vk::ImageLayout::eDepthStencilAttachmentOptimal // Optimal layout for depth/stencil attachment
);

// Attachment references for the subpass
const vk::AttachmentReference colorAttachmentRef(0, vk::ImageLayout::eColorAttachmentOptimal); // Refers to the color attachment
const vk::AttachmentReference depthAttachmentRef(1, vk::ImageLayout::eDepthStencilAttachmentOptimal); // Refers to the depth attachment

// Subpass description
const vk::SubpassDescription subpassDescription(
    vk::SubpassDescriptionFlags(),              // Flags (none)
    vk::PipelineBindPoint::eGraphics,           // Subpass used in graphics pipeline
    0,                                          // Input attachments (none)
    nullptr,                                    // Pointer to input attachments (none)
    1,                                          // Color attachment count
    &colorAttachmentRef,                        // Reference to color attachment
    nullptr,                                    // Resolve attachments (none)
    &depthAttachmentRef                         // Reference to depth attachment
);

// Subpass dependency (for handling pipeline transitions)
const vk::SubpassDependency subpassDependency(
    VK_SUBPASS_EXTERNAL,                        // Source subpass (external dependency)
    0,                                          // Destination subpass
    vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests, // Source stage (before rendering)
    vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests, // Destination stage (during rendering)
    vk::AccessFlagBits::eNone,                  // Source access mask (no read/write operations before rendering)
    vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite // Destination access mask (write operations for color and depth)
);

// Array of attachments (color + depth)
std::array<vk::AttachmentDescription, 2> attachments{ colorAttachment, depthAttachment };

// Render pass creation info
const vk::RenderPassCreateInfo renderPassInfo(
    vk::RenderPassCreateFlagBits(),             // Flags (default)
    attachments.size(),                         // Number of attachments
    attachments.data(),                         // Pointer to the attachments
    1,                                          // Number of subpasses
    &subpassDescription,                        // Subpass description
    1,                                          // Number of dependencies
    &subpassDependency                          // Subpass dependency description
);

// Create the render pass and return it
return device.createRenderPass(renderPassInfo);
//the UI’s
// Define the color attachment description
const vk::AttachmentDescription colorAttachment(
    vk::AttachmentDescriptionFlags(),              // Flags
    swapchainImageFormat,                          // Format of the swapchain image
    vk::SampleCountFlagBits::e1,                   // Sample count (no multisampling)
    vk::AttachmentLoadOp::eLoad,                   // Load operation (load existing data)
    vk::AttachmentStoreOp::eStore,                 // Store operation (store after rendering)
    vk::AttachmentLoadOp::eDontCare,               // Stencil load operation (don't care)
    vk::AttachmentStoreOp::eDontCare,              // Stencil store operation (don't care)
    vk::ImageLayout::eColorAttachmentOptimal,      // Initial layout (optimal for color attachments)
    vk::ImageLayout::ePresentSrcKHR                // Final layout (ready for presentation)
);

// Reference to the color attachment
const vk::AttachmentReference colorAttachmentRef(
    0,                                             // Attachment index in the render pass
    vk::ImageLayout::eColorAttachmentOptimal       // Layout used in the subpass
);

// Describe the subpass
const vk::SubpassDescription subpassDescription(
    vk::SubpassDescriptionFlags(),                 // Subpass flags
    vk::PipelineBindPoint::eGraphics,              // Pipeline bind point (graphics)
    0,                                             // No input attachments
    nullptr,                                       // No input attachments array
    1,                                             // One color attachment
    &colorAttachmentRef,                           // Reference to the color attachment
    nullptr,                                       // No resolve attachments
    nullptr                                        // No depth/stencil attachment
);

// Define subpass dependency (synchronization)
const vk::SubpassDependency subpassDependency{
    VK_SUBPASS_EXTERNAL,                           // Source subpass (external)
    0,                                             // Destination subpass (subpass 0)
    vk::PipelineStageFlagBits::eColorAttachmentOutput, // Wait at color attachment output
    vk::PipelineStageFlagBits::eColorAttachmentOutput, // Signal at color attachment output
    vk::AccessFlagBits::eColorAttachmentWrite,     // Wait for color attachment write access
    vk::AccessFlagBits::eColorAttachmentWrite      // Ensure color attachment write access
};

// Define array of attachments
std::array attachments{ colorAttachment };

// Create render pass creation info
const vk::RenderPassCreateInfo renderPassInfo{
    vk::RenderPassCreateFlags(),                   // Flags for render pass creation
    attachments.size(),                            // Number of attachments
    attachments.data(),                            // Pointer to attachment descriptions
    1,                                             // One subpass
    &subpassDescription,                           // Pointer to subpass description
    1,                                             // One subpass dependency
    &subpassDependency                             // Pointer to subpass dependency
};

// Create and return the render pass
return device.createRenderPass(renderPassInfo);

重新创建后,我应该如何处理这两个渲染通道之间的图像布局转换? 任何建议或指示将不胜感激!

c++ vulkan
1个回答
0
投票

要处理 Vulkan 中的主渲染通道和 ImGui 渲染通道之间的图像布局转换,您需要使用图像内存屏障。在每次渲染过程之前,记录一个障碍,将图像从当前布局(例如,

VK_IMAGE_LAYOUT_UNDEFINED
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
)过渡到所需的布局(例如,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
用于渲染,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
用于演示)。

在渲染通道命令之前添加此障碍:

vk::ImageMemoryBarrier barrier{};
barrier.image = swapchainImage;
barrier.oldLayout = vk::ImageLayout::eUndefined; // Adjust as needed
barrier.newLayout = vk::ImageLayout::eColorAttachmentOptimal; // Adjust as needed
barrier.srcAccessMask = vk::AccessFlagBits::eNone; 
barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput, {}, barrier.srcAccessMask, barrier.dstAccessMask, nullptr, 0, nullptr, 1, &barrier);
© www.soinside.com 2019 - 2024. All rights reserved.