设备需求检测
为了选择合适的设备,我们需要获取更加详细的设备信息。对于基础的设备属性,比如名称,类型和支持的Vulkan版本的查询可以通过vkGetPhysicalDeviceProperties函数进行。
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
纹理压缩,64位浮点和多视口渲染(常用于VR)等特性的支持可以通过vkGetPhysicalDeviceFeatures函数查询:
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
有关设备内存和队列族信息的获取,我们会在下一节说明。
现在,假设我们的应用程序只有在显卡支持几何着色器的情况下才可以运行,那么我们的isDeviceSuitable函数看起来会像这样:
bool isDeviceSuitable(VkPhysicalDevice device) {
VkPhysicalDeviceProperties deviceProperties;
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
return deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && deviceFeatures.geometryShader;
}
除了直接选择第一个满足需求的设备这种方法,一个更好的方法是给每一个满足需求的设备,按照特性加权打分,选择分数最高的设备使用。具体可以这样做:
#include <map>
...
void pickPhysicalDevice() {
...
// Use an ordered map to automatically sort candidates by increasing score
std::multimap<int, VkPhysicalDevice> candidates;
for (const auto& device : devices) {
int score = rateDeviceSuitability(device);
candidates.insert(std::make_pair(score, device));
}
// Check if the best candidate is suitable at all
if (candidates.rbegin()->first > 0) {
physicalDevice = candidates.rbegin()->second;
} else {
throw std::runtime_error("failed to find a suitable GPU!");
}
}
int rateDeviceSuitability(VkPhysicalDevice device) {
...
int score = 0;
// Discrete GPUs have a significant performance advantage
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
score += 1000;
}
// Maximum possible size of textures affects graphics quality
score += deviceProperties.limits.maxImageDimension2D;
// Application can't function without geometry shaders
if (!deviceFeatures.geometryShader) {
return 0;
}
return score;
}
此外,也可以显示满足需求的设备列表,让用户自己选择使用的设备。
由于我们的教程才刚刚开始,我们现在的唯一需求就是显卡设备需要支持Vulkan,显然它对于我们使用Vulkan API获取的设备列表中的所有设备都永远满足: