またカスタムビルド

どうしてもエディタとしてVisual Studioを使いたいPocolです。

一番簡単なカスタムビルドのメモです。
.vcxprojをテキストエディタで開いて,一番下のほうに次ような感じでコマンドを挿入します。

  </ImportGroup>
  <Target Name="Build">
      <Exec Command="call build.bat" />
  </Target>
  <Target Name="Clean">
      <Exec Command="call clean.bat" />
  </Target>
</Project>

ちなみにExecタスクのドキュメントは下記ですので,細かい設定を追加した場合は下記を参考にしてください.
MSBuildリファレンス > タスクリファレンス > Execタスク
https://learn.microsoft.com/ja-jp/visualstudio/msbuild/exec-task?view=vs-2022

Visual Studio上からリビルドを実行した場合は,Clean —> Build の順番で呼び出しされます。
もしリビルド自体をカスタマイズしたいなら

  <Target Name="Rebuild">
    <Exec Command="call rebuild.bat" />
  </Target>

とやってあれば,自前にリビルドコマンドに変更できます。

実行時のコマンドのカスタマイズは,通常のVCと同じようにプロパティから変更すれば良いと思うので,それでやればよいかと思います。
…というわけでカスタムビルドのメモ書きでした。

どっかで

クリックしてtede-msbuild-2.0.pdfにアクセス

とか

あたりを参考にもうちょいちゃんとしたものを今後改造してみたいと思います。

DREDとAftermathのサンプルプログラムを作りました。

こんばんわんわん、Pocolです。

X(旧Tiwtter)でも書いたのですが,DRED(Device Removed Extended Data)のサンプルプログラムを書きました。
サンプルは以下に置いておきました。
https://github.com/ProjectAsura/D3D12Samples/tree/master/D3D12_DRED

DREDなんですが,意外とまともなドキュメントが無いです。ドキュメントあるんですけども,わかりづらい,「この変数の意味は?」みたいな痒いところに手が届くものが無い感じがしますね。(単純に、ドキュメントみて理解できない私がアホなだけなんですが…)
…というわけで,コードを書いてみました。
仕事で使っているのはちゃんと,Push/Popの入れ子とかも考慮しているやつですけども,まぁええでしょ。こまけぇこたぁいいんっすよ。
結局,DREDのサンプルで困るのは「これちゃんとGPUクラッシュ時に出るの?」という所で,故意にGPUクラッシュさせるようなプログラムがなかなかネットで見つからない。
それだと,動作確認に困るので,GPUクラッシュさせるプログラム書きました。
ここ最近,ずっとGPUクラッシュの調査していたので,どうやれば簡単にGPUクラッシュを引き起こせるかなどのノウハウが溜まったので,その知見を活かして書きました。
一番よくある例,実行中にテクスチャを解放しちゃうやつ。これが一番良くあるので,Tボタン押したら,テクスチャをRelease()するようにしました。これで簡単にPageFaultのGPUクラッシュが発生します。TDRはレジストリいじっている場合は,発生までに時間かかるし,意外とGPU側でちゃんと対処してくれちゃったりする場合もあるので,無理やりやろうとしても意外と発生しなかったりします。サクッといかない。
DirectX-Samplesにはhttps://github.com/microsoft/DirectX-Graphics-Samples/tree/master/Tools/DXGIAdapterRemovalSupportTestというやつもあるみたいですが,こっちは触ったことないんで良く分からんっす(詳しい人教えてください)。

…で馬鹿の一つ覚えみたいな感じなんですが,PageFaultを発生できるようになったので,NVIDIA Aftermathのサンプルも書きました。
一応クラッシュ発生時に,ShaderBinaryとShaderPDBを吐き出して,クラッシュログを調査できる感じにしてみました。私のサンプルの場合は,クラッシュが発生している該当シェーダだけを出力するので,そんなにクラッシュダンプ出力に時間はかからないと思います(仕事でつかっているやつは,別の人が既に実装されたやつなんで,全部のシェーダのバイナリとPDBを出力しやがるんで,時間とディスク容量を食いまくって,困るんですよね。直すのは面倒ですし、時間の余裕もないので直す気はサラサラないです)。
サンプルプログラムは下記にあります。
https://github.com/ProjectAsura/D3D12Samples/tree/master/D3D12_NvAftermath
時間があれば,解説書いてもいいんですが,残念ながら,その時間がないのと,若干仕事のせいで鬱気味なのでやる気が起きないっす。(どうせみんなUEやらUnityつかうでしょ?こういう直叩きするひとがもう日本じゃ少数だから,親切に書いてあげても意味が無いんですよ。見る人いないから…)

