Unity2020.1 以降では ComputeBuffer を使わず GraphicsBuffer を使おう

公開:2020/10/08
更新:2020/10/08
3 min読了の目安(約3200字TECH技術記事

GraphicsBuffer とは

ComputeBufferの汎用性を高めた上位互換で将来的に代替するものです。
Unity 2020.1からComputeBufferが使えるほぼすべての局面[1]でGraphicsBufferも使えるようになったので、もはやComputeBufferを使う理由がなくなりました!

何がかわったのか

インデックスバッファ、頂点バッファとして使えるようになった[2]

Mesh.trianglesMesh.verticesのかわりとして使えるイメージです。ComputeShaderで計算した結果をGraphicsBufferに書き込んで表示用のシェーダーに渡すことでCPU側にコピーすることなく動的なメッシュを表現できます。

以前からComputeBufferを表示用シェーダーで参照することで同様のことが可能でしたが、新たにDrawProcedural*系の関数にGraphicsBufferを渡せるようになりMeshRendererと同じ表示処理を走らせられるようになったのだと思います。これは次の2つの利点が考えられます。

  • 表示用シェーダーをDrawProcedural*系とMeshRenererで共通化できる
  • 表示用シェーダーのComputeBuffer参照が不要になるのでパフォーマンスの向上が期待できる

コンストラクタでタイプ指定が必須になった

public ComputeBuffer(int count, int stride);
public ComputeBuffer(int count, int stride, ComputeBufferType type);
public GraphicsBuffer(GraphicsBuffer.Target target, int count, int stride);

唯一ComputeBufferにポジティブな要素があるとすればこれで、Type.Structuredのときだけタイプを省略できます。

インデックスバッファの使用例

何か所かで見たハマリポイントです。
インデックスバッファを作る際、

var type = GraphicsBuffer.Target.Index | GraphicsBuffer.Target.Raw;
var indexBuffer = new GraphicsBuffer(type, count, sizeof(int));

とタイプをIndex|Rawで指定しComputeShaderでは[RW]ByteAddressBufferにバインドするのがセオリーみたいです。
Raw=[RW]ByteAddressBufferのセットがあまり慣れてなくて気づきにくい

いちおうIndex|Structured[RW]StructuredBufferもありみたいです。
どちらでもDrawProcedural*系の関数に渡せるのがGraphicsBufferの汎用性パワーですね!

フォーラムから気になるところを抜粋

ComputeBufferはどうなるの

Yes ComputeBuffer will (one day...) disappear. But usage is almost 100% today. So it is not any day soon.

すぐではないが将来的にはなくなるようです。

ComputeBufferの拡張ではなくGraphicsBufferを新設した理由は

Why not extend ComputeBuffer? Because ComputeBuffer is badly named - it implies it has something to do with Compute and Compute Shaders. GraphicsBuffer is for any type of rendering buffer. Extending ComputeBuffer would be confusing.

名前を変えたかったみたいです。あらゆるタイプのレンダリング関係のバッファを扱うためComputeShaderなどを暗示する名前だと混乱を招きそうだったとのこと。

GraphicsBuffer is a new type intended to encapsulate all types of buffers. ComputeBuffer was a bad idea, because it restricts usage to a certain type of binding in shaders. A GraphicsBuffer can, in theory, have multiple views (e.g. compute + index, so you can populate via compute, then use as an index buffer with no extra effort) on platforms that support it.

ComputeBufferよりも抽象的にバッファを扱いたかったみたいです。
例としてcompute + indexが紹介されています。ComputeBufferはそのまま直接インデックスバッファとしては使用できなかったのですが、GraphicsBufferではUnityが内部的にうまく中継することでこれが可能になった、ということだと思います。

参考

https://forum.unity.com/threads/graphicsbuffer-and-mesh.636631/
https://forum.unity.com/threads/graphicsbuffer-mesh-vertices-and-compute-shaders.777548/

脚注
  1. CommandBuffer.SetComputeBufferCounterValueなどはまだComputeBufferオンリー ↩︎

  2. 頂点バッファはまだ未実装っぽいです ↩︎