OpenGL コア詳細
グラフィックスコマンドバッファ

コンピュートシェーダー

Compute shaders are programs that run on the graphics card, outside of the normal rendering pipeline. They can be used for massively parallel GPGPU algorithms, or to accelerate parts of game rendering. In order to efficiently use them, an in-depth knowledge of GPU architectures and parallel algorithms is often needed; as well as knowledge of DirectCompute, OpenGL Compute, OpenCL, CUDA, or OpenCL.

Unity のコンピュートシェーダーは、DirectX 11 DirectCompute テクノロジーと良く似ています。コンピュートシェーダーが使用できるプラットフォームは以下の通りです。

  • DirectX 11 または DirectX 12 グラフィックス API と Shader Model 5.0 GPU を伴う Windows と Windows ストア

  • Metal グラフィックス API を使用する macOS と iOS

  • Vulkan API を伴う Android、Linux、Windows プラットフォーム

  • 現段階で一般的に使用されている OpenGL プラットフォーム (Linux または Windows の OpenGL 4.3、Android の OpenGL ES 3.1)。Mac OS X は OpenGL 4.3 をサポートしません。

  • 現段階で一般的に使用されている多くのコンソール (Sony PS4、Microsoft Xbox One)

コンピュートシェーダーのサポートの有無はランタイムに SystemInfo.supportsComputeShaders を使って確認できます。

コンピュートシェーダーアセット

通常のシェーダー と同様に、コンピュートシェーダーは、プロジェクトのアセットファイルで .compute ファイル拡張子を持ちます。これらは DirectX 11 スタイルの HLSL 言語で書かれ、最低数の #pragma コンパイラーディレクティブを持ち、コンピュートシェーダーカーネルとしてどの関数をコンパイルするかを示します。

こちらは、コンピュートシェーダーファイルの基本例です。出力テクスチャを赤で塗りつぶします。

// test.compute

#pragma kernel FillWithRed

RWTexture2D<float4> res;

[numthreads(1,1,1)]
void FillWithRed (uint3 dtid : SV_DispatchThreadID)
{
    res[dtid.xy] = float4(1,0,0,1);
}

The language is standard DX11 HLSL, with the only exception of a #pragma kernel FillWithRed directive. One compute shader Asset file must contain at least onecompute kernel that can be invoked, and that function is indicated by the #pragma directive. There can be more kernels in the file; just add multiple #pragma kernel lines.

複数の#pragma kernel を使用する場合は、#pragma kernel ディレクティブと同じ行に// のコメントは許可されていないことに注意してください。使用すると、コンパイルエラーの原因となります。

#pragma kernel 行はオプションとして、カーネルをコンパイルしている間に複数のプリプロセッサーマクロを後に続けて定義することが可能です。サンプルとしては、

# pragma kernel KernelOne SOME_DEFINE DEFINE_WITH_VALUE=1337
# pragma kernel KernelTwo OTHER_DEFINE
// ...

コンピュートシェーダーの実行

スクリプトで ComputeShader 型の変数を定義し、アセットへの参照を割り当てます。こうすると ComputeShader.Dispatch 関数を使用してそれらを呼び出すことができます。 詳細は、ComputeShader class を参照してください。

Closely related to compute shaders is a ComputeBuffer class, which defines arbitrary data buffer (“structured buffer” in DX11 lingo). {Render Textures](../ScriptReference/RenderTexture.html) can also be written into from compute shaders, if they have “random access” flag set (“unordered access view” in DX11). See RenderTexture.enableRandomWrite to learn more about this.

コンピュートシェーダーでのテクスチャサンプラ

テクスチャとサンプラーは、Unity では別々のオブジェクトではありません。そのため、コンピュートシェーダでそれらを使用するには、以下の Unity 特有のルールに従う必要があります。

  • テクスチャ名と同じ名前を使用し、最初にsampler と表記します (たとえば、Texture2D MyTex; SamplerState samplerMyTex)。 この場合、サンプラーはテクスチャの filter/wrap/aniso 設定に初期化されます。

  • あらかじめ定義されたサンプラーを使用してください。 このため、名前にはLinear または Point (フィルタモード用) と、Clamp または Repeat (ラップモード用) が必要です。 たとえば、SamplerState MyLinearClampSampler は、リニアフィルターモードとクランプラップモードを持つサンプラーを作成します。

