世界を動かす技術を、日本語で。

DXGIデバッグ: マイクロソフトが私をリストに載せた

概要

  • Space Station 14 のARM64版で発生したクラッシュの詳細なデバッグ記録。
  • SDL 初期化直後に空のログでクラッシュ、WinDbgも混乱する現象。
  • DXGIのdetour と「ウィンドウゲーム最適化」機能が原因。
  • 実行ファイル名が「SS14.Loader.exe」の場合のみ発生。
  • Microsoftのゲーム互換リスト による影響と対処法。

Space Station 14がARM64でANGLE利用時にクラッシュする理由

  • Space Station 14 のARM64ビルド作業中、 Windows ARM64 環境でのみゲームクライアントがクラッシュする現象を確認。
  • SDL初期化直後 にログが途切れ、WinDbgでもスタックトレース取得や.NETデバッグが困難な状況。
  • USER32!GetDC 関数呼び出し時に不正命令(illegal instruction)でクラッシュ、WinDbgの「ARM64EC」モードによる混乱も発生。
    • WinDbgはx64ネイティブなSS14.Launcher.exeからデバッグを開始すると、子プロセス(ARM64ネイティブ)で混乱し、スタックトレース表示やC#デバッグが機能しなくなる。
    • SS14.Launcher.exeを直接ARM64で起動し直すことでエラーが解消。
  • SDL3.dll のローカルビルド版でソース追跡し、クラッシュ発生箇所を特定。
  • GetDC() は本来安全なWin32 APIだが、 DXGI!My_GetDC によるdetour(ランタイム書き換え)が行われていることを発見。

DXGIと「ウィンドウゲーム最適化」機能によるdetourの影響

  • DXGI はDirectX 10以降の基盤API、Windows 11では「ウィンドウゲーム最適化」機能でflip model強制切替を実施。
    • これにより、古いゲームやbitblt swapchain利用ゲームで互換性維持のためdetourが挿入される仕様。
  • detourの実装ミスかARM64固有の問題で、 GetDC() 呼び出し時にクラッシュ発生。
  • Windows設定で「ウィンドウゲーム最適化」機能を無効化 するとクラッシュが解消。
  • SS14 はANGLE経由でswapchainを生成しており、flip model未対応。
    • ANGLE側の制約により、独自でswapchain管理が困難。

実行ファイル名によるMicrosoftの互換リスト判定

  • クラッシュは「SS14.Loader.exe」の時のみ発生
    • 開発環境(別名実行)では発生しないため、Microsoftの「互換リスト」判定が原因。
  • Microsoftは特定のゲーム名でのみ「ウィンドウゲーム最適化」を強制適用
    • ARM64対応ゲームが少なく、リストに載ったことで副作用が発生。
  • リスト入りの経緯は不明、だがWindowsに同梱されている互換リストが直接影響。

OpenGL on Windows ARM64とANGLE利用の背景

  • 従来のOpenGL はNvidia/AMD/Intelのドライバ依存、Snapdragon XではMicrosoftの「OpenGL on D3D12」ドライバ(Mesaベース)を利用。
  • Space Station 14 では「OpenGL on D3D12」ドライバに深刻なグラフィックバグがあり、 ANGLE (OpenGL→D3D変換レイヤ)を強制使用。
  • ANGLE利用時のswapchain制御制約 により、最新のDirectX最適化機能との相性問題が発生。

まとめ・対策

  • Space Station 14 のARM64版で発生するクラッシュは、「ウィンドウゲーム最適化」機能+互換リスト判定が主因。
  • 実行ファイル名変更 やWindows側設定変更で暫定回避可能。
  • Microsoftのリスト運用・ARM64対応状況 による副作用への注意が必要。
  • ANGLEやOpenGL on D3D12の制約 も移植時の重要課題。

Hackerたちの意見

タイトルはちょっと釣りっぽいけど、いい記事だね ;) これはOSからGPUドライバーまで、APIレベルのソフトウェアで広まってる話だよ。どれくらい文書化されてるかは分からないけど、exeの名前をQuakeとかFIFAとかMinecraftに変えると面白いことが見つかるかも。

