使用几何着色器,图形和计算队列创建逻辑设备
译者注:示例代码点击此处
在Vulkan中,当我们创建各种对象时,需要准备许多描述创建过程本身的不同结构体,但是它们也可能需要创建其他对象。逻辑设备也不例外:我们需要枚举物理设备,检查它们的属性和支持的队列族,并准备一个需要更多信息的VkDeviceCreateInfo结构。
为了组织这些操作,我们将提供一个示例,用于从支持几何着色器,图形和计算队列的可用物理设备之一创建逻辑设备。
怎么做...
1.准备名为logical_device的VkDevice类型变量。
2.准备两个VkQueue类型的变量,分别名为graphics_queue和compute_queue。
3.准备名为physical_devices的std::vector<VkPhysicalDevice>类型变量。
4.获取给定平台上可用的所有物理设备列表,并将其储存在physical_devices向量中(请参阅枚举可用的物理设备)。
5.对physical_devices向量中的每个物理设备:
1.准备一个名为device_features的VkPhysicalDeviceFeatures类型变量。
2.获取给定物理设备支持的功能列表,并将其储存在device_features变量中。
3.检查device_features变量的geometryShader成员是否等于VK_TRUE(不为0)。如果是,则重置device_features变量的所有其他成员(将其值设置为零)(译者注:因为我们不需要其他功能,只想使用geometryShader功能所以,设置device_features变量的所有其他功能为零,只留下geometryShader功能),如果不是,用一个物理设备重新开始。
4.备两个uint32_t类型的变量,分别名为graphics_queue_family_index和compute_queue_family_index。
5.获取支持图形和计算操作的队列族的索引。
6.分别储存在graphics_queue_family_index和compute_queue_family_index变量中(参见选择具有期望能力的队列族的索引)。如果不支持这些操作中的任何一个,则搜索另一个物理设备。
7.在requested_queues变量中储存graphics_queue_family_index变量和浮点向量,其值全为1.0f(译者注:这个向量是每个队列的优先级)。如果compute_queue_family_index变量的值不同于graphics_queue_family_index变量的值,则将另一个元素添加到requested_queues向量(译者注:可能一个族同时支持图形和计算操作,也可能被两个族分别独立支持),其中包括compute_queue_family_index变量和具有值全为1.0f的浮点向量。
8.如果使用physical_device、requested_queues、device_features和logical_device变量创建逻辑设备(请参创建逻辑设备)操作失败,请使用其他物理设备重复上述操作。
9.如果逻辑设备已成功创建,请加载设备级函数(请参阅加载设备级函数)。从graphics_queue_family_index族获取队列句柄并将其存储在graphics_queue变量中。 从compute_queue_family_index族获取队列并将其存储在compute_queue变量中。
这个怎么运作...
要开始创建逻辑设备的过程,我们需要获取给定计算机上可用的所有物理设备的句柄:
std::vector<VkPhysicalDevice> physical_devices;
EnumerateAvailablePhysicalDevices( instance, physical_devices );
接下来,需要遍历所有可用的物理设备并获得他们的功能。 这将为我们提供有关给定物理设备是否支持几何着色器的信息:
for( auto & physical_device : physical_devices ) {
VkPhysicalDeviceFeatures device_features;
VkPhysicalDeviceProperties device_properties;
GetTheFeaturesAndPropertiesOfAPhysicalDevice( physical_device, &device_features, device_properties );
if( !device_features.geometryShader ) {
continue;
} else {
device_features = {};
device_features.geometryShader = VK_TRUE;
}
如果支持几何着色器,我们可以重置device_features所有其他成员。 我们将在逻辑设备创建期间提供此列表,但我们不希望启用任何其他功能。 在此示例中,几何着色器是我们想要使用的唯一附加功能。
接下来,我们需要检查给定的物理设备是否支持图形和计算操作的队列族。可能一个族同时支持图形和计算操作,也可能被两个族分别独立支持。如下获取这些队列族的索引:
uint32_t graphics_queue_family_index;
if( !SelectIndexOfQueueFamilyWithDesiredCapabilities( physical_device, VK_QUEUE_GRAPHICS_BIT, graphics_queue_family_index)
continue;
}
uint32_t compute_queue_family_index;
if( !SelectIndexOfQueueFamilyWithDesiredCapabilities( physical_device, VK_QUEUE_COMPUTE_BIT, graphics_queue_family_index)
continue;
}
然后,需要准备一个队列族列表,我们放入要请求的队列。还需要为每个族的每个队列分配优先级:
std::vector<QueueInfo> requested_queues = { { graphics_queue_family_index, { 1.0f } } };
if( graphics_queue_family_index != compute_queue_family_index ) {
requested_queues.push_back( { compute_queue_family_index, { 1.0f } } );
}
如果图形和计算队列族具有相同的索引,则只请求一个队列族中的一个队列。如果它们是不同的,我们需要请求两个队列:一个来自图形族,一个来自计算族。
我们准备创建一个逻辑设备,提供准备好的数据。 成功后,我们可以加载设备级功能并获取所请求队列的句柄:
if( !CreateLogicalDevice( physical_device, requested_queues, {}, &device_features, logical_device ) ) {
continue;
} else {
if( !LoadDeviceLevelFunctions( logical_device, {} ) ) {
return false;
}
GetDeviceQueue( logical_device, graphics_queue_family_index, 0, graphics_queue );
GetDeviceQueue( logical_device, compute_queue_family_index, 0, compute_queue );
return true;
}
}
return false;