クロスプラットフォームのサポート

通常のシェーダと同様に、Unity はコンピュートシェーダーを HLSL から他のシェーダー言語に 変換 することができます。したがって、最も簡単なクロスプラットフォームビルドのために、HLSL にコンピュートシェーダーを記述します。ただし、これを行う際に考慮が必要な要因がいくつかあります。

クロスプラットフォームでの最良の実践法

DirectX 11 (DX11) は、他のプラットフォーム (MetalOpenGL ES など) ではサポートされていない多くの操作をサポートしています。 したがって、DX11 だけの環境を考えるより、サポートが少ないプラットフォームで、シェーダーの挙動を明確に定義する必要があります。 考慮すべき点は以下のとおりです。

  • アウトオブバンドのメモリアクセスが悪い点。DX11 は、読み込み時に常にゼロを返し、問題なくデータの一部を読み込むかもしれませんが、サポートが少ないプラットフォームでは、これを行う際に GPU がクラッシュする可能性があります。DX11 特有のハック、スレッドグループサイズの倍数と一致しないバッファーサイズ、バッファーの先頭や末尾から隣接するデータ要素を読み取ろうとすること、などの同様の非互換性に注意してください。

  • リソースを初期化する点。 新しいバッファーとテクスチャの内容は未定義です。 プラットフォームの中にはすべてゼロを示すものもありますが、そうでないものでは、NaN を含めどんな値になることもありえます。

  • コンピュートシェーダーが宣言するすべてのリソースをバインドします。シェーダーが分岐のために現在の状態でリソースを使用しないことが確実にわかっていても、リソースがバインドされていることを確認する必要があります。

プラットフォーム特有の相違

  • Metal (for iOS and tvOS platforms) does not support atomic operations on Textures. Metal also does not support GetDimensions queries on buffers. Pass the buffer size info as constant to the shader if needed.

  • OpenGL ES 3.1 (for (Android, iOS, tvOS, Tizen platforms) only guarantees support for 4 compute buffers at a time. Actual implementations typically support more, but in general if developing for OpenGL ES, you should consider grouping related data in structs rather than having each data item in its own buffer.

HLSL または、GLSL のみのコンピュートシェーダー

通常、コンピュートシェーダーファイルは HLSL で記述され、自動的に、必要なすべてのプラットフォームにコンパイルまたは変換されます。ただし、他の言語への変換を避けたり (つまり、HLSL プラットフォームのみを維持する)、GLSL コンピュートコードを記述することも可能です。

以下の情報は、HLSL 専用、または、GLSL 専用のコンピュートシェーダーにのみ適用され、クロスプラットフォームビルドには適用されません。これは、この情報によってコンピュートシェーダーソースが一部のプラットフォームから除外される可能性があるためです。

  • CGPROGRAM キーワードと ENDCG キーワードで囲まれたコンピュートシェーダーソースは、非 HLSL プラットフォームでは処理されません。

  • GLSLPROGRAM キーワードと ENDGLSL キーワードで囲まれたコンピュートシェーダーソースは、GLSL ソースとして扱われ、そのまま出力されます。これは、OpenGL または GLSL プラットフォームをターゲットとする場合にのみ機能します。また、自動的に変換されたシェーダーはバッファーの HLSL データレイアウトに従いますが、記述された GLSL シェーダーは GLSL レイアウトルールに従うということにも注意する必要があります。


  • 2017–05–18 Page amended with limited editorial review - Leave page feedback

  • 5.6 に以下を追加: SystemInfo.supportsComputeShaders, platforms macOS, iOS (using Metal), Android, Linux, Windows (with Vulkan)

OpenGL コア詳細
グラフィックスコマンドバッファ