选择具有期望能力的队列族的索引
译者注:示例代码点击此处
在创建逻辑设备之前,我们需要考虑要在其上执行什么操作,因为这将影响到我们需要请求哪些队列族。
对于简单的事例,单个支持图形操作功能的族就应该足够了。更高级的场景将需要支持图形和计算操作功能,或者需要额外的传输队列来进行非常快速的内存复制。
在本小节中,我们将研究如何搜索支持所需的队列族。
怎么做...
1.获取vkEnumeratePhysicalDevices()函数返回的一个物理设备句柄,并将其储存在名为physical_device的VkPhysicalDevice类型变量中。
2.准备名为queue_family_index的uint32_t类型的变量。我们将存储支持所选类型的队列族索引。
3.准备名为desired_capabilities的VkQueueFlags类型变量。将所需操作功能的类型储存在desired_capabilities中。它可以是一个逻辑处理或者计算方式,有VK_QUEUE_GRAPHICS_BIT,VK_QUEUE_COMPUTE_BIT,VK_QUEUE_TRANSFER_BIT或VK_QUEUE_SPARSE_BINDING_BIT。
4.准备名为queue_families的VkQueueFamilyProperties元素类型的std :: vector类型变量。
5.检查可用队列族的数量并获取其属性,将结果储存在queue_families变量中。
6.使用名为index的uint32_t类型变量循环遍历queue_families向量的所有元素。
7.对于queue_families变量的每个元素:
1.检查当前元素中队列的数量(queueCount成员)是否大于零。
2.对desired_capabilities变量和当前迭代的元素的queueFlags成员进行“与逻辑”检查。
3.上面两次检查都是正整数,则将索引变量(当前循环迭代)的值储存在queue_family_index的变量中,并完成迭代。
8.如果上面检查失败,重复7.1到7.3中的步骤,直到查看queue_families向量的所有元素。
这个怎么运作...
首先,我们获取给定物理设备上可用的队列族的属性。这是检查可用队列系列及其属性中描述的操作功能。我们将查询结果储存在queue_families变量中,该变量是带有VkQueueFamilyProperties元素的std::vector类型:
std::vector<VkQueueFamilyProperties> queue_families;
if( !CheckAvailableQueueFamiliesAndTheirProperties( physical_device, queue_families ) ) {
return false;
}
接下来,我们开始检查queue_families向量的所有元素:
for( uint32_t index = 0; index < static_cast<uint32_t>(queue_families.size()); ++index ) {
if( (queue_families[index].queueCount > 0) && (queue_families[index].queueFlags & desired_capabilities ) ) {
queue_family_index = index;
return true;
}
}
return false;
queue_families向量的每个元素表示一个单独的队列族,其queueCount成员包含给族中可用的队列数量。queueFlags成员是一个位字段,其中每个位代表不同的操作功能类型。如果设置了给定为位,则意味着给定队列族支持相应操作功能类型,我们可以检查支持的功能的任何组合,但是我们可能需要为每种类型的操作功能寻找单独的队列,这完全取决于支持的Vulkan API驱动设备。
译者注:但是我们可能需要为每种类型的操作功能寻找单独的队列(but we may need to search for separate queues for every type of operation)的意思是说,因为可能一个族同时支持多个操作功能,也可能多个功能在不同的族中被分别独立支持,我们可能需要为每种类型的操作功能寻找单独支持的队列族(这里是队列族不是队列他应该写错了),这完全取决于支持的Vulkan API驱动设备。
为了确保我们的获取的数据是正确的,我们还检查每个族是否至少暴露一个队列。
更高级的现实场景将要求我们储存每个族中公开的队列总数,这是因为我们可能想要请求多个队列,但是我们不能请求比给定族中更多的队列。在简单的用例中,来自给定族的一个队列就足够了。