TrickNvidiaDriversForPerformance_javaw.exe.minecraft.exe

昔、Raymond Chenの「The Old New Thing」ブログを読んでた人には驚きじゃない話だよ。Microsoftがこういうトリックで後方互換性や前方互換性を高めるために、かなり absurdなことをやってたからね。この開発者にとっては一つのニッチなケースで不幸な状況になったかもしれないけど、全体的には、基盤となるAPIがどれだけ古くなっても、ほとんどのソフトウェアがそのまま動くのはユーザーにとってすごく助かることだよね(何十年もそうだし)。

2001年、ATIはQuake 3 Arenaを実行しているときに、意図的にすべてのテクスチャをぼかしていたことが明らかになって、ちょっとした騒ぎになったんだ。すべての文字列を「Quake」から「Quack」に変える(実行ファイルの名前も変える)ことで、劣化したミップマップが無効になって、グラフィックスが改善されたんだ(フレームレートも下がったけど)。 https://web.archive.org/web/20190728022442/https://techrepor...

ちょっとクリックベイトっぽいけど、もし会社が俺のソフトウェアの名前をOSに付属する不透明なリストに載せて、俺のソフトが期待通りに動かなくなった上に、何も教えてくれなかったら、こいつよりもずっと怒ると思う。

こういう話を読むと、Windows開発をやったことがない自分はラッキーだなって思う。

心配しないで、OpenGLやVulkanでも同じ体験ができるよ。特定のOSのバージョンやOEMドライバーによるけどね。

こういう通りすがりのコメントは理解できないな。競合のために開発するのが簡単だとか、単純だとかじゃないし。著者は、さまざまなサードパーティライブラリを使った、クロス言語(管理されたものとネイティブの両方)、クロスアーキテクチャのビデオゲームをデバッグしてるんだ。Windowsのグラフィックススタックが複雑なのは、そのためにメンテナンスされてないクローズドソースのプログラムをサポートする必要があるからなんだ。特定のプログラムを最適化するための互換性レイヤーが、著者のプログラムもマスターリストに引っかかっちゃったってわけ。

私もWindowsでこういうことに遭遇したことがあるけど、ほとんどの開発者はこういう問題には直面しないってことを強調したい。これは、コンパイラのバグを見つけるのと同じようなもので、確かに遭遇することもあるけど、一般的には遭遇する問題はコンパイラやOSが原因じゃないことが多いんだ。OSやコンパイラの問題は、10年前よりも今の方が一般的なのかな?可能性はあるけど、逆に少なくなっているかもしれないね。ドライバのバグには何度も遭遇したことがあるけど、OSのバグよりも多いかもしれない。それは本当にイライラする。

各オペレーティングシステムには、そういう余計な層があって、時にはデバッグが難しくなることもあるんだよね。

Windowsでこれらの互換性リストを無効にして、実際に問題やクラッシュを開発者に報告できるようにしたいな。でも、これって自分にとってはすごくLinux的な考え方かも。

Linuxカーネルには、個々のマザーボードやシステム、デバイスのための大きなハックがたくさんあるんだ。残念ながら、どのレベルでもこういうことが起きてる。最近になって、あなたの64コアCPUが初期ブート時に8086のふりをするのをやめたばかりなんだよね。

これは、DirectXグラフィックスチームの全体的に奇妙な戦略によるもので、OS内のAPI呼び出しをデトゥールして多くの最適化や機能強化を実装しているんだ。要するに、Windows OSが自分自身をパッチして機能を実装しているってこと。残念ながら、これはAppCompatシステムのようなコアOSのサポートなしで行われているから、通常のユーザースペースのパッチと同じような問題が出てくるんだよね。今回の場合、DXGIで使われているデトゥールコードは、現在のWindows 11 ARM64のPAC対応関数プロローグをサポートできないんだ。これはOPのシナリオだけに限らず、DirectXを使っているネイティブARM64プログラムでAuto Super Resolution(AutoSR)を有効にしようとすると、EnumDisplaySettings()で同じようにクラッシュすることもあるよ。言及されているフルスクリーン最適化には歴史があるんだ。フレームごとにフルスクリーンコピーを削除してパフォーマンスや効率を上げるという意図は良いんだけど、いくつか問題があった。Windows 10で最初に実装されたとき、DirectX 9のアプリのフルスクリーンモードが壊れたのは、アプリケーションから提供されたウィンドウハンドルに関して誤った仮定をしたからなんだ。でも、これに対処するのはフラストレーションが溜まったよ。メカニズムはほとんど文書化されていなくて、手動のユーザー互換チェックボックス以外にオプトアウトの方法がなかったからね。Microsoftが何をしたのか、どうやって回避するかを理解するのに、プログラムのコアウィンドウ部分を数日間分解する必要があったし、Windowsチームがそれを修正するのに数ヶ月かかったんだ。

この戦略はここに説明されていて、ゲーム開発者がDirectXをOSのバージョンから切り離したいと望んでいることから来ているんだ。 https://devblogs.microsoft.com/directx/gettingstarted-dx12ag...

この場合、DXGIが使っているDetoursコードは、現在のWindows 11 ARM64のPAC対応関数プロローグをサポートできないみたい。マイクロソフトは、そもそもARMでパッチを当てる必要がないようにできたはずだよね?つまり、彼らが使っているゲーティングがARMでは動かないようにすればよかったのに。

いや、これをやった人には本当に敬意を表したい。WindowsでネイティブARM64でゲームを動かすために、すごく努力してるよね。ARM64のWindowsデバイスでゲームをしようとしている人はどれくらいいるんだろう?

最近、Surface Pro 11でSilksongをプレイしたけど、問題なく動いたよ。2Dゲームでグラフィック要件が少ないから、ちょっと違うケースだけどね。

ChromeOSの学校用ノートパソコンでゲームをやりたいって人が結構いるんだけど、これもARMベースなんだよね。

プログラムがSS14.Loader.exeと呼ばれるときだけ発生する。これはMicrosoftだけじゃなくて、グラフィックドライバなどでも起こることだよ。正直、こういうリストを避けるためにビルド時にexe名にGUIDを使うことを考えることもあるよ :-P。

双方に影響があるよね! https://devblogs.microsoft.com/oldnewthing/20040211-00/?p=40...

もちろん、問題はファイル名だよね。最初の段落から、何人かの古いゲーム開発者が「彼のゲーム、game.exeって名前だったの?」って思い浮かべるのが見えるよ。

彼はquack.exeを試してみるべきだね。

マイクロソフトがプログラムの実行を実行ファイルのファイル名に基づいて変更するなんて信じられない。もしかしたら、同じファイル名の別のゲームがあって、このゲームが巻き込まれたのかもしれない。これはクレイジーだよ。

正確にファイル名のせいかは分からないけど、似たような話があるよ。> Windows 3.x用のSimCityのオリジナル版を作ったジョン・ロスが、メモリを解放したばかりのところを読み込むバグをうっかり残してしまったって言ってた。そう、Windows 3.xでは問題なく動いてたんだ。メモリはどこにも行かなかったからね。驚くべきことに、Windows 95のベータ版ではSimCityがテストで動かなかった。マイクロソフトはそのバグを追跡して、SimCityを探す特定のコードをWindows 95に追加したんだ。SimCityが動いているのを見つけると、メモリアロケータを特別なモードで動かして、すぐにメモリを解放しないようにした。それが、Windows 95にアップグレードする気にさせた互換性への執着なんだよ。 https://www.joelonsoftware.com/2000/05/24/strategy-letter-ii...

exeファイル名に基づいて処理をするのは、Windowsではかなり標準的なことだよ。実際、「Image File Execution Options」っていうレジストリキーがあって、そこにexeの名前のサブキーを追加して、デフォルトでどのインタープリターで起動するかを制御する値を追加できるんだ。Linuxのbinfmt登録に似てるけど、マジックバイトではなくファイル名に基づいてる。手動で起動できない特定のサブプロセスにデバッガを付けるのにとても便利だよ、プロセス名が十分にユニークならね。 https://techcommunity.microsoft.com/blog/askperf/two-minute-...

