
2026/08/08 22:33
Triton:QEMU の DirectX 11 ドライバー
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Neptune は QEMU 仮想マシン向けの新規ツールであり、Triton ドライバスタックと連携する専用フォワーディング層として動作することで DirectX 11 対応を実現します。この革新的なアプローチは、危険な DLL 置換手法を回避し、古い解決策で一般的であった高遅延のバイトコード解釈問題を解消します。VirtualBox などが利用していた廃止済み API や複雑なインタープリターに依存せず、Neptune はデータのシリアライズには効率的なリングバッファを、同期には共有メモリを用いて、滑らかなグラフィックレンダリングを保証しています。
macOS においては、DXMT(D3D11→Metal)、Apple の Game Porting Toolkit をラップしたもの(d3dmetal-native で Rosetta 使用)、および UTM fork の open source ヴァーチャルグリッドレンダラー(virglrenderer)の 3 つのバックエンドを提供しています。現在、共有テクスチャ同期は macOS において、MTLBuffers にマッピングされた共有メモリを介して線形テクスチャのみをサポートし、IOSurface などの廃止済み API を使用していません。完全な共有テクスチャについては線形形式に限られますが、このアーキテクチャでは DXBC シェーダーに必要なメタデータを合成し、ゲストドライバー内でスワップチェーンロジックを管理することで、Venus の設計原理と整合しています。
本プロジェクトは DirectX コンポーネントに関する従来の前提を修正するとともに、DDI コールから DirectX API コールへの直接的な逆変換を利用して遅延を低減し、既存モデルを大幅に改善します。今後の開発では、現状では生产用途向けに不安定と标记されているがテスト目的で有用なプリビルトの Windows ドライバ(UMD/KMD)の安定化に焦点を当てます。ユーザーは即座に Linux ホスト上で DXVK 加速ゲームを実行したり、ハイパーバイザ Framework の加速により性能向上を実現した Windows ARM64 ゲストにアクセスしたりすることで恩恵を受けます。企業向けには、従来エミュレーションレイヤーとの互換性に課題があった感度の高いアンチチートソフトウェアとの互換性が改善され、より安定したデスクトップ体験が提供されます。オープンソースコードは適宜 MIT ライセンスまたは LGPL ライセンスの下で利用可能です。
本文
Neptune と Triton:Linux ホスト上の Wine ゲームを高速化し、Windows ゲスト向けグラフィックスアクセラレーションを実現する
背景と概要
前篇で紹介した Neptune は、ハイパーバイザ境界を超えて Direct3D API をシリアライズし、DXVK よりも高速に Linux ホスト上で Wine ゲームを実行するためのプロトコルです。現在、同プロジェクトは以下の新たな目標へ道筋を切り開いています。
- Triton(トライトン):QEMU 仮想マシンにフル機能の DirectX 11 サポート をもたらす新しい Windows ドライバの開発
- 真の目標:Windows ゲスト向けのモダンなグラフィックスアクセラレーションの実現
Triton とは?
Neptune が Direct3D API のシリアライズを可能にしたにもかかわらず、まだ完全ではありません。その理由は以下の 2 点です。
なぜ DLL 置換だけでは不十分か?
d3d11.dll および dxgi.dll をゲーム実行ファイルの隣に配置して Windows エミュレートするのは、一見可能に見えますが以下の重大な欠点があります。
- パフォーマンスの問題:GPU のイメージバッファを CPU がコピーする Blitting(位転送) が必要になり、滑らかなデスクトップ体験は得られません。フルスクリーンアプリでのトリックも限界です。
- セキュリティ・互換性:
は Windows コアコンポーネントのため、システムファイルの置換は検知されやすく、アンチチートソフトウェアにブロックされるリスクがあります。d3d11.dll - 運用の手間:すべてのアプリにファイルをコピーする必要があり、ユーザーフレンドリーではありません。
正解:DDI(デバイスドライバインターフェース)の実装
正しいアプローチは API を実装することではなく、DirectX DDIを直接実装することです。
- 仕組み:アプリケーションが
で行う「状態追跡」作業を Triton が UMD(ユーザーモードドライバ)で処理し、洗浄されたコマンドストリームを KMD(カーネルモードドライバ)へ送信します。d3d11.dll - Venus の技術基盤:KMD の開発は既に Venus プロジェクトにより完了しています。DirectX API と Vulkan が異なるため通常は別物ですが、Neptune は Venus モデルに基づいているため、高レベルなカーネルインターフェースもそのまま活用可能です。
DDI(デバイスドライバインターフェース)と実装戦略
Windows では UMD 上で DirectX API を受け付け、KMD でハードウェアを制御します。DirectX 11 の DDI 実装は難題でしたが、以下のアプローチで解決しました。
参考とした技術スタック
- Mesa:OpenGL の代替として DirectX 10 UMD を持つが、機能不足のため完全な採用は諦めた(統合事例としての価値あり)。
- VirtualBox:動作する唯一のオープンソース DirectX 11 UMD だが、DDI→バイトコード→Direct3D という中間翻訳層による互換性の問題やライセンス不整合から直接採用を断念しました。ただし、「実装されている DDI」リストなど貴重な洞察を得ました。
DDI から API への逆変換を採用する理由
VirtualBox のような「中間転送フォーマット」アプローチは避け、以下の方法をとります。
が Direct3D API を UMD DDI に変換。d3d11.dll- Triton(UMD)が DDI を再び Direct3D API に逆変換し、KMD に渡す。
- 利点:Neptune のシリアライズ済みコマンドをそのまま利用でき、ホスト側で追加の解釈処理が不要です。
- 変換の簡素さ:DDI と API はほぼ対応しており、主にハンドルマッピングと DXBC シェーダコード(DXBC→API)の変換のみ必要です。
DXBC(DirectX バイトコード)への対応
Triton は DDI から API への逆変換を行うため、シェーダーバイトコードをディスアセンブルする必要はありません。しかし、コンパイラ(FXC)が生成するメタデータの再構築が必要です。
- 処理内容:
が期待するメタデータを、渡される生 DXBC バイトコードから再構築し、ホスト DirectX レンダラーが使用するd3d11.dll
を合成します。DXContainer - 課題:この部分は試行錯誤が多く、最も脆弱性が出やすい箇所です(AI アシスタントによる処理が行われています)。
ホストレンダラでのスワップチェーン処理の進化
Linux 上ではスワップチェーンをホスト側に実装していましたが、Triton ではこのアプローチを見直す必要がありました。
- 問題点:Windows 上の DXGI は UMD と通信し、バックバッファ管理などを独自に行います。ホスト側で追加したスワップチェーンロジックは Windows 環境では無効化されます。
- 解決策:Wine ドライバ(ゲスト Neptune ドライバ)にスワップチェーンロジックを移行しました。
- ゲストがバックバッファを DMAbuf としてエクスポートし、ホストでインポートする方式へ変更。
- これにより、ホスト側の複雑性が減り、Venus の設計方針(virglrenderer をクリーンに保つ)と整合します。
macOS への移植と対応
macOS では virglrenderer を動作させる必要がありますが、共有テクスチャや共有フェンスなどの機能実装が課題です。
主要なライブラリとプロジェクト
3 つの DirectX API 実装に対応しています(いずれも Wine 向けですが、機能を拡張して利用)。
- DXVK + MoltenVK:不安定であり、互換性確保に多大な作業が必要。
- DXMT:Vulkan 層を省略し、D3D11 を直接 Metal に翻訳。Wine 向けだが、
というフォークにより共有テクスチャ/フェンスに対応しました。dxmt-native - D3DMetal (D3DMetal-native):Apple の Game Porting Toolkit 用実装(Open Source なわけではなく Swizzling/Vtable Patching を使用)。ライセンス制約がありますが、性能向上のために利用可能です。
システム間通信の工夫
virglrenderer は各コンテキストごとに独立したプロセス(
virgl_render_server)を使用するため、厳格なプロセス分離が必要です。共有テクスチャには以下の手法が検討されました。
| 手法 | メリット・デメリット |
|---|---|
| MTLSharedTextureHandle + XPC | Apple 推奨だが、QEMU/virglrenderer の fd 渡しメカニズムと互換性がない(将来的な課題)。 |
| IOSurface | グローバルハンドル共有が可能だが、廃止技術であり追加の Blitting コストが重い。 |
| CALayerHost | レイテンシが高く、共有テクスチャには不向き。 |
| shm_open + MTLBuffer (採用案) | 共有メモリオブジェクトを作成し CPU/GPU で共有。Apple Silicon (UMA) の特性を利活用。線形テクスチャ限定だが初期実装上は有効。 |
共有フェンスの工夫
描画とコンポジットのタイミング同期にはフェンスが必要です。
MTLSharedEventHandle は XPC を必要とするため、以下の工夫で回避しています。
- CPU 待避時間の最小化:フレーム完了境界でのイベント発生を期待し、レイテンシ増は 1 フェンスに制限。
- エミュレートフェンスの実装:プロデューサーが GPU で共有メモリへタイムライン値を書き込み、消費者 CPU がこれをポーリングして安全なタイミングを検知します。
macOS ビルド手順と構成要素
すべてのコンポーネントは単一のステージングプレフィックスにインストールし、環境変数で互いに接続します。
必須環境変数
export SRC=/path/to/checkouts export PREFIX=/path/to/prefix export ANGLE_INC="$SRC/WebKit/Source/ThirdParty/ANGLE/include" export ANGLE_LIB="$PREFIX/ANGLE.xcarchive/Products/usr/local/lib"
1. ANGLE と libepoxy の構築
QEMU の
-display cocoa および GL バックエンドの前提条件です。
# WebKit (ANGLE) から必要な部分のみクローン git clone --filter=tree:0 --no-checkout https://github.com/utmapp/WebKit.git "$SRC/WebKit" git -C "$SRC/WebKit" sparse-checkout init git -C "$SRC/WebKit" sparse-checkout set Source/ThirdParty/ANGLE Configurations Tools/ccache git -C "$SRC/WebKit" checkout 6a7f464047e2f6f65fe315aaad5d1ff3229cb7 # ANGLE をビルド cd "$SRC/WebKit/Source/ThirdParty/ANGLE" xcodebuild archive \ -archivePath "$PREFIX/ANGLE" \ -scheme ANGLE \ -sdk macosx \ -arch arm64 \ -configuration Release \ WEBCORE_LIBRARY_DIR=/usr/local/lib \ NORMAL_UMBRELLA_FRAMEWORKS_DIR="" \ CODE_SIGNING_ALLOWED=NO \ MACOSX_DEPLOYMENT_TARGET=11.0 # libepoxy をビルド git clone -b macos-venus https://github.com/utmapp/libepoxy.git "$SRC/libepoxy" meson setup "$SRC/libepoxy/build" "$SRC/libepoxy" \ "-Dc_args=-I$ANGLE_INC" \ -Degl=yes \ -Dx11=false \ "--prefix=$PREFIX" meson install -C "$SRC/libepoxy/build"
2. DXMT のビルド
Wine クロスビルドとして、またはネイティブビルド(単一の
libdxmt-native.dylib)として利用します。
export LLVM15=/path/to/llvm@15 git clone https://github.com/utmapp/dxmt.git "$SRC/dxmt" cd "$SRC/dxmt" meson setup build-native \ "-Dnative_llvm_path=$LLVM15" \ --buildtype=release \ "--prefix=$PREFIX" meson install -C build-native
3. d3dmetal-native のビルド
Apple Silicon 向けに x86_64 ライブラリをビルドし、Rosetta 下で動作させます。
git clone https://github.com/utmapp/d3dmetal-native.git "$SRC/d3dmetal-native" cd "$SRC/d3dmetal-native" meson setup build \ --cross-file build-macos-x86_64.txt \ -Dtests=disabled \ "--prefix=$PREFIX" meson install -C build
注意:
はバンドルされません。Game Porting Toolkit から取得するか、コンパイル時にD3DMetal.frameworkを指定します。-Ddev_framework_path=...
4. virglrenderer の構築(ユニバーサルバイナリ化)
ネイティブ ARM64 と Rosetta x86_64 の両スライスを融合します。
git clone -b macos-next https://github.com/utmapp/virglrenderer.git "$SRC/virglrenderer" # ① ネイティブ ARM64 (libdxmt-native.dylib を使用) meson setup "$SRC/virglrenderer/build-arm64" "$SRC/virglrenderer" \ "-Dc_args=-I$ANGLE_INC" \ -Dvenus=true \ -Dneptune=true \ -Drender-server-worker=process \ -Dcheck-gl-errors=false \ "--pkg-config-path=$PREFIX/lib/pkgconfig" \ "--prefix=$PREFIX" meson install -C "$SRC/virglrenderer/build-arm64" cp "$PREFIX/libexec/virgl_render_server" "$SRC/virglrenderer/virgl_render_server.arm64" # ② Rosetta x86_64 (libd3dmetal-native.dylib を使用) # pkgconfig から EGL を無効化し、x86_64 用ディレクトリを準備 cp -R "$PREFIX/lib/pkgconfig" "$PREFIX/lib/pkgconfig-x86_64" sed -i '' 's/epoxy_has_egl=1/epoxy_has_egl=0/' "$PREFIX/lib/pkgconfig-x86_64/epoxy.pc" meson setup "$SRC/virglrenderer/build-x86_64" "$SRC/virglrenderer" \ --cross-file "$SRC/d3dmetal-native/build-macos-x86_64.txt" \ "-Dc_args=-I$ANGLE_INC" \ -Dvenus=false \ -Dneptune=true \ -Dvtest=false \ -Drender-server-worker=process \ -Dcheck-gl-errors=false \ -Ddefault_library=static \ "--pkg-config-path=$PREFIX/lib/pkgconfig-x86_64" \ "--prefix=$PREFIX" meson compile -C "$SRC/virglrenderer/build-x86_64" # ③ lipo で融合 lipo -create \ "$SRC/virglrenderer/virgl_render_server.arm64" \ "$SRC/virglrenderer/build-x86_64/server/virgl_render_server" \ -output "$PREFIX/libexec/virgl_render_server"
5. QEMU の設定とインストール
Neptune 機能有効化のため、
virglrenderer が検出されるようにします。
git clone -b utm-edition https://github.com/utmapp/qemu.git "$SRC/qemu" mkdir -p "$SRC/qemu/build" && cd "$SRC/qemu/build" PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" ../configure \ "--extra-cflags=-I$ANGLE_INC" \ "--extra-ldflags=-L$ANGLE_LIB" \ "--prefix=$PREFIX" \ --target-list=aarch64-softmmu make -j"$(getconf _NPROCESSORS_ONLN)" install
6. Windows ドライバの構築
Windows マシンまたは VM で以下のソースを実行します(詳細は公式サイト参照)。
- UMD:
を使用すると簡素化されます。build-mesa - KMD: Neptune プロトコルと連携する専用インターフェースが必要です。
- 注意:開発バージョンは不安定であり、テスト環境以外でのインストールには注意が必要です。
実行と動作確認
Windows ARM64 ゲストで動作します。
sudo はブリッジドネットワークにのみ必要です。
export VM=/path/to/vm # ディスクイメージ + EFI 変数ストア export D3DMETAL=/path/to/D3DMetal.framework D3DMETAL_FRAMEWORK_PATH="$D3DMETAL" \ DYLD_FALLBACK_LIBRARY_PATH="$PREFIX/lib:$ANGLE_LIB" \ ANGLE_DEFAULT_PLATFORM=metal \ VIRGL_LOG_LEVEL=debug \ "$PREFIX/bin/qemu-system-aarch64" \ -machine virt \ -accel hvf,ipa-granule-size=0x1000 \ -cpu host \ -smp cpus=4,sockets=1,cores=4,threads=1 \ -m 4096 \ -nodefaults \ -vga none \ -device virtio-ramfb-gl,hostmem=8G,blob=true,venus=true,neptune=true \ -display cocoa,gl=es \ -drive if=pflash,format=raw,unit=0,file.filename="$PREFIX/share/qemu/edk2-aarch64-code.fd",readonly=on \ -drive if=pflash,unit=1,file.filename="$VM/efi_vars.fd" \ -device nvme,drive=disk,serial=disk,bootindex=1 \ -drive if=none,media=disk,id=disk,file.filename="$VM/windows.qcow2",discard=unmap,detect-zeroes=unmap \ -device nec-usb-xhci,id=usb-bus \ -device usb-tablet,bus=usb-bus.0 \ -device usb-kbd,bus=usb-bus.0 \ -device virtio-net-pci,netdev=net0 \ -netdev user,id=net0,hostfwd=tcp::2222-:22
グラフィックス関連引数の解説
-device virtio-ramfb-gl,hostmem=8G,blob=true,venus=true,neptune=true
: Neptune capset を広告(必須)。neptune=true
かつblob=true
: スキャンアウト用メモリ確保。hostmem
: さらにゲスト側で Vulkan (Venus) も動作させる場合のオプション。venus=true
-accel hvf,ipa-granule-size=0x1000- Venus 用の 4KiB ページ割り当てが必要になるため。
-display cocoa,gl=es- Cocoa ウィンドウを ANGLE/Metal を経由で描画。
主要な環境変数一覧
| 変数 | 効果 |
|---|---|
| QEMU が 、レンダースerver が / を見つけるパス。 |
| レンダースerver のバイナリパス。ビルド時に baked in の値がデフォルト。 |
| D3DMetal (Rosetta/x86_64) か DXMT (ネイティブ/arm64) を選択。デフォルトは D3DMetal。 |
| が参照する の場所。 |
| ホストサイドワークアラウンド(例:シェーダーシグネチャ合成)の有効/無効設定。0 なら無効。 |
/ | ホストレンダラのログレベル。debug モードは Neptune ホストモジュールの出力を表示。 |
ヒント: AI アシスタントにこのページを示し、セットアップの手順を依頼すると効率的に進めることができます。