Qt GUIにおけるVulkanデバイス検出:QVulkanWindow::availablePhysicalDevices() 関数を徹底解説


QVulkanWindow::availablePhysicalDevices() 関数は、システム上に存在する Vulkan 対応の物理デバイスのリストを取得します。各デバイスは VkPhysicalDeviceProperties 構造体で表現されます。

構文

QList<VkPhysicalDeviceProperties> QVulkanWindow::availablePhysicalDevices();

戻り値

QList<VkPhysicalDeviceProperties> オブジェクト。リストには、システム上に存在するすべての物理デバイスの VkPhysicalDeviceProperties 構造体が含まれます。

詳細

Vulkan API では、物理デバイスはグラフィックカードなどのハードウェアコンポーネントを表します。 QVulkanWindow::availablePhysicalDevices() 関数は、これらのデバイスを列挙し、それぞれの機能や特性に関する情報を提供します。

QList<VkPhysicalDeviceProperties> devices = QVulkanWindow::availablePhysicalDevices();

for (const VkPhysicalDeviceProperties& device : devices) {
    // 各デバイスの情報を処理する
    qDebug() << "Device name:", device.deviceName;
    qDebug() << "API version:", device.apiVersion;
    qDebug() << "Vendor ID:", device.vendorID;
    qDebug() << "Device ID:", device.deviceID;
    // ...
}

注意事項

  • 各デバイスの機能や特性は、デバイスによって異なります。アプリケーションは、特定のデバイスに依存する前に、その機能を確認する必要があります。
  • 関数が返すリストには、使用可能なデバイスのみが含まれます。無効化されているデバイスや、Vulkan ドライバーによってサポートされていないデバイスは含まれません。
  • QVulkanWindow::availablePhysicalDevices() 関数は、Vulkan ライブラリが初期化されていることを前提としています。

例 1: 使用可能な物理デバイスのリストを表示する

QList<VkPhysicalDeviceProperties> devices = QVulkanWindow::availablePhysicalDevices();

for (const VkPhysicalDeviceProperties& device : devices) {
    qDebug() << "Device name:", device.deviceName;
}

例 2: 最初の物理デバイスを選択する

QList<VkPhysicalDeviceProperties> devices = QVulkanWindow::availablePhysicalDevices();

if (!devices.isEmpty()) {
    VkPhysicalDeviceProperties device = devices.first();
    // 選択したデバイスの情報を処理する
    qDebug() << "Selected device name:", device.deviceName;
}
QList<VkPhysicalDeviceProperties> devices = QVulkanWindow::availablePhysicalDevices();

for (const VkPhysicalDeviceProperties& device : devices) {
    if (device.features.geometryShaders) {
        // デバイスがジオメトリシェーダをサポートしている場合
        qDebug() << "Device name:", device.deviceName;
        // ...
        break;
    }
}


サンプル 1: 使用可能な物理デバイスのリストを表示する

#include <QVulkanWindow>
#include <QDebug>

int main() {
    // Vulkan ライブラリを初期化する
    VkApplicationInfo appInfo = {};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.apiVersion = VK_API_VERSION_1_0;
    appInfo.applicationName = "Vulkan Application";
    appInfo.engineName = "Qt Engine";

    VkInstanceCreateInfo instanceCreateInfo = {};
    instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instanceCreateInfo.pApplicationInfo = &appInfo;

    VkInstance instance;
    if (vkCreateInstance(&instanceCreateInfo, nullptr, &instance) != VK_SUCCESS) {
        qDebug() << "Failed to create Vulkan instance";
        return 1;
    }

    // 使用可能な物理デバイスのリストを取得する
    QList<VkPhysicalDeviceProperties> devices = QVulkanWindow::availablePhysicalDevices();

    // 各デバイスの情報を表示する
    for (const VkPhysicalDeviceProperties& device : devices) {
        qDebug() << "Device name:", device.deviceName;
        qDebug() << "API version:", device.apiVersion;
        qDebug() << "Vendor ID:", device.vendorID;
        qDebug() << "Device ID:", device.deviceID;
        qDebug() << "-------------------";
    }

    // Vulkan ライブラリをシャットダウンする
    vkDestroyInstance(instance, nullptr);

    return 0;
}

