Vulkan错误:无法使用已删除的缓冲区0x0

时间:2016-10-23 11:38:06

标签: c++ graphics vulkan

以这种方式将作品提交到我的图形队列时:

void Renderer::Render() {
  VkSemaphore wait_semaphore = vulkan()->image_available_semaphore();
  VkSemaphore signal_semaphore = vulkan()->rendering_finished_semaphore();
  VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  VkCommandBuffer cmd_buff =
    vulkan()->graphics_queue_cmd_buffers()[current_swapchain_img_];
  VkSubmitInfo submit_info = tools::inits::SubmitInfo();
  submit_info.waitSemaphoreCount = 1U;
  submit_info.pWaitSemaphores = &wait_semaphore;
  submit_info.pWaitDstStageMask = &wait_stage;
  submit_info.commandBufferCount = 1U;
  submit_info.pCommandBuffers = &cmd_buff;
  submit_info.signalSemaphoreCount = 1U;
  submit_info.pSignalSemaphores = &signal_semaphore;

  VK_CHECK_RESULT(vkQueueSubmit(
      vulkan()->device().graphics_queue().queue,
      1U,
      &submit_info,
      nullptr));
}

我从验证层收到以下错误:

Cannot submit cmd buffer using deleted buffer 0x0.

重复10次。

我的cmd缓冲区以这种方式生成:

void Renderer::SetupCommandBuffers(const VulkanDevice &device) {
  // Cache common settings to all command buffers 
  VkCommandBufferBeginInfo cmd_buff_begin_info =
    tools::inits::CommandBufferBeginInfo(
        VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT);
  cmd_buff_begin_info.pInheritanceInfo = nullptr;

  std::vector<VkClearValue> clear_values;
  VkClearValue clear_value;
  clear_value.color = {{0.f, 0.f, 0.f, 0.f}};
  clear_values.push_back(clear_value);
  clear_value.color = {{1.f, 0.f, 0.f, 1.f}};
  clear_values.push_back(clear_value);
  clear_value.depthStencil = {1.f, 0U};
  clear_values.push_back(clear_value);

  VkImageSubresourceRange image_subresource_range;
  image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  image_subresource_range.baseMipLevel = 0U;
  image_subresource_range.levelCount = 1U;
  image_subresource_range.baseArrayLayer = 0U;
  image_subresource_range.layerCount = 1U;

  // Record command buffers
  const std::vector<VkCommandBuffer> &graphics_buffs =
    vulkan()->graphics_queue_cmd_buffers();
  uint32_t num_swapchain_images = vulkan()->swapchain().GetNumImages();
  for (uint32_t i = 0U; i < num_swapchain_images; i++) {
    VK_CHECK_RESULT(vkBeginCommandBuffer(
        graphics_buffs[i], &cmd_buff_begin_info));

    VkRenderPassBeginInfo render_pass_begin_info =
      tools::inits::RenderPassBeginInfo();
    render_pass_begin_info.renderPass = render_pass_;
    render_pass_begin_info.framebuffer = framebuffers_[i];
    render_pass_begin_info.renderArea = {0U, 0U, kWindowWidth, kWindowHeight};
    render_pass_begin_info.clearValueCount = SCAST_U32(clear_values.size());
    render_pass_begin_info.pClearValues = clear_values.data();

    vkCmdBeginRenderPass(graphics_buffs[i], &render_pass_begin_info,
                         VK_SUBPASS_CONTENTS_INLINE);

    vis_store_material_.BindPipeline(graphics_buffs[i],
                                     VK_PIPELINE_BIND_POINT_GRAPHICS);

    vkCmdBindDescriptorSets(
        graphics_buffs[i],
        VK_PIPELINE_BIND_POINT_GRAPHICS,
        pipe_layout_vis_,
        0U,
        SCAST_U32(desc_sets_.size()),
        desc_sets_.data(),
        0U,
        nullptr);

    fullscreenquad_->BindVertexBuffer(graphics_buffs[i]);  
    fullscreenquad_->BindIndexBuffer(graphics_buffs[i]);  

    vkCmdDrawIndexed(
        graphics_buffs[i],
        6U,
        1U,
        0U,
        0U,
        0U);

    // Fullscreen quad
    vkCmdNextSubpass(graphics_buffs[i], VK_SUBPASS_CONTENTS_INLINE);

    vis_shade_material_.BindPipeline(graphics_buffs[i],
                                     VK_PIPELINE_BIND_POINT_GRAPHICS);

    fullscreenquad_->BindVertexBuffer(graphics_buffs[i]);  
    fullscreenquad_->BindIndexBuffer(graphics_buffs[i]);  

    vkCmdDrawIndexed(
        graphics_buffs[i],
        6U,
        1U,
        0U,
        0U,
        0U);

    vkCmdEndRenderPass(graphics_buffs[i]);

    VK_CHECK_RESULT(vkEndCommandBuffer(graphics_buffs[i]));
  }
}

尝试调试一段时间后,注释掉vkCmdDrawIndexed次调用会删除错误报告。我注意到只删除一个绘制调用会将错误报告列表从10减少到5。 此外,即使报告错误,无论如何都会正确渲染。

我已经用我的调试器检查过我传递给函数的所有值都不是VK_NULL_HANDLE或未初始化的变量,而且我的cmd缓冲区存在;实际上,在构建命令缓冲区时,验证层不会抛出任何错误。

此外,我确保了每帧缓冲区图像cmd缓冲区的列表 完全存在,我没有得到一个简单的Segfault,因为没有初始化的矢量成员。

我无法弄清楚这个错误报告与命令缓冲区的构建之间的关系,所以如果你能帮助我,我真的很感激。 提前感谢任何人。

1 个答案:

答案 0 :(得分:3)

  

无法使用已删除的缓冲区0x0提交cmd缓冲区。

VkBuffer对象(不是命令缓冲区)的任何({1}}使用时(记录在提交的命令缓冲区中的任何对象),会记录此错误(s ))已被销毁(或者可能尚未创建)。在这种情况下似乎是vkQueueSubmit偶数。

记住VK_NULL_HANDLE是异步的。缓冲区需要在vkQueueSubmit 之后保持活动状态,直到vkQueueSubmit发出信号(或fence)。

在此代码示例中,我看到只使用了两个vkDeviceWaitIdle。绑定顶点和索引缓冲区。事实证明它与顶点缓冲区相关联(详见问题评论)。

作为任何一个好的验证器,它的错误信息通常是不可读的 但验证层是Khronos存储库中的开源:
https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/tree/master/layers

可以帮助查看那些被证明难以破译的错误消息。通常(但不总是)错误消息在core_validation.cpp 中(正在实现VkBuffer层)。