【Vulkan チュートリアル】スワップチェーン画像ビューの取得と活用方法を徹底解説!QVulkanWindow::swapChainImageView() 関数編(応用例付き)

2024-06-22

QVulkanWindow::swapChainImageView() 関数は、指定されたスワップチェーン画像インデックスに対応する画像ビューを取得します。この画像ビューは、レンダリングターゲットとして使用したり、テクスチャサンプリングに使用したりすることができます。

関数引数

  • idx: 取得したい画像ビューのスワップチェーン画像インデックス。このインデックスは、0 から swapChainImageCount() - 1 の範囲内である必要があります。

戻り値

指定されたインデックスに対応する画像ビュー。画像ビューが取得できなかった場合は、nullptr が返されます。

エラー処理

QVulkanWindow::swapChainImageView() 関数は、エラーが発生した場合に例外をスローしません。エラーが発生した場合は、nullptr が返されます。

詳細解説

スワップチェーンは、複数の画像で構成されるバッファです。これらの画像は、レンダリング結果を格納するために使用されます。QVulkanWindow::swapChainImageView() 関数は、これらの画像のいずれか 1 つに対応する画像ビューを取得します。

画像ビューは、画像のリソースへの参照を表すオブジェクトです。画像ビューには、画像のフォーマット、次元、ミップレベルなどの情報が含まれています。

QVulkanWindow::swapChainImageView() 関数は、内部的に Vulkan API の vkCreateImageView() 関数を使用して画像ビューを作成します。この関数は、以下の引数を取ります。

  • device: Vulkan デバイス
  • flags: 画像ビューの作成オプション
  • image: 画像ビューを作成する画像
  • viewCreateInfo: 画像ビューの作成情報

QVulkanWindow::swapChainImageView() 関数は、これらの引数を自動的に設定し、vkCreateImageView() 関数を呼び出して画像ビューを作成します。

// スワップチェーン画像インデックス 0 に対応する画像ビューを取得
VkImageView imageView = window->swapChainImageView(0);

// 画像ビューを使用してレンダリングターゲットを設定
VkImageView attachments[] = { imageView };
VkRenderPassCreateInfo renderPassCreateInfo = {};
renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassCreateInfo.attachmentCount = 1;
renderPassCreateInfo.pAttachments = attachments;
// ...

// 画像ビューを使用してテクスチャサンプリング
VkSamplerCreateInfo samplerCreateInfo = {};
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
// ...

VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {};
descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
// ...

VkDescriptorImageInfo imageInfo = {};
imageInfo.imageView = imageView;
// ...

VkDescriptorSetWriteInfo descriptorSetWriteInfo = {};
descriptorSetWriteInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_WRITE_INFO;
descriptorSetWriteInfo.dstSet = descriptorSet;
descriptorSetWriteInfo.pImageInfo = &imageInfo;
// ...

補足

  • QVulkanWindow::swapChainImageView() 関数は、スワップチェーンが作成された後にのみ呼び出すことができます。
  • QVulkanWindow::swapChainImageView() 関数は、スワップチェーン画像が使用されていないときにのみ呼び出すことができます。
  • QVulkanWindow::swapChainImageView() 関数は、スレッドセーフではありません。複数のスレッドから同時に呼び出す場合は、同期メカニズムを使用する必要があります。

上記以外にも、QVulkanWindow::swapChainImage() 関数を使用してスワップチェーン画像を取得することもできます。この関数は、画像ビューではなく、実際の画像を取得します。

また、QVulkanWindow::currentSwapChainImageIndex() 関数を使用して、現在レンダリングに使用されているスワップチェーン画像のインデックスを取得することもできます。



#include <QVulkanWindow>

class MyWindow : public QVulkanWindow {
public:
    MyWindow(QWidget *parent = nullptr);

protected:
    void initialize() override;
    void paint() override;

private:
    VkImageView imageView;
    VkSampler sampler;
};

MyWindow::MyWindow(QWidget *parent) :
    QVulkanWindow(parent)
{
}

