参考情報

手順書 (index.html) には書かなかった「なぜそうするのか」「うまくいかなかった方法」「測定結果」「困ったときの詳しい対処」をまとめています。作業中に読む必要はありません。

仕組み測定結果トラブルシューティング試して駄目だった方法変更される設定の一覧

1なぜこの構成なのか — 最終的に分かった結論

① vBIOS は必須。UEFI の GOP ROM は不要

VM に vBIOS を渡さないと GPU はコード 43 になりました (実測)。HDMI 音声に GOP ROM を付けても付けなくても結果は同じでした。

② 渡すのは GPU (.0) と HDMI 音声 (.1) だけ

同じスロットの USB コントローラには、NanoKVM のキーボードが載っていました。丸ごと渡すとホストが KVM から操作できなくなるため、機能を個別に指定します。

③ リセットバグは「シャットダウン前に無効化」で回避

AMD の内蔵 GPU は VM を止めたあと初期化されず、次の起動でコード 43 になります。Windows のシャットダウン時に GPU を無効化し、起動時に有効化し直すと、繰り返しても OK でした。

④ 普段は QXL を主画面にする

SPICE で見えるのは QXL の画面だけです。GPU の仮想モニタを同時に有効にすると、SPICE エージェントが混乱してマウスが動かなくなります。

① vBIOS とコード 43 (詳細を見る)
  • 内蔵 GPU には /sys/bus/pci/devices/…/rom がありません。AMD のファームウェアは vBIOS を ACPI の VFCT テーブルに入れているので、そこから取り出します (extract-vbios-from-vfct.py・16,896 バイト・先頭が 55 AA)。
  • VM には hostpci0: …,romfile=ファイル名 で渡します。ファイルは /usr/share/kvm/ に置く必要があります (ファイル名だけ指定できる)。
  • 実測: vBIOS あり → コード 0 / vBIOS なし (他は同じ) → コード 43。
  • 途中で「HDMI 音声に AMDGopDriver.rom を付ける」方法も試しましたが、結果に影響しませんでした。最初のコード 43 の本当の原因は、直前の BSOD で GPU が汚れていたことと考えられます。
③ AMD リセットバグの詳細 (詳細を見る)
  • 症状: ホストを起動したあとの 最初の VM 起動だけ正常。VM を止めて起動し直すとコード 43。
  • PVE の起動ログに failed to reset PCI device … Inappropriate ioctl for device と出ます。GPU が FLR (機能単位のリセット) に対応していないためで、VM の起動は続きます (害のないメッセージ)。
  • 有効だった方法: ゲストの シャットダウンスクリプト で GPU を無効化 → 次の起動の スタートアップタスク で有効化 (コード 22 を検知)。qm shutdown / qm reboot / Windows の再起動、いずれの繰り返しでも OK。
  • 限界: 強制停止 (qm stop)・クラッシュ・BSOD ではスクリプトが走らず、次の起動はコード 43。その状態からは、正常な停止・起動を繰り返しても戻りません。ホストの再起動で戻ります。
  • 高速スタートアップ (休止状態を使うシャットダウン) はスクリプトを走らせないことがあるため powercfg /hibernate off にしています。
④ SPICE のマウスが効かなくなる原因 (詳細を見る)
  • 古い SPICE エージェントは「モニタの付いたディスプレイが 2 種類以上ある」と、画面レイアウトを管理しなくなり、マウスの位置変換が壊れます。パススルーした GPU の仮想モニタ (AMD vDisplay) がこれに当たります。ログ (C:\Windows\Temp\vdagent.log) に #qxls 1 #others 1 と出ていたら該当です。
  • 修正は上流で 2024 年 8 月に入っています (「モニタが接続されていないディスプレイを無視する」)。この手順では、その修正を含むコミュニティ版 (nefarius/vd_agent 0.13.0) を使います。
  • ただし GPU の仮想モニタが 有効 だと (たとえデスクトップに使っていなくても) 数えられてしまうので、SPICE モードでは 無効化 します。
  • 古い「SPICE Guest Tools」のエージェントが同居すると、2 つのエージェントが同じ通信ポートを取り合ってカーソルが消えます。古い方のサービス vdservice は無効化します。
  • モード切替のたびに spice-agent サービスを再起動するのは、エージェントが画面の組み合わせを起動時にしか読み直さないためです。

Blender はなぜ遅くなり、「GPU fast」でなぜ速くなるのか

SPICE モードとストリームモード
図A 2 つの表示モード
結論 (測定済み)

