Vulkan, D3D11 InterOp

Vulkan 1.1 で クロスプロセス API の相互運用機能 が標準に含まれたようだったので、再び Vulkan と DirectX11 (D3D11) の相互運用にチャレンジしてみました。
使用した拡張名としては以下のものになります。

  • VK_KHR_external_memory_capabilities
  • VK_KHR_external_memory
  • VK_KHR_external_memory_win32

動作結果としては以下のようになり、一応は動作させることができました。

動作確認環境

全ての環境で動作できるものに仕上げることが出来ませんでした。自分の環境は以下のものですが、これでのみ動作を確認できました。

  • Windows10 FCU x64
  • NVIDIA Geforce 1060
  • ドライババージョン: 390.77
  • Vulkan SDK 1.1.70.0

先に示している拡張については、最新の Intel のドライバや AMD のドライバでも対応しているようで、動作可能のように見えましたが何かが悪いのかうまく動作しませんでした。

方法

Vulkan API を見ていると、 DirectX <=> Vulkan でリソースをやりとりできるように見えます。しかし手元で確認出来たのは DirectX(D3D11) から Vulkan の方向へ共有するのみとなりました。
ここでは D3D11 のデバイスおよびレンダーターゲットを作成し、この描画テクスチャを Vulkan と共有して描画させました。

手順としては以下のようになります。
1. D3D11 のデバイスを作成、スワップチェインは不要
2. D3D11 で描画に必要なリソースを作成(ここでは Cube 描画のための各種リソース)
3. D3D11 でレンダーターゲットのテクスチャの作成 (※)
4. Vulkan 初期化。スワップチェインは必要
5. Vulkan で※のリソースをインポート (※)
6. Vulkan で描画

続いてキモとなる※の部分について説明します。
レンダーターゲットのテクスチャの生成フラグでは、 D3D11_RESOURCE_MISC_SHARED_NTHANDLE を付与させておきます。 D3D11 による描画処理が終わった後では、 Flush() を呼び出すようにします。
Vulkan でインポートするときには、 VkExternalMemoryImageCreateInfoKHR, VkImportMemoryWin32HandleInfoKHR らの構造体にデータをセットするところから始めます。これらの構造体で使用するハンドルのタイプには、今回 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT を使用しました。あとは、これらを pNext のポインタチェインにセットして vkCreateImage や vkAllocateMemory を呼び出します。

まとめ

NVIDIA の環境であればこれで一応の動作の確認ができました。今回結果の同期については処理していませんので、このまま使うのは問題があると思います。NVIDIA であれば KeyedMutex を使うことができ、これを使用すれば同期も楽に記述することができるように思います。そうでない環境では、 Semaphore, Fence などの同期オブジェクトを使って同期を取る必要があります。こちらのオブジェクトらも拡張の中に含まれています。

Intel, AMD の環境では、 Vulkan でのテクスチャとして描画させることに失敗しました。うまく動作させることが出来た人がいれば情報をいただければ嬉しいです。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする