GNU/LinuxネイティブのDirect3D 9を実装したGallium Nineとその使い方

Last modified: 2021-02-15

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実装では

  • GLSL (既定値)
  • OpenGL拡張のARB_vertex_program/ARB_fragment_program (GLSL無効時・非推奨)

のいずれかを用いる形で実装されているが、これらは自由なソフトウェアのグラフィックドライバ使用時は一旦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のみに対応するドライバからも使用できるようになった。

短所

  • 9以外のバージョンのDirect3Dでは使えない
    • D3D9を用いて他バージョンのDirect3Dのアプリケーションを動かすラッパーDLLを用いることで動くかもしれないが未確認
  • Galliumアーキテクチャに準拠していないドライバでは使えない
  • WineのDirect3D実装では動くソフトウェアが正しく動かない場合がある(改善はされてきている)
  • 特定のGalliumドライバ内にあるバグによってGPUドライバ依存の不具合が存在することが起こりうる

ハードウェアとソフトウェアの要件

Direct3D 9世代以上に対応したGPUが必要。

  • Intel GPUでは新しい “Iris” ドライバのみが直接対応しており、Broadwell(Gen8・第8世代)かそれより新しい世代(Skylakeなど末尾に “lake” の付く世代は全てOK)でかつグラフィックドライバがMesa 19.2-rc4以上でないとバグにより描画不具合が出る
  • AMDやNVIDIAのGPUの場合、メーカーのプロプライエタリドライバでは対応しておらず自由なソフトウェアのドライバが必要

Mesa 19.2系時点では、Intel GPUで “Iris” ドライバを使用するには環境変数MESA_LOADER_DRIVER_OVERRIDEirisという値を指定する必要がある。

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” によって本体の修正が不要になったと同時に導入が容易になった。

Gallium Nineの導入と使用

ライブラリ部分と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.soninewinecfg.exe.so)をそのままコピーするため、ディストリやWineのバージョンによっては動かない可能性もある。その場合は必要な開発パッケージを用意した上でビルドし、それを配置することもできる(詳細はここでは扱わない)。

Wine 6.0.x系の時点ではバージョン0.7のgalliumnine07をインストールすることで動いている。

デバッグ用にソースからD3D9実装部分をビルド(デバッグまたはバグ報告用)

下は実行時に環境変数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)
  • Debian系でないディストリの場合は必要に応じて-Dd3d-drivers-path=/path/to/libdir/d3dのように配置先のオプションを追加する
  • 2020年末時点では、Debian系ディストリで32bit版をビルドするにはLLVMの開発パッケージの32bit/64bitの共存の関係で32bitのchrootなどの環境が必要

有効化/無効化の設定

Gallium Nine Standaloneにおいては、その一部であるninewinecfgというGUIツールによって簡単に有効/無効がチェックボックスで切り替えられるようになっている。

(GUI設定ツールninewinecfgを起動)
$ WINEPREFIX=[Wine環境の場所] wine ninewinecfg

このツールでは、 “d3dadapter9” のライブラリやGallium Nine Standaloneが正しくインストールされているかを確認することもできる。

動作テスト (任意)

ninewinecfgがインストールの状態を知らせてくれるので、動作のテストはしなくても正しくインストールや設定がされているかどうかは分かるが、手元で動作確認済みのソフトウェアが複数あるので、動作を確認してみたいのであれば、以下から好きなものを選んでテストする。

  • Windows版のdxdiag
    • winetricksdxdiagをインストールし、dxdiagコマンドを実行してDirect3Dのテストを実行すると、Direct3D 9を用いたテストでGallium Nineが使用される
      • Direct3D 9を用いたテストは3番目
  • 3DMark05
    • インストール後にプログラム(3DMark05.exe)のあるディレクトリに移動後に引数-nosysteminfo付きで実行
    • 非常に古くサポートも終了しているため、3DMarkの公式サイトからリンクされているページにプロダクトキーが公開されており、これを入力することで全ての機能が無料で使用可能
  • ウディタの本体に付属するサンプルゲーム
    • 日本語を含む名前のファイルやディレクトリが含まれるため、書庫の展開はunarコマンドを推奨
    • ウディタのバージョン2.22以上ではConfig.exeを同じディレクトリ内に移動後に実行してDirect3D 9を用いるように設定するか、Game.iniOld_DirectX_Use=1となるように編集する
    • 画面が真っ黒になる不具合の回避策として、6.0.x系以上のWineでは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までのバージョンではRendererDirectDrawRendererにする)を事前に実行しておく
      • このレジストリはWine 4.0系以上で有効で、古いバージョンではRendererの代わりにDirectDrawRendererを指定する必要があった
      • Wine 4.0系以上でこのレジストリ設定を適用するとRPGツクール作品など他のGame.exeの動作がおかしくなるため、それらと同じWine環境を使わないようにするか、または先述のレジストリのGame.exeの部分をWolfRpgGame.exeなどの別の文字列にしてGame.exeのファイルもその名前に変更しておく
    • バージョン2.10のGame.exeではサンプルゲーム開始後 “ベースシステム” の “ス” の文字が正常に表示されており、フォントキャッシュ破壊による文字化けが起こらないことが確認できる

端末に緑色のメッセージが表示されていればGallium Nineが使われている。


  1. Wine内のWindows APIをライブラリとして呼び出せるもの ↩︎

  2. Galliumのドライバ部分,libdrm,カーネルのDRMモジュールといったプログラム ↩︎

  3. ソフトウェアの仕組みとしてはZink上ではGallium Nineは動作するはずなのだが、実際にはMesa 20.3系時点ではMESA_LOADER_DRIVER_OVERRIDE=zink指定をしても動作していない ↩︎