
コンピュータグラフィックスにおいて、シェーダーとは、レンダリングパイプラインを通過するデータに適用されるプログラム可能な操作です。[ 1 ] [ 2 ]シェーダーは、頂点やプリミティブなどのデータに作用してジオメトリを生成または変形したり、フラグメントに作用してレンダリングされた画像の値を計算したりします。[ 2 ]
シェーダーは多種多様な演算を実行でき、様々なハードウェア上で実行できます。現代のリアルタイムコンピュータグラフィックスでは、シェーダーはグラフィックス処理装置(GPU)上で実行されます。GPUは、プログラムの高度な並列実行を可能にする専用ハードウェアです。画像のレンダリングは驚くほど並列であるため、フラグメントシェーダーとピクセルシェーダーはSIMDハードウェア上で高いスケーラビリティを発揮します。歴史的に、レンダリングの高速化を求める動きは、高度に並列化されたプロセッサを生み出し、それらを他のSIMD対応アルゴリズムに利用してきました。[ 3 ]計算パイプラインで実行されるこのようなシェーダーは、一般的にコンピュートシェーダーと呼ばれます。
「シェーダー」という用語が初めて一般に公開されたのは、ピクサーが1988年5月に公開したRenderManインターフェース仕様のバージョン3.0でした。 [ 4 ]
グラフィックス処理ユニット(GPU)の進化に伴い、OpenGLやDirect3Dなどの主要なグラフィックスソフトウェアライブラリがシェーダーのサポートを開始しました。最初のシェーダー対応GPUはピクセルシェーディングのみをサポートしていましたが、開発者がシェーダーの威力を認識すると、すぐに頂点シェーダーが導入されました。プログラマブルピクセルシェーダーを搭載した最初のビデオカードは、2001年にリリースされたNvidia GeForce 3(NV20)でした。[ 5 ]ジオメトリシェーダーはDirect3D 10とOpenGL 3.2で導入されました。最終的に、グラフィックスハードウェアは統一されたシェーダーモデルへと進化しました。
シェーダーの従来の用途は、グラフィックスパイプライン内のデータを操作して画像のレンダリングを制御することです。グラフィックスシェーダーは、パイプライン内の位置、操作対象となるデータ、および使用されるグラフィックスAPIに応じて分類できます。
フラグメントシェーダー(ピクセルシェーダーとも呼ばれる)は、各「フラグメント」の色やその他の属性を計算します。フラグメントとは、最大で1つの出力ピクセルに影響を与えるレンダリング処理の単位です。最も単純な種類のピクセルシェーダーは、1つの画面ピクセルを色値として出力します。複数の入出力を持つより複雑なシェーダーも可能です。[ 6 ]ピクセルシェーダーは、常に同じ色を出力するものから、ライティング値を適用するもの、バンプマッピング、シャドウ、スペキュラハイライト、半透明などの処理まで、多岐にわたります。また、フラグメントの深度(Zバッファリング用)を変更したり、複数のレンダーターゲットがアクティブな場合に複数の色を出力したりすることもできます。3Dグラフィックスでは、ピクセルシェーダーだけでは複雑な効果を生成できません。これは、ピクセルシェーダーが単一のフラグメントのみを処理し、シーンのジオメトリ(頂点データなど)を認識できないためです。しかし、ピクセルシェーダーは描画対象の画面座標を認識しており、画面全体のコンテンツがテクスチャとしてシェーダーに渡された場合、画面とその周辺のピクセルをサンプリングできます。この技術により、ブラーや、カートゥーン/セルシェーダーのエッジ検出/強調など、幅広い2次元ポストプロセス効果を実現できます。ピクセルシェーダーは、パイプライン内のスプライトやテクスチャなどの2次元画像に中間段階で適用することもできますが、頂点シェーダーは常に3Dシーンを必要とします。例えば、ピクセルシェーダーは、ラスタライズされたビデオストリームのポストプロセッサまたはフィルタとして機能できる唯一のシェーダーです。
頂点シェーダーは、グラフィックスプロセッサに与えられた3D頂点ごとに1回実行されます。その目的は、仮想空間における各頂点の3D位置を、画面に表示される2D座標(およびZバッファの深度値)に変換することです。 [ 7 ]頂点シェーダーは位置、色、テクスチャ座標などのプロパティを操作できますが、新しい頂点を作成することはできません。頂点シェーダーの出力はパイプラインの次の段階、つまりジオメトリシェーダー(存在する場合)またはラスタライザーに送られます。頂点シェーダーを使用すると、 3Dモデルを含むあらゆるシーンの位置、動き、照明、色の詳細を強力に制御できます。
ジオメトリシェーダーはDirect3D 10とOpenGL 3.2で導入されました。以前はOpenGL 2.0以降でも拡張機能を使用することで利用可能でした。[ 8 ]このタイプのシェーダーは、グラフィックスパイプラインの先頭に送信されたプリミティブから、点、線、三角形などの新しいグラフィックスプリミティブを生成することができます。[ 9 ]
ジオメトリシェーダープログラムは、頂点シェーダーの後に実行されます。入力としてプリミティブ全体を受け取り、隣接情報も持つ場合があります。例えば、三角形を操作する場合、3つの頂点がジオメトリシェーダーの入力となります。シェーダーは0個以上のプリミティブを出力し、それらはラスタライズされ、そのフラグメントは最終的にピクセルシェーダーに渡されます。
ジオメトリシェーダーの典型的な用途としては、ポイントスプライトの生成、ジオメトリテッセレーション、シャドウボリュームの押し出し、キューブマップへのシングルパスレンダリングなどが挙げられます。ジオメトリシェーダーの利点を示す実世界の典型的な例としては、メッシュの複雑度の自動調整が挙げられます。曲線の制御点を表す一連のラインストリップがジオメトリシェーダーに渡され、必要な複雑度に応じてシェーダーは自動的に追加のラインを生成します。これらのラインはそれぞれ、曲線をより正確に近似します。
OpenGL 4.0 および Direct3D 11 では、テッセレーション シェーダーと呼ばれる新しいシェーダー クラスが追加されました。このシェーダー クラスは、従来のモデルに 2 つの新しいシェーダー ステージを追加します。テッセレーション コントロール シェーダー (ハル シェーダーとも呼ばれる) とテッセレーション評価シェーダー (ドメイン シェーダーとも呼ばれる) です。これらを組み合わせることで、実行時に数学関数に従って単純なメッシュをより細かいメッシュに分割できます。この関数はさまざまな変数、特にビュー カメラからの距離に関連付けることができ、アクティブなレベル オブ 詳細スケーリングが可能になります。これにより、カメラに近いオブジェクトは細かいディテールを持つことができ、遠くにあるオブジェクトはメッシュが粗くても品質は同等に見えます。また、非常に複雑なメッシュをメモリからダウンサンプリングするのではなく、シェーダー ユニット内でメッシュを一度リファインできるため、必要なメッシュ帯域幅を大幅に削減できます。一部のアルゴリズムでは任意のメッシュをアップサンプリングできますが、他のアルゴリズムではメッシュ内の「ヒント」を使用して最も特徴的な頂点とエッジを指示できます。
2017年頃、AMD Vegaマイクロアーキテクチャは、ジオメトリを処理するために必要なデータにアクセスできるコンピュートシェーダーに似た新しいシェーダーステージ(プリミティブシェーダー)のサポートを追加しました。[ 10 ] [ 11 ]
Nvidiaは2018年にTuringマイクロアーキテクチャでメッシュシェーダとタスクシェーダを導入しましたが、これらもコンピュートシェーダをモデルにしています。 [ 12 ] [ 13 ] Nvidia Turingは、Ampere RTX 30シリーズがリリースされる数ヶ月前に、DirectX 12 Ultimate APIを介してメッシュシェーディングをサポートする世界初のGPUマイクロアーキテクチャです。[ 14 ]
2020年に、AMDとNvidiaは、DirectX 12 Ultimateを介してメッシュシェーディングをサポートするRDNA 2とAmpereマイクロアーキテクチャをリリースしました。[ 15 ]これらのメッシュシェーダーにより、GPUはより複雑なアルゴリズムを処理できるようになり、CPUからGPUに多くの作業をオフロードし、アルゴリズムを集中的に使用するレンダリングでは、フレームレートまたはシーン内の三角形の数を桁違いに増加させます。[ 16 ] Intelは、2022年第1四半期に出荷されるIntel Arc Alchemist GPUがメッシュシェーダーをサポートすると発表しました。[ 17 ]
レイトレーシングシェーダーは、MicrosoftではDirectX Raytracing、Khronos GroupではVulkan、GLSL、SPIR-V、[ 18 ] 、 AppleではMetalでサポートされています。NVIDIAとAMDは「レイトレーシングシェーダー」を「レイトレーシングコア」と呼んでいます。ユニファイドシェーダーとは異なり、1つのレイトレーシングシェーダーに複数のALUを含めることができます。[ 19 ]
コンピュートシェーダーはグラフィックスアプリケーションに限定されず、 GPGPUでも同じ実行リソースを使用します。アニメーションやライティングアルゴリズム(タイルフォワードレンダリングなど)の追加ステージなど、グラフィックスパイプライン内でも使用できます。一部のレンダリングAPIでは、コンピュートシェーダーがグラフィックスパイプラインとデータリソースを簡単に共有できます。
テンソルシェーダはNPUまたはGPUに統合できます。テンソルシェーダは、MicrosoftではDirectML、Khronos GroupではOpenVX、AppleではCore ML、GoogleではTensorFlow、Linux FoundationではONNXによってサポートされています。[ 20 ] NVIDIAとAMDは「テンソルシェーダ」を「テンソルコア」と呼んでいます。統合シェーダとは異なり、1つのテンソルシェーダに複数のALUを含めることができます。[ 21 ]
コンピューティング カーネルは、高スループットアクセラレータ(グラフィックス プロセッシング ユニット(GPU)、デジタル信号プロセッサ(DSP)、フィールド プログラマブル ゲート アレイ(FPGA) など) 用にコンパイルされたルーチンで、メイン プログラム (通常は中央処理装置上で実行) とは別個に使用されます。これらは、シェーディング言語で記述された「コンピューティング シェーダ」として「 OpenCL C 」などの別のプログラミング言語で指定することも、高級言語で記述されたアプリケーション コードに直接埋め込むこともできます。コンピューティング カーネルは、 GPU 上の頂点シェーダやピクセル シェーダと実行ユニットを共有するため、コンピューティング シェーダと呼ばれることもありますが、1 つのクラスのデバイスやグラフィックス API上での実行に限定されません。[ 22 ] [ 23 ]コンピューティング カーネルは、従来の言語でアルゴリズムを実装する際の内部ループ(暗黙の順次操作がないことを除く)、または内部反復子に渡されるコードにおおよそ相当します。Microsoft はこれをDirectComputeとしてサポートしています。
このプログラミングパラダイムはベクトルプロセッサによく適合します。バッチ内のカーネルの各呼び出しは独立しているという前提があり、データの並列実行が可能です。ただし、シナリオによっては、要素間の同期(相互依存的な作業)にアトミック操作が使用される場合もあります。個々の呼び出しにはインデックス(1次元または複数次元)が与えられ、そこからバッファデータの任意のアドレス指定(スキャッターギャザー操作を含む)を実行できます。ただし、重複しないという前提が守られる必要があります。
Vulkan APIは、言語およびマシンに依存しない方法でグラフィカルシェーダと計算カーネルの両方を記述するための中間表現SPIR-Vを提供します。その目的は、言語の進化を促進し、ユニファイドメモリアーキテクチャやヘテロジニアスシステムアーキテクチャなどのハードウェアの進歩に合わせて、GPUの計算能力をより自然に活用できるようにすることです。これにより、CPUとGPUのより緊密な連携が可能になります。
コード最適化の手段として、LLMによるカーネル生成の分野では多くの研究が行われてきました。スタンフォード大学のScaling Intelligence Labが開発したKernelBench [ 24 ]は、LLMが効率的なGPUカーネルを生成する能力を評価するためのフレームワークを提供しています。Cognitionは、効率的なCUDAカーネルを生成するためにKevin 32-B [ 25 ]を開発しました。これは現在、KernelBench上で最高性能のモデルとなっています。
シェーダーを記述するためのプログラミング言語は複数存在し、どの言語を使用するかはターゲット環境によって異なります。OpenGLのシェーディング言語はGLSLで、Direct3DはHLSLを使用します。Appleデバイスで使用されるMetalフレームワークには、 Metal Shading Languageと呼ばれる独自のシェーディング言語があります。
近年のグラフィックスAPIでは、シェーダーがエンドユーザーに配布される前に、中間言語であるSPIR-Vにコンパイルされることが増えています。この標準規格により、ターゲットプラットフォームに関わらず、より柔軟なシェーディング言語の選択が可能になります。[ 26 ] SPIR - VはVulkanとOpenGLで初めてサポートされ、Direct3Dでも採用されつつあります。[ 27 ]
Unity、Unreal Engine、Godotといった現代のビデオゲーム開発プラットフォームには、コードを書かずにシェーダーを作成できるノードベースのエディタがますます多く搭載されています。ユーザーには、接続されたノードの有向グラフが表示され、様々なテクスチャ、マップ、数学関数を、拡散色、鏡面反射色と強度、粗さ/金属度、高さ、法線などの出力値に反映させることができます。このグラフはシェーダーにコンパイルされます。