ResourceBarrierについて、見かけない情報というか小ネタを。 | 備忘録

備忘録

C++/DirectX/Metal 等のネタを書いていきます。
基本あちこちで解説されてるような内容は書かないです。
プログラミング以外のネタを書くこともありますが、備忘録なので消す可能性があります。

 自分はD3D12そのものはロクに触ってないんだけど、Metalで同じインターフェースを作る上で疑問に思って調べた結果をメモ。

 とりあえず、公式の解説を大前提として、そこにも載ってない細かい部分。

1) リソースステートの昇格(Promotion)は、その状態が必要になったタイミング(ResourceBarrier()を含む)で必要なサブリソースだけに起きる、というか起きるとみなされる。

2) 降格(Decay)は、ExecuteCommandLists()によるGPU上でのコマンド実行が終わったタイミングでそのリソースの降格の条件を満たす全てのサブリソースに起きる、とみなされる。

 1のカッコ内はちょっと誤解しやすい挙動になる。仮にStateBeforeをD3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCEとして遷移(Transition)バリアをやろうとするとき、対象のリソース(のサブリソース)が現在COMMONであったとしても、遷移実行時にorコマンドを積むときにResourceBarrier()によってPIXEL_SHADER_RESOURCEに昇格するとみなされるので警告が出ない。
 また、何かしら昇格されたRead-Onlyのステートを持つ状態で、そのステートと別のRead-OnlyステートをOR結合したものをBeforeに設定しても、昇格扱い?で合法(別のRead-Onlyステート単体で指定するのは警告が出る)("Note that promotion from one promoted read state into multiple read state is valid")



3) リソースステートが要件を満たさない場合に警告が出る&昇格が起きるとみなされるタイミングは、
・IASetVertexBuffers()/IndexBuffer()、OMSetRenderTargets()等はその場ではなく、Draw系コール(RTはClearRenderTargetView()でも)。
・Set◯◯RootDescriptorTable()/RootShaderResourceView()等のルートシグニチャ周りは即時。

4) Map()の呼び出しでは、現在のステートが非COMMONであった場合、Map()内で強制的にCOMMONにされる(降格扱い??CPU上で読み書きするにはCOMMONである必要があるからか)。


 4は、バッファのみ。テクスチャはそもそもMap出来ないと思うので該当しない。



 一部CPU上で起きること(チェック等)をGPU上と勘違いしていたので訂正(多分GPU上では厳密なステートの定義など無いんだと思う。警告も昇格もコマンド積むときに起きる(ResourceBarrierの警告はExecute終了後にも出るが)ので、あくまで事前チェックと捉えるべき。)
 1の説明でResourceBarrier()時の挙動について一部間違ってたので訂正。

 また、一部D3D12_RESOURCE_DIMENSION_UNKNOWNが使える場面があるとして、その場合どうなるかはまだ調べてません。


(追記)
 昇格降格の実際の挙動については Look Inside D3D12 Resource State Barriers にハッキリ書かれてました。
 「What is important to understand is that these state transitions are truly *implicit*. In other words, neither the D3D12 runtime or drivers actively *do* anything to promote or decay a resource state.」
 (理解する上で重要なことは、これらの状態遷移は本当に*暗黙的*であるということです。言い換えると、D3D12ランタイムもドライバも、リソースの状態を昇格させたり降格させたりするために、能動的に*何かをする*わけではありません。)

 ↑多分本当に何もしないんだろう。例えば降格なら「コマンドリストのGPU上での実行が終わったら、レイアウトを持つ(=ALLOW_SIMULTANEOUS_ACCESSでない)テクスチャとかでない限り、COMMON状態(複数のReadまたは単一のWriteに移れるし、CPUからのアクセスにも移れる状態)に事実上なる」ということだと思う。

そう考えると、↑この動画とかで「(降格ではなく)明示的なCOMMONステートへの遷移はパイプラインのストールを招くので避けろ」と言われてるのも、非常に納得がいく。


 てかこれ、Metalで実装するのキツイんだよなぁ・・・


 まだあまり調べてないけど、Enhanced Barrier の方がまだMetalに近くて実装しやすいかもしれない。


 多分他にも追記します。