遅いのは 3D の計算ではなく、絵を SPICE の画面 (QXL) に渡す部分です。Blender の 3D ビューの描画自体は約 0.01 ms でした。

  1. SPICE の画面 (QXL) は「表示専用」で、描画の機能がありません。Windows のデスクトップ合成 (dwm.exe) は、GPU ではなく ソフトウェア描画 (Microsoft Basic Render Driver) で動きます。GPU が描いた絵は毎フレーム、別のアダプタを経由して合成側に渡されます。Vulkan や DirectX の「flip 方式」の表示では、この受け渡しが非常に遅く、1 回約 105 ms / 百万画素かかりました。

  2. OpenGL は、ウィンドウを作った画面のドライバで決まります。QXL の画面で作ると Windows 標準の OpenGL 1.1 になり、Blender は「OpenGL 4.3 以上が必要」と言って起動できません。そのため、普通に使うと遅い Vulkan しか選べませんでした。

  3. GPU の画面で OpenGL のウィンドウを作ると、AMD の OpenGL 4.6 ドライバが使われます。そのあとデスクトップを SPICE に戻しても AMD のままで、従来の方式 (blt) の表示は同じ QXL の画面でも約 7 ms で済みました。新しく開いたウィンドウも同様でした。

  4. これを自動化したのが「Blender (GPU fast)」です。表示を GPU 側にする → Blender 起動 → メインループが動いたら目印のファイル (blender-ready.py が作る) を確認 → SPICE に戻す、という流れです。

ストリームモード (Moonlight) で速い理由と、接続前に切り替える理由 (詳細を見る)
  • ストリームモードではデスクトップそのものが GPU の仮想モニタ上にあるので、合成も描画も GPU で完結します (画面更新は約 3 ms)。映像は GPU のエンコーダ (AMF) で圧縮して PC に送ります。
  • Sunshine は接続のたびに使えるエンコーダを探し直し、その「後」に接続時のコマンド (表示モード切替) を実行します。QXL だけの画面で探すと GPU が見えず、CPU の libx264 になります。GPU の画面が有効なときに探すと h264_amf / hevc_amf / av1_amf が見つかります。このため、PC のスクリプトで先にストリームモードにしてから Moonlight を起動します。
  • Moonlight でセッションを終了 (Ctrl+Alt+Shift+Q) すると、Sunshine が「アプリ終了時のコマンド」(SPICE モードへ) を実行します。プロセスを強制終了した場合は実行されないことがあります。

2測定結果

速度の比較
図B Blender の画面更新 1 回あたりの時間
条件 (Blender 5.2.2)画面全パネル描画+表示の 1 回あたり
SPICE モード・Vulkan (普通に起動)1692x1073約 222 ms
同・小さいウィンドウ1280x720 / 1024x576 / 900x600約 119 / 84 / 77 ms
3D ビューの描画のみ (表示なし)—約 0.01 ms
全パネルの描画 (表示なし)—約 1.1〜1.4 ms
GPU fast (OpenGL を先に GPU 側で起動 → SPICE に戻す)1692x1073約 7 ms (新規ウィンドウも約 7 ms)
ストリームモード・OpenGL1920x1080約 3 ms
ストリームモード・Vulkan1920x1080約 19.5 ms
Blender を使わない DirectX 11 のテスト (詳細を見る)
表示先 / 方式640x400900x6001692x1000
GPU で描いて QXL の画面のウィンドウへ (flip 方式)34 ms62 ms183 ms
同 (従来の blt 方式)3.9 ms9.7 ms25〜275 ms (ばらつき大)
GPU 自身の画面のウィンドウへ0.1〜0.4 ms
(参考) ソフトウェア描画 (WARP) を QXL へ10.9 ms26.6 ms45.5 ms

GPU のメモリから CPU への読み戻しは約 8 GB/s で、メモリ帯域や IOMMU が原因ではありませんでした。

その他: FINAL FANTASY XV ベンチマーク (標準画質) はスコア約 2000、GPU 使用率 約 70% (ユーザー報告)。Unity の簡単なシーン (キューブ 1 個) は遅延なく表示。

3トラブルシューティング