アプリの互換性サポートにはこれがたくさんあるよ。これは、すでに出荷したプログラムに対してベンダーがパッチを当てることが期待されていなかった時代から来てるんだ。だから、SimCityを動かしているのを見つけたら、その動作を維持するためのハックを有効にするんだよ。そして、SimCityのCD-ROMは決してアップデートされることはないんだ。

これは、後方互換性の話があるすべてのプラットフォームに共通してるね。

Microsoftだけじゃないよ。NvidiaやAMDのWindowsドライバーも同じことしてるし、Mesaにもプログラム特有のフラグのリストがいくつかあるよ。https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/uti...

Protonにも結構あるけど、Steamのappidごとに分かれてるね。https://github.com/ValveSoftware/Proton/blob/proton_10.0/pro...

ファイル名に基づいて実行動作を変えるのは、Linux環境でもよくあることだよね。いくつかの例を挙げると、 1. BusyBoxは、どのシンボリックリンクを使って呼び出すかで異なるコマンドを実行する単一の実行ファイル 2. Bashは「sh」として呼び出されると互換モードになる 3. 「ping」は「ping4」や「ping6」として呼び出せる 4. gitのサブコマンドのいくつかは、メインの実行ファイルへのシンボリックリンク 5. Clangは「clang++」として呼び出されるとC++モードに切り替わる 6. AppArmorのプロファイルはファイルパスに応じてアクティブになる

「マイクロソフトが実行ファイルのファイル名に基づいてプログラムの実行を変更するなんて信じられない。」 これは、マイクロソフトが数十年にわたって互換性を管理してきた主な方法の一つだよ。Windows 95では、人気のゲームがWindowsで動くようにファイル名に基づくハックがあったんだ。レイモンド・チェンはこのことについての本を一冊書いてるし、無料の章もあるよ!(まさにこれについての!) https://ptgmedia.pearsoncmg.com/images/9780321440303/samplec... 彼らはWing CommanderやSimcity、さらにはMicrosoft Office自体のために大規模なハックをしなきゃいけなかったんだ(Windows 2000のソースコードのリークの中には、Officeチームを無能でバカだと罵る部分がかなりあるくらい)。 >「我々が知る限り、同じファイル名の別のゲームがあって、このゲームが巻き込まれた可能性がある。マイクロソフトは30年間これをやってきたけど、「プログラムが間違った互換性ハックを受けた」っていうケースは一つも知らないよ!報告されることはあまりないだろうから、あまり良い証拠ではないけど、これは大成功だね。」

あなたはユニークな人だね。グラフィックスアセンブリやWindows APIに詳しいし、ゲームを書くクリエイティビティも持ってる。絵を描くためのサイドスキルも必要だし。この膨大な知識は珍しいよ。それについて書く能力も普通じゃない。あなたは本当に才能があって、努力家だね。尊敬するよ。

それだけじゃなくて、彼はゲームのインフラのシステム管理もやってるし、トラブルが多いコミュニティの管理もしてるんだよね。裏で何が起こってるかは分からないけど、正直、見た中で最高の開発者の一人だよ。

「壊れたAPIで作業を続けるより、OpenGLを捨てる方が脳のリソースを使いたい」 「この壊れたAPI」って、ライブラリのモンキーパッチに関係してるの?それに、Linuxのライブラリは一般的にそんなハックを使わないから、ラッキーだよね。本当に悪いプログラミングスタイルだと思う。レガシーゲームも、古いソフトでうまく動いてたら、bitbltで普通に動くはずだよ。

作者を知っていると、OpenGL/EGLやそれに似たものを指しているに違いないね。彼はOpenGLがクソだって愚痴って、DirectXがトーストにバターが塗られた以来の最高のものだって言ってた。