質問: 私はグラフィックプログラミングをしたことがないのですが、GPUに関する記事を読んでいると、ピクセルの描画をするのに複数の三角形の前後を判定するために深度バッファ法を用いると書いてありました。 それについて調べてみると、深度バッファ法というのは深度バッファを見て自らの深度値と比較し更新することで、上書きするかどうか決めるアルゴリズムのようでしたが、これは複数のピクセル処理が同時に同じ深度バッファに読み書きする可能性があるということですから、アトミック操作で更新する必要があるように見えます。しかしこれでは、三角形がたくさん重なってる場面では並列性が損なわれるように思います。更に、同じ三角形について近くのZバッファを読み書きするわけですから、何度も同じキャッシュラインが無効化されそうにも見えます。(GPUのアーキテクチャをよくわかっていないので、これに関してはかなり意味不明なことを言っているかもしれません) 1. そもそも、GPUはピクセルごとに並列ななんらかの計算していますか? 2. これは現代のGPUでも用いられている手法ですか? 3. 三角形がたくさん重なっているときに並列性が損なわれてしまうことに対するなんらかの解決策がありますか? 4. あるいは、そのCAS程度ではほとんど並列性が損なわれないという見方がありますか? 私はグラフィックについて全く知識がないため、変なことに疑問を持っていたらすみません。
回答: レイトレーシングでない従来のラスタライズ法による3Dグラフィックスエンジンでは、ほぼ間違いなく何らかの形で深度バッファを使っています。 ラスタライズベースのDirect3Dレンダリングパイプラインでは、ポリゴン(三角形リストやラインリストなど)の描画は、簡略化すると 1. インプットアセンブラーによるメモリからの頂点情報の読み出し 2. 頂点シェーダーによる頂点単位処理(座標の同次変換など) 3. ラスタライザーによるラスタライズ(ピクセル化) 4. ピクセルシェーダーによるピクセル単位処理(陰影計算など) 5. アウトプットマージャーによる統合処理 という流れになるのですが、アウトプットマージャーのステージで深度バッファを使ったZテストを実行します。 詳しくは以下(Direct3D 10のレンダリングパイプライン)を参照してください。ジオメトリシェーダーはオプションなので上記では省略しています。Direct3D 11以降ではテッセレーション用のシェーダーステージが追加されていますが、これもオプションなので基本は同じです。OpenGLやVulkanも用語が違うだけで、やっていることはほぼ同じです。 * Rendering Pipeline - Windows drivers | Microsoft Docs 頂点シェーダーによる頂点単位の処理に関しては、複数の三角形やラインのプリミティブ情報が入力されても個々の頂点は完全に独立しているので並列処理されますが、ピクセル単位の処理に関しては、複数の異なるプリミティブを個々に並列処理しているわけではないです。とはいえ、もちろん単純に1つ1つのプリミティブを順次処理しているわけではなく、出力先の画面(レンダーターゲット)を複数の小さなタイル(例えば8ピクセル×8ピクセルなど)に分割して、各タイルに1つずつストリームプロセッサーの集合(クラスター)を割り当て、1つのプリミティブに対する処理を分割して並列実行します。各クラスター内でキャッシュは共有されており、またクラスター内のプロセッサー群により駆動されるハードウェアスレッド群はすべて連動して同じ命令(同じシェーダープログラム内の同じステップ行)を実行するため、1つのタイル内の処理は並列かつ同時に実行されます (Single Instruction, Multiple Threads; SIMT)。個々のクラスターは独立して動作し、タイルごとの処理も失速しないように並列にパイプライン実行されます。 なお、GPUの中には、視点から見てオーバーラップすることがない三角形が同じタイル内に複数ある場合、同時に描画するものもあるそうです。 * opengl - Parallelism in GPU's rasterization process - Game Development Stack Exchange Zテストはパイプラインの最後段で実行されますが、最終的に描画されない三角形に対するピクセルシェーダーの実行は無駄なので、早期Zカリングという機能を使って描画を早めに打ち切ってしまうこともあります。 * * PowerVRのようなモバイルデバイス用GPUだと、タイルベースの遅延レンダリング (Tile-Based Deferred Rendering; TBDR) という、Zテストを早期に実行することで描画の無駄をより小さくするアーキテクチャ設計になっていて、深度バッファの実装形態も異なります。 最近ではモバイルだけでなく、NVIDIA/AMD/IntelのようなPC用GPUでもTBDRの設計を取り入れているそうです。 * * * GPUの詳しい設計や並列処理の実装形態に関しては英語の情報を探したほうが良いと思います。全般的に日本語の情報は少なく、嘘が混じっていることも多々あります。 (上記の説明にも誤りが含まれているかもしれないので、話半分にとらえてください)