はじめに
Pixel Sortを実装しようと四苦八苦していた時にCompute ShaderでのRWTextureへのランダムアクセスがかなり遅い印象を受けた。そこで、テクスチャへのランダムアクセスを使わないGPU処理においては、ラスタライズなどのパイプラインの機能をフルに起動しないことでCompute Shaderの方がFragment Shaderより処理速度が早くなるのではないかと思い、実験した。結果としてはほぼ変化がなかったが、私の実行環境ではRadeonと古いGeforceでのみFragment Shaderの方が若干速くなっていた。ここでは実験方法、得られた結果のプロットと実験環境をまとめる。
また、実験に使ったプロジェクトは以下のリポジトリで公開している。
https://github.com/Kuyuri-Iroha/compute_fragment_test
実験
実験方法
まず、今回行う実験では実際の処理速度に重きを置いて実験をしたかったこともあり、Unityのレンダリング統計ウィンドウのTime per frame(ms)を評価することとした。Time per frameの値は、実行画面を動画として撮影。撮影した動画の開始20秒を除いた30秒間を3秒ごとにサンプリングしたものを各実行環境で取得し、その平均値を処理時間として評価した。
実験環境
また、実験環境は以下の5つのPCとする。
- Windows Desktop 1
- Intel Core i9-9900K (オーバークロックなし)
- 16GB RAM
- GeForce RTX 2070 (8GB VRAM)
- Windows Desktop 2
- Intel Core i7-4770K(オーバークロックなし)
- 16GB RAM
- GeForce GTX 770 (2GB VRAM)
- Windows Laptop
- Intel Core i7-4710MQ
- 8GB RAM
- GeForce GTX 960M (2GB VRAM)
- Macbook Pro
- Intel Core i7-7567U
- 16GB RAM
- Intel Iris Plus Graphics 650 (1.5GB VRAM)
- iMac
- Intel Core i5
- 16GB RAM
- Radeon Pro 555 (2GB VRM)
実験用プログラム
実験用プログラムはinigo quilez氏のIterations - inversion 2をCgへの書き換えた後、#define AA 4
に変更、72行目をコメントアウトしたものを使用した。また、描画サイズは400x400で統一した。
Compute Shaderでは、ARGB32のRenderTextureに出力して、PlaneのUnlitマテリアルのTextureとして設定することでレイマーチングを実行。スレッド数は(20, 20, 1)
、グループ数は(20, 20, 1)
としている。
Fragment Shaderでは、ARGB32の空のTexture2Dをsrc、同じくARGB32のRenderTextureをdestとしてGraphics.Blit
を実行する形の実装とした。マテリアルとTextureの設定はCompute Shaderと同様の処理にて行っている。
実験結果
Windows Desktop 1 (ms) | Windows Desktop 2 (ms) | Windows Laptop (ms) | Macbook Pro (ms) | iMac (ms) | |
---|---|---|---|---|---|
Compute Shader | 15.5 | 18.6 | 40.6 | 146.1 | 110.3 |
Fragment Shader | 15.3 | 18.7 | 37.8 | 147.7 | 81.2 |
結果としてはこのようになった。どのPCにおいても実行速度にほとんど差はなかったが、RadeonのiMacのみFragment Shaderの方が速いという結果になった。
正直この差についてはサンプル数が少ないためなんとも言えないが、5つの中では一番古いWindows Laptopも若干Fragment Shaderの方が速かった。そのため、2次元の画像として扱えるデータならFragment Shaderで計算した方が良さげである。
おわりに
最初はCompute Shaderの方が速いんじゃないかという期待を持って実験を始めたので、結果としてかなり残念なものとなった。しかし、Compute Shader使いたいマンであった私に待ったをかけることになったので、それだけでも私にとっては有意義である。また、Compute Shaderは1次元であっても3次元であっても直感的に記述できるため、この程度の処理速度差であれば十分選択肢に入るということが検証できたわけでもあるので、今後より身近に使っていければと思う。