如何在 Vulkan 中将交换链图像复制到 VkBuffer?

How to Copy Swap Chain Image to a VkBuffer in Vulkan?

我目前正在修改Triangle的Adreno SDK Vulkan示例。我想读取渲染的交换链图像的颜色值。我遵循的过程如下:

  1. 我使用交换链图像的宽度和高度创建 VkBuffer。 它的详细信息:

    VkBufferCreateInfo outputinfo = {};
    outputinfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    outputinfo.size = m_width * m_height * 3 * sizeof(int8_t);
    outputinfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
    outputinfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;`
    

    Int 因为图像格式是 VK_FORMAT_R8G8B8_SINT 然后分配内存并将其绑定到类型为 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT

  2. 的缓冲区
  3. vkCmdDrawvkCmdEndRenderPass之后在命令缓冲区中调用vkCmdCopyImageToBuffer

  4. 然后执行vkQueueSubmitvkQueueWaitIdle。 为Buffer内存调用vkMapMemory读取数据,但都是垃圾值。对于 malloc,我将数据格式保持为 int。

Vulkan 中的交换链图像不属于您的代码;他们属于平台。因此,您无法控制它们的大多数方面。您改为通过 vkGetPhysicalDeviceSurfaceCapabilitiesKHR查询 它们的方面。特别重要的是 VkSurfaceCapabilitiesKHR::supportedUsageFlags.

这些是交换链图像支持的图像使用标志。它们需要支持颜色附件,但这是需要支持的 用法。这包括使用图像作为传输操作的来源。

如果未在该标志中设置 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,则您根本无法从交换链映像中复制 。因此,您必须将所需内容渲染到不同的图像,然后复制到交换链图像。当然假设它有 TRANSFER_DST_BIT;如果没有,那么您将不得不对其进行渲染。

假设您已验证表面完全可以读取:

Call vkCmdCopyImageToBuffer in Command Buffer after the vkCmdDraw, vkCmdEndRenderPass.

您的 renderpass 需要在写入图像和传输阶段之间存在执行依赖性。