update.はじめに前回、Vulkan初期化の第一歩としてVulkanインスタンスを作りました。今回は第2歩目として、物理デバイスのクエリを行います。OpenGLESでは、「どんなGPUが何個搭載されているか」といった物理デバイス構成について何も意識する必要はありません。これは初期化の手間が省ける反面、描画実行にどのGPUを稼働させるかの選択をOpenGLESに権限移譲することを意味します。システムに接続されるGPUは1つだけ、という想定のもとではそれで充分でした。GPUを複数搭載し、より高負荷な処理を行わせることを目的としたシステムでは、「どのGPUにどんなタスクをいつ割り当てるか」を細かく制御することができれば、システム性能をさらに改善することが可能となります。GPUを複数搭載したシステムは珍しいものではなく、組み込みの世界でも、nVIDIAのDrivePXのような例があります。Vulkanでは、システム性能を最大限引き出すために、「システムに接続された物理デバイスの能力」をアプリ開発者が収集し、活用することを求めています。注)EXT_device_base拡張をサポートしている環境であれば、OpenGLESでも明示的にGPUを指定可能です。Vulkanにおける2つの「デバイス」Vulkanには、2つの「デバイス」という用語があります。GPU1個が物理デバイス1個。物理デバイスと論理デバイスとは必ずしも1対1ではない処理の流れは、下記の通りです。今回は、1)の物理デバイスの生成までをやります。物理デバイス情報の収集それでは物理デバイスの情報を取得していきます。vkEnumeratePhysicalDevicesvkEnumeratePhysicalDevices()関数で、物理デバイスのハンドルを取得します。1回目の呼び出しで個数を取得し、2回目の呼び出しでその個数分のハンドルを一気に取得します。内蔵GPUと、グラボGPUとがカウントされているようです。vkGetPhysicalDeviceProperties取得した物理デバイスのハンドルを人間が見てわかる情報に変換していきます。*/デバイス名とAPIバージョン番号を表示させています。実行結果は、下記です。1.0.50Core-i7内蔵GPUの存在なんてすっかり忘れていたのですが、きっちりVulkan対応しているとのこと。私の環境でのAPIバージョンをまとめると次の通りです。1.0.50このように、デバイスごとにapiVersionが異なることの注意が必要です。APIしか使えないこともある、という実例です。QueueファミリGPUに仕事を依頼するには、描画用コマンドやコンピュート用コマンド、メモリ転送用コマンド等、様々なコマンドをキューに並べてGPUに仕事を依頼します。OpenGLESでは、すべてのコマンドを1本のキューに登録し、仕事を順にひとつずつ実行させています。GPUアーキとしては「描画用コマンドとメモリ転送用コマンドは同時実行可能」というように、並列性を高めたものもあります。全ての仕事が1つのキューに並んでいると、前の仕事が終わるまで次の仕事を始めることができず、せっかくの並列性が活かせません。して分類することで、並列性を高めることができるようになっています。具体的には、「なんでも登録できるキュー」「コンピュート用コマンドしか登録できないキュー」「メモリ転送用コマンドしか登録できないキュー」のように、キューに登録可能なコマンド種別ごとに分類することで、並列実行可能なキューを明示的に分離し、それぞれ別に管理します。vkGetPhysicalDeviceQueueFamilyPropertiesQueueファミリ情報は、vkGetPhysicalDeviceQueueFamilyProperties()で取得します。例のごとく、1回目の呼び出しで個数を取得して、2回目の呼び出しで情報取得します。}実行結果は下記の通り。nVIDIAグラボはQueueファミリが3つ。それぞれ「何でも登録可能」「メモリ転送のみ」「コンピュートのみ」。「何でも登録可能」なQueueファミリが1つでした。作成しますが、その際「どのQueueファミリを使うか」の指定が必要になります。Vulkanで描画を行うには、「描画用コマンドを登録可能」なQueueファミリを指定する必要があるので、覚えておきましょう。他にも複数のQuery関数により、デバイスに関する様々な情報を取得できます。デバイス情報をわかりやすいHTMLで出力してくれる機能があるので、それを眺めるのも楽しいです。vkGetPhysicalDeviceFeatures()を使います。&physDevFeatures);ジオメトリシェーダやテセレーションシェーダが使えるのかといったOpenGLESにも馴染みのある情報が取得できます。OpenGLESでは、そのバージョン番号によって使える描画機能が保証されていますが、Vulkanの場合は、このFeature情報を取得して使える機能を確認する必要があるのですね。vkGetPhysicalDeviceFormatProperties使用可能なカラーフォーマット情報を取得します。取得可能なフォーマットの一覧がわらわらと取得できるようなAPIではなく、「このフォーマットに関する情報ちょうだい」と問い合わせると、「使える」「使えない」が返ってくるAPI仕様になっています。vkGetPhysicalDeviceMemoryProperties使用可能なメモリ情報を取得します。vkEnumerateDeviceExtensionPropertiesデバイスごとに使えるExtensionも違うはずなので、調べましょう。2段階で呼び出します。}参考までに、Extension数を書いておきます。glGetXXX()をチマチマ呼び出す必要がありました。パッキングされて取得できるので便利です。将来の機能拡張で、取得したい情報が増えたらどうするんだろう。VkPhysicalDeviceProperties構造体のメンバを増やしたくなったらどうするんでしょうか。構造体の識別子を指定するメンバもないので、互換性を維持したままメンバを増やすのは困難に思えます。実はその答えはすでに用意されています。いう名の、拡張性を持たせた別APIが定義されています。*/API構文は、バージョン1と同じなのですが、引数で渡す構造体が変更されています。VkPhysicalDeviceProperties2;構造体をチェーン接続することで、将来の拡張性にも対応できるようにしています。チェーンを作るのはVulkanライブラリではなくアプリの仕事です。呼ぶ前に、アプリで空の構造体チェーンを作って、それを引数で渡さないといけません。サンプルコードは一番下のリンクにあります。今回のまとめVulkanで物理デバイスの様々な情報を取得しました。nVIDIAのグラボとIntel内蔵GPUの情報が何の隔たりなく統一的に取得できることに今更ながら便利だなと感じました。論理デバイスの作成をする予定です。requestStockLike3@terrykyOpenGLESユーザでしたが、最近Vulkanの勉強を始めました。upLoginユーザーは見つかりませんでした。