…というわけで,リリースして精神的に落ち着いたら,のんびりゆったり解説を書こうかなと思います。
まぁ,そんなの期待する人はほぼいないと居ないと思いますが。

GPUクラッシュが激減した…

こんばんわ、Pocolです。

このところ,仕事でずっとGPUクラッシュを追っていたのですが,なんとなくノウハウが溜まってきました。
ほぼ、毎日のようにGPUクラッシュが何十件もあり,色々な人に手伝ってもらいながら,調査していたんですが,ようやくそれがパッタリ収まりました。

いくつか対策を入れていたのですが,結局どれが効いたのかは正直分からないのですが…
groupsharedで,UINT32_MAXでアクセスして,GPU上でメモリ破壊を発生させるコードがあったので,修正した所,謎に発生していたGPUクラッシュが治まりました。
多分,数年レベルで放置されていたバグなんじゃないかと思います。

NVIDIA AftermathとかでGPUクラッシュダンプを調べても,PageFault,さらにシェーダ情報もでない,挙句の果てにはResourceBarrierを実行するとGPUクラッシュする,定数バッファが壊れて無限ループして,TDRで落ちるなど,過去のクラッシュログを見ても,まったく共通性もなく,しかも結構頻発する。でも全然再現性が無い,手元で全く発生しない…という困ったちゃんで,困りまくった挙句何かないのか?と調べてみたら,NVIDIA Aftermathに,GFSDK_Aftermath_FeatureFlags_EnableShaderErrorReportingというフラグがあるのですが,これを有効にしたところ即クラッシュするようになりました。
何で無効だったのか聞いたんですが,こちらはヘッダファイルにも書かれているようにパフォーマンスペナルティがあるということで,ゲームプレイに支障があるとのことで無効化していたとのことでした。
結局,このフラグを有効にしたところ,先ほど述べたgroupsharedのバグを発見できたのと,他にもクラッシュする原因が見つかって,大いに役立ちました。

今後は,確定で発生しないものはGPU上のメモリ破壊を疑った方が良いという知見が得られました。
基本的にはUAVとかSRVとかのLoad()とかoperator []あたりミスっているんじゃないかって思いがちなんですが,これらはAPIドキュメントを見ると、安全に良しなにしてくれそうなことがあるので,メモリ破壊が発生するのは,CPU上での書き換えか,groupsharedのアクセスミスによる2パターンしかないように思えます(他のパターンがあったら教えてください)。CPU上でのメモリ破壊の可能性がほとんど低いことが分かったなら,groupsharedでの破壊が無いかどうかを調べましょう。
今回のバグは,

groupshared g_Variable[XXX][XXX];
みたいなのが定義されていて,
float temp0 = saturate(XXX);
uint temp1 = temp0 * MAX_VALUE – 1;
uint index = min(temp, MAX_VALUE);
g_Variable[index][XXX] = ….;
っぽいような,謎の計算がされていて(uintをマイナス1する時点でぞわぞわしちゃんですが…)
temp0がゼロになったときに,アボンするみたいケースでした。
よくよく見ると「馬鹿か!」って怒鳴りたくなったっちゃうような,不具合なんですが,変数がごちゃごちゃ定義されていたりとか,ジュニアレベルのエンジニアだとこういうチェックがおざなりになりがちなんで,気を付けた方が良いよ!…という良い事例になりました。

…というわけで,社内でも共有したんですが,この場でも共有してみました。
謎バグに困っている方は,groupsharedで変なことしていないかどうか確認してみると良いかもです。
(※ちなみ1個あったら,他にも絶対あるだろうと思って全シェーダをチェックしてみたのですが,確認した所発生しているのは該当シェーダの1個だけでした。)