Dynamitos
Dynamitos

Reputation: 511

Vulkan Device Lost after submitting single-time CommandBuffer

I have written a basic Vulkan renderer a while and it worked fine. It then broke(something with the power supply) and I reinstalled the Vulkan drivers to version 1.0.42.0 and since then it gives me the error VK_ERROR_DEVICE_LOST when submitting a CommandBuffer for singe-time use(loading textures etc). I have tried the code on a different device with a different GPU, and there it works just fine. The exact breaking code:

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

It also only seems to happen during initialization, since it isn't giving me any errors during runtime(actual rendering code), but they occur again during cleanup(deleting textures and buffers) Have there been any reports or workarounds for this problem?

The exact validation layer output is:

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

EDIT: since it seems to only happen when transitioning image layouts, here is the code for that:

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);
}

Upvotes: 1

Views: 5632

Answers (1)

Sascha Willems
Sascha Willems

Reputation: 5788

As noted in the comments you need to keep track of image ownership, esp. if you work with different queue families.

So make sure you specify all queue familiy indices that access an image at creation time (VkImageCreateInfo.pQueueFamilyIndices and VkImageCreateInfo.queueFamilyIndexCount) if you're using VK_SHARING_MODE_CONCURRENT. If you don't need concurrent queue access to the images you can also go with VK_SHARING_MODE_EXCLUSIVE without the need to specify queue family indices.

When dealing with different queue family indices (graphics and compute e.g.) it's also important to do proper queue family ownership transfer in your barriers via their srcQueueFamilyIndex and dstQueueFamilyIndex members in both directions.

Upvotes: 6

Related Questions