ピクセルシェーダーでテクスチャを設定し、それをレンダーターゲットにしますか?
-
06-07-2019 - |
質問
シェーダーを使用してシーンをレンダリングすると、そのシーンのレンダーターゲットでもあるテクスチャを渡すと、不必要な動作が発生しますか?
基本的に:
texture t;
shader->SetTexture("texture",t);
device->SetRenderTarget( 0, t->surface );
shader->Begin("effect")
// do some more shader stuff
device->EndScene();
これは正確に何を引き起こしますか?
レンダリングの前にレンダリングターゲットをクリアしない場合、テクスチャはすべて同じように機能しますか? device-> Endが呼び出されるまで、最終的な変更はテクスチャに書き込まれないと思いますか?
解決
あなたはDirectX9について話していると思います。ドキュメントでは、この特定のケースについては何も言及していませんが、次のことを説明できます。
device-> Endが呼び出されるまで、最終的な変更はテクスチャに書き込まれないと思います
これは間違った仮定です。考えてみてください。描画するすべての三角形のすべてのピクセルが「どこか」に保存され、ピクセルがレンダリングターゲットに書き戻されることなく、すべてのテクスチャフェッチが実行されると仮定しています。これには、任意の量のメモリが必要なので、不可能です。
実際には:
- ハードウェアは通常、一度に多くの三角形を一度に処理します
- 競合状態が発生しないと仮定して、必要に応じてフレームバッファ(これはテクスチャメモリのバッキング)を更新します
だから、DX9が文句を言わないとしたら(本当に知りたいなら試してみてください、もうDX9はしません)、 は未定義です。
とはいえ、DirectX10はそれについてより明示的です(ソース):
サブリソースも現在ある場合 読み取りまたは書き込みにバインド(おそらく パイプラインの別の部分で)、 これらのバインドポイントはNULLになります 同じサブリソースが 同時に読み書きされる 単一のレンダリング操作で。
したがって、DirectX10では、テクスチャ設定はAPIによって削除されます。
他のヒント
詳細を指摘することはできませんが、未定義の動作であると確信しています。グラフィックカードがフラグメントのシェーディングに使用する方法はさまざまです(一度に異なる量を行うなど)が、実際のケースでは、一度に複数のフラグメントを行います。つまり、同じ場所で読み取りと書き込みの両方を行うことになり、競合状態が発生します。推奨されるとは思わない。
デバッグランタイムにより、これを行うことができなくなり、警告が表示されます。リリースランタイムの「might」 (ただし、おそらく動作しません)。
問題は、テクスチャからピクセルをロードしてから使用するまでにかなりの遅延があるという事実から生じます。これは、テクセルのブロックをキャッシュにロードすることで修正されます。書き込みはバッファリングされ、メモリに直接書き込まれます。したがって、すでに更新されている可能性のあるテクセルを読み取っている可能性がありますが、キャッシュは古くなってしまう可能性があります。書き込み中のテクセルのみを読んでいる場合は、「可能性があります」動作しますが、現実的にはそのような実装の詳細はIHVに任されています。彼らはこれを機能させる義務を負いません。
他の人が言ったように...それは非常に未定義の振る舞いです。