Vulkan グラフィックスを Qt GUI アプリに導入: QWindow::setVulkanInstance() のステップバイステップガイド


QWindow::setVulkanInstance() 関数は、Qt GUIアプリケーションで Vulkan API を使用する際に、Vulkan インスタンスをウィンドウに設定するために使用されます。Vulkan インスタンスは、Vulkan API を使用するアプリケーション全体で共有されるオブジェクトであり、物理デバイスや論理デバイスなどの Vulkan リソースを作成するために必要です。

使用方法

QWindow::setVulkanInstance() 関数は、Vulkan インスタンスのポインタ (VkInstance) を引数として取ります。このインスタンスは、Vulkan API の vkCreateInstance() 関数を使用して作成する必要があります。

VkInstance vkInstance;
vkCreateInstance(&createInfo, nullptr, &vkInstance);

// ...

window->setVulkanInstance(vkInstance);

注意点

  • 複数のウィンドウで同じ Vulkan インスタンスを使用できます。
  • Vulkan インスタンスは、アプリケーションが終了する前に解放する必要があります。
  • QWindow::setVulkanInstance() 関数は、ウィンドウが作成された後にのみ呼び出す必要があります。

以下の例は、Vulkan インスタンスを作成し、それをウィンドウに設定する方法を示します。

#include <QtVulkan>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // Vulkan インスタンスを作成
  VkInstance vkInstance;
  VkApplicationInfo createInfo = {};
  createInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  createInfo.apiVersion = VK_API_VERSION_1_0;
  VkInstanceCreateInfo instanceCreateInfo = {};
  instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  instanceCreateInfo.pApplicationInfo = &createInfo;
  vkCreateInstance(&instanceCreateInfo, nullptr, &vkInstance);

  // ウィンドウを作成
  QWindow window;
  window.setTitle("Vulkan Window");
  window.resize(500, 500);
  window.show();

  // Vulkan インスタンスをウィンドウに設定
  window.setVulkanInstance(vkInstance);

  // ...

  return app.exec();
}

QWindow::setVulkanInstance() 関数は、Qt GUI 6.0 以降で使用できます。古いバージョンの Qt を使用している場合は、Vulkan API を直接使用する必要があります。



Vulkan インスタンスの作成

VkInstance vkInstance;
VkApplicationInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
createInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo instanceCreateInfo = {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &createInfo;
vkCreateInstance(&instanceCreateInfo, nullptr, &vkInstance);

Vulkan インスタンスのウィンドウへの設定

window->setVulkanInstance(vkInstance);

このコードは、Vulkan インスタンスをウィンドウに設定します。QWindow::setVulkanInstance() 関数は、Vulkan インスタンスのポインタ (VkInstance) を引数として取ります。

Vulkan インスタンスの解放

vkDestroyInstance(vkInstance, nullptr);

このコードは、Vulkan インスタンスを解放します。vkDestroyInstance() 関数は、Vulkan インスタンスのポインタ (VkInstance) を引数として取ります。

#include <QtVulkan>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // Vulkan インスタンスを作成
  VkInstance vkInstance;
  VkApplicationInfo createInfo = {};
  createInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  createInfo.apiVersion = VK_API_VERSION_1_0;
  VkInstanceCreateInfo instanceCreateInfo = {};
  instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  instanceCreateInfo.pApplicationInfo = &createInfo;
  vkCreateInstance(&instanceCreateInfo, nullptr, &vkInstance);

  // ウィンドウを作成
  QWindow window;
  window.setTitle("Vulkan Window");
  window.resize(500, 500);
  window.show();

  // Vulkan インスタンスをウィンドウに設定
  window.setVulkanInstance(vkInstance);

  // ...

  // Vulkan インスタンスを解放
  vkDestroyInstance(vkInstance, nullptr);

  return app.exec();
}

このコードは、Vulkan インスタンスを作成し、それをウィンドウに設定し、アプリケーションが終了する前に解放する方法を示します。このコードは、Qt GUI 6.0 以降で使用できます。



  • 複数のウィンドウで同じ Vulkan インスタンスを使用できない
  • Vulkan インスタンスは、アプリケーションが終了する前に解放する必要がある
  • ウィンドウが作成された後にのみ呼び出すことができる

これらの制限を回避するために、QWindow::setVulkanInstance() 関数の代替方法を使用することができます。

QVulkanWindow クラスを使用する

QVulkanWindow クラスは、Vulkan API を使用する Qt ウィンドウを作成するために使用されます。このクラスには、setVulkanInstance() 関数と同等の機能を提供する setVulkanInstanceInfo() メソッドがあります。

QVulkanWindow window;
window.setTitle("Vulkan Window");
window.resize(500, 500);
window.show();

// Vulkan インスタンス情報を作成
QVulkanInstanceInfo instanceInfo;
instanceInfo.instance = vkInstance;
instanceInfo.layers = layers;
instanceInfo.extensions = extensions;

// Vulkan インスタンス情報をウィンドウに設定
window.setVulkanInstanceInfo(instanceInfo);

このコードは、QVulkanWindow クラスを使用して Vulkan インスタンスをウィンドウに設定する方法を示します。setVulkanInstanceInfo() メソッドは、Vulkan インスタンス、レイヤー、拡張機能に関する情報を指定するために使用される QVulkanInstanceInfo 構造体を受け取ります。

Vulkan API を直接使用して、Vulkan インスタンスをウィンドウに設定することもできます。これは、より高度な制御が必要な場合に役立ちます。

// Vulkan インスタンスを作成
VkInstance vkInstance;
VkApplicationInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
createInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo instanceCreateInfo = {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &createInfo;
vkCreateInstance(&instanceCreateInfo, nullptr, &vkInstance);

// ウィンドウを作成
QWindow window;
window.setTitle("Vulkan Window");
window.resize(500, 500);
window.show();

// Vulkan サurfaceを作成
VkSurfaceKHR surface;
VkSurfaceCreateInfoKHR surfaceCreateInfo = {};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_KHR;
surfaceCreateInfo.window = (NativeWindowType) window.nativeHandle();
vkCreateSurfaceKHR(vkInstance, &surfaceCreateInfo, nullptr, &surface);

// Vulkan デバイスを作成
VkPhysicalDevice physicalDevice;
vkEnumeratePhysicalDevices(vkInstance, nullptr, &physicalDeviceCount, &physicalDevice);
VkDeviceCreateInfo deviceCreateInfo = {};
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceCreateInfo.queueCount = 1;
VkQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_QUEUE_CREATE_INFO;
queueCreateInfo.flags = VK_QUEUE_GRAPHICS_BIT;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
VkDevice device;
vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);

// Vulkan コマンドキューを作成
VkQueue queue;
vkGetDeviceQueue(device, 0, 0, &queue);

// Vulkan スワップチェーンを作成
VkSwapchainKHR swapchain;
VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.surface = surface;
swapchainCreateInfo.minImageCount = 2;
swapchainCreateInfo.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
swapchainCreateInfo.extent = { window.width(), window.height() };
swapchainCreateInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
swapchainCreateInfo.swapchainUsage = VK_SWAPCHAIN_USAGE_PRESENT_BIT;
vkCreateSwapchainKHR(device, &swapchainCreateInfo, nullptr, &swapchain);

// ...

// Vulkan インスタンスを解放
vkDestroyInstance(vkInstance, nullptr);

// Vulkan デバイスを解放
vkDestroyDevice(device, nullptr);

// Vulkan サurfaceを解放
vkDestroySurfaceKHR(vkInstance, surface, nullptr);