OpenGL 4.6 の発表の中で、各Graphics API との Interop の話がありました。
ここで、EXT_external_objects 拡張 (スライドでは EXT_memory_object となっていましたが) が、面白そうだったので触ってみました。
ただしこの内容は OpenGL 4.6 に含まれるものではなく、追加という位置付けとなっているようです。
説明など
この EXT_external_objects 拡張は、 OpenGL に他の API で作成されたオブジェクトを利用するためのものとなっているようです。
提供される API 群は、こちらの仕様の方を確認してください。
OpenGL にとっての外部メモリを利用して、OpenGL のリソースを生成する(インポートする)といった感じで、機能が準備されています。
実験
今までにも Interop を実験してきたこともあり、 Vulkan でレンダーターゲットにキューブを描画する部分を流用しました。
Vulkan 側でもメモリ領域を OpenGL で使うために、準備が必要です。
これには、 VK_KHR_external_memory_win32, VK_KHX_external_memory_win32, VK_NV_external_memory_win32 といった共有のための拡張を使用する必要があります。
これらを使用して、メモリをエクスポート可能な状態にして、共有ハンドルを取得しておくことが必要です。
OpenGL 側では、以下のようにしてテクスチャをインポートしました。
glCreateMemoryObjectsEXT(1, &memObject); GLint params = GL_TRUE; glMemoryObjectParameterivEXT(memObject, GL_DEDICATED_MEMORY_OBJECT_EXT, ¶ms); glImportMemoryWin32HandleEXT(memObject, memSize, GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT, hSharedHandle); glGenTextures(1, &texId); glBindTexture(GL_TEXTURE_2D, texId); glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256, memObject, 0);
こうやってインポートしたテクスチャを、 OpenGL としては古いタイプのコードで使ってみました。
glBindTexture(GL_TEXTURE_2D, texId ); glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); glBegin(GL_TRIANGLE_STRIP); glLoadIdentity(); glTexCoord2f(0.0, 0.0f); glVertex3f(-0.75f, 0.75f, 0.0f); glTexCoord2f(0.0, 1.0f); glVertex3f(-0.75f,-0.75f, 0.0f); glTexCoord2f(1.0, 0.0f); glVertex3f( 0.75f, 0.75f, 0.0f); glTexCoord2f(1.0, 1.0f); glVertex3f( 0.75f,-0.75f, 0.0f); glEnd();
こうやって動いたのか以下のものです。描画自体は Vulkan で最近のもので、OpenGL 側ではずいぶん昔風のコードでという描画で書いてみました。
ちなみに、Vulkan-> OpenGL だけでなく、少しのパラメータ変更で DirectX11 -> OpenGL もこの仕組みを用いてテクスチャの共有使用が可能でした。
今回省略していますが、 実際に使う際には セマフォや Keyed Mutex などで同期をとりつつ処理を行うといったことが必要です。
まとめ
OpenGL でうまく Vulkan のテクスチャを使用することが出来ました。今回はテクスチャだけでしたが、拡張のドキュメントを読んでみるとわかるとおり他のリソースについても共有が可能となっています。
API の Interop は可能性を広げてくれる面白いものだと思うのですが、事例が少なく残念に思います。
また以前に、「Vulkan のテクスチャを DirectX11 へ」という記事で interop 動作させていたのですが、今の状態・環境では正常に動かないものとなってました。
共有関連は仕様が変わるのか、一度書いたコードがずっと動く、といったことがなさそうです。今回のこの拡張についても、この先はどうなるか不明です。
ただ Vulkan からテクスチャだけを使用したいのであれば、先日の glDrawVkImageNV を使ったほうが実装は楽になると思います。
環境
今回使用している環境は、 NVIDIA ドライバの 382.88 バージョンを使用しています。
これは先日の Siggraph での発表に合わせて、 NVIDIA より公開された OpenGL 4.6 対応ドライバです。
発表されたスライド