Vulkan设备在提交一次性CommandBuffer后丢失

时间:2017-07-05 17:51:43

标签: vulkan

我写了一段基本的Vulkan渲染器,但它运行良好。然后它破坏了(有电源的东西)并且我将Vulkan驱动程序重新安装到1.0.42.0版本,从那以后它在提交CommandBuffer时使用了错误VK_ERROR_DEVICE_LOST(加载纹理等)。我已经尝试使用不同GPU的不同设备上的代码,并且它工作得很好。确切的破解代码:

vkEndCommandBuffer(commandBuffer);

VkSubmitInfo submitInfo =
    init::SubmitInfo();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;


vkQueueSubmit(context->transferQueue, 1, &submitInfo, VK_NULL_HANDLE);
//works fine until now
vkQueueWaitIdle(context->transferQueue);
//This gives me VK_ERROR_DEVICE_LOST
vkFreeCommandBuffers(context->device, context->cmdTempPool, 1, &commandBuffer);
//Also doesn't work since commandbuffer is still in queue

它似乎也只是在初始化期间发生,因为它在运行时(实际渲染代码)没有给我任何错误,但它们在清理期间再次出现(删除纹理和缓冲区) 是否有针对此问题的报告或解决方法?

确切的验证图层输出为:

ParameterValidation: vkQueueWaitIdle: returned VK_ERROR_DEVICE_LOST, 
indicating that the logical device has been lost
DS: Attempt to free command buffer (0x000002D18AAF1A90) which is in use. For 
more information refer to Vulkan Spec Section '5.3. Command Buffer 
Allocation and Management' which states 'All elements of pCommandBuffers 
must not be in the pending state' 
(https://www.khronos.org/registry/vulkan/specs/1.0-
extensions/html/vkspec.html#vkFreeCommandBuffers)
ParameterValidation: vkQueueSubmit: returned VK_ERROR_DEVICE_LOST, 
indicating that the logical device has been lost

修改 因为它似乎只在转换图像布局时发生,所以这里是代码:

void util::transitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout)
{
VkCommandBuffer commandBuffer = beginSingleTimeCommands();

VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
}
else {
    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
if (oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
    barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
    barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
    barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
    barrier.srcAccessMask = 0;
    barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
else {
    throw std::invalid_argument("unsupported layout transition!");
}

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

endSingleTimeCommands(commandBuffer);
}

1 个答案:

答案 0 :(得分:1)

如评论中所述,您需要跟踪图像所有权,尤其是如果您使用不同的队列系列。

因此,如果您正在使用VkImageCreateInfo.pQueueFamilyIndices,请确保指定在创建时(VkImageCreateInfo.queueFamilyIndexCountVK_SHARING_MODE_CONCURRENT)访问图像的所有队列家族索引。如果您不需要对映像进行并发队列访问,则还可以使用VK_SHARING_MODE_EXCLUSIVE,而无需指定队列系列索引。

在处理不同的队列系列索引(例如图形和计算)时,通过他们的srcQueueFamilyIndexdstQueueFamilyIndex成员在两个方向上进行适当的队列系列所有权转移也非常重要