Reputation: 2665
Here is what I do:
My first graphics and first present queue families are both at 0, while my transfer family is at index 1, here is how they look:
float queuePriorities[] = { 1.0f };
VkDeviceQueueCreateInfo devideQueueInfos[3];
devideQueueInfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
devideQueueInfos[0].pNext = null;
devideQueueInfos[0].flags = 0;
devideQueueInfos[0].queueFamilyIndex = device.FirstGraphicsQueueFamily(); //This is always 0
devideQueueInfos[0].queueCount = 1;
devideQueueInfos[0].pQueuePriorities = queuePriorities;
devideQueueInfos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
devideQueueInfos[1].pNext = null;
devideQueueInfos[1].flags = 0;
devideQueueInfos[1].queueFamilyIndex = device.FirstPresentQueueFamily(); //This is always 0
devideQueueInfos[1].queueCount = 1;
devideQueueInfos[1].pQueuePriorities = queuePriorities;
devideQueueInfos[2].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
devideQueueInfos[2].pNext = null;
devideQueueInfos[2].flags = 0;
devideQueueInfos[2].queueFamilyIndex = device.FirstTransferQueueFamily(); //This is always 1
devideQueueInfos[2].queueCount = 1;
devideQueueInfos[2].pQueuePriorities = queuePriorities;
deviceInfo.queueCreateInfoCount = 3;
deviceInfo.pQueueCreateInfos = devideQueueInfos;
VkResult result = vkCreateDevice(deviceHandle, &deviceInfo, null, logicalDeviceHandle);
The problem is, vkCreateDevice returns VK_ERROR_INITIALIZATION_FAILED. If I set queueCreateInfoCount to 2 and ignore the transfer queue, the function returns success. But if I don't create the device with the transfer queue options, my vkGetDeviceQueue crashes later on when I try to use the transfer family.
Upvotes: 1
Views: 607
Reputation: 29240
devideQueueInfos[1].queueFamilyIndex = device.FirstPresentQueueFamily(); //This is always 0
devideQueueInfos[0].queueFamilyIndex = device.FirstGraphicsQueueFamily(); //This is always 0
Passing the same queue index multiple times to vkCreateDevice
is disallowed.
A queue with present support is always going to have graphics support. Similarly a Queue with graphics support is always going to have compute and transfer support.
What you need to do is determine if there's a queue that has only transfer support, and specify it as your transfer queue only in that case. Otherwise, you need to use the graphics queues for transfers as well. You can still have a dedicated transfer queue, it's just going to be the case that it's also a graphics queue, because the device isn't exposing any specialized transfer functionality, or for whatever reason doesn't require it to be exposed distinctly from the graphics functionality.
So if you want one queue for transfers and one for graphics and the device doesn't have dedicated transfer queues, you need to ask for two graphics queues in the create struct, not one graphics queue two times. With presentation, I don't get why you'd divide them. There's no 'presentation' queue type. It's always a graphics queue that has presentation support, so there's no point in referring to it in the create struct at all.
Edit: as Nicol points out, there's no guarantee that there will be a dedicated transfer queue, or even anything other than one graphics queue. So always make sure you cover all your potential bases in your setup code.
Upvotes: 3