テクスチャを読み込んでミップマップを自動的に作るときは、UAVを経由で書き込むためD3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESSのフラグを付けてリソースを作っていた。
ただ、リファレンスにはUAVを殆ど使わない場合はコピーして使うのを検討したほうがいいと書いてあり、このフラグのコストが高いことが伺える。
このケースでは確かにUAVは最初のミップマップ生成の為だけに使っておりUAV無しのリソースにコピーしたほうが良さそうだ。
毎フレームレンダーターゲットのミップマップを作ってテクスチャとして利用するような場合は、UAV付きのままで使っても良さそう。
実際の処理時間を計測してみるとコピーした方が20~30usぐらい時間が伸びていて、「UAV付きテクスチャを参照のコスト < Copy+UAV無しテクスチャ参照のコスト」になる為、毎フレームコピーするのは逆にもったいない結果になっていた。
CopyTexture
CopyTextureコマンドにサブリソース番号を追加してミップマップの各階層もコピーできるように拡張し、要求側ではミップマップの階層分ループしてコマンドを発行するように修正。
今まではサブリソースインデックス0固定だったものをインデックス指定に変えただけなので特に問題なくできた。
CreateTexture
テクスチャリソース作成関数内でテクスチャをロードしてバッファをコピーするとき、一時的なUAV付きリソースにコピーするように変更。
そのリソースでミップマップを生成して全て出来上がったら、全体をCopyTextureしてUAV付きのリソースは破棄。
実行して試してみたところ問題なく動く。
ただいつもこういった修正後に、デバッグ実行するといつもデバッグレイヤーに何かが表示されている。
今回もやっぱりエラーが出ていた。
D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists: Resource(0x000001C4E398C710:'Mesh<MeshAlbedoTex1>') (subresource : 8) is bound as DATA_STATIC on Command List 0x000001C4E34C5510:'DirectCL1'. Its state was changed by a previous command list execution which indicates a change to its data (or possibly resource metadata), but it is invalid to change it until this command list has finished executing for the last time. [ EXECUTION ERROR #1002: DATA_STATIC_DESCRIPTOR_INVALID_DATA_CHANGE]
イマイチよくわからないけど、テクスチャのコピー完了を待たずに次々に処理しているからかと思って、完了を待つようにしたりしたが状況は変わらず。
このメッセージが出力されるタイミングはテクスチャ読み込み時ではなく、テクスチャを描画するタイミングで出力されている。また、一旦エラーが出ると毎フレーム出ることが普通なのに今回のケースでは、最初の1回だけで以降は出ていない。
描画タイミングまでコピーが終わってないと言うのは考えられないし何のことを言っているのか再考してみると、DATA_STATICというのと、最初の1回だけ出力されるというのがヒントになった。
シェーダのルート署名では、純粋なテクスチャの場合DATA_STATIC、レンダーターゲットなどをテクスチャとして使う場合は、DATA_STATIC_WHILE_SET_AT_EXECUTEを指定している。
テクスチャのその前のステータスはCOPY_DESTになっている。
今までUAV付きのテクスチャではこのエラーは出ていなかったが、今回UAVなしになったことでDATA_STATICの恩恵を受けられるようになったからなのか、チェック対象になって怒られるようになったとか?
リソースの遷移は、はじめてライブラリを作った頃はマイクロソフトのサンプルの通り使う状態に遷移させて元に戻すということをしていたが、今は使う場面の状態に合わせて遷移させてそのままという風にしている。そのため、各リソースの作成直後はだいたいCOPY_DESTのままになっている。
DATA_STATICを宣言しているシェーダの実行中にテクスチャの状態遷移を行ってしまっているのがだめだと予想して、コピー直後にステータスの遷移まで完了させてみた。こうすることで以降このテクスチャに対して状態遷移は発生せず、まさにSTATICって感じになる。
この状態で試してみるとエラーは消えて動作するようになった。
0 件のコメント:
コメントを投稿