Version: 5.3 (switch to 5.4b)
OpenGL Core Details
Graphics Command Buffers

Вычислительные шейдеры

Вычислительные шейдеры - программы, запущенные на видеокарте за пределами территории обычного рендеринга. Они могут быть использованы для массивных параллельных GPGPU алгоритмов или для ускорения элементов рендеринга игры. Для того, чтобы эффективно их использовать, зачастую требуется глубокое знание GPU архитектур и параллельных алгоритмов; так же, как и знание DirectCompute, OpenCL или CUDA.

Compute shaders in Unity closely match DirectX 11 DirectCompute technology. Platforms where compute shaders work:

  • Windows and Windows Store, with a DirectX 11 graphics API and Shader Model 5.0 GPU.
  • Modern OpenGL platforms (OpenGL 4.3 on Linux or Windows; OpenGL ES 3.1 on Android). Note that Mac OS X does not support OpenGL 4.3, so no compute shaders there yet.
  • Modern consoles (Sony PS4 and Microsoft XboxOne).

Ассеты вычислительных шейдеров

Подобно обычным шейдерам, вычислительные шейдеры являются файлами ассетов в вашем проекте с расширением файла *.compute. Они написаны на языке HLSL в стиле DirectX 11 с минимальным количеством компиляционных директив #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);
}

Учтите, что пример, указанный выше, не делает ничего интересного - он просто заливает итоговую текстуру красным.

Языком является стандартный DX11 HLSL, с исключением в виде директивы #pragma kernel FillWithRed. Один файл ассета вычислительного шейдера должен содержать по крайней мере “вычислительное ядро”, которое может быть вызвано, и эта функция помечена директивой #pragma. В файле может быть ещё больше ядер; просто добавьте несколько строк #pragma kernel.

Please note when using multiple #pragma kernel lines that comments of the style // text are not permitted on the same line as the #pragma kernel directives and will cause compilation errors.

По желанию, после строки #pragma kernel может быть указан номер макроса препроцессора, для назначения во время компиляции этого ядра, например:

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

Вызов вычислительных шейдеров

В вашем скрипте, задайте переменную типа ComputeShader, назначьте ссылку на ассет, и тогда вы сможете вызывать их при помощи функции ComputeShader.Dispatch. Для деталей, см. класс ComputeShader

С вычислительными шейдерами тесно связан класс ComputeBuffer, который задаёт произвольный буфер данных (“структурированный буфер”, говоря языком DX11). Рендер текстуры также могут быть записаны в вычислительные шейдеры, если у них включён флажок “Random access” (“unordered access view” в DX11), см. RenderTexture.enableRandomWrite.

Семплеры текстур в вычислительных шейдерах

Текстуры и семплеры в Unity не являются отдельными объектами, так что для того, чтобы их использовать в вычислительном шейдере, вам надо следовать некоторым особым правилам Unity:

  • Либо использовать такое же имя текстуры, с припиской “sampler” (например, Texture2D MyTex; SamplerState samplerMyTex). В таком случае семплер будет определён в настройках фильтра/оборачивания/анизотропной фильтрации текстуры.
  • Либо использовать один из “презаданных” семплеров; имя, которое должно быть указано - “Linear” или “Point” (для режима фильтра) и “Clamp” или “Repeat” (для режима оборачивания). Например, "SamplerState MyLinearClampSampler" - линейный фильтр с “Clamp” режимом оборачивания.

Cross-platform support

As with regular shaders, Unity is capable of translating compute shaders from HLSL to GLSL. Therefore for the easiest cross-platform builds it is recommended to write compute shaders in HLSL.

OpenGL compute differences from D3D

In order to achieve shaders working on multiple different platforms one should consider these limitations:

  • D3D and OpenGL have different data layout rules. Automatically translated GLSL shaders use std430 layout on compute buffers. Therefore for example using float3 based structured buffers will cause compatibility issues as DX allows tight packing but OpenGL enforces padding to float4. Scalars, two-component and four-component vectors are safe to use as they are. Extra care should be taken when constructing structs.
  • OpenGL ES 3.1 guarantees support for only 4 simultaneous shader storage buffers. Actual implementations typically support a bit more but in general one should consider grouping related data in structs as opposed to having each data item in its own buffer.

HLSL-only or GLSL-only compute shaders

Typically compute shader files are written in HLSL, and compiled or translated into all needed platforms automatically. However it is possible to either prevent translation to GLSL (i.e. only keep HLSL platforms), or to write GLSL compute code manually.

  • Compute shader source surrounded by CGPROGRAM and ENDCG keywords will not be processed for OpenGL/GLSL platforms.
  • Compute shader source surrounded by GLSLPROGRAM and ENDGLSL keywords will be treated as GLSL source, and emitted verbatim. This will only work when targetting OpenGL/GLSL platforms.

Note that for cross-platform builds neither of the above is recommended, since it very much ties compute shader source into being excluded from some platforms.

OpenGL Core Details
Graphics Command Buffers