サンプル 2: 最初の物理デバイスを選択する

#include <QVulkanWindow>
#include <QDebug>

int main() {
    // Vulkan ライブラリを初期化する (サンプル 1 と同じ)

    // 使用可能な物理デバイスのリストを取得する
    QList<VkPhysicalDeviceProperties> devices = QVulkanWindow::availablePhysicalDevices();

    // 最初のデバイスを選択する
    if (!devices.isEmpty()) {
        VkPhysicalDeviceProperties device = devices.first();
        qDebug() << "Selected device name:", device.deviceName;
    } else {
        qDebug() << "No available physical devices found";
    }

    // Vulkan ライブラリをシャットダウンする (サンプル 1 と同じ)

    return 0;
}
#include <QVulkanWindow>
#include <QDebug>

int main() {
    // Vulkan ライブラリを初期化する (サンプル 1 と同じ)

    // 使用可能な物理デバイスのリストを取得する
    QList<VkPhysicalDeviceProperties> devices = QVulkanWindow::availablePhysicalDevices();

    // ジオメトリシェーダをサポートするデバイスを選択する
    for (const VkPhysicalDeviceProperties& device : devices) {
        if (device.features.geometryShaders) {
            // デバイスがジオメトリシェーダをサポートしている場合
            qDebug() << "Device name:", device.deviceName;
            // ...
            break;
        }
    }

    // Vulkan ライブラリをシャットダウンする (サンプル 1 と同じ)

    return 0;
}
  • Vulkan アプリケーションでは、適切な物理デバイスを選択することが、パフォーマンスと安定性を向上させるために重要です。
  • QVulkanWindow::availablePhysicalDevices() 関数は、Vulkan API の vkEnumeratePhysicalDevices() 関数を内部的に呼び出して動作します。


以下、QVulkanWindow::availablePhysicalDevices() 関数の代替方法として検討できるいくつかの方法をご紹介します。

vkEnumeratePhysicalDevices() 関数の直接利用

QVulkanWindow::availablePhysicalDevices() 関数は、内部的に vkEnumeratePhysicalDevices() 関数を呼び出して動作します。そのため、この関数を直接利用することで、より詳細な制御と柔軟性を獲得することができます。

VkInstance instance;
// ... (Vulkan インスタンスを作成)

uint32_t deviceCount;
vkEnumeratePhysicalDevices(instance, nullptr, &deviceCount, nullptr);

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

    // 各デバイスの情報を処理する
    for (VkPhysicalDevice device : devices) {
        // ...
    }
}

QVulkanLoader クラスの利用

QVulkanLoader クラスは、Vulkan API のローディングと関数ポインタの取得を簡素化するためのユーティリティクラスです。このクラスには、vkEnumeratePhysicalDevices() 関数を呼び出すためのメソッドも用意されています。

QVulkanLoader loader;
loader.initialize();

uint32_t deviceCount;
loader.EnumeratePhysicalDevices(nullptr, &deviceCount, nullptr);

if (deviceCount > 0) {
    std::vector<VkPhysicalDevice> devices(deviceCount);
    loader.EnumeratePhysicalDevices(nullptr, &deviceCount, devices.data());

    // 各デバイスの情報を処理する
    for (VkPhysicalDevice device : devices) {
        // ...
    }
}

サードパーティのライブラリの利用

Vulkan API のラッパーライブラリの中には、QVulkanWindow::availablePhysicalDevices() 関数の機能と同等の機能を提供するものがあります。これらのライブラリを利用することで、コードを簡潔化したり、追加機能を利用したりすることができます。

手動でのデバイス情報の収集

システム上のすべてのデバイス情報を手動で収集することも可能です。これは、特定のデバイス情報のみが必要な場合や、より詳細な制御が必要な場合に有効です。

どの方法を選択するべきか

どの方法を選択するかは、アプリケーションの要件と開発者の好みによって異なります。一般的には、QVulkanWindow::availablePhysicalDevices() 関数はシンプルで使いやすいので、多くの場合で十分です。しかし、より詳細な制御や柔軟性が必要な場合は、上記の代替方法を検討する必要があります。