ulak blade
ulak blade

Reputation: 2665

Unable to create VkDevice with transfer queue support

Here is what I do:

  1. I use vkEnumeratePhysicalDevices and get one VkPhysicalDevice
  2. I use vkGetPhysicalDeviceQueueFamilyProperties to query the queue families of the device to see which queues support graphic and/or transfer operations.
  3. I use vkGetPhysicalDeviceSurfaceSupportKHR to get present support as well for the queues.
  4. I loop trough the queue info I gathered to find the first suitable graphics queue, the first present queue and the first dedicated transfer queue(the first one that has the VK_QUEUE_TRANSFER_BIT flag, but not the VK_QUEUE_GRAPHICS_BIT flag)
  5. I use vkCreateDevice to create a VkDevice with an array of 3 VkDeviceQueueCreateInfo objects as the pQueueCreateInfos member in the VkDeviceCreateInfo structure
  6. 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

Answers (1)

Jherico
Jherico

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

Related Questions