症状考えられる原因確認と対処
コード 43 (ドライバ導入直後・ホスト起動直後)vBIOS (romfile) が渡っていない / 直前の強制停止・BSOD で GPU が汚れている qm showcmd VMID --pretty | grep vfio-pci に romfile=/usr/share/kvm/….rom があるか。無ければ ./02-add-gpu-to-vm.sh をやり直す。あれば VM を止めてホスト再起動→ VM 起動
コード 43 (VM を止めて起動し直した後)シャットダウンスクリプトが走っていない (強制停止・高速スタートアップ・スクリプト未登録) VM で Get-Content C:\ProgramData\gpu-reset-fix\log.txt に shutdown: disabling GPU があるか。無ければ install-all.ps1 を再実行し、gpedit.msc でシャットダウンスクリプトを確認。ホスト再起動で復旧
ホスト再起動後も amdgpu が GPU を使っているvfio が initramfs に入っていない / vfio.conf の id が違う lsinitramfs /boot/initrd.img-$(uname -r) | grep vfio で vfio-pci.ko が出るか。/etc/initramfs-tools/modules に 3 行あるか。dmesg | grep -i vfio。01-setup-vfio.sh をもう一度実行して再起動
qm start がエラー / VM が起動しないGPU がまだ vfio-pci でない / 別の VM が GPU を使っている lspci -nnk -s GPU_ADDR。GPU は 1 台の VM にしか渡せません
ホスト再起動で BIOS の青い画面で止まる機種の BIOS 機能 (検証に使ったミニ PC で確認) ホストの画面 (KVM) で Continue boot / Always continue boot を選ぶ
NanoKVM などのキーボードが効かなくなったKVM が載っている USB コントローラ (.3 など) を VM に渡した hostpci には .0 と .1 だけを指定する (All Functions を使わない)
SPICE のマウスが効かない・カーソルが消える古い SPICE エージェント / 2 つのエージェントが同居 / GPU の仮想モニタが有効 C:\Windows\Temp\vdagent.log の最後が log_version::0.13.0.0 と #others 0 か。違えば install-spice-agent.ps1 と schtasks /run /tn GpuMode-spice
SPICE の画面が黒いままストリームモードのまま (Moonlight を強制終了した等) ssh WINUSER@VM_IP schtasks /run /tn GpuMode-spice。ログイン 25 秒後にも自動で戻る
Blender が「OpenGL 4.3 以上」と出て起動しないSPICE の画面 (QXL) で OpenGL を作ろうとしている 「Blender (GPU fast)」で起動する。または --gpu-backend vulkan (遅いが動く)
Blender が数秒待たされるSPICE モードで Vulkan 起動している いったん Blender を閉じて「Blender (GPU fast)」で開き直す
「Blender (GPU fast)」で Blender が出ないBlender の場所が変わった・主ループの目印が出ない C:\ProgramData\gpu-reset-fix\launcher.log を見る (Blender not found / blender main loop ready: False)
Windows Update のあと青い画面 / GPU が変古い AMD ドライバが自動で入った VM を止めてホスト再起動 → 起動 → install-amd-driver.ps1
Moonlight の映像が真っ黒・帯状に崩れる(推定) クライアント PC が GPU の無い仮想マシンで、ソフトウェアデコード・描画になっている GPU のある実機 PC の Moonlight で試す。この環境では実機 PC で正常に表示されました
Sunshine の PIN 送信で CSRF Protection Error別の PC のブラウザは、許可リストに無いと拒否される .\install-sunshine.ps1 -SkipInstall -AllowedOrigin https://開いたアドレス:47990
ペアリングが Incorrect PIN / 409 … already existsPIN の入力違い・古い途中状態が残っている VM で Sunshine サービスを再起動 → Moonlight で追加し直す (Moonlight の登録を消す場合は PC のレジストリ HKCU\Software\Moonlight Game Streaming Project\Moonlight\hosts)
配信が CPU エンコード (libx264) になるストリームモードになる前に Moonlight が接続した Start-Blender-Stream.cmd を使う。Sunshine のログ (C:\Program Files\Sunshine\config\sunshine.log) の Found H.264 encoder を確認

4試して駄目だった方法 (結論として採用しなかったもの)

方法結果
echo 1 > /sys/bus/pci/devices/…/reset で GPU をリセット失敗 (Inappropriate ioctl for device)。同じバスの他の機能がホストで使用中のため
VM 停止中にホストの amdgpu を GPU に付けて初期化し、vfio に戻す失敗 (PSP firmware loading failed)。ホストはフリーズせず vfio に戻せたが、初期化の役には立たなかった
バス上の全機能 (USB を含む) を vfio に渡して、バス全体をリセットNanoKVM のキーボードが載る USB を失うため不採用 (試していません)
vendor-reset などのカーネルモジュール試していません
HDMI 音声に UEFI GOP ROM (AMDGopDriver.rom) を付ける不要。付けても付けなくても同じ結果
QXL を無効にして GPU の仮想モニタだけにする (常時)OpenGL は GPU で動くが SPICE が黒くなる → 「ストリームモード」としてだけ採用
QXL と GPU の仮想モニタを同時に有効 (拡張)GPU 側の画面は速いが、SPICE にはその画面が映らず、SPICE のマウスも壊れる
QXL と GPU の仮想モニタを「複製」Windows が拒否 (SetDisplayConfig エラー 87)
Windows の「グラフィックの設定 → 高パフォーマンス」を Blender に設定して OpenGL を GPU にQXL が主画面のままでは効かない (OpenGL は起動できない)
RDP で使う動作はするが、操作が遅い (ユーザーの感想)。SPICE を優先
Sunshine の画面取得を capture = wgc に変更サービスとして動かすと使えない (0x80070424)
Sunshine をサービスではなくユーザーのセッションで起動接続時の表示モード切替コマンドが error 5 で失敗
カーネルオプション amd_iommu=on不要 (カーネルが Unknown option と表示)。BIOS の IOMMU 設定だけでよい。iommu=pt は性能のために付ける
AMD のインストーラを VM で直接実行「AMD 製品ではない」と判定されることがあるため、ドライバだけ取り出して pnputil で導入する方式にした

