syghの新フラグメント置き場

プログラミングTipsやコード断片の保管場所です。お絵描きもときどき載せます。

GeForceドライバー380系列のDirect3D 11バグ

3DグラフィックスとC++の研究目的で、DirectX 11 (Direct3D 11) を使った自前FBXビューアーを開発しているのですが、とある自作FBXファイル(約18,000ポリゴン程度)を開いて、カメラを回転させながら描画すると、レンダリングが停止する現象に遭遇しました。デバッグ レイヤーからは以下のようなエラーメッセージが出ます。いわゆるTDRハングアップです。

D3D11: Removing Device.
D3D11 ERROR: ID3D11Device::RemoveDevice: Device removal has been triggered for the following reason (DXGI_ERROR_DEVICE_HUNG: The Device took an unreasonable amount of time to execute its commands, or the hardware crashed/hung. As a result, the TDR (Timeout Detection and Recovery) mechanism has been triggered. The current Device Context was executing commands when the hang occurred. The application may want to respawn and fallback to less aggressive use of the display hardware). [ EXECUTION ERROR #378: DEVICE_REMOVAL_PROCESS_AT_FAULT]

具体的にどのメソッドコールやシェーダーがタイムアウトのトリガーになっているのかまでは調べ切れていないのですが、以前は同じFBXファイルをまったく問題なく表示できていました。検証した組み合わせ環境は以下の通りですが、どうやらNVIDIA GeForceドライバーを384.94に更新したことが原因のようです。Windows 7 (SP1 Platform Update) でもWindows 10でも発生します。

  • Win10 (1703) x64 + GeForce GTX 760 4GB + 384.94: hang
  • Win10 (1703) x64 + Quadro M4000 + 382.48: OK
  • Win10 (1703) x64 + Quadro M4000 + 386.01: OK

少なくともQuadro M4000では比較的新しいドライバーを適用しても問題が発生しないことを確認できています。Quadroのドライバーは基本的にGeForceよりも厳密度や品質・安定性が重視されているので当然と言えば当然かもしれません。Kepler固有の現象なのか、それともGeForceであればMaxwellPascalでも発生するのかは不明です。

Direct3D 11は現在のハイエンド3Dゲーム開発における中核ともいえるAPIで、すでに次世代ローレベルAPIであるDirect3D 12やVulkanが正式リリースされて2年ほど経つものの、アプリケーション開発のしやすさの点から言えば、いまだDirect3D 11の地位は揺るぎません。今回発見したバグは、現役のAPIに関する基本的なリグレッションなので、すでにゲーム開発者やゲーマーからNVIDIAにバグ報告が寄せられて修正されていてもいいような気がしますが、2017年12月にリリースされたドライバーでも修正されていないようです。

逆にある程度古いドライバーだとタイムアウト現象は確かに出ないのですが、古いドライバーにはセキュリティ脆弱性が潜んでいることがあるので、古いドライバーを使い続けるのも得策ではありません。もともと384.94は、重大なセキュリティ脆弱性が修正されたとかいう話だったので急遽インストールしたものです。

なお、年明け早々に大々的に報じられたCPU脆弱性Spectre/Meltdownのうち、Spectreの修正に対応した390系列のドライバーが先日公開されました。とはいってもGPU側の予測分岐機能などがシステムのセキュリティに影響を及ぼすわけではなく、たとえばWebブラウザ上で実行するJavaScriptのように、悪意のあるコードの踏み台となりえるソフトウェアプログラムが含まれていたせいか、もしくはパッチ適用によるシステム低速化を緩和させる目的で、おそらく今回の修正対象となったものと思われます。通例ドライバーはシステムメモリにカーネルモードでアクセスできるため、対策も必要となるのでしょう。近いうちに390系列も試す予定です(ただし人柱になるのは御免こうむりたいので、しばらくは様子見)。

余談:ドライバー更新時の問題

バージョン番号の新しいNVIDIAドライバーをインストール(バージョンアップ)する場合は通例上書きインストールできるものなのですが、検証などのためにロールバック(バージョンダウン)しなければならない場合、まず現在のドライバーをアンインストールするのが常套手段です。
しかし、NVIDIAのグラフィックスドライバーおよびHDオーディオドライバー*1をコントロールパネルからアンインストールした後、Windowsを再起動すると、Windowsによって勝手にハードウェアの認識と古いデフォルトドライバーのインストールが始まってしまうのが厄介です(しかも結構時間がかかる)。マウスやキーボード、フラッシュメモリなどのUSBデバイスに関しては、こういったプラグ&プレイによる自動認識動作は非常にありがたいのですが、グラフィックスやオーディオまで勝手にデフォルトドライバーをインストールされると非常に困ります。
なお、XPまではグラフィックスとオーディオのドライバーは自動インストールされず、OSインストール直後はハードウェアアクセラレーションが使えない状態となるのがデフォルト動作になっていました。このグラフィックスとオーディオのデフォルトドライバー自動インストール動作はWindows Vista以降で実装されたものです。ドライバーのインストール作業の方法が分からないビギナーにとってはありがたいものなのかもしれませんが、ドライバーバージョンを完全に自分でコントロールしたいパワーユーザーにとっては単なるおせっかいでしかない迷惑機能です。「デバイスのインストール設定」でWindows Update経由のドライバーインストールを無効化していても抑制できない模様で、またローカルのどこかにデフォルトドライバーのインストーラーパッケージを隠し持っているためか、ネットワークを切断していても抑制できません。どうやら抑制するにはレジストリ操作が必要らしく、面倒なので今回はあきらめることにしました。

*1:HDMIなど、グラフィックス以外にオーディオ伝送も可能とするインターフェイスが存在します。そういったものをグラフィックスデバイス経由でサポートする目的で、NVIDIAのドライバースイートにはオーディオドライバーも含まれています。