on
on

三天速成Vulkan(3)-Physical devices logical devices and queue familie

Author:

在创建完成Vulkan后,我们需要在设备上寻找一个支持所需特性的物理设备,或者同时调用多个设备。选中 物理设备将被存储到 VkPhysicalDevice 的句柄中,并称为一个新的需要管理的成员类,该对象的销毁无需我们手动进行管理。查找可选的Devices的过程与Extensions的过程类似。

VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;

    void pickPhysicalDevice() {
        uint32_t deviceCount = 0;
        vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

        if (deviceCount == 0) {
            throw std::runtime_error("failed to find GPUs with Vulkan support");
        }

        std::vector<VkPhysicalDevice> devices(deviceCount);
        vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());

        for (const auto &device: devices) {
            if (isDeviceSuitable(device)) {
                physicalDevice = device;
                break;
            }
        }


        if (physicalDevice == VK_NULL_HANDLE) {
            throw std::runtime_error("Failed to find a suitable GPU");
        }
    }

Device对象的suitability检查

    bool isDeviceSuitable(VkPhysicalDevice device) {

        VkPhysicalDeviceProperties  deviceProperties;
        vkGetPhysicalDeviceProperties(device, &deviceProperties);

        VkPhysicalDeviceFeatures deviceFeatures;
        vkGetPhysicalDeviceFeatures(device, &deviceFeatures);

        return deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && deviceFeatures.geometryShader;
    }

    void pickPhysicalDevice() {
        uint32_t deviceCount = 0;
        vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

        if (deviceCount == 0) {
            throw std::runtime_error("failed to find GPUs with Vulkan support");
        }

        std::vector<VkPhysicalDevice> devices(deviceCount);
        vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());

        for (const auto &device: devices) {
            if (isDeviceSuitable(device)) {
                physicalDevice = device;
                break;
            }
        }


        if (physicalDevice == VK_NULL_HANDLE) {
            throw std::runtime_error("Failed to find a suitable GPU");
        }

        VkPhysicalDeviceProperties  deviceProperties;
        vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);

        std::cout << "Selected GPU: " << deviceProperties.deviceName << std::endl;
    }

可以根据各个Device拥有的特性选择最合适的那个Device。


Queue familie

在Vulkan中,从不同的queue families中衍生出了不同种类的queues并且不同家族的queues只会允许一个子类的命令。例如有些queue family只允许处理compute commands,而有些只能执行memory transfer related commands。
我们需要检查那些queue familes是能够被设备支持的,以及哪些指令是我们需要用到的。因此,我们可以创建一个新的function ‘findQueueFamilies’ 来查找那些我们需要用到的queue families。