gpt4 book ai didi

c++ - 将 `VkImage` 清除为单一颜色的最佳方法是什么?

转载 作者:行者123 更新时间:2023-12-04 17:08:50 28 4
gpt4 key购买 nike

我正在学习 vulkan,作为一个(非常)简单的项目,我想简单地将单个交换链图像清除为单一颜色(红色)。我的代码有效,但出现两个验证错误。我想知道:

  • 如何修复代码中的验证错误
  • 有没有更好的方法来简单地清除交换链图像

  • 关于(2):我特别不想使用图形管道:将来我想使用计算着色器直接绘制到屏幕上。
    我目前的做法
    我的项目使用 vk-bootstrap设置,然后我尝试按如下方式渲染单个帧:
  • 从交换链中获取图像
  • 使用以下命令记录命令缓冲区:
  • vkCmdPipelineBarrier
  • vkCmdClearColorImage
  • vkEndCommandBuffer

  • 将命令缓冲区提交到图形队列
  • 使用 vkQueuePresentKHR 呈现先前获得的交换链图像

  • 相关代码可以在下面找到,但似乎验证错误来自对 vkCmdClearColorImage 的调用。和 vkQueuePresentKHR .
    错误信息
    第一个验证错误来自 vkCmdClearColorImage调用,似乎是由我选择的 layout 触发的:
    VkImageLayout layout = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR;
    // (... snip ...)
    vkCmdClearColorImage(commandBuffer, swapChainImages[nextImageIndex], layout, &color, 1, &imageSubresourceRange);
    错误消息说:
    [ERROR: Validation]
    Validation Error: [ VUID-vkCmdClearColorImage-imageLayout-00005 ] Object 0: handle = 0xf56c9b0000000004, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x9740ed23 | vkCmdClearColorImage(): Layout for cleared image is VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR but can only be TRANSFER_DST_OPTIMAL or GENERAL. The Vulkan spec states: imageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (https://www.khronos.org/registry/vulkan/specs/1.2/html/vkspec.html#VUID-vkCmdClearColorImage-imageLayout-00005)
    我对此消息感到困惑,因为尽管此错误消息中的链接确实说

    imageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL


    我也找到了 this page在规范中说

    imageLayout specifies the current layout of the image subresource ranges to be cleared, and must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL


    第二个错误是由对 vkQueuePresentKHR 的调用触发的。而且特别奇怪……
    [ERROR: Validation]
    Validation Error: [ VUID-VkPresentInfoKHR-pImageIndices-01296 ] Object 0: handle = 0x55a3c6b9e408, 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_SHARED_PRESENT_KHR. 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)
    ...因为消息似乎自相矛盾(添加了换行符):
    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_SHARED_PRESENT_KHR
    步骤 (2) 的代码
      VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = 0;
    beginInfo.pInheritanceInfo = nullptr;
    if(vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
    throw std::runtime_error("failed vkBeginCommandBuffer");
    }

    VkImageMemoryBarrier barrier{};
    barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    barrier.newLayout = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR;
    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.image = swapChainImages[nextImageIndex];
    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    barrier.subresourceRange.baseMipLevel = 0;
    barrier.subresourceRange.levelCount = 1;
    barrier.subresourceRange.baseArrayLayer = 0;
    barrier.subresourceRange.layerCount = 1;

    vkCmdPipelineBarrier(
    commandBuffer,
    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
    VK_PIPELINE_STAGE_TRANSFER_BIT,
    0,
    0, nullptr,
    0, nullptr,
    1, &barrier);


    VkImageLayout layout = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR;
    VkClearColorValue color = { .float32 = {1.0, 0.0, 0.0} };
    VkImageSubresourceRange imageSubresourceRange { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
    vkCmdClearColorImage(commandBuffer, swapChainImages[nextImageIndex], layout, &color, 1, &imageSubresourceRange);

    vkEndCommandBuffer(commandBuffer);
    问题(再次)
    所以再说一遍:我想知道:
  • 如何修复代码中的两个验证错误?
  • 有没有更好的方法来简单地清除交换链图像?

  • 软件版本 vulkaninfo命令报告 Vulkan Instance Version 1.2.194

    最佳答案

    我找到了一个有效但看起来有点恶心的解决方案。基本上我将步骤(2)修改为以下内容:

  • 使用以下命令记录命令缓冲区:
  • vkCmdPipelineBarrier
  • vkCmdClearColorImage
  • vkCmdPipelineBarrier
  • vkEndCommandBuffer


  • 本质上,该管道的逻辑流程是:
  • 使用屏障,从 VK_IMAGE_LAYOUT_UNDEFINED 转换图像至 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
  • 使用 vkCmdClearColorImage 清除图像
  • 使用屏障,将图像转换为 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR所以它可以呈现

  • 这是有效的,因为:
  • vkCmdClearColorImage要求图像具有布局 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,但是
  • vkQueuePresent要求图像具有布局 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR

  • 由于这看起来有点 hacky/恶心,我会将这个问题保留一段时间,看看是否有人有更好的解决方案。为了完整起见,这里是步骤 (2) 的新代码
    步骤(2)的修改代码
      VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = 0;
    beginInfo.pInheritanceInfo = nullptr;
    if(vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
    throw std::runtime_error("failed vkBeginCommandBuffer");
    }

    //VkImageLayout clearLayout = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR;
    VkImageLayout clearLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;

    VkImageMemoryBarrier barrier{};
    barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    barrier.newLayout = clearLayout;
    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.image = swapChainImages[nextImageIndex];
    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    barrier.subresourceRange.baseMipLevel = 0;
    barrier.subresourceRange.levelCount = 1;
    barrier.subresourceRange.baseArrayLayer = 0;
    barrier.subresourceRange.layerCount = 1;

    vkCmdPipelineBarrier(
    commandBuffer,
    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
    VK_PIPELINE_STAGE_TRANSFER_BIT,
    0,
    0, nullptr,
    0, nullptr,
    1, &barrier);


    VkImageLayout layout = clearLayout;
    VkClearColorValue color = { .float32 = {1.0, 0.0, 0.0} };
    VkImageSubresourceRange imageSubresourceRange { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
    vkCmdClearColorImage(commandBuffer, swapChainImages[nextImageIndex], layout, &color, 1, &imageSubresourceRange);

    // Add another barrier and put the image in VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
    VkImageLayout finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
    VkImageMemoryBarrier finalBarrier{};
    finalBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    finalBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    finalBarrier.newLayout = finalLayout;
    finalBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    finalBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    finalBarrier.image = swapChainImages[nextImageIndex];
    finalBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    finalBarrier.subresourceRange.baseMipLevel = 0;
    finalBarrier.subresourceRange.levelCount = 1;
    finalBarrier.subresourceRange.baseArrayLayer = 0;
    finalBarrier.subresourceRange.layerCount = 1;

    vkCmdPipelineBarrier(
    commandBuffer,
    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
    VK_PIPELINE_STAGE_TRANSFER_BIT,
    0,
    0, nullptr,
    0, nullptr,
    1, &finalBarrier);

    vkEndCommandBuffer(commandBuffer);

    关于c++ - 将 `VkImage` 清除为单一颜色的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69915270/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com