Reputation: 675
vkAcquireNextImageKHR
throws std::out_of_range
when certain queue families are used. Is this expected behavior? How to debug?
The Vulkan program I use is based on vulkan-tutorial.com. I discovered that my VkPhysicalDevice
has three queue families, each flagged with VK_QUEUE_GRAPHICS_BIT
and present support:
uint32_t queueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
std::vector<uint32_t> graphicsQueueFamilyIndices;
std::vector<uint32_t> presentQueueFamilyIndices;
int i = 0;
for (const auto& queueFamily : queueFamilies)
{
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
graphicsQueueFamilyIndices.push_back(i);
}
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(
device,
i,
surface,
&presentSupport
);
if (presentSupport)
{
presentQueueFamilyIndices.push_back(i);
}
++i;
}
// graphicsQueueFamilyIndices = {0, 1, 2}
// presentQueueFamilyIndices = {0, 1, 2}
These are later used when creating the logical device, the swapchain (the queue families all have present capability) and the command pool. Later the program calls
vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, semaphore, VK_NULL_HANDLE, &imageIndex);
But using any other than
But using any combination of present and graphics queue indices of the following causes this API call to throw an uncaught 0
causes this API call to throw an uncaught std::out_of_range
(output is that of lldb
):std::out_of_range
: (1, 1)
, (1, 2)
, (2, 1)
, (2, 2)
.
lldb
output is as follows:
2019-12-01 11:36:35.599882+0100 main[22130:167876] flock failed to lock maps file: errno = 35
2019-12-01 11:36:35.600165+0100 main[22130:167876] flock failed to lock maps file: errno = 35
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: Index out of range
Process 22130 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff675c949a libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
-> 0x7fff675c949a <+10>: jae 0x7fff675c94a4 ; <+20>
0x7fff675c949c <+12>: movq %rax, %rdi
0x7fff675c949f <+15>: jmp 0x7fff675c33b7 ; cerror_nocancel
0x7fff675c94a4 <+20>: retq
Target 0: (main) stopped.
The same error is caused when using an indices that doesn't even refer to a queue, like 123
. I'm using the VK_LAYER_KHRONOS_validation
layer, which doesn't utter any complaint.
(1) Is this the expected behavior for passing the wrong queue family index to Vk?
(2) Are there validation layers that are capable of catching this error and making it more verbose?
(3) Why do these choices of queue families cause this error?
Using queue family indices (1, 1)
for graphics and present queue families during logical device creation while using index 0
for everything else already causes vkAcquireNextImage
to raise the error. Of course, VK_LAYER_KHRONOS_validation
raises the following warning upon command pool creation:
Validation layer: vkCreateCommandPool: pCreateInfo->queueFamilyIndex (= 0) is not one of the queue families given via VkDeviceQueueCreateInfo structures when the device was created. The Vulkan spec states: pCreateInfo::queueFamilyIndex must be the index of a queue family available in the logical device device. (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCreateCommandPool-queueFamilyIndex-01937)
I'm using MoltenVK (from the Vulkan SDK, version 1.1.126.0) on macOS Catalina 10.15.1.
Using version 1.1.121.1 of the SDK prevents the throw from occurring.
Creating a device queue family with index 0
alongside any other device queues one might require prevents the throw from occurring.
This has now been raised as issue on GitHub [here].
Upvotes: 0
Views: 571
Reputation: 13276
That seems to be a bug in MoltenVK. Inspection of the MoltenVK source indicates that it always implicitly uses queue 0
of queue family 0
for vkAcquireNextImage
. The fact that you have no problems if you create that queue explicitly, or if you use just a Fence tells me MoltenVk probably forgets to initialize that implicit queue properly for itself.
The GitHub Issue is filed at KhronosGroup/MoltenVK#791.
Upvotes: 2