5変更される設定の一覧 (透明性のために)

PVE ホスト
  • /etc/modprobe.d/vfio.conf (新規)
  • /etc/modules・/etc/initramfs-tools/modules (3 行追加)
  • /etc/default/grub (iommu=pt 追加)
  • initramfs の再生成
  • /usr/share/kvm/vbios_….rom (新規)
  • VM の設定 (hostpci0/1)
  • バックアップ: /root/gpu-passthrough-backup-…
VM Windows
  • AMD ディスプレイドライバ (pnputil)
  • OpenSSH サーバー・ファイアウォール規則
  • SPICE エージェント 0.13.0 / 旧 vdservice を無効化
  • グループポリシーのシャットダウンスクリプト
  • タスク: GpuResetFix-Startup / GpuMode-spice / GpuMode-stream / GpuMode-spice-onlogon
  • 高速スタートアップ (休止) を無効
  • C:\ProgramData\gpu-reset-fix\・デスクトップのショートカット
  • (任意) Sunshine サービス・apps.json・sunshine.conf
PC あなたの PC
  • SSH 鍵 (~\.ssh\id_ed25519)
  • (任意) Moonlight (%LOCALAPPDATA%\Programs\Moonlight) とペアリング情報 (レジストリ)
  • (任意) Start-Blender-Stream スクリプト
  • 一時的な C:\amd-extract (終わったら削除してよい)

6ログと確認コマンド

見たいものどこ / コマンド
GPU のリセット対策の動きVM: C:\ProgramData\gpu-reset-fix\log.txt
表示モードの切替VM: C:\ProgramData\gpu-reset-fix\mode.log (done: の行に、いまのモニタ構成が出る)
「GPU fast」ショートカットの動きVM: C:\ProgramData\gpu-reset-fix\launcher.log
SPICE エージェントVM: C:\Windows\Temp\vdagent.log (#qxls 1 #others 0 が正常)
SunshineVM: C:\Program Files\Sunshine\config\sunshine.log
GPU の状態 (VM)Get-PnpDevice -Class Display | Format-Table FriendlyName,Status
GPU の状態 (ホスト)lspci -nnk -s GPU_ADDR
VM に渡った設定qm showcmd VMID --pretty | grep -A2 vfio-pci
VM の画面だけ取りたいときホスト: echo "screendump /tmp/s.ppm" | qm monitor VMID (SPICE や noVNC が固まっていても取れる)

7未検証・制限

8安全面の注意

9用語集

用語意味
PCI パススルーPC の部品 (ここでは GPU) を、ホストではなく VM に直接つなぐ仕組み。VM はその部品を専用で使えます
IOMMU (AMD-Vi)パススルーに必要な CPU の機能。BIOS で有効にします
vfio-pci部品をホストのドライバから切り離して、VM に渡せる状態にする Linux のドライバ
vBIOS / VFCTGPU のビデオ BIOS。内蔵 GPU では ACPI の VFCT テーブルから取り出します
リセットバグ / FLRAMD の GPU は VM を止めたあとにリセットされず、次の起動でコード 43 になる問題。FLR は PCI のリセット機能で、この GPU は非対応
コード 43Windows のデバイス マネージャーで「デバイスが問題を報告したため停止」の意味。このときは GPU が初期化できていません
SPICE / QXLVM の画面をネットワーク越しに見るための仕組み (SPICE) と、その仮想ディスプレイ (QXL)
vd_agent (SPICE エージェント)VM の中で動き、マウスの位置合わせ・解像度・クリップボードを SPICE と連携するソフト
Sunshine / MoonlightPC の画面を GPU で圧縮して LAN で送る仕組み (Sunshine=送る側 / Moonlight=見る側)
AMFAMD GPU の動画エンコーダ機能
OpenGL / Vulkan / DirectX3D 描画の API。Blender は OpenGL と Vulkan に対応しています
DWMWindows のデスクトップ合成 (dwm.exe)。すべてのウィンドウをまとめて 1 枚の画面にします
GPU の仮想モニタ (AMD vDisplay)モニタが無くても GPU が自分で作る、仮想のモニタ。ストリームモードで使います