GNU/Linuxネイティブな描画APIとしてのDirect3D 9を実装した “Gallium Nine” とその使い方について。
MesaのGalliumアーキテクチャに対応した自由なソフトウェアのグラフィックドライバを使用している場合にAPI変換処理を経由しないネイティブな描画APIとしてのDirect3D 9をGNU/Linuxで使用可能にするもの。
自由なソフトウェアのグラフィックドライバでは、Intelのi965
ドライバなどの一部を除き “Gallium” (または “Gallium3D”)と呼ばれるグラフィックドライバの枠組みが用いられるが、Gallium NineのDirect3D 9実装部分はこの中の “State Tracker” と呼ばれる種類のモジュールとして動作し、 “d3dadapter9” と呼ばれるライブラリ(d3dadapter9.so.[数字]
)の形をとる。
主な使われ方としては、Wineにおいて既存の低速なDirect3D 9の実装を置き換えて高速化やCPU負荷軽減をする用途がある。以前はGallium NineをWineで使用するためにはWine本体にそれなりの規模のパッチを適用したものが必要だったが、Winelib1を用いてその修正部分を独立させたパッケージ “Gallium Nine Standalone” のリリース版が2019年に公開され始めたことで、普通のWineのパッケージにこれを付け加える形で動かせるようになっている。
また、WineにおけるDirect3D 9実装の不具合の一部はGallium Nineには存在しないため、その不具合の回避を目的とした用途もある(例:ウディタ2.10作品の文字の描画が崩れる問題)が、逆にGallium Nineにのみ存在する不具合もあるため、どちらを使うのが適しているかは動かしたいソフトウェアによって異なる。
WineのDirect3D 9は既に機能としては実装済みだが、最初はOpenGLを用いて実装されており、Direct3Dの描画命令を実行する際にはその構造上、CPUの処理コストが余計にかかっていた。
Gallium Nineはこれと比較するとOpenGLを経由しない分処理コストが少なく、より高速に動作する場合が多い。
どの程度高速化されるかはグラフィックドライバ2やGPUによるが、特に、高性能なGPUの使用時には大きな差が出るとされる。Windows上より速くなるかどうかはそれぞれのOSのグラフィックドライバなどによる。
動作速度があまり向上しないケースでもCPU使用率が減ってわずかに省電力になる場合もある。
ただ、WineのDirect3DでVulkanを使用できるようにする仕組みが導入されたり、外部プロジェクトとしてVulkanを用いてDirect3Dを実装するソフトウェアが出てきたりもしているため、Vulkan対応GPUでは動作速度面での恩恵は以前ほどはなくなっている。GPUの世代がDirect3D 9から11のバージョンまでにしか対応しておらずVulkanに未対応の場合には確実に恩恵がある。
下はDirect3D 9の描画処理の大まかな流れを比較した図。WineのDirect3D 9がVulkanに対応した後は流れが変わる部分があるが、ここではOpenGLを用いた場合との比較を行っている。
(WineでDirect3D 9アプリケーションをOpenGL経由で動かす際の描画処理の流れ)
Wine/d3d9 -[Direct3D 9命令]-> Wine/wined3d(OpenGLを用いてその都度実行) -[OpenGL命令]-> OpenGLライブラリ -> Galliumドライバ -> GPU
(Gallium Nineを用いた際の描画処理の流れ)
Wine/d3d9(命令をそのまま渡す) -[Direct3D 9命令]-> d3dadapter9 -> Galliumドライバ -> GPU
シェーダ処理については、OpenGLを用いたWineのDirect3D実装では
のいずれかを用いる形で実装されているが、これらは自由なソフトウェアのグラフィックドライバ使用時は一旦Mesaのドライバ内の中間表現に変換されてから各GPU向けのGalliumドライバを経由して実行される。
Gallium Nineからシェーダを用いる際には上記のいずれかを経由せずに内部の中間表現へ変換されるため、それよりも処理コストが削減される。
(WineでDirect3D 9アプリケーションを動かす際のシェーダ処理の流れ)
Wine/d3d9 -[Direct3D 9命令]-> Wine/wined3d(GLSL or GL拡張としてその都度実行) -[GLSL or GL拡張]-> OpenGLライブラリ(中間表現に変換) -[中間表現]-> Galliumドライバ -> GPU
(Gallium Nineを用いた際のシェーダ処理の流れ)
Wine/d3d9 -[Direct3D 9命令]-> d3dadapter9(中間表現に変換) -[中間表現]-> Galliumドライバ -> GPU
Gallium Nineはその後Intelの “Iris” ドライバなどが用いている “NIR” と呼ばれる新しいMesa内部の中間表現への変換(TTN:TGSI to NIR)を経由した動作にも対応し、それらのNIRのみに対応するドライバからも使用できるようになった。
Direct3D 9世代以上に対応したGPUが必要。
Mesa 19.2系時点では、Intel GPUで “Iris” ドライバを使用するには環境変数MESA_LOADER_DRIVER_OVERRIDE
にiris
という値を指定する必要がある。
Vulkanドライバ上で動作するGalliumアーキテクチャ準拠の “Zink” というドライバの中の機能実装状況3によっては、Intelのi965
ドライバしか使えない環境でもVulkanドライバ経由で使えるようになる可能性がある。また、プロプライエタリドライバについてもVulkanに対応していればこれを用いて動く可能性がある。ただ、いずれの場合もVulkan上にDirect3D 9を実装した “DXVK” が既に存在する上にZink経由より高速と考えられるため、そちらを先に試すのがよさそう。
最初に話題になったのは2013年夏、Mesaのメーリングリストへの投稿のときだった。
2014年春まではこのときの開発リポジトリで開発が続いていたが、その後は新しい開発者によって派生リポジトリ上で活発に開発が行われるようになった。
更に、Mesaの公式リポジトリに取り込んでもらうよう働きかける動きも進んで、バージョン10.4では初めて公式のリリースの中に含まれることになった。
Mesa 10.4系や10.5系の時期は開発が活発で、多数のパッチが取り込まれていた。
Wine本体の修正についてのパッチはなかなか取り込まれず、最終的には先述の “Gallium Nine Standalone” によって本体の修正が不要になったと同時に導入が容易になった。
以前は “d3dadapter9” のライブラリ(API実装部分)はディストリのパッケージになっていないことが多かったが、2019年秋の時点ではパッケージとしてインストールできることが多くなっている。
Debian/Ubuntuではlibd3dadapter9-mesa
をインストールする。32bitのアプリケーションを動かす場合はlibd3dadapter9-mesa:i386
が必要となる。動かすソフトウェアの時期的に考えると、32bitのアプリケーションを動かすための後者が必要になるケースのほうが多くなると思われる。
“Gallium Nine Standalone” についてはWine環境ごとに導入する。最も楽なのがWinetricksを使用した方法。
$ WINEPREFIX=[Wine環境の場所] winetricks galliumnine
この方法ではパッケージとして配布されているLinux用バイナリ(32bit/64bitそれぞれのd3d9-nine.dll.so
とninewinecfg.exe.so
)をそのままコピーするため、ディストリやWineのバージョンによっては動かない可能性もある。その場合は必要な開発パッケージを用意した上でビルドし、それを配置することもできる(詳細はここでは扱わない)。
Wine 6.0.x系の時点ではバージョン0.7のgalliumnine07
をインストールすることで動いている。
下は実行時に環境変数NINE_DEBUG
で詳細な動作のログが出力できるようにするためのd3dadapter9
のみをMesaのソースからビルドして上書きインストールするための作業例。MesaのビルドシステムがMesonに移行した後の単独でのビルドを行うための作業例が書かれているところが見つからないため、ここに載せておく。
(ビルドの設定)
$ CFLAGS="-Og -ggdb -g -gdwarf-2 -gstrict-dwarf" CXXFLAGS="-Og -ggdb -g -gdwarf-2 -gstrict-dwarf" meson --prefix=/usr -Ddri-drivers= -Dgallium-drivers=radeonsi,swrast -Dgallium-nine=true -Dvulkan-drivers= -Dgles1=disabled -Dgles2=disabled -Dopengl=false -Dglx=disabled -Dgallium-vdpau=disabled -Dgallium-va=disabled -Dlmsensors=disabled -Dgbm=disabled -Degl=disabled -Ddri3=enabled -Dbuildtype=debug _build
(ビルド)
$ ninja -C _build
(上書きインストール)
$ sudo ninja -C _build install
radeonsi
(Southern Islandsファミリとそれより新しいAMD GPU向け)の部分はiris
(Intel GPU)やnouveau
(NVIDIA GPU),r600
(radeonsi
より少し古いAMD GPU)など実際に使用しているGPUに合ったドライバ名に置き換えるか、コンマ区切りでそれらを並べる(-Dgallium-drivers=radeonsi,iris,nouveau,r600,swrast
)-Dd3d-drivers-path=/path/to/libdir/d3d
のように配置先のオプションを追加するGallium Nine Standaloneにおいては、その一部であるninewinecfg
というGUIツールによって簡単に有効/無効がチェックボックスで切り替えられるようになっている。
(GUI設定ツールninewinecfgを起動)
$ WINEPREFIX=[Wine環境の場所] wine ninewinecfg
このツールでは、 “d3dadapter9” のライブラリやGallium Nine Standaloneが正しくインストールされているかを確認することもできる。
ninewinecfg
がインストールの状態を知らせてくれるので、動作のテストはしなくても正しくインストールや設定がされているかどうかは分かるが、手元で動作確認済みのソフトウェアが複数あるので、動作を確認してみたいのであれば、以下から好きなものを選んでテストする。
dxdiag
winetricks
でdxdiag
をインストールし、dxdiag
コマンドを実行してDirect3Dのテストを実行すると、Direct3D 9を用いたテストでGallium Nineが使用される
3DMark05.exe
)のあるディレクトリに移動後に引数-nosysteminfo
付きで実行unar
コマンドを推奨Config.exe
を同じディレクトリ内に移動後に実行してDirect3D 9を用いるように設定するか、Game.ini
をOld_DirectX_Use=1
となるように編集するwine reg add "HKCU\Software\Wine\AppDefaults\Game.exe\Direct3D" /v "renderer" /t REG_SZ /d "no3d"
、5.0.x系までのWineではwine reg add "HKCU\Software\Wine\AppDefaults\Game.exe\Direct3D" /v "Renderer" /t REG_SZ /d "gdi"
(3.0.xまでのバージョンではRenderer
をDirectDrawRenderer
にする)を事前に実行しておく
Renderer
の代わりにDirectDrawRenderer
を指定する必要があったGame.exe
の動作がおかしくなるため、それらと同じWine環境を使わないようにするか、または先述のレジストリのGame.exe
の部分をWolfRpgGame.exe
などの別の文字列にしてGame.exe
のファイルもその名前に変更しておくGame.exe
ではサンプルゲーム開始後 “ベースシステム” の “ス” の文字が正常に表示されており、フォントキャッシュ破壊による文字化けが起こらないことが確認できる端末に緑色のメッセージが表示されていればGallium Nineが使われている。