LinuxでvkEnumerateInstanceLayerPropertiesが何も返さないのをなんとかした

Posted on

ちなみに環境はUbuntu 19.04 + Radeon RX 580です。

OpenGLに疲れた

最近OpenGLに疲れはて、Vulkanに乗り換えようかと思っています。

  • メインスレッドからしか叩け無い制限。
  • bindというグローバル変数より邪悪な概念。
  • 関数を呼び出した後にglGetError()を毎回叩かなけばならない苦痛(叩き忘れるといつエラーになったのか、わからん)。
  • シェーダーへ変数へ渡すためのあの無限の関数群。
  • OpenGLのバージョンによって今では利用が必須だったり、逆に使えなかったりする「拡張機能」。
  • IndexBufferObjectだのElementArrayBufferだのVertexArrayObjectという意味不明な命名(これ…何だと思う?)。
  • 同じ関数でもOpenGLバージョンによってたまに意味が違ったりするあのややこしさ。
  • ググって出てきた情報の「今では使えなさ」(だいたいそのままコピペしても動かない)
  • GLSLのバージョンごとの気まぐれさ。
  • 結局何が起こるのかよくわからん関数のドキュメント。
  • Core ProfileだのCompat Profileだの

…ぼくもう疲れたよパトラッシュ。

そんな感じで最近Vulkanでなんとかする方向でやってこうと思ってまして、で最近引っかかった問題の解放を備忘録代わりにメモっておきます。

VulkanにはLayerなるものがあるらしい

Vulkanではある種の拡張機能を「Layer」といいます1

たとえば、標準ではこんなLayerがあるんだってさ(LunarGのサイトから引用。CC=BY=ND):

Layer Name Layer Type Description
VK_LAYER_LUNARG_api_dump utility print API calls and their parameters and values
VK_LAYER_LUNARG_assistant_layer utility highlight potential application issues that are not specifically prohibited by the Vulkan spec, but which can still create problems
VK_LAYER_KHRONOS_validation validation the main, comprehensive Khronos validation layer — this layer encompasses the entire functionality of the deprecated layers listed below, and supercedes them. As the other layers are deprecated this layer should be used for all validation going forward.
VK_LAYER_LUNARG_device_simulation utility allows modification of an actual device’s reported features, limits, and capabilities
VK_LAYER_LUNARG_monitor utility outputs the frames-per-second of the target application in the applications title bar
VK_LAYER_LUNARG_screenshot utility outputs specified frames to an image file as they are presented

VK_LAYER_KHRONOS_validation、便利そうだなー使いたいなー。

環境によってはこれ以外のLayerも使えるらしく、実際にどんなレイヤーが使えるか列挙して調べるためのvkEnumerateInstanceLayerPropertiesという関数があります。

で、これを使って実際に列挙してみました。

std::vector<VkLayerProperties> vk::enumerateInstanceLayerProperties() {
  uint32_t numProps = 0;
  {
    VkResult const result = vkEnumerateInstanceLayerProperties(&numProps, nullptr);
    if(result != VK_SUCCESS) {
      return std::vector<VkLayerProperties>();
    }
  }
  std::vector<VkLayerProperties> props;
  props.resize(numProps);
  VkResult const result = vkEnumerateInstanceLayerProperties(&numProps, props.data());
  if(result != VK_SUCCESS) {
    return std::vector<VkLayerProperties>();
  }
  return std::move(props);
}

が、これを動かしても空配列しか返ってこない。エラーではなく、成功した上で0個です。たぶん呼ぶタイミングを間違ったりはしてない。

うーん、おかしい。さっきの6つのレイヤーは、Vulkanの仕様上必ず入っているはずなのです。

ためしにググって見た所、こんな感じだったので、みんな困ってんだろなーと思って解法を書いておきます:

解法:sudo apt install vulkan-validationlayers-devしろ

apt search vulkanと入れると

libvulkan-dev/disco,now 1.1.101.0-2 amd64 [installed]
  Vulkan loader library -- development files

が出てくるのでこれだけいれときゃOK、Vulkanが全部使えるようになるんだぜ!と思いきや、実はこれだけではUbuntu 19.04ではLayerは入りません。

正解はこちらも入れることです:

vulkan-validationlayers-dev/disco,now 1.1.101.0-1 amd64
  Vulkan validation layers -- development files

要するに黙ってsudo apt install vulkan-validationlayers-devしろ。

結果

ちゃんと6つ返ってきました:

[2019/10/30 20:43:35 DEBUG] Layer: VK_LAYER_LUNARG_parameter_validation (spec=4198501, impl=1) :: LunarG Validation Layer
[2019/10/30 20:43:35 DEBUG] Layer: VK_LAYER_LUNARG_object_tracker (spec=4198501, impl=1) :: LunarG Validation Layer
[2019/10/30 20:43:35 DEBUG] Layer: VK_LAYER_GOOGLE_unique_objects (spec=4198501, impl=1) :: Google Validation Layer
[2019/10/30 20:43:35 DEBUG] Layer: VK_LAYER_LUNARG_standard_validation (spec=4198501, impl=1) :: LunarG Standard Validation
[2019/10/30 20:43:35 DEBUG] Layer: VK_LAYER_LUNARG_core_validation (spec=4198501, impl=1) :: LunarG Validation Layer
[2019/10/30 20:43:35 DEBUG] Layer: VK_LAYER_GOOGLE_threading (spec=4198501, impl=1) :: Google Validation Layer

あれ、ちょっとまって、名前全然ちがくない?GOOGLEってなんや??

今日のところはVK_LAYER_LUNARG_standard_validation使って勘弁しといたるわ。

Vulkan難しい

Vulkanとの対話は続く…。

  1. この時点で若干OpenGL時代の命名規則センスを感じヤバみは感じる… []

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください