やっていくVulkan入門

補講1. バリデーションレイヤー

このページは本編の2章2節(論理デバイス)までを理解していることを前提としています。


Vulkanには「バリデーションレイヤー」という機能があり、これを使うとデバッグに非常に役立ちます。本編ではかっ飛ばしてますが、数行付け加えるだけで使えるので利用することをおススメします。


バリデーションレイヤーというのはその名の通り、バリデーション(検証)処理を行ってくれるものです。

Vulkanは速度を重視した低レベルなAPIであり、通常は細かい検証処理などを行ってくれません。APIに変な引数を渡してもまともなチェックはされず、ある日突然変な不具合が出て原因も分からないということがよくあります。

プログラマーの失敗に対して逐一エラーや警告を出してくれる高級な環境というのは、本来非常にありがたいものなのです。

Vulkanには「レイヤー」という機能があります。これを使うと、VulkanのAPIを呼んだ際の処理に様々な追加処理を入れることができます。これでレイヤーとして追加できるものの1つが、今回説明するバリデーションレイヤーです。

こんな感じで追加することができます。

auto requiredLayers = { "VK_LAYER_KHRONOS_validation" };

vk::InstanceCreateInfo createInfo;

createInfo.enabledLayerCount = requiredLayers.size();
createInfo.ppEnabledLayerNames = requiredLayers.begin();

vk::UniqueInstance instance;
instance = vk::createInstanceUnique(createInfo);

インスタンスの初期化時にvk::InstanceCreateInfo構造体に設定を指定することでレイヤーを追加することができます。バリデーションレイヤー("VK_LAYER_KHRONOS_validation")を追加すると、正しくない引数を指定してAPIを呼び出してしまった際などに、標準出力に警告やエラー情報を吐き出してくれます。デバッグのために非常に役立つのでぜひ利用しましょう。

注意ですがバリデーションエラーは標準出力に出るため、ターミナルを表示するなどしていないと意味がありません。コンソールなしで実行している場合は気を付けましょう。

インスタンスレベル・デバイスレベルのレイヤ

以下の内容は古いバージョンのVulkanに関する内容です。現在では多くの場合行わずとも問題ありません(参考)が、互換性上の問題を考慮する場合は同様の記述を行うことを推奨します。

レイヤーには「インスタンスレベルのレイヤー」と「デバイスレベルのレイヤー」があります。インスタンスレベルでバリデーションレイヤーをオンにしてもデバイスレベルでオンになっていなければ、論理デバイスから生成したオブジェクトに関するAPIについてはバリデーションは行われません。論理デバイスのバリデーションレイヤーもオンにしましょう。

auto requiredLayers = { "VK_LAYER_KHRONOS_validation" };

// (略)

vk::DeviceCreateInfo devCreateInfo;

devCreateInfo.enabledLayerCount = requiredLayers.size();
devCreateInfo.ppEnabledLayerNames = requiredLayers.begin();

vk::UniqueDevice device = physicalDevice.createDeviceUnique(devCreateInfo);