void MyWindow::initialize()
{
    // ... (Vulkan デバイスとスワップチェーンを作成)

    // スワップチェーン画像インデックス 0 に対応する画像ビューを取得
    imageView = swapChainImageView(0);

    // テクスチャサンプラを作成
    VkSamplerCreateInfo samplerCreateInfo = {};
    samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
    samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
    samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
    samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
    samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    vkCreateSampler(device, &samplerCreateInfo, nullptr, &sampler);
}

void MyWindow::paint()
{
    // ... (レンダリングコマンドを記録)

    // テクスチャサンプリングを実行
    VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {};
    descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    // ...

    VkDescriptorImageInfo imageInfo = {};
    imageInfo.imageView = imageView;
    // ...

    VkDescriptorSetWriteInfo descriptorSetWriteInfo = {};
    descriptorSetWriteInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_WRITE_INFO;
    descriptorSetWriteInfo.dstSet = descriptorSet;
    descriptorSetWriteInfo.pImageInfo = &imageInfo;
    // ...

    // ... (レンダリングコマンドを完了)
}

このコードでは、まず initialize() 関数内で swapChainImageView() 関数を使用してスワップチェーン画像ビューを取得します。次に、samplerCreateInfo 構造体を使用してテクスチャサンプラを作成します。

paint() 関数内では、テクスチャサンプリングを実行するために、descriptorSetAllocateInfoimageInfodescriptorSetWriteInfo 構造体を設定します。これらの構造体は、Vulkan API の vkCmdBindDescriptorSets() コマンドで使用されます。

補足

  • このコードは、Vulkan API の基本的な使用方法のみを示しています。Vulkan API の詳細については、Vulkan ドキュメントを参照してください。
  • このコードは、エラー処理や同期メカニズムを考慮していません。実際のアプリケーションでは、これらの要素を適切に処理する必要があります。

注意事項



QVulkanWindow::swapChainImageView() の代替方法

VkImageSubresourceLayers 構造体を使用する**

Vulkan API では、VkImageSubresourceLayers 構造体を使用して、画像ビューを作成することができます。この構造体は、画像のレベル、層、範囲を指定するために使用されます。

VkImageSubresourceLayers subresourceLayers = {};
subresourceLayers.sType = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_LAYERS;
subresourceLayers.mipLevel = 0;
subresourceLayers.baseArrayLayer = 0;
subresourceLayers.layerCount = 1;

次に、vkCreateImageView() 関数を使用して、画像ビューを作成します。

VkImageViewCreateInfo imageViewCreateInfo = {};
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.image = image;
imageViewCreateInfo.format = format;
imageViewCreateInfo.subresourceLayers = subresourceLayers;
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.flags = 0;
vkCreateImageView(device, &imageViewCreateInfo, nullptr, &imageView);

この方法は、より詳細な制御が必要な場合に役立ちます。

QVulkanSwapChain クラスには、imageAt() 関数があります。この関数は、指定されたインデックスのスワップチェーン画像を取得します。

VkImage image = swapChain->imageAt(0);
VkImageViewCreateInfo imageViewCreateInfo = {};
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.image = image;
imageViewCreateInfo.format = format;
imageViewCreateInfo.subresourceLayers = {
    { 0, 0, 1 }
};
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.flags = 0;
vkCreateImageView(device, &imageViewCreateInfo, nullptr, &imageView);

この方法は、QVulkanWindow::swapChainImageView() 関数よりもシンプルですが、QVulkanSwapChain オブジェクトへの参照が必要になります。

手動で画像ビューを作成する

Vulkan API では、vkCreateImageView() 関数を使用して、手動で画像ビューを作成することができます。この関数は、以下の引数を取ります。

  • device: Vulkan デバイス
  • flags: 画像ビューの作成オプション
  • image: 画像ビューを作成する画像
  • viewCreateInfo: 画像ビューの作成情報

QVulkanWindow::swapChainImageView() 関数は、スワップチェーン画像ビューを取得するための便利な方法ですが、いくつかの代替方法があります。どの方法を使用するかは、状況とニーズによって異なります。