A protected queue can read both protected and unprotected memory, but can only write to protected memory. If a queue can write to unprotected memory, then it can’t also read from protected memory.
Note | Often performance counters and other timing measurement systems are disabled or less accurate for protected queues to prevent side-channel attacks. |
Using vkGetPhysicalDeviceQueueFamilyProperties
to get the VkQueueFlags
of each queue, an application can find a queue family with VK_QUEUE_PROTECTED_BIT
flag exposed. This does not mean the queues from the family are always protected, but rather the queues can be a protected queue.
To tell the driver to make the VkQueue
protected, the VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT
is needed in VkDeviceQueueCreateInfo
during vkCreateDevice
.
The following pseudo code is how an application could request for 2 protected VkQueue
objects to be created from the same queue family:
VkDeviceQueueCreateInfo queueCreateInfo[1];
queueCreateInfo[0].flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
queueCreateInfo[0].queueFamilyIndex = queueFamilyFound;
queueCreateInfo[0].queueCount = 2; // assuming 2 queues are in the queue family
VkDeviceCreateInfo deviceCreateInfo = {};
deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &deviceHandle);
It is also possible to split the queues in a queue family so some are protected and some are not. The following pseudo code is how an application could request for 1 protected VkQueue
and 1 unprotected VkQueue
objects to be created from the same queue family:
VkDeviceQueueCreateInfo queueCreateInfo[2];
queueCreateInfo[0].flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
queueCreateInfo[0].queueFamilyIndex = queueFamilyFound;
queueCreateInfo[0].queueCount = 1;
queueCreateInfo[1].flags = 0; // unprotected because the protected flag is not set
queueCreateInfo[1].queueFamilyIndex = queueFamilyFound;
queueCreateInfo[1].queueCount = 1;
VkDeviceCreateInfo deviceCreateInfo = {};
deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 2;
vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &deviceHandle);
Now instead of using vkGetDeviceQueue
an application has to use vkGetDeviceQueue2
in order to pass the VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT
flag when getting the VkQueue
handle.
VkDeviceQueueInfo2 info = {};
info.queueFamilyIndex = queueFamilyFound;
info.queueIndex = 0;
info.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
vkGetDeviceQueue2(deviceHandle, &info, &protectedQueue);