初めてのVulkanプログラミング step3 スワップチェーンの作成


目次に戻る

ソースコードは以下の場所に置いておきます。各自のバージョンに合わせたプロパティ設定をしてから自由にご利用ください。

GitHub

スワップチェーン

VUlkanでは、標準のデフォルトのフレームバッファがありません。画面に表示したい場合、レンダリング可能な一連のバッファーを持つインフラをを作成する必要があります。これらのバッファとプロパティは、スワップチェーンと呼ばれます。

スワップチェーンのサポート確認

vkGetPhysicalDeviceSurfaceSupportKHR()関数はあるデバイスが、スワップチェーンをサポートしているか確認します。

    VkBool32 surfaceSupport;
    vkGetPhysicalDeviceSurfaceSupportKHR(_renderer->GetVulkanPhysicalDevice(), 0, _surface, &surfaceSupport);

デバイス拡張

スワップチェーンはGPUが描写する画像バッファーのインフラであるため、GPUレベルの拡張が必要です。
そのためサンプルコードではVK_KHR_SWAPCHAIN_EXTENSION_NAMEを挿入しています

使用するデバイス拡張をvkDeviceCreateInfoに入れる

    std::vector<const char*>    _device_extensions;
    _device_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
//vkdevicecreateinfoに挿入
    device_create_info.enabledExtensionCount = _device_extensions.size();
    device_create_info.ppEnabledExtensionNames = _device_extensions.data();

プロパティの取得

画面に表示するための互換性がないため、スワップチェーンが利用可能かどうかの確認だけでは、スワップチェーンを使用できません。
スワップチェーンに必要な情報としては、3種類の情報が必要です。

・基本的なサーフェスの機能 (スワップチェーンの画面の大きさ、バッファの数、etc...)
・描写フォーマット (24ビットカラー、白黒画像、赤だけの画面、etc...)
・利用可能なプレゼンテーションモード

    //基本的なサーフェスの機能

    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, _surface, &_surface_capabilities);

    //描写フォーマット
    uint32_t format_count = 0;
    vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, _surface, &format_count, nullptr);
    std::vector<VkSurfaceFormatKHR>formats(format_count);
    vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, _surface, &format_count, formats.data());
    std::cout << "DeviceSurfaceFormats: " << format_count << std::endl;
    for (int i = 0; i < format_count;i++) {
        std::cout << "Format: " << formats[i].format << std::endl;
    }

    //利用可能なプレゼンテーションモード
    uint32_t present_mode_count;
    vkGetPhysicalDeviceSurfacePresentModesKHR(_renderer->GetVulkanPhysicalDevice(),_surface, &present_mode_count, nullptr);
    std::vector<VkPresentModeKHR>present_mode_list(present_mode_count);
    vkGetPhysicalDeviceSurfacePresentModesKHR(_renderer->GetVulkanPhysicalDevice(), _surface, &present_mode_count, present_mode_list.data());
    std::cout << "DeviceSurfaceFormats: " << present_mode_count << std::endl;
    for (int i = 0; i < present_mode_count; i++) {
        std::cout << "support present mode: " << present_mode_list[i] << std::endl;
    }

プレゼンテーションモード

プレゼンテーションモードは、実際に画面に描写するときのアルゴリズムを指定します。
vulkanでは、以下の4つがあります。

VK_PRESENT_MODE_IMMEDIATE_KHR

送信された画像をすぐに表示します。

VK_PRESENT_MODE_FIFO_KHR

ディスプレイのリフレッシュレートを保持するために単一のキューを使用します。新しい要求がキューにおくられ、1つの要求がキューの先頭からでます。キューがいっぱいになったときには、待ち時間が発生します。

VK_PRESENT_MODE_MAILBOX_KHR

キューがいっぱいになったときにアプリケーションをブロックせずに、すぐに表示します。トリプルバッファリングに実装する際に使用します。これによりダブルバッファリングを使う場合よりも滑らかにに表示することができる可能性があります。その代わりに処理が重くなる可能性があります

スワップチェーンの作成

実行時に必要な情報がそろったのでスワップチェーンを作成します

まずサーフェスを指定します。

    VkSwapchainCreateInfoKHR swapchain_create_info = {};
    swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    swapchain_create_info.pNext = nullptr;
    swapchain_create_info.flags = 0;
    swapchain_create_info.surface = _surface;

基本的なサーフェスの機能を指定します
imageformat B8G8R8A8...フルビットカラーです。UNORM...8ビットカラーだけど0.0~1.0fとして変換するよ
color space...色空間を指定
imageArrayLayers...マルチビュー/ステレオサーフェスの数 非立体画像の場合は1

    swapchain_create_info.minImageCount = _surface_capabilities.minImageCount;
    swapchain_create_info.imageFormat = VK_FORMAT_B8G8R8A8_UNORM; //_surface_format.format
    swapchain_create_info.imageColorSpace = _surface_format.colorSpace;
    swapchain_create_info.imageExtent.width = _surface_size_x;
    swapchain_create_info.imageExtent.height = _surface_size_y;
    swapchain_create_info.imageArrayLayers = 1;

描写フォーマットのオプションを指定します

imageUsage ... imageの使い方 、
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT...Image viewを作成して、colorを含んだ,Imageをフレームバッファーに渡す。

sharingmode ...Imageのキューへの共有
一つのキューファミリーにシェアする。

queueFamilyIndexCount... 他のキューファミリーと共有する場合は、入れる。SHARING_MODE_CONCURRENTの時
preTransform...画像を表示する際に画像を回転する。
compositeAlpha...Alpha値の値.デフォルトで1.0にする.

    swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
    swapchain_create_info.queueFamilyIndexCount = 0;
    swapchain_create_info.pQueueFamilyIndices = nullptr;
    swapchain_create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
    swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

プレゼンテーションモードを指定します
clipped...表示よりも外側にあるrenderは破棄しますか?。true

    swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
    swapchain_create_info.clipped =VK_TRUE;
    swapchain_create_info.oldSwapchain = VK_NULL_HANDLE;

最後vkCreateSwapchainKHR関数を呼び出し完成です

     vkCreateSwapchainKHR(gpu,&swapchain_create_info,nullptr,&_swapchain);

連絡先

tweeter: tositada_nakada
mail: [email protected]

寄付

paypal: tositada_nakada
Amazon:欲しいものリスト