WebGPU シェーディング言語

W3C 勧告候補草案,

この文書の詳細
このバージョン:
https://www.w3.org/TR/2026/CRD-WGSL-20260921/
最新の公開バージョン:
https://www.w3.org/TR/WGSL/
編集者草案:
https://gpuweb.github.io/gpuweb/wgsl/
以前のバージョン:
履歴:
https://www.w3.org/standards/history/WGSL/
フィードバック:
public-gpu@w3.org 件名を「[WGSL] … メッセージのトピック …」として送信してください(アーカイブ)
GitHub
編集者:
(Google)
(Google)
元編集者:
(Apple Inc.)
(Google)
参加:
Issue を報告 (未解決の Issue)
テストスイート:
WebGPU CTS shader/

概要

WebGPU 用のシェーディング言語。

この文書のステータス

この節では、この文書の公開時点におけるステータスについて説明します。現在の W3C の公開文書およびこの 技術報告書の最新リビジョンの一覧は、W3C 標準および草案のインデックスで確認できます。

この仕様に対するフィードバックおよびコメントを歓迎します。 この仕様に関する議論には、GitHub Issues の利用を推奨します。 または、GPU for the Web Working Group のメーリングリスト public-gpu@w3.org(アーカイブ)にコメントを送信することもできます。 この草案では、ワーキンググループでまだ議論されていない保留中の課題の一部を強調表示しています。 それらが妥当であるかどうかを含め、これらの課題の結論については何も決定されていません。

この文書は、GPU for the Web Working Group によって、勧告トラックを使用した勧告候補草案として公開されました。この 文書は、少なくとも までは勧告候補のままとなります。

グループは、各機能の実装を、最新の GPU システム API 上で動作する少なくとも 2 つの配備済みブラウザーで実証することを期待しています。 テストスイートは、実装報告書の作成に使用されます。

勧告候補としての公開は、W3C およびその会員による承認を意味するものではありません。勧告候補 草案には、ワーキンググループが後続の勧告候補スナップショットに 含めることを意図している、以前の勧告候補からの変更が統合されています。

この文書は随時保守および更新されます。この文書の一部は作業中です。

この文書は、W3C 特許ポリシーの下で活動するグループによって作成されました。W3C は、グループの成果物に関連して行われた特許開示の公開リストを維持しています。 そのページには、特許を開示するための手順も記載されています。個人が、必須クレームを含むとその個人が考える特許について実際に 知っている場合、その情報をW3C 特許ポリシーの第 6 節に従って開示しなければなりません。

この文書には、2025年8月18日付 W3C プロセス文書が適用されます。

1. 序論

WebGPU Shading Language (WGSL) は、[WebGPU] のシェーダー言語です。 つまり、WebGPU API を使用するアプリケーションは、GPU 上で実行されるシェーダーと呼ばれるプログラムを WGSL を使用して表現します。

// ポイントライトでテクスチャ付きジオメトリを照明するフラグメントシェーダー。

// ストレージバッファーバインディングからのライト。
struct PointLight {
  position : vec3f,
  color : vec3f,
}

struct LightStorage {
  pointCount : u32,
  point : array<PointLight>,
}
@group(0) @binding(0) var<storage> lights : LightStorage;

// テクスチャーとサンプラー。
@group(1) @binding(0) var baseColorSampler : sampler;
@group(1) @binding(1) var baseColorTexture : texture_2d<f32>;

// 関数の引数は頂点シェーダーからの値。
@fragment
fn fragmentMain(@location(0) worldPos : vec3f,
                @location(1) normal : vec3f,
                @location(2) uv : vec2f) -> @location(0) vec4f {
  // テクスチャーからサーフェスのベースカラーをサンプリングする。
  let baseColor = textureSample(baseColorTexture, baseColorSampler, uv);

  let N = normalize(normal);
  var surfaceColor = vec3f(0);

  // シーンのポイントライトを反復処理する。
  for (var i = 0u; i < lights.pointCount; i++) {
    let worldToLight = lights.point[i].position - worldPos;
    let dist = length(worldToLight);
    let dir = normalize(worldToLight);

    // このライトのサーフェスカラーへの寄与を決定する。
    let radiance = lights.point[i].color * (1 / pow(dist, 2));
    let nDotL = max(dot(N, dir), 0);

    // ライトの寄与をサーフェスカラーに累積する。
    surfaceColor += baseColor.rgb * radiance * nDotL;
  }

  // 累積したサーフェスカラーを返す。
  return vec4(surfaceColor, baseColor.a);
}

1.1. 概要

WebGPU は、GPU コマンドの形式で作業単位を GPU に発行します。 WGSL は 2 種類の GPU コマンドを対象とします:

どちらの種類のパイプラインも、WGSL で記述されたシェーダーを使用します。

シェーダーは、 パイプライン内でシェーダー ステージを実行する WGSL プログラムの一部分です。 シェーダーは次のものから構成されます:

注: WGSL プログラムにエントリーポイントは必須ではありません。ただし、そのような プログラムは、GPUProgrammableStage の作成にエントリーポイントが必要なため、API によって実行できません。

シェーダーステージを実行するとき、実装は次のことを行います:

WGSL プログラムは次の要素で構成されます:

注: WGSL プログラムは現在、単一の WGSL モジュールで構成されます。

WGSL は命令型言語です。動作は、実行する文のシーケンスとして指定されます。 文では次のことができます:

WGSL は静的型付けです。特定の式によって計算される各値は、 プログラムソースを調べることだけで決定される特定の型に属します。

WGSL には、ブール値および数値 (整数と浮動小数点数)を記述する型があります。 これらの型は、複合型 (ベクトル、行列、 配列、および構造体)に集約できます。 WGSL には、固有の操作を提供する特殊な型(例: アトミック型)があります。 WGSL は、メモリーに格納できる型をメモリービューとして記述します。 WGSL は、一般的に使用されるレンダリング型を テクスチャーとサンプラーの形式で提供します。 これらの型には、グラフィックスレンダリング向けに一般的に提供される GPU ハードウェア機能を公開する 組み込み関数が関連付けられています。

WGSL の暗黙の変換と昇格は非常に限定されています。 暗黙の変換と昇格は、抽象 型、および関数呼び出しの引数として渡されるバッファーポインターに対してのみ提供されます。 値をある具象数値型またはブール型から 別の型へ変換するには、明示的な変換、 値コンストラクター、または ビットの再解釈が必要です。ただし、WGSL にはスカラー 型をベクトル型へ昇格するための限定的な機能があります。 これは複合型にも適用されます。

シェーダーステージの処理は、1 つ以上の呼び出しに分割され、 それぞれがエントリーポイントを実行しますが、条件はわずかに異なります。 シェーダーステージ内の呼び出しは、特定の変数へのアクセスを共有します:

ただし、呼び出しは異なるシェーダーステージ入力の集合に作用します。これには、 呼び出しを他の呼び出しと区別する識別値を提供する組み込み入力も含まれます。 各呼び出しには、private およびfunction アドレス空間内の変数という形式で、 独立した独自のメモリー空間があります。

シェーダーステージ内の呼び出しは同時に実行され、多くの場合並列に実行されることがあります。 シェーダー作者は、シェーダーステージ内の呼び出しの動的な動作が次を満たすようにする責任があります:

WGSL は、特定の機能について複数の可能な動作を許可することがあります。 異なる実装が異なる動作を示す可能性があるため、これは移植性上の危険要因です。 WGSL の設計では、このようなケースを最小限に抑えることを目指していますが、実現可能性や、 幅広いデバイスで高いパフォーマンスを実現するという目標による制約があります。

動作 要件とは、WGSL プログラムを処理または実行するときに実装が 行う動作です。これは、プログラマーとの契約における 実装の義務を記述します。 仕様では、それらの義務が他の方法では明らかでない場合に、明示的に記述します。

1.2. 構文表記

以下の構文表記は、WGSL の構文文法の規約を記述します:

1.3. 数学的な用語と表記

角度:

双曲角は、 従来の意味での角度ではなく、無次元の面積です。 具体的には:

このとき、面積 a は双曲角であり、x は a の双曲線余弦、 y は a の双曲線正弦です。

正の無限大は +∞ で表され、すべての実数より厳密に大きい一意の値です。

負の無限大は −∞ で表され、すべての実数より厳密に小さい一意の値です。

拡張実数 (アフィン拡張実数とも呼ばれます)は、実数に +∞ と −∞ を加えた集合です。 コンピューターは浮動小数点型を使用して、 両方の無限大の値を含む拡張実数を近似的に表現します。 § 15.7 浮動小数点評価を参照してください。

区間は、 下限と上限を持つ連続した数の集合です。 コンテキストに応じて、それらは整数、浮動小数点数、実数、または拡張実数の集合です。

床関数式は、 拡張実数 x に対して次のように定義されます:

天井 関数式は、拡張実数 x に対して次のように定義されます:

truncate 関数は、 拡張実数 x に対して次のように定義されます:

roundUp 関数は、 正の整数 k および n に対して次のように定義されます:

roundDown 関数は、 正の整数 k および n に対して次のように定義されます:

c 列 r 行の行列 A の転置は、 A の行を AT の列としてコピーすることによって形成される、r 列 c 行の行列 AT です:

列ベクトルの転置は、列ベクトルを 1 行の行列として解釈することで定義されます。 同様に、行ベクトルの転置は、行ベクトルを 1 列の行列として解釈することで定義されます。

2. WGSL モジュール

WGSL プログラムは単一の WGSL モジュールで構成されます。

モジュールは、任意のディレクティブのシーケンスと、それに続くモジュールスコープの宣言およびアサーションからなります。 モジュールは次の要素で構成されます:

translation_unit :

global_directive * ( global_decl | global_assert | ';' ) *

global_decl :

global_variable_decl ';'

| global_value_decl ';'

| type_alias_decl ';'

| struct_decl

| function_decl

2.1. シェーダーのライフサイクル

WGSL プログラムおよびそこに含まれる可能性のあるシェーダーのライフサイクルには、4 つの主要なイベントがあります。 最初の 2 つは、WGSL プログラムを実行用に準備するために使用される WebGPU API メソッドに対応します。 最後の 2 つは、シェーダー実行の開始と終了です。

イベントは次のとおりです:

  1. シェーダーモジュール 作成

    • これは、 WebGPU createShaderModule() メソッド が呼び出されたときに発生します。 この時点で WGSL プログラムのソーステキストが提供されます。

  2. パイプライン 作成

    • これは、 WebGPU createComputePipeline() メソッド または WebGPU createRenderPipeline() メソッド が呼び出されたときに発生します。 これらのメソッドは、以前に作成された 1 つ以上のシェーダーモジュールを、他の 設定情報とともに使用します。

    • パイプライン作成時に考慮されるのは、 GPUProgrammableStage の指定されたエントリーポイントの シェーダーを形成するコードのみです。 つまり、エントリーポイントと無関係なコードは、コンパイル前に事実上除去されます。

    • 注: 各シェーダーステージは個別に コンパイルされるものとみなされるため、 モジュールの異なる部分が含まれる場合があります。

  3. シェーダー 実行開始

  4. シェーダー実行 終了

    • これは、シェーダー内のすべての処理が完了したときに発生します:

      • そのすべての呼び出しが終了し、

      • リソースへのすべてのアクセスが完了し、

      • 出力がある場合、それが下流のパイプラインステージに渡されます。

これらのイベントは、次の理由により順序付けられます:

2.2. エラー

WebGPU 実装がシェーダーの処理に失敗する理由は 2 つあります:

処理エラーは、シェーダーのライフサイクルにおける 3 つの段階で発生する可能性があります:

注: たとえば、データ競合は検出できない場合があります。

各要件は、可能な限り早い機会に検査されます。 つまり:

コンテキストから明確でない場合、この仕様では、 特定の要件を満たさないことが シェーダー作成エラー、パイプライン作成エラー、または動的エラーのいずれを引き起こすかを示します。

エラーの結果は次のとおりです:

2.3. 診断

実装は、シェーダーモジュール作成中またはパイプライン作成中に 診断を生成できます。 診断は、 アプリケーション作者のために実装によって生成されるメッセージです。

診断は、トリガーされるとき、すなわち トリガールールと呼ばれる特定の条件が満たされたときに作成されます。 条件が満たされたソーステキスト内の場所を、ソーステキスト内の点または範囲として表したものを、 トリガー位置と呼びます。

診断には次の プロパティがあります:

診断の重大度は次のいずれかであり、高いものから低いものの順に並んでいます:

error

診断はエラーです。 これはシェーダー作成エラーまたはパイプライン作成 エラーに対応します。

warning

診断は、アプリケーション開発者が注意を払うに値する異常を記述しますが、 エラーではありません。

info

診断は、アプリケーション開発者が注意を払うに値する特筆すべき状態を記述しますが、 エラーでも警告でもありません。

off

診断は無効です。アプリケーションには通知されません。

トリガールールの名前は、次のいずれかです:

diagnostic_rule_name :

diagnostic_name_token

| diagnostic_name_token '.' diagnostic_name_token

2.3.1. 診断処理

トリガーされた診断は次のように処理されます:

  1. 各診断 D について、D のトリガー 位置を含み、同じトリガールールを持つ、 影響範囲が最も小さい診断フィルターを見つけます。

    • そのようなフィルターが存在する場合、それを D に適用し、D の重大度を更新します。

    • それ以外の場合、D は変更されません。

  2. 重大度がoff の診断を破棄します。

  3. 残っている診断の少なくとも 1 つ DI の重大度がinfo である場合:

    • 同じトリガールールを持つ他のinfo 診断を破棄し、元の診断 DI のみを残してもかまいません。

  4. 残っている診断の少なくとも 1 つ DW の重大度がwarning である場合:

    • 同じトリガールールを持つ他のinfo または warning 診断を破棄し、元の診断 DW のみを残してもかまいません。

  5. 残っている診断の少なくとも 1 つがerror 重大度を持つ場合:

  6. シェーダーモジュール作成時の処理の場合、残りの診断は WebGPU GPUCompilationInfo オブジェクトの messages メンバーに格納されます。

  7. パイプライン作成中の処理の場合、error 診断は、 GPUProgrammableStage を検証するときに WebGPU 検証失敗を引き起こします。

注: 規則では、エラーが検出されるとすぐに実装が WGSL モジュールの処理を停止することが許可されています。 さらに、特定の種類の警告の解析は最初の警告で停止でき、 特定の種類の info 診断の解析は最初の発生で停止できます。 WGSL は、異なる種類の解析を実行する順序や、単一の解析内での順序を指定しません。 したがって、同じ WGSL モジュールに対して、異なる実装が 同じ重大度を持つ診断の異なるインスタンスを報告する場合があります。

2.3.2. フィルター可能なトリガールール

ほとんどの診断は無条件に WebGPU アプリケーションへ報告されます。 一部の種類の診断は、そのトリガールールを指定することなどによって、 フィルターできます。 次の表は、フィルター可能なトリガールールの標準セットを示します。

フィルター可能な診断トリガールール
フィルター可能なトリガールール 既定の重大度 トリガー位置 説明
derivative_uniformity error 導関数を計算する組み込み関数の 任意の呼び出し サイトの位置。 つまり、次のいずれかの呼び出しの位置: 組み込み関数の呼び出しが導関数を計算するが、一様性解析で その呼び出しが一様な制御フロー内で発生することを証明できない場合。

§ 15.2 一様性を参照してください。

subgroup_uniformity error 任意のサブグループまたはクアッド 組み込み関数の呼び出し サイトの位置。 サブグループまたはクアッド組み込み関数の呼び出しだが、一様性解析で その呼び出しが一様な制御フロー内で発生することを証明できない場合。 さらに、一様性解析で次のパラメーター値が一様であることを証明できない場合:

§ 15.2 一様性を参照してください。

単一の診断 name-tokenで構成される、 認識されないトリガールールを使用した場合、ユーザーエージェントは警告を トリガーするべきです。

実装は、ここで指定されていないトリガールールをサポートしてもかまいません。 ただし、それらはdiagnostic_rule_name の複数トークン形式を使用して記述されなければなりません。 複数トークン形式で記述された認識されないトリガールールの使用自体が、 診断をトリガーしてもかまいません。

この仕様の将来のバージョンでは、特定の規則を削除したり、その既定の重大度を弱めたり (つまり、現在の既定値をより低い重大度の既定値に置き換えたり)しても、後方互換性を 満たしていると見なされる場合があります。 たとえば、WGSL の将来のバージョンでは、derivative_uniformity の既定の重大度を error から warning または info に変更する可能性があります。 仕様にそのような変更が加えられた後も、それ以前に有効だったプログラムは有効なままです。

2.3.3. 診断フィルタリング

フィルター可能なトリガールールを持つ診断が トリガーされると、WGSL は 診断を破棄したり、その重大度を変更したりするための機構を提供します。

診断フィルター DF には 3 つのパラメーターがあります:

診断フィルター DF(AR,NS,TR) を診断 D に適用すると、 次の効果があります:

範囲診断 フィルターは、診断フィルターのうち、その影響範囲が指定された ソーステキストの範囲であるものです。 範囲診断フィルターは、次の表に示すように、影響を受けるソース範囲の先頭に @diagnostic 属性として指定します。 @diagnostic 属性は、それ以外の場所に現れてはなりません。

範囲診断フィルターの配置
配置 影響範囲
複合文の先頭。 複合文。
関数宣言の先頭。 関数宣言。
if 文の先頭。 if 文: if_clause と、関連付けられたすべてのelse_if_clause およびelse_clause 節。 すべての制御条件式を含みます。
switch 文の先頭。 switch 文: セレクター式およびswitch_body。
switch_body の先頭。 switch_body。
loop 文の先頭。 loop 文。
while 文の先頭。 while 文: 条件式とループ本体の両方。
for 文の先頭。 for 文: for_header およびループ本体。
loop、while、またはfor ループのループ本体の開始波括弧('{')の直前。 ループ本体。
continuing_compound_statement の先頭。 continuing_compound_statement。

注: 次のものも複合文です: 関数本体、case 節、default-alone 節、 while およびfor ループの本体、 ならびにif_clause、else_if_clause、およびelse_clause の本体。

例: テクスチャーサンプリングに対する範囲診断フィルター
var<private> d: f32;
fn helper() -> vec4<f32> {
  // 「if」の本体で derivative_uniformity 診断を
  // 無効にする。
  if (d < 0.5) @diagnostic(off,derivative_uniformity) {
    return textureSample(t,s,vec2(0,0));
  }
  return vec4(0.0);
}

グローバル 診断フィルターを使用すると、WGSL モジュール全体に診断フィルターを適用できます。

例: 導関数の一様性に対するグローバル診断フィルター
diagnostic(off,derivative_uniformity);
var<private> d: f32;
fn helper() -> vec4<f32> {
  if (d < 0.5) {
    // ここではグローバル診断フィルターによって
    // derivative_uniformity 診断が無効にされている。
    return textureSample(t,s,vec2(0,0));
  } else {
    // derivative_uniformity 診断は 'warning' 重大度に設定される。
    @diagnostic(warning,derivative_uniformity) {
      return textureSample(t,s,vec2(0,0));
    }
  }
  return vec4(0.0);
}

2 つの診断フィルター DF(AR1,NS1,TR1) と DF(AR2,NS2,TR2) は、 次の場合に競合します:

診断フィルターは競合してはなりません。

注: 複数のグローバル診断フィルターは、 競合しない場合に許可されます。

WGSL の診断フィルターは、その影響範囲が完全に入れ子になるよう設計されています。 DF1 の影響範囲と DF2 の影響範囲が重なる場合、 DF1 の影響範囲が DF2 の影響範囲に完全に含まれるか、その逆のいずれかです。

ソース位置 L およびトリガールール TR に対する 最も近い包含診断フィルターは、存在する場合、 次を満たす診断フィルター DF(AR,NS,TR) です:

影響範囲は入れ子になるため、最も近い包含診断フィルターは:

2.4. 制限

WGSL 実装は、次の制限を満たすシェーダーをサポートします。 WGSL 実装は、指定された制限を超えるシェーダーをサポートしてもかまいません。

注: WGSL 実装は、 指定された制限を超えるシェーダーをサポートしない場合、エラーを発行するべきです。

定量化可能なシェーダー複雑度の制限
制限 サポートされる最小値
構造体型のメンバーの最大数 1023
複合型の最大ネスト 深度 15
関数内で波括弧によって囲まれた文の最大ネスト深度 127
関数のパラメーターの最大数 255
switch 文における case セレクター値の最大数。 各 case 文について、default 節を含む case 値の数を合計したもの。 1023
単一のシェーダーによって 静的にアクセスされる 、 private アドレス空間にインスタンス化された すべての変数の 合計バイトサイズの最大値 8192
単一の関数で 宣言され、 function アドレス空間にインスタンス化された すべての変数の 合計バイトサイズの最大値 8192
単一のシェーダーによって 静的にアクセスされる 、 workgroup アドレス空間にインスタンス化された すべての変数の 合計バイトサイズの最大値

この制限の目的では、 override 値を代入するとき、固定フットプリント配列は作成時固定フットプリント配列として扱われます。

これは WebGPU のmaxComputeWorkgroupStorageSize 制限を 独立した WGSL 制限に対応付けます。

16384
即時データ 変数の 最大バイトサイズ。

これは WebGPU のmaxImmediateSize 制限を 独立した WGSL 制限に対応付けます。

64
配列型の値 コンストラクター式における要素の最大数 2047

3. テキスト構造

text/wgsl メディアタイプは、コンテンツを WGSL モジュールとして識別するために使用されます。 付録 A: text/wgsl メディアタイプを参照してください。

WGSL モジュールは、バイトオーダーマーク (BOM) を持たない UTF-8 エンコーディングの Unicode テキストです。

WGSL モジュールのテキストは、Unicode コードポイントのシーケンスからなり、連続した空でない集合として次のものにグループ化されます:

プログラムテキストには null コードポイント (U+0000) を含めてはなりません。

3.1. 構文解析

WGSL モジュールを構文解析するには:

  1. コメントを削除します:

    • 最初のコメントを空白コードポイント (U+0020) に置き換えます。

    • コメントがなくなるまで繰り返します。

  2. § 3.9 テンプレートリストにあるアルゴリズムを使用して、 テンプレートリストを見つけます。 この手順では、'<' (U+003C) および '>' (U+003E) コードポイントを テンプレートリストの区切りとして使用する場合と、比較演算子など他の用途で使用する場合を曖昧さなく区別します。

  3. テキスト全体を構文解析し、translation_unit 文法規則との一致を試みます。 構文解析では、次のカスタマイズを施した LALR(1) パーサー(1 トークン先読み)[DeRemer1969]を使用します:

    • トークン化は構文解析と交互に行われ、コンテキストを認識します。 パーサーが次のトークンを要求したとき:

      • 先頭の空白コードポイントのシーケンスを消費して無視します。

      • 次のコードポイントがテンプレートリストの開始である場合、 それを消費して_template_args_start を返します。

      • 次のコードポイントがテンプレートリストの終了である場合、 それを消費して_template_args_end を返します。

      • それ以外の場合:

        • トークン候補とは、まだ消費されていないコードポイントの 空でない接頭辞から形成される任意の WGSL トークンです。

        • 返されるトークンは、現在のパーサー状態に対して有効な先読みトークンでもある、 最長のトークン 候補です。[VanWyk2007]

次の場合、シェーダー作成 エラーになります:

注:上記の手順では、 テンプレートリスト 検出を、文法ベースの構文解析(手順 3)の前に実行される独立した段階(手順 2)として記述しています。 この分離により仕様が単純になります。 ただし、トークン化の前に独立した処理段階を挿入するため、 上記の手順を一部のツールに対応付けるには不便な場合があります。

代替手法は、テンプレートリストの検出をトークン化と交互に行うことです。 この手法では、テンプレートリストが出現し得る任意の場所で、合成トークン(_disambiguate_template)を 文法規則に配置します。 スキャナーが_disambiguate_template トークンとの一致を試みるとき:

今後のトークンスキャン手順では、記録されたテンプレートリスト区切り位置を使用して、 指定どおり_template_args_start および_template_args_end トークンを生成します。

この代替手法は非規範的です。 規範的な文法には、代替手法を使用する 実装を支援するため、_disambiguate_template トークンが含まれています。 標準手法を使用するパーサーは、合成トークンを無視するか、同等に、常に 空文字列との一致に成功させることができます。

3.2. 空白と改行

空白は、 Unicode Pattern_White_Space プロパティに含まれる 1 つ以上のコードポイントの任意の組み合わせです。 次はPattern_White_Space のコードポイント集合です:

改行は、 行の終端を示す空白コードポイントの連続したシーケンスです。 これは、 UAX14 第 6.1 節「カスタマイズ不可能な改行規則」のLB4 およびLB5 で定義される「強制改行」を示す空白として定義されます。 つまり、改行は次のいずれかです:

注: 行番号を単位としてソーステキスト位置を報告する診断では、 行数を数えるために改行を 使用するべきです。

3.3. コメント

コメントは、 コメントによってトークンを分離できることを除き、 WGSL プログラムの妥当性や意味に影響を与えないテキスト範囲です。 シェーダー作者はコメントを使用してプログラムを文書化できます。

行末 コメントは、コメントの一種で、 2 つのコードポイント //(U+002F に続いて U+002F)と、それに続く コードポイントからなり、次の直前まで続きます:

ブロックコメントは、 コメントの一種で、次の要素からなります:

注: ブロックコメントはネストできます。 ブロックコメントには対応する開始テキストシーケンスと終了テキストシーケンスが必要であり、任意のネストが許可されるため、 ブロックコメントを正規表現で認識することはできません。 これは正規言語のポンピング補題から導かれる結果です。

例: コメント
const f = 1.5; // これは行末コメント。
const g = 2.5; /* これは複数行にまたがる
                ブロックコメント。
                /* ブロックコメントはネストできる。
                 */
                ただし、すべてのブロックコメントは終了しなければならない。
               */

3.4. トークン

トークンは、 次のいずれかを形成する連続したコードポイントのシーケンスです:

3.5. リテラル

リテラルは次のいずれかです:

literal :

int_literal

| float_literal

| bool_literal

3.5.1. ブールリテラル

例: ブールリテラル
const a = true;
const b = false;
bool_literal :

'true'

| 'false'

3.5.2. 数値リテラル

数値 リテラルの形式は、パターンマッチングによって定義されます。

整数リテラルは:

注: 0 ではない整数リテラルの先頭に 0 を付けること(例: 012)は禁止されています。 これは、他の言語で「先頭の 0 は 8 進数を意味する」という表記との混同を避けるためです。

int_literal :

decimal_int_literal

| hex_int_literal

decimal_int_literal :

/0[iu]?/

| /[1-9][0-9]*[iu]?/

例: 10 進整数リテラル
const a = 1u;
const b = 123;
const c = 0;
const d = 0i;
hex_int_literal :

/0[xX][0-9a-fA-F]+[iu]?/

例: 16 進整数リテラル
const a = 0x123;
const b = 0X123u;
const c = 0x3f;

浮動小数点 リテラルは、10 進浮動小数点リテラル または16 進浮動小数点リテラルのいずれかです。

float_literal :

decimal_float_literal

| hex_float_literal

浮動小数点 リテラルには、論理的に 2 つの部分があります。小数を表す仮数部と、任意の指数部です。 おおまかには、リテラルの値は、仮数部に底の値を指定された指数で累乗したものを掛けた値です。 仮数部の桁が 0 ではない場合、またはその左右の仮数部の桁の両方が 0 ではない場合、 その桁を有効とします。 有効桁は左から右に数えます。N 番目の有効桁の左側には N-1 個の 有効桁があります。

10 進 浮動小数点リテラルは:

decimal_float_literal :

/0[fh]/

| /[1-9][0-9]*[fh]/

| /[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[fh]?/

| /[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?[fh]?/

| /[0-9]+[eE][+-]?[0-9]+[fh]?/

例: 10 進浮動小数点リテラル
const a = 0.e+4f;
const b = 01.;
const c = .01;
const d = 12.34;
const f = .0f;
const g = 0h;
const h = 1e-3;
10 進浮動小数点リテラルの数学的な値は、次のように計算されます:

注: 10 進の仮数部は 20 桁の 10 進数字の後で切り捨てられ、小数部にはおよそ log(10)/log(2)×20 ≈ 66.4 有効ビットが保持されます。

16 進浮動小数点リテラルは:

hex_float_literal :

/0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+([pP][+-]?[0-9]+[fh]?)?/

| /0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*([pP][+-]?[0-9]+[fh]?)?/

| /0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?/

例: 16 進浮動小数点リテラル
const a = 0xa.fp+2;
const b = 0x1P+4f;
const c = 0X.3;
const d = 0x3p+2h;
const e = 0X1.fp-4;
const f = 0x3.2p+2h;
16 進浮動小数点リテラルの数学的な値は、 次のように計算されます:

注: 16 進の仮数部は 16 桁の 16 進数字の後で切り捨てられ、小数部にはおよそ 4 ×16 = 64 有効ビットが保持されます。

数値リテラルに 接尾辞がある場合、そのリテラルは特定の具象スカラー型の値を表します。 それ以外の場合、リテラルは以下で定義される抽象数値型のいずれかの値を表します。 どちらの場合も、リテラルが表す値は、その数学的な値を対象型に変換した後の値であり、 § 15.7.6 浮動小数点変換の規則に従います。

数値リテラルから型への対応付け
数値リテラル 接尾辞 型 例
整数 リテラル i i32 42i
整数 リテラル u u32 42u
整数 リテラル AbstractInt 124
浮動小数点リテラル f f32 42f 1e5f 1.2f 0x1.0p10f
浮動小数点リテラル h f16 42h 1e5h 1.2h 0x1.0p10h
浮動小数点リテラル AbstractFloat 1e5 1.2 0x1.0p10

次の場合、シェーダー作成 エラーになります:

注: 16 進浮動小数点値 0x1.00000001p0 を 正確に表現するには 33 個の仮数ビットが必要ですが、 f32 には明示的な仮数ビットが 23 個しかありません。

注: f 接尾辞を使用して 16 進浮動小数点リテラルの型を強制したい場合、そのリテラルでは 2 進指数も使用する必要があります。たとえば 0x1p0f と記述します。これに対して、0x1f は 16 進整数リテラルです。

3.6. キーワード

キーワードは、 事前定義された言語概念を参照するトークンです。 WGSL キーワードの一覧については、§ 16.1 キーワード概要を参照してください。

3.7. 識別子

識別子は、 名前として使用されるトークンの一種です。 § 5 宣言とスコープを参照してください。

WGSL は、ユースケースを分離するために 2 つの文法非終端記号を使用します:

ident :

ident_pattern_token _disambiguate_template

member_ident :

ident_pattern_token

識別子の形式は、 Unicode 標準附属書 #31の Unicode バージョン 14.0.0 に基づき、次の詳細化を加えています。

識別子は、UAX31 文法の観点から記述される 次のプロファイルを使用します:

<Identifier> := <Start> <Continue>* (<Medial> <Continue>+)*

<Start> := XID_Start + U+005F
<Continue> := <Start> + XID_Continue
<Medial> :=

これは、次のような非 ASCII コードポイントを含む識別子が 有効であることを意味します: Δέλτα、réflexion、Кызыл、𐰓𐰏𐰇、 朝焼け、سلام、검정、שָׁלוֹם、गुलाबी、 փիրուզ。

ただし、次の例外があります:

ident_pattern_token :

/([_\p{XID_Start}][\p{XID_Continue}]+)|([\p{XID_Start}])/u

Unicode バージョン 14.0.0 の Unicode 文字データベースには、 XID_Start と XID_Continue の両方について、 すべての有効なコードポイントを含む非規範的な一覧があります。

注: 一部の組み込み関数の戻り値の型は、その名前を WGSL ソースで使用できない構造体型です。 それらの構造体型は、2 つのアンダースコアで始まる名前を持つ事前宣言済みであるかのように記述されます。 結果値は、型推論を使用して新たに宣言された let または var に保存するか、 そのメンバーの 1 つを名前によって直ちに 取り出すことができます。使用例については frexp および modf の説明を参照してください。

3.7.1. 識別子の比較

2 つの WGSL 識別子は、同じコードポイントのシーケンスから構成される場合に限り、同一です。

注: この仕様では、比較を目的とした値の Unicode 正規化を許可しません。 視覚的および意味的に同一でも、異なる Unicode 文字シーケンスを使用する値は 一致しません。 コンテンツ作者には、同じエンコーディングシーケンスを一貫して使用するか、 値を選択するときに問題を引き起こす可能性のある 文字を避けることを推奨します。詳細については、[CHARMOD-NORM]を参照してください。

注: 識別子のすべてのインスタンスを その識別子の同形異義文字のいずれかで置き換えた場合に WGSL モジュールの意味が変わるなら、 ユーザーエージェントは開発者から見える警告を発行するべきです。 (同形異義文字とは、別のコードポイントシーケンスと読者には同じように見える可能性があるコードポイントのシーケンスです。 同形異義文字を検出するための対応付けの例としては、前段落で述べた 変換、対応付け、およびマッチングアルゴリズムがあります。 識別子が部分シーケンスをその同形異義文字で繰り返し置き換えることで一方を他方に 変換できる場合、2 つのコードポイントシーケンスは同形異義です。)

3.8. コンテキスト依存名

コンテキスト依存 名は、概念に名前を付けるために使用されるトークンですが、 特定の文法的コンテキストでのみ使用されます。 トークンの綴りは識別子と同じ場合がありますが、そのトークンは宣言されたオブジェクトに解決されません。 この節では、コンテキスト依存名として使用されるトークンを列挙します。 トークンはキーワードまたは予約語であってはなりません。

3.8.1. 属性名

§ 12 属性を参照してください。

属性名は次のとおりです:

3.8.2. 組み込み値名

組み込み値 name-tokenは、組み込み値の 名前で使用されるトークンです。

§ 13.3.1.1 組み込み入力と出力を参照してください。

builtin_value_name :

ident_pattern_token

組み込み値名は 次のとおりです:

3.8.3. 診断ルール名

診断 name-tokenは、診断のトリガールールの名前で使用されるトークンです。

§ 2.3 診断を参照してください。

diagnostic_name_token :

ident_pattern_token

事前定義された診断ルール名は次のとおりです:

3.8.4. 診断重大度制御名

有効な診断 フィルターの重大度制御名は§ 2.3 診断に列挙されていますが、 識別子と同じ形式を持ちます:

severity_control_name :

ident_pattern_token

診断フィルターの 重大度制御名は次のとおりです:

3.8.5. 拡張名

有効なenable-extension 名は§ 4.1.1 Enable 拡張に列挙されていますが、一般には 識別子と同じ形式を持ちます:

enable_extension_name :

ident_pattern_token

enable-extension 名は次のとおりです:

有効な言語 拡張名は§ 4.1.2 言語拡張に列挙されていますが、 一般には識別子と同じ形式を持ちます:

language_extension_name :

ident_pattern_token

言語 拡張名は次のとおりです:

3.8.6. 補間型名

補間型 name-tokenは、interpolate_type_name の補間型の名前で使用されるトークンです。

§ 13.3.1.4 補間を参照してください。

補間 型名は次のとおりです:

3.8.7. 補間サンプリング名

補間サンプリング name-tokenは、補間 サンプリングの名前で使用されるトークンです。

§ 13.3.1.4 補間を参照してください。

interpolate_sampling_name :

ident_pattern_token

補間 サンプリング名は次のとおりです:

3.8.8. スウィズル名

スウィズル名は、ベクトルアクセス式およびスウィズルビュー 式で使用されます:

swizzle_name :

/[rgba]/

| /[rgba][rgba]/

| /[rgba][rgba][rgba]/

| /[rgba][rgba][rgba][rgba]/

| /[xyzw]/

| /[xyzw][xyzw]/

| /[xyzw][xyzw][xyzw]/

| /[xyzw][xyzw][xyzw][xyzw]/

3.8.9. 深度モード名

深度モード name-tokenは、fragment_depth 機能がサポートされている場合に、 frag_depth 組み込みで使用されるトークンです。

3.9. テンプレートリスト

テンプレート パラメーター化は、一般的な概念を変更するパラメーターを指定する方法です。 テンプレートパラメーター化を記述するには、一般的な概念に続けてテンプレートリストを記述します。

コメントと空白を無視すると、テンプレートリストは次のものです:

テンプレート パラメーターの形式は、以下のテンプレートリスト検出アルゴリズムによって暗黙的に定義されます。 一般に、それらは名前、式、または型です。

注: たとえば、vec3<f32> という句は テンプレートパラメーター化であり、vec3 は変更される一般的な概念で、 <f32> は 1 つのパラメーターであるf32 型を含むテンプレートリストです。 これらを合わせた vec3<f32> は、特定のベクトル型を表します。

注: たとえば、 var<storage,read_write> という句は、一般的な var 概念を テンプレートパラメーター storage および read_write で変更します。

注:たとえば、array<vec4<f32>> という句には 2 つの テンプレートパラメーター化があります:

テンプレートリストを区切る '<' (U+003C) および '>' (U+003E) コードポイントは、 次の記述にも使用されます:

構文上の曖昧さは、テンプレートリストを優先して解決されます:

テンプレート リスト検出アルゴリズムを以下に示します。 これは次の仮定および特性を使用します:

  1. テンプレート パラメーターは式であるため、 '<' (U+003C) または '=' (U+003D) コードポイントのいずれでも始まりません。

  2. 式には、';' (U+003B)、'{' (U+007B)、または ':' (U+003A) コードポイントは含まれません。

  3. 式には代入は含まれません。

  4. '=' (U+003D) コードポイントが現れるのは、比較操作の一部として、 つまり次のいずれかの場合のみです: '<='、 '>='、 '=='、または '!='。 それ以外の場合、'=' (U+003D) コードポイントは代入の一部として現れます。

  5. テンプレートリスト区切りは、括弧 '(...)' および配列インデックス '[...]' によって形成されるネストした式を考慮します。 テンプレートリストの開始と終了は同じネストレベルに現れなければなりません。

アルゴリズム: テンプレートリスト検出

入力: プログラムのソーステキスト。

レコード型:

UnclosedCandidate を、次を含むレコード型とします:

TemplateList を、次を含むレコード型とします:

出力: DiscoveredTemplateLists、TemplateList レコードのリスト。

手順:

注:アルゴリズムは、テンプレート パラメーターのソース範囲を検出するよう、次のように変更できます:

注: 一部の数値リテラルは、たとえば 1.0f のように 文字で終わるため、アルゴリズムはリテラルを明示的に読み飛ばします。 終端の f をident_pattern_token の開始と誤認してはなりません。

注: A ( B < C, D > ( E ) ) という句では、< C, D > の部分はテンプレートリストです。

注: アルゴリズムは式のネストを考慮します。特定の テンプレートリストの開始と終了が異なる式ネストレベルに現れることはできません。 たとえば、array<i32,select(2,3,a>b)> ではテンプレートリストに 3 つのパラメーターがあり、 最後のパラメーターは select(2,3,a>b) です。 a>b 内の '>' は、select 関数を呼び出す式の括弧付き部分内に あるため、テンプレートリストを終了しません。

注: テンプレートリストの両端は、同じ インデックス 式内に現れなければなりません。たとえば a[b<d]>() には有効なテンプレートリストは含まれません。

注: A<B<<C> という句では、 B<<C という句は B、左シフト演算子'<<'、C の順として構文解析されます。 テンプレート検出アルゴリズムは B、続いて '<' (U+003C) を調べ始めますが、 次の '<' (U+003C) コードポイントがテンプレート引数を開始できないことを確認するため、 B の直後の '<' はテンプレートリストの開始ではありません。 最初の '<' と最後の '>' のみがテンプレートリストの区切りであり、 テンプレートパラメーターは B<<C です。

注: A<B<=C> という句も 前の注記と同様に解析されるため、B<=C という句は B、小なりイコール演算子'<='、C の順として構文解析されます。 テンプレート検出アルゴリズムは B、続いて '<' (U+003C) を調べ始めますが、 次の '=' (U+003D) コードポイントがテンプレート引数を開始できないことを確認するため、 B の直後の '<' はテンプレートリストの開始ではありません。 最初の '<' と最後の '>' のみがテンプレートリストの区切りであり、 テンプレートパラメーターは B<=C です。

注: A<(B>=C)> という句を調べると、最初の '<' (U+003C) コードポイントから始まり、最後の '>' (U+003E) コードポイントで終わる 1 つのテンプレートリストがあり、 テンプレート引数は B>=C です。 最初の '>' (U+003C) コードポイント(B の後)を調べた後、 '=' (U+003D) コードポイントが代入の一部であるとみなされないよう、特別に認識する必要があります。

注: A<(B!=C)> という句を調べると、最初の '<'' (U+003C) コードポイントから始まり、最後の '>' (U+003E) コードポイントで終わる 1 つのテンプレートリストがあり、 テンプレート引数は B!=C です。 '!' (U+0021) コードポイント('B' の後)を調べた後、 '=' (U+003D) コードポイントが代入の一部であるとみなされないよう、特別に認識する必要があります。

注: A<(B==C)> という句を調べると、最初の '<' (U+003C) コードポイントから始まり、最後の '>' (U+003E) コードポイントで終わる 1 つのテンプレートリストがあり、 テンプレート引数は B==C です。 最初の '=' (U+003D) コードポイント('B' の後)を調べた後、2 番目の '=' (U+003D) コードポイントを特別に認識し、どちらも代入の一部であるとみなされないようにする必要があります。

テンプレート リスト検出が完了した後、 構文解析は、各テンプレートリストをtemplate_list 文法規則と一致させようとします。

template_list :

_template_args_start template_arg_comma_list _template_args_end

template_arg_comma_list :

template_arg_expression ( ',' template_arg_expression ) * ',' ?

template_arg_expression :

expression

4. ディレクティブ

ディレクティブは、 WebGPU 実装による WGSL プログラムの処理方法を変更するトークンシーケンスです。

ディレクティブは任意です。 存在する場合、すべてのディレクティブは、あらゆる宣言またはconst アサーションより前に現れなければなりません。

global_directive :

diagnostic_directive

| enable_directive

| requires_directive

4.1. 拡張

WGSL は時間とともに進化することが想定されています。

拡張は、 WGSL 仕様に対する一貫した変更の集合に名前を付けてグループ化したものであり、 次の任意の組み合わせからなります:

仮に、拡張では次のことが可能です:

拡張には 2 種類あります: enable-extension と言語拡張です。

4.1.1. 拡張の有効化

enable-extensionは、 次のすべてを満たす場合にのみ機能を利用できる拡張です:

Enable-extensionは、 普遍的にはサポートされていないハードウェア機能を公開することを目的としています。

enable ディレクティブは、 1 つ以上の enable-extension のサポートを有効にするディレクティブです。 実装が列挙された enable-extension のすべてをサポートしていない場合、シェーダー作成 エラーになります。

enable_directive :

'enable' enable_extension_list ';'

enable_extension_list :

enable_extension_name ( ',' enable_extension_name ) * ',' ?

他のディレクティブと同様に、enable ディレクティブが存在する場合、それはすべての宣言およびconst アサーションより前に現れなければなりません。 拡張名は識別子ではありません: 宣言に解決されません。

有効なenable-extensionを次の表に示します。

Enable-extension
WGSL enable-extension WebGPU GPUFeatureName 説明
f16 "shader-f16" f16 型を WGSL モジュール内で有効に使用できます。 それ以外の場合、f16 を (直接または間接的に)使用するとシェーダー作成エラーになります。
clip_distances "clip-distances" 組み込み変数clip_distances を WGSL モジュール内で有効に使用できます。それ以外の場合、clip_distances を使用すると シェーダー作成エラーになります。
dual_source_blending "dual-source-blending" 属性blend_src を WGSL モジュール内で有効に使用できます。 それ以外の場合、 blend_src を使用するとシェーダー作成 エラーになります。
subgroups "subgroups" WGSL モジュール内でサブグループ組み込み値、 サブグループ組み込み関数、および クアッド組み込み関数を有効に使用できます。 それ以外の場合、いずれを使用してもシェーダー作成エラーになります。
primitive_index "primitive-index" 組み込み変数primitive_index を WGSL モジュール内で有効に使用できます。それ以外の場合、primitive_index を使用すると シェーダー作成エラーになります。
subgroup_size_control "subgroup-size-control" 属性subgroup_size を WGSL モジュール内で有効に使用できます。 それ以外の場合、subgroup_size を使用するとシェーダー作成エラーになります。 subgroup_size_control が有効になると、 subgroups も自動的に有効になります。
atomic_vec2u_min_max "atomic-vec2u-min-max" 組み込み関数 atomicStoreMin および atomicStoreMax を、storage アドレス空間内のatomic<vec2<u32>> 型に対して有効に使用できます。それ以外の場合、これらを使用すると シェーダー作成エラーになります。
例: 仮想的な enable-extension の使用
// 任意精度浮動小数点型のための仮想的な拡張を有効にする。
enable arbitrary_precision_float;
enable arbitrary_precision_float; // 冗長な enable ディレクティブでも問題ない。

// 丸めモードを制御するための仮想的な拡張を有効にする。
enable rounding_mode;

// arbitrary_precision_float により次の使用が有効になると仮定する:
//    - 型 f<E,M>
//    - 関数の戻り値、仮引数、および let 宣言における型として
//    - AbstractFloat からの値コンストラクターとして
//    - 除算演算子 / のオペランドとして
// @rounding_mode 属性が rounding_mode enable ディレクティブによって有効になると仮定する。
@rounding_mode(round_to_even)
fn halve_it(x : f<8, 7>) -> f<8, 7> {
  let two = f<8, 7>(2);
  return x / 2; // 最近接偶数への丸めモードを使用する。
}

4.1.2. 言語拡張

言語拡張は、 実装がサポートしている場合に自動的に利用可能になる拡張です。 プログラムが明示的に要求する必要はありません。

言語拡張は、 どの WebGPU 実装でも合理的にサポートできる機能を具体化します。 機能が普遍的にサポートされていない場合、それは一部の WebGPU 実装がまだ実装していないためです。

注: たとえば、do-while ループは言語 拡張になり得ます。

WebGPU GPU オブジェクトの wgslLanguageFeatures メンバーは、実装がサポートする 言語拡張の集合を列挙します。

requires-directiveは、 プログラムによる 1 つ以上の言語拡張の使用を文書化するディレクティブです。 実装が公開する機能は変更しません。 実装が必須拡張のいずれかをサポートしていない場合、シェーダー作成 エラーになります。

WGSL モジュールは、requires-directive を使用して、移植性がない可能性を示し、 移植性に対する意図された最低条件を示すことができます。

注: WebGPU 実装の外部にあるツールは、 プログラムで使用されるすべての言語拡張が、そのプログラム内のrequires-directiveによって網羅されているかどうかを確認できます。

requires_directive :

'requires' language_extension_list ';'

language_extension_list :

language_extension_name ( ',' language_extension_name ) * ',' ?

他のディレクティブと同様に、requires-directive が存在する場合、それはすべての宣言およびconst アサーションより前に現れなければなりません。 拡張名は識別子ではありません: 宣言に解決されません。

言語拡張
WGSL 言語拡張 説明
readonly_and_readwrite_storage_textures ストレージテクスチャーで、 read およびread_write アクセスモードを使用できるようにします。 さらに、textureBarrier 組み込み関数を追加します。
packed_4x8_integer_dot_product dot4U8Packed および dot4I8Packed 組み込み関数を使用する内積命令への入力として、 4 成分の 8 ビット整数ベクトルをパックした 32 ビット整数スカラーの使用をサポートします。 さらに、pack4xI8、pack4xU8、 pack4xI8Clamp、pack4xU8Clamp、 unpack4xI8、およびunpack4xU8 組み込み関数による、4 成分の 8 ビット整数ベクトルをパックしたパッキングおよびアンパッキング命令を追加します。
unrestricted_pointer_parameters ユーザー定義関数から、次の制限を削除します:

ユーザー定義関数では、ポインター型のパラメーターは 次のいずれかのアドレス空間になければなりません:

ユーザー定義関数へのポインター型の各引数は、 そのルート 識別子と同じメモリービューを持たなければなりません。

pointer_composite_access ルート式がポインターであり、参照を生成する複合値 分解式をサポートします。

たとえば、p がメンバー m を持つ構造体へのポインターの場合、 p.m は、p が指す構造体内の m の メモリー位置への参照です。

同様に、pa が配列へのポインターの場合、pa[i] は、 pa が指す配列の i 番目の要素の メモリー位置への参照です。

uniform_buffer_standard_layout uniform アドレス空間内のバッファーが、 他のアドレス空間と同じメモリーレイアウト制約を使用できるようにします。
subgroup_id subgroups 拡張が有効な場合に、subgroup_id およびnum_subgroups 組み込み値を使用できるようにします。
subgroup_uniformity サブグループおよび クアッド組み込み関数の一様な制御フローに対して、 同じサブグループ内の すべての呼び出しを対象とする追加のスコープ「subgroup」を追加します。

注: サブグループおよびクアッド 組み込み関数を使用するには、 subgroups 拡張が有効である必要があります。

texture_and_sampler_let let 宣言の実効値型を、 テクスチャーまたはサンプラー型にできるようにします。
texture_formats_tier1 追加のテクセル フォーマットをサポートします: rgba16unorm, rgba16snorm, rg8unorm, rg8snorm, rg8uint, rg8sint, rg16unorm, rg16snorm, rg16uint, rg16sint, rg16float, r8unorm, r8snorm, r8uint, r8sint, r16unorm, r16snorm, r16uint, r16sint, r16float, rgb10a2unorm, rgb10a2uint, rg11b10ufloat
linear_indexing global_invocation_index および workgroup_index 組み込み値をサポートします。
immediate_address_space immediate アドレス空間を有効にし、 変数を var<immediate> で宣言して、 WebGPU API を介してコマンドエンコーダーから直接渡される、少量で頻繁に更新されるデータに バインドできるようにします。
fragment_depth frag-depth 組み込みに、 depth_mode という新しい組み込みパラメーターを導入します。 モードはless およびgreater で、 フラグメントシェーダーが、既存の深度より小さい(または大きい)ことが 保証された深度値のみを書き込むと宣言するときに使用されます。
buffer_view buffer 型および buffer_view 組み込み関数の使用を有効にします。

他のホスト共有可能型として再解釈できる不透明な格納型を持つ 変数の宣言を可能にします。

swizzle_assignment スウィズルビュー 型をサポートします。

これによりスウィズル代入が有効になります: 単一の代入文で、ベクトル全体を更新することなく、 ベクトルの複数の成分を更新できます。

たとえば、変数 v が 4 要素ベクトルの場合、 v.xz = vec2(1,2); は v.x = 1; v.z = 2; を、1 回の読み取りと 1 回の書き込みで実行する 短縮記法です。

pointer_composite_access もサポートされている場合、 これはポインターでも機能します。p が少なくとも 3 要素を持つベクトルへのポインターの場合、 p.xz = vec2(1,2); は (*p).x = 1; (*p).z = 2; の短縮記法です。

atomic_vec2u_min_max atomic<vec2<u32>> オブジェクトに対する atomicStoreMin および atomicStoreMax 組み込み関数をサポートします。

注: 意図としては、時間の経過とともに WGSL が、 その時点で一般的にサポートされている言語拡張内のすべての機能を具体化する言語拡張を定義することです。 requires-directive では、これらは そのような一般的な機能をすべて列挙するための短縮記法として機能します。 それらは段階的に増加する機能の集合を表し、ある意味では言語バージョンと考えることができます。

4.2. グローバル診断フィルター

グローバル診断 フィルターは、影響範囲が WGSL モジュール全体である診断フィルターです。 これはディレクティブであるため、 あらゆるモジュールスコープ 宣言より前に現れます。 属性形式と同じように記述しますが、先頭の @ (U+0040) コードポイントはなく、 末尾にセミコロンが付きます。

diagnostic_directive :

'diagnostic' diagnostic_control ';'

5. 宣言とスコープ

宣言は、 識別子を次のいずれかの種類の オブジェクトに関連付けます:

言い換えると、宣言はオブジェクトの名前を導入します。

宣言がプログラムソース内に現れるものの、他の宣言のテキストの外側にある場合、 その宣言はモジュール スコープにあります。

関数宣言は モジュールスコープに現れます。 関数宣言は、仮引数がある場合にはその宣言を含み、 またその本体内に 変数および値の宣言を含む場合があります。 したがって、それらの包含された宣言はモジュールスコープにはありません。

注: 別の宣言を含む唯一の種類の宣言は、 関数宣言です。

特定のオブジェクトは WebGPU 実装によって提供され、 WGSL モジュールのソース開始前に宣言されているかのように扱われます。 このようなオブジェクトを事前宣言済みと呼びます。 たとえば、WGSL は次を事前宣言します:

宣言のスコープとは、 宣言された識別子が関連付けられたオブジェクトを表し得る プログラムソース位置の集合です。 それらのソース位置では、その識別子が宣言のスコープ内にあるといいます。

宣言が現れる場所によって、そのスコープが決まります:

同じ WGSL ソースプログラム内の 2 つの宣言は、同時に次を満たしてはなりません:

注: 事前宣言済みオブジェクトには WGSL ソース内の 宣言がありません。 したがって、モジュールスコープまたは関数内のユーザー指定宣言は、事前宣言済み オブジェクトと同じ名前を持つことができます。

識別子は、文法的コンテキストによって区別され、次のように使用されます:

別の場所で宣言されたオブジェクトを表す名前としてident トークンが現れる場合、それはいずれかの宣言についてスコープ内になければなりません。 識別子トークンが表すオブジェクトは次のように決定されます:

上記のアルゴリズムを使用して識別子を宣言に対応付ける場合、その識別子がその宣言に 解決されるといいます。 同様に、識別子が宣言されたオブジェクトに解決されるともいいます。

いずれかのモジュールスコープ宣言が再帰的である場合、 シェーダー作成エラーになります。 つまり、宣言間に循環が存在してはなりません:

次の有向グラフを考えます:

このグラフに循環があってはなりません。

注: 関数本体は関数宣言の一部であるため、 関数は直接的にも間接的にも再帰的であってはなりません。

注: 非モジュールスコープの識別子宣言は、 テキスト内でその使用より前に置かれなければなりません。

例: 有効および無効な宣言
// 有効。ユーザー定義変数は組み込み関数と同じ名前を持つことができる。
var<private> modf: f32 = 0.0;

// 有効。foo_1 はプログラム全体でスコープ内にある。
var<private> foo: f32 = 0.0; // foo_1

// 有効。bar_1 はプログラム全体でスコープ内にある。
var<private> bar: u32 = 0u; // bar_1

// 有効。my_func_1 はプログラム全体でスコープ内にある。
// 有効。foo_2 は関数の終端までスコープ内にある。
fn my_func(foo: f32) { // my_func_1, foo_2
  // 'foo' へのあらゆる参照は関数パラメーターに解決される。

  // 無効。modf はモジュールスコープ変数に解決される。
  let res = modf(foo);

  // 無効。foo_2 のスコープは関数の終端で終了する。
  var foo: f32; // foo_3

  // 有効。bar_2 は関数の終端までスコープ内にある。
  var bar: u32; // bar_2
  // 'bar' への参照は bar_2 に解決される。
  {
    // 有効。foo_4 は複合文の終端までスコープ内にある。
    var foo : f32; // foo_4

    // 有効。bar_3 は複合文の終端までスコープ内にある。
    var bar: u32; // bar_3
    // 'bar' への参照は bar_3 に解決される。
    
    // 無効。bar_4 は bar_3 と同じスコープ終了位置を持つ。
    var bar: i32; // bar_4

    // 有効。i_1 は for ループの終端までスコープ内にある。
    for ( var i: i32 = 0; i < 10; i++ ) { // i_1
      // 無効。i_2 は i_1 と同じスコープ終了位置を持つ。
      var i: i32 = 1; // i_2.
    }
  }

  // 無効。bar_5 は bar_2 と同じスコープ終了位置を持つ。
  var bar: u32; // bar_5

  // 有効。モジュールスコープ宣言 later_def はプログラム全体でスコープ内にある。
  var early_use : i32 = later_def;
}

// 無効。bar_6 は bar_1 と同じスコープを持つ。
var<private> bar: u32 = 1u; // bar_6

// 無効。my_func_2 は my_func_1 と同じスコープ終了位置を持つ。
fn my_func() { } // my_func_2

// 有効。my_foo_1 はプログラム全体でスコープ内にある。
fn my_foo( //my_foo_1
  // 有効。my_foo_2 は関数の終端までスコープ内にある。
  my_foo: i32 // my_foo_2
) { }

var<private> later_def : i32 = 1;
例: 事前宣言済みオブジェクトのシャドーイング
// この宣言は、事前宣言済みの 'min' 組み込み関数を隠す。
// この宣言はモジュールスコープにあるため、ソース全体でスコープ内にある。
// 組み込み関数にはアクセスできなくなる。
fn min() -> u32 { return 0; }

const rgba8unorm = 12; // これは事前宣言済みの 'rgba8unorm' 列挙子をシャドーイングする。

6. 型

プログラムは値を計算します。

WGSL において、型は 値の集合であり、各値は正確に 1 つの型に属します。 値の型は、その値に対して実行できる操作の構文とセマンティクスを決定します。

たとえば、数学的な数 1 は、WGSL では次の異なる値に対応します:

WGSL は、これらのマシン表現と操作が異なるため、別々のものとして扱います。

一部の型は不透明です。 これは、その値が実装定義の表現を持ち、 WGSL プログラム内で直接検査、分解、または操作できないことを意味します。

型は事前宣言済みであるか、 WGSL ソース内の宣言によって作成されます。

一部の型はテンプレートパラメーター化として表現されます。 型ジェネレーターは、 テンプレート リストでパラメーター化されたときに型を表す事前宣言済みオブジェクトです。 たとえば、型 atomic<u32> は、型ジェネレーター atomic と テンプレートリスト <u32> を組み合わせています。

型という概念と、その型を表す WGSL の構文とを区別します。 多くの場合、この仕様での型の綴りは WGSL 構文と同じです。 たとえば:

一部の WGSL 型は、ソースプログラムの解析と プログラムの実行時動作の決定にのみ使用されます。 この仕様ではそのような型について説明しますが、WGSL ソーステキストには現れません。

注: 参照型は WGSL モジュールには記述されません。§ 6.5.3 参照型とポインター型を参照してください。

注: スウィズルビュー型は WGSL モジュールには記述されません。§ 6.5.4 スウィズルビュー型を参照してください。

6.1. 型チェック

WGSL の値は、式を評価することによって計算されます。 式は、 名前が「expression」で終わる WGSL 文法規則のいずれかとして 構文解析されたソーステキストの一部分です。 式 E は、外側の式 E に適切に含まれる式である 部分式を含むことができます。 トップレベル 式は、それ自体が部分式ではない式です。 § 8.19 式文法の概要を参照してください。

式の評価によって生成される具体的な値は、次に依存します:

特定の式を評価した結果として得られる可能性のある値は、常に特定の WGSL 型に属します。これを式の静的型 と呼びます。 WGSL の規則は、式の静的型が式の静的 コンテキストのみに依存するように設計されています。

型アサーションは、 ある WGSL ソース式から WGSL 型への対応付けです。 次の表記

e : T

は、T が WGSL 式 e の静的型であることを意味する型アサーションです。

注: 型アサーションは、プログラムの テキストに関する事実の記述です。 実行時チェックではありません。

文では式が頻繁に使用され、それらの式の静的型に要件が課される場合があります。 たとえば:

正常に構文解析された WGSL モジュールの型チェックとは、 各式をその静的型に対応付け、 各文の型要件が満たされていることを検証するプロセスです。 型チェックが失敗すると、シェーダー作成エラーの特殊な場合である 型エラーになります。

型チェックは、構文句に型規則を再帰的に適用することで実行できます。ここで、 構文句とは、式または文のいずれかです。 型規則は、 構文句の静的コンテキストが、 その句に含まれる式の静的型をどのように決定するかを記述します。 型規則には 2 つの部分があります:

型規則は、その前提条件と結論に型 パラメーターを持つ場合があります。 型規則の結論または前提条件に型パラメーターが含まれる場合、その規則は パラメーター化されているといいます。 含まれない場合、その規則は完全に具体化されているといいます。 パラメーター化された型規則から、各型パラメーターに型を代入することで、 完全に具体化された型規則を作成できます。 このとき、規則内の同じパラメーターのすべての出現箇所には同じ型を使用します。 規則の型パラメーターへの型の割り当てを 代入と呼びます。

たとえば、次は論理否定 (!e 形式の式)の型規則です:

前提条件 結論
e: T
T は bool または vecN<bool>
!e: T

これは型パラメーター T を含むため、パラメーター化された規則です。 T は次の 4 つの型のいずれかを表すことができます: bool、vec2<bool>、 vec3<bool>、または vec4<bool>。 T を vec3<bool> に対応付ける代入を適用すると、 次の完全に具体化された型規則が生成されます:

前提条件 結論
e: vec3<bool>
!e: vec3<bool>

規則のその他の条件を満たす何らかの代入を適用することで パラメーター化された規則から生成できる各完全に具体化された規則を、 そのパラメーター化された規則のオーバーロードと呼びます。 たとえば、ブール否定規則には 4 つのオーバーロードがあります。 これは、その型パラメーター T に型を割り当てる方法が 4 通りあるためです。

注: 言い換えると、パラメーター化された型規則は、 完全に具体化された型規則の集合に対するパターンを提供し、 それぞれはパラメーター化された規則に異なる代入を適用して生成されます。

型規則が構文句に適用されるのは、次の場合です:

パラメーター化された型規則が 式に適用されるのは、その式に適用される完全に 具体化された型規則を生成する代入が 存在する場合です。

式 1u+2u を考えます。 これには 1u と 2u という 2 つのリテラル部分式があり、 どちらも型は u32 です。 トップレベル 式は加算です。 § 8.8 算術式の規則を参照すると、 加算の型規則は次の理由でこの式に適用されます:

構文 句を解析するとき、次の 3 つの場合があります:

上記の例を続けると、式 1u+2u に適用される型規則は 1 つだけであるため、 型チェックはその型規則の結論、すなわち 1u+2u の型が u32 であることを受け入れます。

WGSL ソースプログラムが適切に型付けされているのは、次の場合です:

それ以外の場合、型エラーがあり、 ソースプログラムは有効な WGSL モジュールではありません。

WGSL が静的型付け言語であるのは、 WGSL モジュールの型チェックが、プログラムのソーステキストを調べるだけで、 成功するか型エラーを検出するかのいずれかになるためです。

6.1.1. 型規則表

式に対する WGSL の型規則は、 型規則 表として編成され、型規則ごとに 1 行があります。

式の セマンティクスとは、その式を評価することによる効果であり、 主として結果値の生成です。 式に適用される型規則の説明列で、その式の セマンティクスを指定します。 セマンティクスは通常、部分式の想定値を含む、 型規則パラメーターの値に依存します。 式のセマンティクスには、部分式の非結果値効果など、 結果値を生成する以外の効果が含まれる場合もあります。

例: 式の副作用
fn foo(p : ptr<function, i32>) -> i32 {
  let x = *p;
  *p += 1;
  return x;
}

fn bar() {
  var a: i32;
  let x = foo(&a); // foo の呼び出しは値を返し
                   // a の値を更新する
}

6.1.2. 変換ランク

型アサーション e:T が型規則の前提条件として使用される場合、 次のとき満たされます:

この規則は、以下の表で定義される型の組に対するConversionRank 関数によって形式化されます。 ConversionRank 関数は、 ある型(Src)の値を別の型(Dest)に自動変換する際の 優先度と実行可能性を表します。 ランクが低いほど望ましいものです。

実行可能な 自動変換は、値を型 Src から型 Dest に変換するもので、 ConversionRank(Src,Dest) が有限の場合に許可されます。 このような変換は、§ 15.7 浮動小数点評価で説明される制限の範囲内で、値を保持します。

注: 自動変換が発生する状況は 2 種類だけです。 1 つ目は、const 式を、GPU で使用できる対応する型付き数値に変換する場合です。 2 つ目は、メモリーへの参照からロードが発生し、そのメモリーに格納された値が得られる場合です。

注: 無限ランクの変換は実行不可能、すなわち 許可されません。

注: 変換が行われない場合、変換ランクは 0 です。

ある型から別の型への ConversionRank
Src Dest ConversionRank(Src,Dest) 説明
T T 0 恒等変換。変換は実行されません。
ref<AS,T,AM>
アドレス空間 AS について、 かつアクセスモード AM がread またはread_write である場合。
T 0 ロード規則を適用して、 メモリー参照から値をロードします。
swizzle<AS,S,N,K>
vecK<S> 0 スウィズルビューロード規則を適用して、 スウィズルビューから ベクトル値をロードします。
AbstractFloat f32 1 § 15.7.6 浮動小数点変換を参照
AbstractFloat f16 2 § 15.7.6 浮動小数点変換を参照
AbstractInt i32 3 値がi32 の範囲内であれば恒等変換です。 それ以外の場合はシェーダー作成エラーになります。
AbstractInt u32 4 値がu32 の範囲内であれば恒等変換です。 それ以外の場合はシェーダー作成エラーになります。
AbstractInt AbstractFloat 5 § 15.7.6 浮動小数点変換を参照
AbstractInt f32 6 AbstractInt から AbstractFloat、 その後AbstractFloat から f32 への変換として動作します
AbstractInt f16 7 AbstractInt から AbstractFloat、 その後AbstractFloat から f16 への変換として動作します
vecN<S> vecN<T> ConversionRank(S,T) 成分型から変換ランクを継承します。
matCxR<S> matCxR<T> ConversionRank(S,T) 成分型から変換ランクを継承します。
array<S,N> array<T,N> ConversionRank(S,T) 成分型から変換ランクを継承します。 注: 固定サイズ配列のみが抽象成分型を持つことができます。
__frexp_result_abstract __frexp_result_f32 1
__frexp_result_abstract __frexp_result_f16 2
__frexp_result_vecN_abstract __frexp_result_vecN_f32 1
__frexp_result_vecN_abstract __frexp_result_vecN_f16 2
__modf_result_abstract __modf_result_f32 1
__modf_result_abstract __modf_result_f16 2
__modf_result_vecN_abstract __modf_result_vecN_f32 1
__modf_result_vecN_abstract __modf_result_vecN_f16 2
ptr<AS, buffer<N1>, AM>
Src が関数呼び出しへの引数の型である場合
ptr<AS, buffer<N2>, AM>
N1 と N2 がともにconst 式であり、Dest が Src の引数に対応する 仮引数の型である場合
N2 < N1 の場合は 1、
それ以外は infinity
固定サイズバッファーのポインター引数を、より小さいサイズの ポインターパラメーターへ変換します。1
ptr<AS, buffer<N>, AM>
Src が関数呼び出しへの引数の型である場合
ptr<AS, buffer, AM>
Dest が Src の引数に対応する仮引数の型である場合
1 固定サイズバッファーのポインター引数をランタイムサイズバッファーのポインターパラメーターへ変換します。1
S T
上記の場合が適用されない場合
infinity 他の型の間には自動変換はありません。
  1. これらの変換には、unrestricted_pointer_parameters およびbuffer_view 言語機能が必要です。

型 T が型 S の具象化であるのは、次の場合です:

型 T の値 e の値の 具象化とは、e に対して、T を T の 具象化へ対応付ける実行可能な変換を適用して得られる値です。

注: f32 への変換は常にf16 より優先されるため、 自動変換がf16 値を生成するのは、 モジュールでf16 拡張が有効な場合だけです。

6.1.3. オーバーロード解決

複数の型規則が構文句に適用される場合、 どれを有効にするべきかを決定するために タイブレーク手順を使用します。 この手順をオーバーロード解決と呼び、 部分式の静的型を見つける型チェックが すでに成功しているものと仮定します。

構文 句 P と、P に適用されるすべての型規則を考えます。 オーバーロード解決アルゴリズムでは、これらの型規則をオーバーロード候補と呼びます。 各候補について:

P に対するオーバーロード解決は、単一の最も望ましいオーバーロード 候補を見つけることを目的として、次のように進めます:

  1. 各候補 C について、構文句内の部分式の変換ランクを列挙します。 候補の前提条件は満たされているため、P 内の i 番目の部分式について:

    • その静的型は計算済みです。

    • 式の静的型から、前提条件内の対応する型アサーションが要求する型への 実行可能な自動変換があります。 C.R(i) を、その変換のConversionRank とします。

  2. 実行可能な自動変換後、その部分式の 1 つが抽象型に解決される一方で、 候補の別の部分式がconst 式ではない候補を除外します。

    注: その結果、句内のいずれかの部分式が const 式でない場合、 句内のすべての部分式は具象型を持たなければなりません。

  3. 候補を順位付けします: 2 つのオーバーロード候補 C1 と C2 があるとき、 次の場合、C1 は C2 より優先されます:

    • P 内の各式位置 i について、C1.R(i) ≤ C2.R(i)。

      • つまり、C1 を P に適用するために必要な各式変換が、 C2 を P に適用するために必要な対応する式変換と 少なくとも同程度に望ましいということです。

    • C1.R(i) < C2.R(i) となる式位置 i が少なくとも 1 つ存在する。

      • つまり、C1 を適用するために必要な式変換のうち少なくとも 1 つが、 C2 を適用するために必要な対応する変換より厳密に望ましいということです。

  4. 他のすべてより優先される候補 C が 1 つだけ存在する場合、オーバーロード解決は成功し、候補型規則 C が得られます。 それ以外の場合、オーバーロード解決は失敗します。

6.2. プレーン型

プレーン型は、ブール値、数値、ベクトル、 行列、またはそのような値の集合体のマシン表現のための型です。

プレーン型は、スカラー型、アトミック 型、または複合型のいずれかです。

注: WGSL のプレーン型は C++ の Plain-Old-Data 型に似ていますが、 アトミック型および抽象数値型も含みます。

6.2.1. 抽象数値型

これらの型は WGSL ソースで記述できません。型チェックでのみ使用されます。

特定の式はシェーダー作成時に評価され、 GPU が直接実装する範囲より大きな数値範囲および精度を持つ場合があります。

WGSL は、これらの評価のために 2 つの抽象数値型を定義します:

これらの型のいずれかでの式の評価は、オーバーフローしたり、無限大または NaN 値を生成したりしてはなりません。

型が抽象数値型であるか、抽象数値型を含む場合、その型は抽象です。 型が抽象ではない場合、その型は具象です。

接尾辞のない数値リテラルは、 抽象数値型の値を表します:

例: 式 log2(32) は次のように解析されます:

例: 式 1 + 2.5 は次のように解析されます:

例: let x = 1 + 2.5;

例: 1u + 2.5 はシェーダー作成エラーになります:

例: -1 * i32(-2147483648) はシェーダー作成エラーにはなりません:

例: リテラルの型推論
// 明示的に型指定された符号なし整数リテラル。
var u32_1 = 1u; // 変数は u32 を保持する

// 明示的に型指定された符号付き整数リテラル。
var i32_1 = 1i; // 変数は i32 を保持する

// 明示的に型指定された浮動小数点リテラル。
var f32_1 = 1f; // 変数は f32 を保持する

// 明示的に型指定された符号なし整数リテラルは否定できない。
var u32_neg = -1u; // 無効: 単項マイナスは u32 をサポートしない

// 具象型が必要だが、文または式のどの部分も
// 特定の具象型を強制しない場合、整数リテラルは
// i32 値として解釈される:
//   let 宣言の初期化子は構築可能(またはポインター)でなければならない。
//   AbstractInt から構築可能型への最も優先される自動変換は
//   AbstractInt から i32 で、変換ランクは 2。したがって '1' は i32 と推論される。
let some_i32 = 1; // let some_i32: i32 = 1i; と同様

// 宣言型から推論される。
var i32_from_type : i32 = 1; // 変数は i32 を保持する。AbstractInt から i32、変換ランク 2
var u32_from_type : u32 = 1; // 変数は u32 を保持する。AbstractInt から u32、変換ランク 3

// 接尾辞のない整数リテラルは、必要に応じて浮動小数点へ変換できる:
//   AbstractInt を f32 に自動変換する。変換ランクは 5。
var f32_promotion : f32 = 1; // 変数は f32 を保持する

// 無効: 浮動小数点から整数への実行可能な変換はない
var i32_demotion : i32 = 1.0; // 無効

// 式から推論される。
var u32_from_expr = 1 + u32_1; // 変数は u32 を保持する
var i32_from_expr = 1 + i32_1; // 変数は i32 を保持する

// 値は表現可能でなければならない。
let u32_too_large   : u32 = 1234567890123456890; // 無効、オーバーフロー
let i32_too_large   : i32 = 1234567890123456890; // 無効、オーバーフロー
let u32_large : u32 = 2147483649; // 有効
let i32_large : i32 = 2147483649; // 無効、オーバーフロー
let f32_out_of_range1 = 0x1p500; // 無効、範囲外
let f32_hex_lost_bits = 0x1.0000000001p0; // 無効、f32 で正確に表現できない

// 最小整数: AbstractInt に単項否定を適用し、その後 i32 を推論する。
// AbstractInt から構築可能型への最も優先される変換(最小の
// 変換ランク)は AbstractInt から i32。
let i32_min = -2147483648;  // 型は i32

// 無効。上記と同様に AbstractInt から i32 を選択するが、値が
// 範囲外であり、シェーダー作成エラーになる。
let i32_too_large_2 = 2147483648; // 無効。

// 部分式は AbstractInt および AbstractFloat に解決できる。
// 次の例はすべて有効で、変数の値は 6u。
var u32_expr1 = (1 + (1 + (1 + (1 + 1)))) + 1u;
var u32_expr2 = 1u + (1 + (1 + (1 + (1 + 1))));
var u32_expr3 = (1 + (1 + (1 + (1u + 1)))) + 1;
var u32_expr4 = 1 + (1 + (1 + (1 + (1u + 1))));

// 組み込み関数のパラメーターに基づく推論。

// 最優先候補は clamp(i32,i32,i32)->i32
let i32_clamp = clamp(1, -5, 5);
// 最優先候補は clamp(u32,u32,u32)。
// リテラルは AbstractInt から u32 への自動変換を使用する。
let u32_clamp = clamp(5, 0, u32_from_expr);
// 最優先候補は clamp(f32,f32,f32)->f32
// リテラルは AbstractInt から f32 への自動変換を使用する。
let f32_clamp = clamp(0, f32_1, 1);

// 次の例はすべて、初期値 10f を持つ f32 に昇格する。
let f32_promotion1 = 1.0 + 2 + 3 + 4;
let f32_promotion2 = 2 + 1.0 + 3 + 4;
let f32_promotion3 = 1f + ((2 + 3) + 4);
let f32_promotion4 = ((2 + (3 + 1f)) + 4);

// 型規則違反。

// 無効。初期化子は f32 にしか解決できない:
// AbstractFloat から u32 への実行可能な自動変換はない。
let mismatch : u32 = 1.0;

// 無効。符号の異なるパラメーターを許可する clamp のオーバーロードはない。
let ambiguous_clamp = clamp(1u, 0, 1i);

// 推論は文レベルで完了する。

// let 宣言の初期化子は構築可能(またはポインター)でなければならない。
// AbstractInt から構築可能型への最も優先される自動変換は
// AbstractInt から i32 で、変換ランクは 2。したがって '1' は i32 と推論される。
let some_i32 = 1; // let some_i32: i32 = 1i; と同様

let some_f32 : f32 = some_i32; // 型エラー: i32 は f32 に代入できない

// 別のオーバーフローの例
let overflow_u32 = (1 -2) + 1u; // 無効、-1 は u32 の範囲外

// 理想値は 32 ビットの範囲外だが、その後範囲内に戻される
let out_and_in_again = (0x1ffffffff / 8);

// 同様だが無効
let out_of_range = (0x1ffffffff / 8u); // 計算を 32 ビットで行う必要があり、
                                       // 0x1ffffffff が範囲外になる。

6.2.2. ブール型

bool 型は、 true および false の値を含みます。

ブールリテラルの型規則
前提条件 結論 説明
true: bool true 値。
false: bool false 値。

6.2.3. 整数型

u32 型は、32 ビット 符号なし整数の集合です。

i32 型は、32 ビット 符号付き整数の集合です。 符号ビットを最上位ビット位置に持つ 2 の補数表現を使用します。

オーバーフローする具象整数型に対する式は、 2bitwidth を法とする結果を生成します

整数型の極値
型 最小値 最大値
i32 i32(-2147483648) 2147483647i
i32(-0x80000000) 0x7fffffffi
u32 0u 4294967295u
0x0u 0xffffffffu

注: AbstractInt も整数型です。

6.2.4. 浮動小数点型

f32 型は、 IEEE-754 のbinary32(単精度)形式の 32 ビット浮動小数点値の集合です。 詳細については§ 15.7 浮動小数点評価を参照してください。

f16 型は、 IEEE-754 のbinary16(半精度)形式の 16 ビット浮動小数点値の集合です。プログラムに f16 拡張を有効にする enable f16; ディレクティブが含まれていない状態でf16 型を使用すると、シェーダー作成 エラーになります。詳細については§ 15.7 浮動小数点評価を参照してください。

次の表は、浮動小数点型の特定の極値を示します。 それぞれに対応する負の値があります。

浮動小数点型の極値
型 最小の正の非正規化数 最小の正の正規化数 最大の正の有限値 最大の有限な 2 のべき乗
f32 1.40129846432481707092e-45f 1.17549435082228750797e-38f 3.40282346638528859812e+38f 0x1p+127f
0x1p-149f 0x1p-126f 0x1.fffffep+127f
f16 5.9604644775390625e-8h 0.00006103515625h 65504.0h 0x1p+15h
0x1p-24h 0x1p-14h 0x1.ffcp+15h

注: AbstractFloat も浮動小数点型です。

6.2.5. スカラー型

スカラー型は、bool、AbstractInt、 AbstractFloat、i32、u32、f32、およびf16 です。

数値スカラー型は、 AbstractInt、 AbstractFloat、i32、u32、f32、およびf16 です。

整数スカラー型は、 AbstractInt、i32、および u32 です。

スカラー変換は、 あるスカラー型の値を別のスカラー型の値へ対応付けます。 一般に、結果値は、変換先の型の制限の範囲内で元の値に近いものになります。 スカラー変換は次のいずれかによって発生します:

6.2.6. ベクトル型

ベクトルは、 2、3、または 4 個のスカラー 成分をグループ化したシーケンスです。

型 説明
vecN<T> 型 T の N 個の成分からなるベクトル。 N は {2, 3, 4} のいずれかでなければならず、T はスカラー型のいずれかでなければなりません。 T をベクトルの成分型と呼びます。

ベクトルの成分型が数値スカラーである場合、そのベクトルは数値 ベクトルです。

ベクトルの主な用途には次のものがあります:

ベクトル(および行列)に対する多くの演算は、 成分ごとに動作します。つまり、 各スカラー成分を独立して演算することで結果が形成されます。

例: ベクトル
vec2<f32>  // 2 つの f32 からなるベクトル。
例: 成分ごとの加算
let x : vec3<f32> = a + b; // a と b は vec3<f32>
// x[0] = a[0] + b[0]
// x[1] = a[1] + b[1]
// x[2] = a[2] + b[2]

WGSL は、次の型エイリアスも 事前宣言します:

事前宣言済みエイリアス 元の型 制限
vec2i vec2<i32>
vec3i vec3<i32>
vec4i vec4<i32>
vec2u vec2<u32>
vec3u vec3<u32>
vec4u vec4<u32>
vec2f vec2<f32>
vec3f vec3<f32>
vec4f vec4<f32>
vec2h vec2<f16> f16 拡張が必要です。
vec3h vec3<f16>
vec4h vec4<f16>

6.2.7. 行列型

行列は、 2、3、または 4 個の浮動小数点ベクトルをグループ化したシーケンスです。

型 説明
matCxR<T> 型 T の C 列 R 行の行列。C と R はともに {2, 3, 4} のいずれかで、T はf32、f16、またはAbstractFloat でなければなりません。 同等に、型 vecR<T> の C 個の列ベクトルとして 見ることができます。

行列の主な用途は、線形変換を表現することです。 この解釈では、行列のベクトルは列ベクトルとして扱われます。

積演算子(*)は、次のいずれかに使用されます:

§ 8.8 算術式を参照してください。

例: 行列
mat2x3<f32>  // これは 32 ビット浮動小数点数の 2 列 3 行の行列。
             // 同等に、型 vec3<f32> の 2 つの列ベクトル。

WGSL は、次の型エイリアスも 事前宣言します:

事前宣言済みエイリアス 元の型 制限
mat2x2f mat2x2<f32>
mat2x3f mat2x3<f32>
mat2x4f mat2x4<f32>
mat3x2f mat3x2<f32>
mat3x3f mat3x3<f32>
mat3x4f mat3x4<f32>
mat4x2f mat4x2<f32>
mat4x3f mat4x3<f32>
mat4x4f mat4x4<f32>
mat2x2h mat2x2<f16> f16 拡張が必要です。
mat2x3h mat2x3<f16>
mat2x4h mat2x4<f16>
mat3x2h mat3x2<f16>
mat3x3h mat3x3<f16>
mat3x4h mat3x4<f16>
mat4x2h mat4x2<f16>
mat4x3h mat4x3<f16>
mat4x4h mat4x4<f16>

6.2.8. アトミック型

アトミック型は、 具象整数 型をカプセル化し、次を満たします:

型 説明
atomic<T> 型 T のアトミック。T はu32 またはi32 の いずれかでなければなりません。
atomic<vec2<u32>> 型 vec2<u32> のアトミック。 この型の値は符号なし64 ビット整数型を表し、下位 32 ビットがベクトル 成分 0 に、上位 32 ビットがベクトル成分 1 に格納されます。

atomic_vec2u_min_max 拡張によって有効になります。

式はアトミック型に評価されてはなりません。

アトミック型は、workgroup アドレス空間内の変数、またはread_write アクセスモードを持つストレージ バッファー変数によってのみインスタンス化できます。 格納型が atomic<vec2<u32>> であるかこれを含む場合、その変数はstorage アドレス空間になければなりません。

その型に対する操作のメモリースコープは、 インスタンス化されたアドレス空間によって決まります。 workgroup アドレス空間内のアトミック型は Workgroup のメモリースコープを持ち、 storage アドレス空間内のものは QueueFamily のメモリースコープを持ちます。

アトミック 変更とは、アトミックオブジェクトの内容を設定する、そのオブジェクトに対する任意の 操作です。 新しい値がオブジェクトの既存値と同じであっても、その操作は変更として数えられます。

WGSL では、アトミック変更はオブジェクトごとに相互に順序付けられます。 つまり、シェーダーステージの実行中、各アトミックオブジェクト A について、すべての エージェントは A に適用される変更操作の同じ順序を観測します。 異なるアトミックオブジェクトの順序付けは互いに関連しない場合があり、 因果関係は暗示されません。 workgroup 空間の変数は ワークグループ内では共有されますが、 異なるワークグループ間では共有されないことに注意してください。

6.2.9. 配列型

配列は、 インデックス付け可能な要素値のシーケンスです。

型 説明
array<E,N> 型 E の要素を N 個持つ固定サイズ 配列。
N を配列の要素数と呼びます。
array<E> 型 E の要素からなるランタイムサイズ配列。 これらは特定のコンテキストにのみ現れることができます。

配列の最初の要素はインデックス 0 にあり、後続の各要素は次の整数インデックスにあります。 § 8.5.3 配列アクセス式を参照してください。

式はランタイムサイズ配列型に評価されてはなりません。

固定サイズ配列の要素数式 N には、次の制約が適用されます:

注: N がoverride 宣言に依存する場合、要素数の値はパイプライン作成時に完全に決定され、 それ以外の場合はシェーダーモジュール作成時に完全に決定されます。

注: 型の同値性を満たすには、const 式ではない override 式は識別子でなければなりません。 オーバーライド可能な定数によってサイズ指定される ワークグループ変数を参照してください

ランタイムサイズ配列の要素数は、 対応するストレージバッファー変数に関連付けられた バッファーバインディングのサイズによって決まります。 § 13.3.4 バッファーバインディングによる ランタイムサイズ配列の要素数の決定を参照してください。

配列の要素型は次のいずれかでなければなりません:

注: 配列の要素型をbuffer 型にすることはできません。

注: 要素型はプレーン型でなければなりません。

2 つの配列型が同一であるのは、次のすべてが真である場合に限ります:

例: オーバーライド不可能な要素数を持つ固定サイズ配列型の例
// array<f32,8> と array<i32,8> は異なる型:
// 要素型が異なる
var<private> a: array<f32,8>;
var<private> b: array<i32,8>;
var<private> c: array<i32,8u>;  // array<i32,8> と array<i32,8u> は同じ型

const width = 8;
const height = 8;

// array<i32,8>、array<i32,8u>、array<i32,width> は同じ型。
// それらの要素数は 8 に評価される。
var<private> d: array<i32,width>;

// array<i32,height> と array<i32,width> は同じ型。
var<private> e: array<i32,width>;
var<private> f: array<i32,height>;

注: オーバーライド可能な定数によってサイズ指定された配列型の 唯一の有効な使用法は、workgroup アドレス空間内のメモリービューとしての使用です。 これには、workgroup 変数の格納型が含まれます。 § 7 変数と値の宣言を参照してください。

例: オーバーライド可能な定数によってサイズ指定されるワークグループ変数
override blockSize = 16;

var<workgroup> odds: array<i32,blockSize>;
var<workgroup> evens: array<i32,blockSize>; // 同じ型

// 次のどれも 'odds' および 'evens' と同じ型ではない。

// 異なる型: 識別子 'blockSize' ではない
var<workgroup> evens_0: array<i32,16>;
// 異なる型: 要素数を表すために算術を使用している。
var<workgroup> evens_1: array<i32,(blockSize * 2 / 2)>;
// 異なる型: 単なる識別子ではなく括弧を使用している。
var<workgroup> evens_2: array<i32,(blockSize)>;

// 無効な例。オーバーライド可能な要素数は最外層にのみ現れることができるため。
// var<workgroup> both: array<array<i32,blockSize>,2>;

// 無効な例。オーバーライド可能な要素数は
// workgroup 変数に対してのみ有効であるため。
// var<private> bad_address_space: array<i32,blockSize>;

6.2.10. 構造体型

構造体は、 名前付きのメンバー値を 名前付きでグループ化したものです。

型 説明
struct AStructName {
M1 : T1,
...
MN : TN,
}
識別子 AStructName で名前が付けられ、 N 個のメンバーを持つ構造体型の宣言。 メンバー i は識別子 Mi で名前が付けられ、 型は Ti です。

N は少なくとも 1 でなければなりません。

同じ構造体型の 2 つのメンバーが同じ名前を持ってはなりません。

構造体型はモジュールスコープで宣言されます。 プログラムソースの他の場所では、構造体型はその識別子名によって表されます。 § 5 宣言とスコープを参照してください。

2 つの構造体型が同一であるのは、それらが同じ名前を持つ場合に限ります。

構造体メンバー型は次のいずれかでなければなりません:

注: 構造体メンバー型をbuffer 型にすることはできません。

注: ユーザー宣言されたすべての構造体型は具象です。

注: 各メンバー型はプレーン型でなければなりません。

構造体メンバー型および配列要素型に対する制限から生じる結果には次のものがあります:

例: 構造体
// 3 つのメンバーを持つ構造体。
struct Data {
  a: i32,
  b: vec2<f32>,
  c: array<i32,10>, // 最後のカンマは任意
}

// Data 型の値を格納する変数を宣言する。
var<private> some_data: Data;
struct_decl :

'struct' ident struct_body_decl

struct_body_decl :

'{' struct_member ( ',' struct_member ) * ',' ? '}'

struct_member :

attribute * member_ident ':' type_specifier

構造体メンバーには次の属性を適用できます:

属性 builtin、location、blend_src、 interpolate、 およびinvariant は IO 属性です。 構造体 S のメンバーにあるIO 属性が効果を持つのは、 S がエントリーポイントの仮引数または戻り値の型として使用される場合だけです。 § 13.3.1 ステージ間入力および出力インターフェイスを参照してください。

属性 align およびsize はレイアウト属性であり、 構造体型をuniform バッファーまたは storage バッファーの定義に使用する場合に 必要になることがあります。 § 14.4 メモリーレイアウトを参照してください。

例: 構造体宣言
struct my_struct {
  a: f32,
  b: vec4<f32>
}
例: バッファーの宣言に使用される構造体
// ランタイム配列
alias RTArr = array<vec4<f32>>;
struct S {
  a: f32,
  b: f32,
  data: RTArr
}
@group(0) @binding(0) var<storage> buffer: S;

6.2.11. 複合型

他の型の合成として表現される内部構造を持つ場合、その型は複合です。 内部部分は重ならず、成分と呼ばれます。 複合値はその成分に分解できます。§ 8.5 複合値分解式を参照してください。

複合型は次のとおりです:

複合型 T について、T のネスト深度を NestDepth(T) と表すと、次のようになります:

6.2.12. 構築可能型

多くの種類の値は、作成、ロード、格納、関数への受け渡し、 および関数からの返却が可能です。 これらを構築可能と呼びます。

型が構築可能であるのは、 次のいずれかである場合です:

注: すべての構築可能型は作成時固定フットプリントを持ちます。

注: アトミック型およびランタイムサイズ配列型は 構築可能ではありません。 アトミックまたはランタイムサイズ配列を含む複合型も構築可能ではありません。

6.2.13. 固定フットプリント型

変数のメモリーフットプリントは、 変数の内容を格納するために使用されるメモリー位置の数です。 変数のメモリーフットプリントはその格納型に依存し、 シェーダーライフサイクルのある時点で確定します。 ほとんどの変数は非常に早い段階、すなわちシェーダー作成時にサイズが決まります。 一部の変数は後のパイプライン作成時にサイズが決まる場合があり、 また他の変数はシェーダー実行開始時までサイズが決まらない場合があります。

型の具象化のサイズが シェーダー作成時に完全に決定される場合、その型は 作成時固定フットプリントを持ちます。

型のサイズがパイプライン作成 時に完全に決定される場合、その型は固定 フットプリントを持ちます。

注: すべての具象の作成時固定フットプリント型および固定フットプリント型は格納可能です。

注: パイプライン作成はシェーダー作成に依存するため、 作成時固定フットプリントを持つ型は固定フットプリントも持ちます。

作成時固定フットプリントを持つ型は次のとおりです:

注: 構築可能型は作成時固定フットプリントを持ちます。

固定 フットプリントを持つ型は次のいずれかです:

注: 要素数が const 式ではないoverride 式である固定サイズ配列の唯一の有効な使用法は、 workgroup アドレス空間内のメモリービューとしての使用です。 これには workgroup 変数の格納型が含まれます。

注: 固定フットプリント型はアトミック型を直接または 間接的に含むことができますが、構築可能型は含むことができません。

注: 固定フットプリント型にはランタイムサイズ配列、 ランタイムサイズ バッファー、およびランタイムサイズ配列を含む構造体は含まれません。

6.3. バッファー型

これらの型にはbuffer_view 言語機能が必要です。

buffer 値は、 その内容を別のホスト共有可能型として 解釈できるメモリーを表します。 それ以外では、バッファー値は不透明です。 これは、変数内のデータに複数の異なる型としてアクセスする必要がある場合や、 シェーダー作者が 1 つの変数を複数の論理変数に分割したい場合に役立ちます。

バッファー型は構築可能ではなく、 buffer_view 組み込み関数を介して データを不透明でないホスト共有可能型として解釈した後にのみアクセスできます。

型 説明
buffer<N> N バイトのストレージを持つ固定サイズ バッファー。
N はoverride 式でなければなりません。
buffer ランタイムサイズバッファー。

式は バッファー型に評価されてはなりません。

固定サイズバッファーは、storage、uniform、およびworkgroup アドレス空間の変数によってのみインスタンス化できます。 storage および uniform アドレス空間では、サイズはconst 式でなければなりません。 ランタイムサイズバッファーは storage アドレス空間の変数によってのみインスタンス化できます。

N が 0 より大きくない場合:

f16 拡張が有効で、 N が 2 で割り切れない場合:

f16 拡張が 有効ではなく、N が 4 で割り切れない場合:

2 つのバッファー型が同一であるのは、次の条件のいずれかを満たす場合に限ります:

6.4. 列挙型

列挙型は、 名前付きの値からなる限定された集合です。 列挙は、有効なテクセルフォーマットの集合など、 特定の概念について可能な選択肢の集合を区別するために使用されます。

列挙子は、 列挙内の名前付き値の 1 つです。 各列挙子は他のすべての列挙子とは異なり、 また他のすべての種類の値とも異なります。

WGSL ソースで新しい列挙子または新しい列挙型を宣言する機構はありません。

注: 列挙子はテンプレートパラメーターとして使用されます。

注: 列挙子をコピーしたり、別名を作成したりする方法はありません:

6.4.1. 事前宣言済み列挙子

次の表は、WGSL の列挙型、それらの事前宣言済み列挙子、および列挙型に必要な言語拡張を示します。 列挙型は存在しますが、WGSL ソースでは記述できません。

事前宣言済み列挙子
列挙
(WGSL では記述不可)
事前宣言済み列挙子 必要な言語拡張
アクセス モード read
write
read_write
アドレス空間

注: handle アドレス 空間は WGSL ソースには決して記述されません。

function
private
workgroup
uniform
storage
テクセル フォーマット rgba8unorm
rgba8snorm
rgba8uint
rgba8sint
rgba16unorm texture_formats_tier1
rgba16snorm texture_formats_tier1
rgba16uint
rgba16sint
rgba16float
rg8unorm texture_formats_tier1
rg8snorm texture_formats_tier1
rg8uint texture_formats_tier1
rg8sint texture_formats_tier1
rg16unorm texture_formats_tier1
rg16snorm texture_formats_tier1
rg16uint texture_formats_tier1
rg16sint texture_formats_tier1
rg16float texture_formats_tier1
r32uint
r32sint
r32float
rg32uint
rg32sint
rg32float
rgba32uint
rgba32sint
rgba32float
bgra8unorm
r8unorm texture_formats_tier1
r8snorm texture_formats_tier1
r8uint texture_formats_tier1
r8sint texture_formats_tier1
r16unorm texture_formats_tier1
r16snorm texture_formats_tier1
r16uint texture_formats_tier1
r16sint texture_formats_tier1
r16float texture_formats_tier1
rgb10a2unorm texture_formats_tier1
rgb10a2uint texture_formats_tier1
rg11b10ufloat texture_formats_tier1

6.5. メモリービュー

プレーン 値を使用した計算に加えて、WGSL プログラムは メモリーアクセス操作を介して、 メモリーから値を読み取ったり、メモリーに値を書き込んだりすることもよくあります。 各メモリーアクセスはメモリービューを介して実行されます。

メモリービューは次のものから構成されます:

メモリービューのアクセスモードは、アドレス空間でサポートされていなければなりません。§ 7 変数と値の宣言を参照してください。

6.5.1. 格納可能型

変数に含まれる値は、 格納可能型でなければなりません。 格納可能型は、§ 14.4.4 値の内部レイアウトで説明されるように、 WGSL によって定義された明示的な表現を持つ場合もあれば、テクスチャーやサンプラーのように 不透明である場合もあります。

型が格納可能であるのは、 具象であり、かつ次のいずれかである場合です:

注: つまり、格納可能型は具象のプレーン型、 テクスチャー型、サンプラー型、およびバッファー型です。

6.5.2. ホスト共有可能型

ホスト共有可能型は、ホストと GPU の間で共有されるバッファー、 またはフォーマット変換なしでホストと GPU の間でコピーされるバッファーの内容を記述するために使用されます。 この目的で使用する場合、§ 14.4 メモリーレイアウトで説明されるように、 型にはさらにレイアウト属性を適用できます。 § 7.3 var 宣言で説明されるように、uniform バッファーおよびstorage バッファー 変数の格納型は ホスト共有可能でなければなりません。

型がホスト共有可能であるのは、 具象であり、かつ 次のいずれかである場合です:

注: ステージ間の入力および出力の型に対する制限は、 § 13.3.1 ステージ間入力および出力インターフェイスおよび それ以降の節で説明されています。 これらの型にもサイズがありますが、数え方が異なります。

注: テクスチャーと サンプラーもホストと GPU の間で共有できますが、その内容は不透明です。 この節のホスト共有可能型は、特にstorage およびuniform バッファーで使用するためのものです。

6.5.3. 参照型とポインター型

WGSL には、メモリービューを表現するための 2 種類の型があります: 参照型とポインター型です。

制約 型 説明
AS はアドレス空間、
T は格納可能型、
AM はアクセスモード
ref<AS,T,AM> AS 内の、型 T の値を保持するメモリー位置に対する メモリービューの集合で識別され、 モード AM で記述されるメモリーアクセスをサポートする 参照 型。

ここで、T は格納型です。

参照型は WGSL ソースには記述されません。 代わりに WGSL モジュールの解析に使用されます。

AS はアドレス空間、
T は格納可能型、
AM はアクセスモード
ptr<AS,T,AM> AS 内の、型 T の値を保持するメモリー位置に対する メモリービューの集合で識別され、 モード AM で記述されるメモリーアクセスをサポートする ポインター 型。

ここで、T は格納型です。

ポインター型は WGSL ソースに現れることがあります。

2 つのポインター型が同一であるのは、アドレス空間、格納型、およびアクセスモードが同じ場合に限ります。

WGSL モジュールを解析するとき、参照型とポインター型は、 アドレス空間、格納可能型、およびアクセスモードによって完全にパラメーター化されます。 この仕様のコード例では、コメントにこの完全にパラメーター化された形式を示します。

ただし、WGSL ソーステキストでは:

例: ポインター型
fn my_function(
  /* 'ptr<function,i32,read_write>' は、'function' アドレス空間のメモリー位置を使用して
     'i32' 値を保持するためのメモリーを参照するポインター値の型。
     ここでは 'i32' が格納型。
     暗黙のアクセスモードは 'read_write'。
     既定値については「アドレス空間」節を参照。 */
  ptr_int: ptr<function,i32>,

  // 'ptr<private,array<f32,50>,read_write>' は、'private' アドレス空間の
  // メモリー位置を使用して、型 'f32' の 50 個の要素からなる配列を保持する
  // メモリーを参照するポインター値の型。
  // ここで格納型は 'array<f32,50>'。
  // 暗黙のアクセスモードは 'read_write'。
  // 既定値については「アドレス空間」節を参照。
  ptr_array: ptr<private, array<f32, 50>>
) { }

参照型とポインター型は、どちらもメモリービューの集合です: 特定のメモリービューには、一意の参照値と一意のポインター値の両方が関連付けられます:

型 ptr<AS,T,AM> の各ポインター値 p は、 型 ref<AS,T,AM> の一意の参照値 r に対応し、 その逆も同様です。 ここで p と r は同じメモリービューを記述します。

6.5.4. スウィズルビュー型

スウィズルビューを使用すると、 メモリー内のベクトルの成分の部分集合にアクセスし、 読み取り時にはそれらを並べ替え、書き込み時にはそれらを散在させることができます。

スウィズルビューはswizzle_assignment 言語拡張によって有効になります。

スウィズルビューは、 次を満たす組 (p,IndexList) です:

アルゴリズム: SwizzleViewRead

ポインター p を介して読み取ったベクトルの成分を選択し、任意で並べ替えて形成したベクトルを生成します。

注: スウィズルビューを介した読み取りでは、 一部のベクトル成分が結果に現れない場合でも、ベクトル全体をメモリーから読み取ります。

入力: 型 swizzle<AS,S,N,K> のスウィズル ビュー (p, IndexList)

出力: (p, IndexList) を読み取った結果である、 型 vecK<S> のベクトル値 v。

手順:

  1. 慣例により IndexList = « Idx0, ..., IdxK−1 »

  2. p が参照するメモリーからベクトル u を読み取ります。u の型は vecN<S> です。

  3. 次を満たす型 vecK<S> の値 v を形成します:

    • v の成分 i は、 u の成分 Idxi の値に等しい。 インデックス構文を使用すると: v[i] = u[Idxi]

アルゴリズム: SwizzleViewWrite

update ベクトルの成分を、ポインター p が参照するメモリー内の ベクトルの指定された成分へ書き込みます。

注: スウィズルビューを介した書き込みでは、処理によって成分値が変更されない場合でも、 メモリー内のベクトル全体を書き込みます。

スウィズルビューへの書き込みが一様性解析および メモリーモデルとどのように相互作用するかについては、以下の説明を参照してください。

入力:

IndexList 内のすべてのインデックスは互いに異なっていなければなりません。 この要件から K ≤ N が導かれます。

変数:

手順:

  1. 慣例により IndexList = « Idx0, ..., IdxK−1 »

  2. 変数 new を old_contents で初期化します。

  3. 0..K-1 の各 i について:

    • new の成分 Idxi を、 update の成分 i の値に設定します。 インデックス構文を使用すると: new[Idxi] = update[i]。

  4. new を p が参照するメモリーに書き込みます。

注: すべての Idxi を 異なるものとすることで、 手順 3 が new の各成分を最大 1 回しか更新しないことが保証されます。

注: 手順 2 と 3 は、次の宣言的な規則に置き換えることができます:

型 vecN<S> のベクトル new を形成します。ここで new の成分 i は:

  • 0...K−1 のある j について i = Idxj の場合、 update の成分 j。

  • それ以外の場合、old_contents の成分 i。

スウィズルビューにはスウィズルビュー型があります:

制約 型 説明
S は具象スカラー型、
N と K は整数で、 vecN<S> と vecK<S> はともに有効なベクトル型。
ptr<AS,vecN<S>,read_write> は有効なポインター 型。
swizzle<AS,S,N,K> 次を満たすスウィズルビュー (p, IndexList) の 集合で識別されるスウィズル ビュー型:

スウィズルビュー型は WGSL ソースには記述されません。 代わりに WGSL モジュールの解析に使用されます。

スウィズルビューは次の方法で形成されます:

これらの規則により、スウィズルビューの IndexList 部分は シェーダー 作成時に完全に決定されます。

詳細については§ 8.6 スウィズルビュー式を参照してください。

例: 参照上のスウィズルビューを介した読み取りと書き込み
fn swizzle_read_and_write() {
  var v: vec4u;

  // 次と同じ:  v.y = 1; v.z = 2;
  // ただし、ベクトルはメモリーから正確に 1 回読み取られ、メモリーへ正確に 1 回書き込まれる。
  v.yz = vec2u(1,2);

  // 次と同じ: let u = vec3(v.a, v.g, v.b);
  // 式 v.agb は型 swizzle<function,u32,4,3> のスウィズルビュー。
  // let 宣言の実効値型は具象の構築可能型
  // またはポインター型でなければならない。そのためスウィズルビューは、
  // スウィズルビューロード規則を呼び出すことで自動的に vec3u に変換される。
  let u = v.agb;

  // スウィズルは連鎖できる。
  // 次と同じ: v.zy = vec2(99,100);
  v.yz.yx = vec2(99,100);

  // スウィズルビューに単一文字を適用すると、基礎となるベクトルの
  // スカラー成分への参照が得られる。
  // 次と同じ: v.z = 99;
  v.yz.y = 99;

  // スウィズルビューをインデックス付けすると、ベクトルの成分の 1 つへの参照が得られる。
  // 単一文字のベクトルアクセスを形成するかのように動作するが、
  // インデックスによって、スウィズル名からどの文字を使用するかが選択される。
  v.zy[1] = 50; // v.y = 50; と同じ
}
例: ポインター上のスウィズルビューを介した読み取りと書き込み
// この例では、swizzle_assignment に加えて pointer_composite_access のサポートも前提とする。
requires pointer_composite_access;

fn swizzle_read_and_write_via_pointer(p: ptr<function,vec4u>) {
  // 次と同じ:  (*p).y = 1; (*p).z = 2;
  p.yz = vec2u(1,2);

  // 次と同じ: let u = vec3((*p).a, (*p).g, (*p).b);
  let u = p.agb;

  // スウィズルは連鎖できる。
  // 次と同じ: p.zy = vec2(99,100);
  p.yz.yx = vec2(99,100);

  // スウィズルビューはポインターから構築できる。
  // スウィズルビューに単一文字を適用すると、基礎となるベクトルの
  // スカラー成分への参照が得られる。
  // 次と同じ: (*p).z = 99;
  p.yz.y = 99;

  // スウィズルビューをインデックス付けすると、ベクトルの成分の 1 つへの参照が得られる。
  // 単一文字のベクトルアクセスを形成するかのように動作するが、
  // インデックスによって、スウィズル名からどの文字を使用するかが選択される。
  p.zy[1] = 50; // (*p).y = 50; と同じ
}
例: 無効なスウィズルビュー
fn invalid_swizzle_cases() {
  var v: vec2u;

  // 無効: 成分が繰り返されるスウィズルには代入できない
  v.xx = vec2u(1,2);

  // 無効: 'z' は対象ベクトルの範囲外。
  v.xz = vec2u(1,2);
  let u = v.xz;

  // 無効: xyzw と rgba の文字体系を混在させてはならない
  v.xr = vec2u(1,2);

  // スウィズルビューのアドレスを取得することはできない。
  // ここで、v.xy はスウィズルビュー (&v,`01`)
  // & 演算子はスウィズルビューには適用されないため、型チェックは失敗する。
  let p = &v.xy;
}

一様性解析の目的では、 スウィズルビュー書き込みは、 更新される成分の値の一様性にのみ影響してもかまいません。 これが完全スウィズルビューと部分スウィズルビューを区別する理由です。

ただし、基礎となるベクトルのすべての成分を書き込むことは、メモリーモデルにとって重要です。 同じメモリー内ベクトルの異なる成分を 2 つの異なる呼び出しが同時に更新すると、 データ競合が発生します。

例: 異なるベクトル成分へのスウィズル書き込みは競合する場合がある
var<workgroup> w: vec4u;

@compute @workgroup_size(2)
fn this_races(@builtin(local_invocation_index) gid: u32) {
  if (gid == 0) {
    w.xy = vec2u(0,1);  // ベクトル全体を書き込み、他の呼び出しと競合する。
  } else {
    w.zw = vec2u(2,3);  // ベクトル全体を書き込み、他の呼び出しと競合する。
  }
}

6.5.5. 有効および無効なメモリー参照

参照値は、 有効または無効のいずれかです。

参照は、§ 6.5.9 参照値とポインター値の形成で 詳細に説明されるように形成されます。 一般に、有効な 参照は次の方法で形成されます:

一般に、無効なメモリー参照は次の方法で形成されます:

無効なポインターは 次の方法で形成されます:

有効なポインターは、 有効な参照に対応するポインターです。

有効なスウィズルビュー は、そのポインター値が有効である スウィズルビューです。 無効なスウィズル ビューは、そのポインター値が無効であるスウィズルビュー です。

6.5.6. 起点変数

参照値 R の起点 変数は、次のように定義されます:

ポインター値の起点 変数は、対応する参照値の起点変数として定義されます。

スウィズル ビューの起点 変数は、そのスウィズルビューのポインターの起点変数として定義されます。

注: 起点変数は動的な概念です。 関数の仮引数の起点変数は、その関数の 呼び出しサイトに依存します。 異なる呼び出しサイトは、異なる起点変数内へのポインターを提供する場合があります。

有効な参照は常に、 ある変数のメモリー位置の一部または全部に対する空でないメモリービューに対応します。

有効なスウィズルビューは 常に、ある変数内のベクトルのメモリー位置に対応します。

注: 参照は変数内部のメモリー位置に対応していても、 無効である場合があります。 これは、インデックスがインデックス付けされる型に対して大きすぎるが、 参照される位置が後続の兄弟データメンバー内にある場合に発生する可能性があります。

次の例では、参照 the_particle.position[i] は i が 0 または 1 の場合に限り有効です。 i が 2 の場合、参照は無効なメモリー 参照になりますが、それ以外では the_particle.color_index のメモリー位置に対応することになります。

例: 変数内にあるにもかかわらず無効なメモリー参照
struct Particle {
   position: vec2f,
   velocity: vec2f,
   color_index: i32,
}

@group(0) @binding(0)
var<storage,read_write> the_particle: Particle;

fn particle_velocity_component(p: Particle, i: i32) -> f32 {
  return the_particle.velocity[i]; // i が 0 または 1 の場合は有効な参照。
}

6.5.7. 範囲外アクセス

無効な メモリー参照または無効なスウィズルビューにアクセスする 操作は、範囲外アクセスです。

範囲外アクセスはプログラムの欠陥です。記述どおりに実行された場合、通常は次のようになるためです:

このため、実装はアクセスを記述どおりには実行しません。 範囲外アクセスを実行すると動的エラーが生成されます。

注: 格納型を誤って解釈する例は、 前節の例で発生します。 i が 2 の場合、式 the_particle.velocity[i] の 型は ref<storage,f32,read_write> であり、これはf32 を 格納型とするメモリービューであることを意味します。 しかし、メモリー位置は color_index メンバーに割り当てられているため、格納された値は実際にはi32 型です。

注:範囲外アクセスは動的エラーを引き起こし、 多くの結果が生じる可能性があります。

その結果には、次のものが含まれますが、これらに限定されません:

トラップ

シェーダー呼び出しは直ちに終了し、シェーダーステージ出力は ゼロ値に設定されます。

無効な ロード

無効な参照からのロードは、 次のいずれかを返す場合があります:

無効な ストア

無効な参照へのストアは、次のいずれかを行う場合があります:

無効なロードまたはストアが、共有アドレス空間内の変数の別の位置へアクセスするよう リダイレクトされた場合、データ競合が発生する可能性があります。 たとえば、同時に実行される複数の呼び出しのアクセスが 配列の最初の要素へリダイレクトされる場合があります。 少なくとも 1 つのアクセスが書き込みであり、それ以外に同期されていない場合、 結果はデータ競合となり、したがって動的エラーになります。

範囲外アクセスは一様性解析の仮定を無効にします。 たとえば、範囲外アクセスによって呼び出しが早期終了した場合、その呼び出しは 集合操作に参加できなくなります。 特に、workgroupBarrier の呼び出しによってシェーダーが停止する場合があり、 微分によって無効な結果が生成される場合があります。

6.5.8. 参照とポインターのユースケース

参照とポインターは、使用方法によって区別されます:

このように参照を定義することで、変数を単純かつ慣用的に使用できます:

例: 参照型による変数の単純な使用
@compute @workgroup_size(1)
fn main() {
  // 'i' の参照型は ref<function,i32,read_write>
  // 'i' のメモリー位置は i32 値 0 を格納する。
  var i: i32 = 0;

  // 'i + 1' は、'i' 部分式が i32 型である型規則にのみ一致できる。
  // そのため式 'i + 1' は i32 型であり、評価時に 'i' 部分式は
  // 評価時点で 'i' のメモリー位置に格納されている i32 値に
  // 評価される。
  let one: i32 = i + 1;

  // 'i' が参照する位置の値を更新し、値 2 を保持させる。
  i = one + 1;

  // 'i' が参照する位置の値を更新し、値 5 を保持させる。
  // 右辺の評価は代入が有効になる前に行われる。
  i = i + 3;
}
例: 参照を返すと、その参照を介してロードされた値が返される
var<private> age: i32;
fn get_age() -> i32 {
  // return 文内の式の型は、関数の宣言された戻り値型と
  // 一致しなければならないため、'i32' でなければならない。
  // 'age' 式の型は ref<private,i32,read_write>。
  // 参照の格納型が式に要求される型と一致し、他の型規則が適用されないため、
  // ロード規則を適用する。
  // このコンテキストでの 'age' の評価結果は、return 文が
  // 実行された時点で 'age' が参照するメモリー位置からロードされた
  // i32 値。
  return age;
}

fn caller() {
  age = 21;
  // copy_age 定数は i32 値 21 を得る。
  let copy_age: i32 = get_age();
}

このようにポインターを定義することで、2 つの主要なユースケースが可能になります:

例: 変数の一部の短い名前としてポインターを使用する
struct Particle {
  position: vec3<f32>,
  velocity: vec3<f32>
}
struct System {
  active_index: i32,
  timestep: f32,
  particles: array<Particle,100>
}
@group(0) @binding(0) var<storage,read_write> system: System;

@compute @workgroup_size(1)
fn main() {
  // storage メモリー内の特定の Particle へのポインターを形成する。
  let active_particle = &system.particles[system.active_index];

  let delta_position: vec3<f32> = (*active_particle).velocity * system.timestep;
  let current_position: vec3<f32>  = (*active_particle).position;
  (*active_particle).position = delta_position + current_position;
}
例: 仮引数としてポインターを使用する
fn add_one(x: ptr<function,i32>) {
  /* 'x' の位置を更新し、次に大きい整数値を格納する。
     (または最大の負の i32 値にラップアラウンドする)。
     左辺では、単項 '*' がポインターを参照に変換し、
     その参照に代入できる。既定では read_write アクセスモードを持つ。
     /* 右辺では:
        - 単項 '*' がポインターを read_write アクセスモードの
          参照に変換する。
        - 一致する唯一の型規則は加算 (+) で、'*x' に
          '*x' の格納型である i32 型を要求する。そのためロード規則が
          適用され、'*x' は評価時点で '*x' のメモリーに格納されている
          値、すなわち i32 値 0 に評価される。
        - 0 に 1 を加え、右辺の最終値 1 を生成する。 */
     '*x' のメモリーに 1 を格納する。 */
  *x = *x + 1;
}

@compute @workgroup_size(1)
fn main() {
  var i: i32 = 0;

  // 'i' の内容を変更し、1 を格納するようにする。
  // 単項 '&' を使用して 'i' のポインター値を取得する。
  // これは、呼び出された関数が 'i' のメモリーにアクセスでき、
  // 変更する可能性があることを明確に示す。
  add_one(&i);
  let one: i32 = i;  // 'one' の値は 1。
}

6.5.9. 参照値とポインター値の形成

参照値は次のいずれかの方法で形成されます:

すべての場合において、結果のアクセスモードは、 元の参照のアクセスモードと同じです。

例: 複合参照からの成分参照
struct S {
    age: i32,
    weight: f32
}
var<private> person: S;
// 他の場所では、'person' は変数の基礎となるメモリーへの参照を表し、
// 型は ref<private,S,read_write> になる。

fn f() {
    var uv: vec2<f32>;
    // この関数本体の残りでは、'uv' は変数の基礎となる
    // メモリーへの参照を表し、型は
    // ref<function,vec2<f32>,read_write> になる。

    // 代入の左辺を評価する:
    //   'uv.x' を評価して参照を生成する:
    //   1. まず 'uv' を評価し、'uv' 変数のメモリーへの参照を生成する。
    //      結果の型は ref<function,vec2<f32>,read_write>。
    //   2. 次に '.x' ベクトルアクセス句を適用し、前の手順の
    //      参照値が指すベクトルの最初の成分のメモリーへの
    //      参照を生成する。
    //      結果の型は ref<function,f32,read_write>。
    // 代入の右辺を評価すると f32 値 1.0 が得られる。
    // f32 値 1.0 を uv.x が参照する storage メモリー位置に格納する。
    uv.x = 1.0;

    // 代入の左辺を評価する:
    //   'uv[1]' を評価して参照を生成する:
    //   1. まず 'uv' を評価し、'uv' 変数のメモリーへの参照を生成する。
    //      結果の型は ref<function,vec2<f32>,read_write>。
    //   2. 次に '[1]' 配列インデックス句を適用し、前の手順で
    //      参照されたベクトルの 2 番目の成分のメモリーへの参照を
    //      生成する。結果の型は ref<function,f32,read_write>。
    // 代入の右辺を評価すると f32 値 2.0 が得られる。
    // f32 値 2.0 を uv[1] が参照する storage メモリー位置に格納する。
    uv[1] = 2.0;

    var m: mat3x2<f32>;
    // 'm[2]' を評価するとき:
    // 1. まず 'm' を評価し、'm' 変数のメモリーへの参照を生成する。
    //    結果の型は ref<function,mat3x2<f32>,read_write>。
    // 2. 次に '[2]' 配列インデックス句を適用し、前の手順の参照値が
    //    指す 3 番目の列ベクトルのメモリーへの参照を生成する。
    //    したがって 'm[2]' 式の型は ref<function,vec2<f32>,read_write>。
    // 'let' 宣言の型は vec2<f32> なので、宣言文は
    // 初期化子が vec2<f32> 型であることを要求する。
    // ロード規則が適用され(他の型規則は適用できないため)、
    // 初期化子の評価結果は、宣言が実行された時点で 'm[2]' が参照する
    // メモリー位置からロードされた vec2<f32> 値になる。
    let p_m_col2: vec2<f32> = m[2];

    var A: array<i32,5>;
    // 'A[4]' を評価するとき
    // 1. まず 'A' を評価し、'A' 変数のメモリーへの参照を生成する。
    //    結果の型は ref<function,array<i32,5>,read_write>。
    // 2. 次に '[4]' 配列インデックス句を適用し、前の手順の参照値が
    //    参照する配列の 5 番目の要素のメモリーへの参照を生成する。
    //    結果値の型は ref<function,i32,read_write>。
    // let 宣言は右辺が i32 型であることを要求する。
    // ロード規則が適用され(他の型規則は適用できないため)、
    // 初期化子の評価結果は、宣言が実行された時点で 'A[4]' が参照する
    // メモリー位置からロードされた i32 値になる。
    let A_4_value: i32 = A[4];

    // 'person.weight' を評価するとき
    // 1. まず 'person' を評価し、モジュールスコープで宣言された
    //    'person' 変数のメモリーへの参照を生成する。
    //    結果の型は ref<private,S,read_write>。
    // 2. 次に '.weight' メンバーアクセス句を適用し、前の手順の
    //    参照値が参照するメモリーの 2 番目のメンバーのメモリーへの
    //    参照を生成する。
    //    結果の型は ref<private,f32,read_write>。
    // let 宣言は右辺が f32 型であることを要求する。
    // ロード規則が適用され(他の型規則は適用できないため)、
    // 初期化子の評価結果は、宣言が実行された時点で
    // 'person.weight' が参照するメモリー位置からロードされた
    // f32 値になる。
    let person_weight: f32 = person.weight;

    // 代わりに、同じ構文を使用してポインターから参照を形成することもできる。

    let uv_ptr = &uv;
    // この関数本体の残りでは、'uv_ptr' は 'uv' の基礎となる
    // メモリーへのポインターを表し、型は
    // ptr<function,vec2<f32>,read_write> になる。

    // 代入の左辺を評価する:
    //   '*uv_ptr' を評価して参照を生成する:
    //   1. まず 'uv_ptr' を評価し、'uv' 変数のメモリーへのポインターを生成する。
    //      結果の型は ptr<function,vec2<f32>,read_write>。
    //   2. 次に間接参照式演算子を適用し、
    //      'uv' のメモリーへの参照を生成する。
    // 代入の右辺を評価すると vec2<f32> 値 (1.0, 2.0) が得られる。
    // 値 (1.0, 2.0) を uv が参照する storage メモリー位置に格納する。
    *uv_ptr = vec2f(1.0, 2.0);

    // 代入の左辺を評価する:
    //   'uv_ptr.x' を評価して参照を生成する:
    //   1. まず 'uv_ptr' を評価し、'uv' 変数のメモリーへのポインターを生成する。
    //      結果の型は ptr<function,vec2<f32>,read_write>。
    //   2. 次に '.x' ベクトルアクセス句を適用し、前の手順の
    //      ポインター値が指すベクトルの最初の成分のメモリーへの
    //      参照を生成する。
    //      結果の型は ref<function,f32,read_write>。
    // 代入の右辺を評価すると f32 値 1.0 が得られる。
    // f32 値 1.0 を uv.x が参照する storage メモリー位置に格納する。
    uv_ptr.x = 1.0;

    // 代入の左辺を評価する:
    //   'uv_ptr[1]' を評価して参照を生成する:
    //   1. まず 'uv_ptr' を評価し、'uv' 変数のメモリーへのポインターを生成する。
    //      結果の型は ptr<function,vec2<f32>,read_write>。
    //   2. 次に '[1]' 配列インデックス句を適用し、前の手順で
    //      参照されたベクトルの 2 番目の成分のメモリーへの参照を
    //      生成する。結果の型は ref<function,f32,read_write>。
    // 代入の右辺を評価すると f32 値 2.0 が得られる。
    // f32 値 2.0 を uv[1] が参照する storage メモリー位置に格納する。
    uv_ptr[1] = 2.0;

    let m_ptr = &m;
    // 'm_ptr[2]' を評価するとき:
    // 1. まず 'm_ptr' を評価し、'm' 変数のメモリーへのポインターを生成する。
    //    結果の型は ptr<function,mat3x2<f32>,read_write>。
    // 2. 次に '[2]' 配列インデックス句を適用し、前の手順の参照値が
    //    指す 3 番目の列ベクトルのメモリーへの参照を生成する。
    //    したがって 'm[2]' 式の型は ref<function,vec2<f32>,read_write>。
    // 'let' 宣言の型は vec2<f32> なので、宣言文は
    // 初期化子が vec2<f32> 型であることを要求する。
    // ロード規則が適用され(他の型規則は適用できないため)、
    // 初期化子の評価結果は、宣言が実行された時点で 'm[2]' が参照する
    // メモリー位置からロードされた vec2<f32> 値になる。
    let p_m_col2: vec2<f32> = m_ptr[2];

    let A_ptr = &A;
    // 'A[4]' を評価するとき
    // 1. まず 'A' を評価し、'A' 変数のメモリーへのポインターを生成する。
    //    結果の型は ptr<function,array<i32,5>,read_write>。
    // 2. 次に '[4]' 配列インデックス句を適用し、前の手順の参照値が
    //    参照する配列の 5 番目の要素のメモリーへの参照を生成する。
    //    結果値の型は ref<function,i32,read_write>。
    // let 宣言は右辺が i32 型であることを要求する。
    // ロード規則が適用され(他の型規則は適用できないため)、
    // 初期化子の評価結果は、宣言が実行された時点で 'A[4]' が参照する
    // メモリー位置からロードされた i32 値になる。
    let A_4_value: i32 = A_ptr[4];

    let person_ptr = &person;
    // 'person.weight' を評価するとき
    // 1. まず 'person_ptr' を評価し、モジュールスコープで宣言された
    //    'person' 変数のメモリーへのポインターを生成する。
    //    結果の型は ptr<private,S,read_write>。
    // 2. 次に '.weight' メンバーアクセス句を適用し、前の手順の
    //    参照値が参照するメモリーの 2 番目のメンバーのメモリーへの
    //    参照を生成する。
    //    結果の型は ref<private,f32,read_write>。
    // let 宣言は右辺が f32 型であることを要求する。
    // ロード規則が適用され(他の型規則は適用できないため)、
    // 初期化子の評価結果は、宣言が実行された時点で
    // 'person.weight' が参照するメモリー位置からロードされた
    // f32 値になる。
    let person_weight: f32 = person_ptr.weight;
}

ポインター値は次のいずれかの方法で形成されます:

すべての場合において、結果のアクセスモードは、 元のポインターのアクセスモードと同じです。

例: 変数からのポインター
// f32 値を格納するため、private アドレス空間に変数を宣言する。
var<private> x: f32;

fn f() {
    // i32 値を格納するため、function アドレス空間に変数を宣言する。
    var y: i32;

    // 名前 'x' はモジュールスコープ変数 'x' に解決され、
    // 参照型 ref<private,f32,read_write> を持つ。
    // 単項 '&' 演算子を適用すると、参照がポインターに変換される。
    // アクセスモードは元の変数のアクセスモードと同じなので、
    // 完全指定された型は ptr<private,f32,read_write>。ただし read_write は
    // function アドレス空間の既定アクセスモードなので、この場合 read_write を
    // 記述する必要はない
    let x_ptr: ptr<private,f32> = &x;

    // 名前 'y' は関数スコープ変数 'y' に解決され、
    // 参照型 ref<private,i32,read_write> を持つ。
    // 単項 '&' 演算子を適用すると、参照がポインターに変換される。
    // アクセスモードの既定値は 'read_write'。
    let y_ptr: ptr<function,i32> = &y;

    // モジュールスコープで宣言された変数とは異なる新しい変数。
    var x: u32;

    // ここでは、名前 'x' は前の文で宣言された関数スコープ変数 'x' に
    // 解決され、型 ref<function,u32,read_write> を持つ。
    // 単項 '&' 演算子を適用すると、参照がポインターに変換される。
    // アクセスモードの既定値は 'read_write'。
    let inner_x_ptr: ptr<function,u32> = &x;
}

6.5.10. 他の言語における参照およびポインターとの比較

この節は参考情報であり、規範的ではありません。

WGSL の参照とポインターは、他の言語よりも制限されています。 特に:

注: 上記の規則により、 「ダングリング」ポインター、すなわち「存続中」の 起点変数のメモリーを参照しないポインターを形成することはできません。 メモリービューは無効な メモリー参照である場合がありますが、 起点変数またはバッファーに関連付けられていないメモリー 位置には決して アクセスしません。

6.6. テクスチャーおよびサンプラー型

テクセルは、 テクスチャーの独立してアクセス可能な最小要素として使用されるスカラーまたはベクトルです。 texel という語は texture element の略です。

テクスチャーは、 レンダリングに有用な特殊な操作をサポートするテクセルの集合です。 WGSL では、これらの操作はテクスチャー組み込み関数を介して呼び出されます。 完全な一覧については§ 17.7 テクスチャー組み込み関数を参照してください。

WGSL テクスチャーは WebGPU GPUTexture に対応します。

テクスチャーには次の特性があります:

テクセルフォーマット

各テクセルのデータ表現。§ 6.6.1 テクセルフォーマットを参照してください。

次元数

グリッド座標の次元数と、座標がどのように解釈されるか。 次元数は 1、2、または 3 です。 ほとんどのテクスチャーはデカルト座標を使用します。 キューブテクスチャーには 6 つの正方形の面があり、 原点を中心とするキューブに向かう原点からの方向ベクトルとして解釈される 3 次元座標を使用してサンプリングされます。

GPUTextureViewDimension を参照してください。

サイズ

各次元に沿ったグリッド座標の範囲。これはミップレベルの関数です。

ミップレベル数

ミップレベル数は、サンプリングテクスチャーおよび深度テクスチャーでは少なくとも 1 であり、 ストレージ テクスチャーでは 1 に等しくなります。
ミップレベル 0 は テクスチャーのフルサイズ版を含みます。 後続の各ミップレベルは、前のミップレベルの半分のサイズ(丸めの範囲内)で、 前のミップレベルをフィルタリングした版を含みます。
テクスチャーをサンプリングするときは、明示的または暗黙的に計算された詳細レベルを使用して、 テクセルデータを読み取るミップレベルを選択します。その後、それらを フィルタリングによって組み合わせてサンプリング値を生成します。

配列化

テクスチャーが配列化されているかどうか。

  • 非配列化テクスチャーはテクセルのグリッドです。

  • 配列化テクスチャーは、テクセルグリッドの同種配列です。

配列サイズ

テクスチャーが配列化されている場合の同種グリッドの数。

サンプル数

テクスチャーがマルチサンプリングされている場合のサンプル数。

テクスチャー内の各テクセルには一意の論理テクセルアドレスが関連付けられます。 これは次を持つ整数タプルです:

テクスチャーの物理的な構成は、通常、レンダリング操作向けに最適化されています。 これを実現するため、データレイアウト、データ型、シェーダー言語で直接表現できない 内部操作など、多くの詳細がプログラマーから隠されています。

その結果、シェーダーはテクスチャー変数内のテクセルメモリーへ直接アクセスできません。 代わりに、アクセスは不透明ハンドルを介して行われます:

このように、テクスチャー型でサポートされる操作の集合は、 そのテクスチャー型の仮 引数を持つテクスチャー組み込み関数が 利用可能かどうかによって決まります。

注: テクスチャー変数に格納されたハンドルは、 シェーダーによって変更できません。 つまり、基礎となるテクスチャーが変更可能である場合 (例: 書き込み専用のストレージテクスチャー)でも、変数は読み取り専用です。

テクスチャー型は、 次で定義される型の集合です:

サンプラーは、 サンプリング テクスチャーまたは深度テクスチャーからテクセルにアクセスする方法を制御する不透明ハンドルです。

WGSL サンプラーは WebGPU GPUSampler に対応します。

テクセルアクセスは、サンプラーの複数のプロパティによって制御されます:

アドレッシングモード

テクスチャー境界および範囲外座標をどのように解決するかを制御します。 各テクスチャー次元のアドレッシングモードは独立して設定できます。 WebGPU GPUAddressMode を参照してください。

フィルターモード

最終結果を生成するためにどのテクセルへアクセスするかを制御します。 フィルタリングでは、最も近いテクセルを使用するか、 複数のテクセル間を補間できます。 複数のフィルターモードを独立して設定できます。 WebGPU GPUFilterMode を参照してください。

LOD クランプ

アクセスされる詳細レベルの最小値と最大値を制御します。

比較

比較サンプラーに対して行われる比較の種類を制御します。 WebGPU GPUCompareFunction を参照してください。

最大異方性

サンプラーが使用する最大異方性値を制御します。

サンプラーは WGSL モジュール内で作成できず、その状態(例: 上記の プロパティ)はシェーダー内では不変であり、WebGPU API によってのみ設定できます。

補間フィルタリングを使用するサンプラーが、フィルタリング不可能な フォーマットのテクスチャーとともに使用される場合、パイプライン作成エラーになります。

注: サンプラー変数に格納されたハンドルは、 シェーダーによって変更できません。

6.6.1. テクセルフォーマット

WGSL では、特定のテクスチャー型はテクセルフォーマットによってパラメーター化されます。

テクセルフォーマットは、 次の要素によって特徴付けられます:

チャンネル

各チャンネルはスカラーを含みます。 テクセルフォーマットは最大 4 つのチャンネルを持ちます: r、g、b、および a。 通常、それぞれ赤、緑、青、およびアルファチャンネルの概念に対応します。

チャンネル フォーマット

チャンネル内のビット数と、それらのビットがどのように解釈されるか。

WGSL の各テクセルフォーマットは、同じ名前を持つ WebGPU GPUTextureFormat に対応します。

WGSL ソースコードでは、特定のテクセルフォーマットのみが使用されます。 それらのテクセルフォーマットを定義するために使用されるチャンネルフォーマットは、 チャンネルフォーマット表に列挙されています。 最後から 2 番目の列は、格納されたチャンネルビットからシェーダーで使用される値への変換を指定します。 これはチャンネル伝達関数、または CTF とも呼ばれます。 3 番目の列は、シェーダー値から格納されたチャンネルビットへの変換を指定します。 これは逆チャンネル伝達関数、または ICTF とも呼ばれます。 最後の列は、テクセルフォーマットに必要な言語拡張を指定します。

注: 8unorm のチャンネル伝達関数は、 {0,...,255} を浮動小数点区間 [0.0, 1.0] に対応付けます。

注: 8snorm のチャンネル伝達関数は、 {-128,...,127} を浮動小数点区間 [-1.0, 1.0] に対応付けます。

チャンネルフォーマット
チャンネルフォーマット 格納ビット数 格納ビットの解釈 シェーダー型 シェーダー値(チャンネル伝達関数) 書き込み値 T(逆チャンネル伝達関数)
8unorm 8 符号なし整数 v ∈ {0,...,255} f32 v ÷ 255 max(0, min(1, T))
8snorm 8 符号付き整数 v ∈ {-128,...,127} f32 v ÷ 127 max(-1, min(1, T))
8uint 8 符号なし整数 v ∈ {0,...,255} u32 v min(255, T)
8sint 8 符号付き整数 v ∈ {-128,...,127} i32 v max(-128, min(127, T))
16unorm 16 符号なし整数 v ∈ {0,...,65535} f32 v ÷ 65535 max(0, min(1, T))
16snorm 16 符号付き整数 v ∈ {-32768,...,32767} f32 v ÷ 32767 max(-1, min(1, T))
16uint 16 符号なし整数 v ∈ {0,...,65535} u32 v min(65535, T)
16sint 16 符号付き整数 v ∈ {-32768,...,32767} i32 v max(-32768, min(32767, T))
16float 16 IEEE-754 binary16 16 ビット浮動小数点 値 v f32 v quantizeToF16(T)
32uint 32 32 ビット符号なし整数値 v u32 v T
32sint 32 32 ビット符号付き整数値 v i32 v T
32float 32 IEEE-754 binary32 32 ビット浮動小数点 値 v f32 v T
2unorm 2 符号なし整数 v ∈ {0,...,3} f32 v ÷ 3 max(0, min(1, T))
2uint 2 符号なし整数 v ∈ {0,...,3} u32 v min(3, T)
10unorm 10 符号なし整数 v ∈ {0,...,1023} f32 v ÷ 1023 max(0, min(1, T))
10uint 10 符号なし整数 v ∈ {0,...,1023} u32 v min(1023, T)
10float 10 10 ビット浮動小数点値: バイアス付き指数 5 ビット、小数部 5 ビット v f32 v max(0, T)
11float 11 11 ビット浮動小数点値: バイアス付き指数 5 ビット、小数部 6 ビット v f32 v max(0, T)

ストレージテクスチャー用テクセルフォーマット表に列挙されるテクセルフォーマットは、 少なくとも 1 つのアクセス モードで WebGPU STORAGE_BINDING 用途をサポートするWebGPU プレーンカラーフォーマット に対応します。 これらのテクセルフォーマットは、§ 6.6.5 ストレージテクスチャー型で定義される ストレージテクスチャー型をパラメーター化するために使用されます。

テクセルフォーマットが 4 つすべてのチャンネルを持たない場合:

以下の表の最後の列では、チャンネルフォーマット表のフォーマット固有の チャンネル 伝達関数を使用します。

ストレージテクスチャー用テクセルフォーマット
テクセルフォーマット チャンネルフォーマット メモリー順のチャンネル 対応するシェーダー値 必要な言語拡張
rgba8unorm 8unorm r, g, b, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba8snorm 8snorm r, g, b, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba8uint 8uint r, g, b, a vec4<u32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba8sint 8sint r, g, b, a vec4<i32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba16unorm 16unorm r, g, b, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a)) texture_formats_tier1
rgba16snorm 16snorm r, g, b, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a)) texture_formats_tier1
rgba16uint 16uint r, g, b, a vec4<u32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba16sint 16sint r, g, b, a vec4<i32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba16float 16float r, g, b, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a))
rg8unorm 8unorm r, g vec4<f32>(CTF(r), CTF(g), 0.0, 1.0) texture_formats_tier1
rg8snorm 8snorm r, g vec4<f32>(CTF(r), CTF(g), 0.0, 1.0) texture_formats_tier1
rg8uint 8uint r, g vec4<u32>(CTF(r), CTF(g), 0u, 1u) texture_formats_tier1
rg8sint 8sint r, g vec4<i32>(CTF(r), CTF(g), 0, 1) texture_formats_tier1
rg16unorm 16unorm r, g vec4<f32>(CTF(r), CTF(g), 0.0, 1.0) texture_formats_tier1
rg16snorm 16snorm r, g vec4<f32>(CTF(r), CTF(g), 0.0, 1.0) texture_formats_tier1
rg16uint 16uint r, g vec4<u32>(CTF(r), CTF(g), 0u, 1u) texture_formats_tier1
rg16sint 16sint r, g vec4<i32>(CTF(r), CTF(g), 0, 1) texture_formats_tier1
rg16float 16float r, g vec4<f32>(CTF(r), CTF(g), 0.0, 1.0) texture_formats_tier1
r32uint 32uint r vec4<u32>(CTF(r), 0u, 0u, 1u)
r32sint 32sint r vec4<i32>(CTF(r), 0, 0, 1)
r32float 32float r vec4<f32>(CTF(r), 0.0, 0.0, 1.0)
rg32uint 32uint r, g vec4<u32>(CTF(r), CTF(g), 0u, 1u)
rg32sint 32sint r, g vec4<i32>(CTF(r), CTF(g), 0, 1)
rg32float 32float r, g vec4<f32>(CTF(r), CTF(g), 0.0, 1.0)
rgba32uint 32uint r, g, b, a vec4<u32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba32sint 32sint r, g, b, a vec4<i32>(CTF(r), CTF(g), CTF(b), CTF(a))
rgba32float 32float r, g, b, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a))
bgra8unorm 8unorm b, g, r, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a))
r8unorm 8unorm r vec4<f32>(CTF(r), 0.0, 0.0, 1.0) texture_formats_tier1
r8snorm 8snorm r vec4<f32>(CTF(r), 0.0, 0.0, 1.0) texture_formats_tier1
r8uint 8uint r vec4<u32>(CTF(r), 0u, 0u, 1u) texture_formats_tier1
r8sint 8sint r vec4<i32>(CTF(r), 0, 0, 1) texture_formats_tier1
r16unorm 16unorm r vec4<f32>(CTF(r), 0.0, 0.0, 1.0) texture_formats_tier1
r16snorm 16snorm r vec4<f32>(CTF(r), 0.0, 0.0, 1.0) texture_formats_tier1
r16uint 16uint r vec4<u32>(CTF(r), 0u, 0u, 1u) texture_formats_tier1
r16sint 16sint r vec4<i32>(CTF(r), 0, 0, 1) texture_formats_tier1
r16float 16float r vec4<f32>(CTF(r), 0.0, 0.0, 1.0) texture_formats_tier1
rgb10a2unorm r, g, b: 10unorm a: 2unorm r, g, b, a vec4<f32>(CTF(r), CTF(g), CTF(b), CTF(a)) texture_formats_tier1
rgb10a2uint r, g, b: 10uint a: 2uint r, g, b, a vec4<u32>(CTF(r), CTF(g), CTF(b), CTF(a)) texture_formats_tier1
rg11b10ufloat r, g: 11float b: 10float r, g, b vec4<f32>(CTF(r), CTF(g), CTF(b), 1.0) texture_formats_tier1

WGSL は、表内の各テクセルフォーマットについて列挙子を事前宣言します。

6.6.2. サンプリングテクスチャー型

サンプリングテクスチャーは、 サンプラーと組み合わせて アクセスできます。 サンプラーを使用せずにアクセスすることもできます。 サンプリングテクスチャーでは読み取り アクセスのみが許可されます。

テクセルフォーマットは、 テクスチャー変数にバインドされた GPUTexture の format 属性です。 WebGPU は、テクスチャー、バインドグループレイアウトの sampleType、 およびテクスチャー変数のサンプリング型の 互換性を検証します。

テクスチャーはサンプリング型によってパラメーター化され、 f32、i32、または u32 でなければなりません。

型 次元数 配列化
texture_1d<T> 1D いいえ
texture_2d<T> 2D いいえ
texture_2d_array<T> 2D はい
texture_3d<T> 3D いいえ
texture_cube<T> Cube いいえ
texture_cube_array<T> Cube はい

6.6.3. マルチサンプリングテクスチャー型

マルチサンプリングテクスチャーは、 1 以上のサンプル数を持ちます。 その名前にもかかわらず、サンプラーとともに使用することはできません。 サンプルインデックスを無視した場合、論理テクセル アドレスごとに、実質的に複数のテクセル分の データを格納します。

テクセルフォーマットは、 テクスチャー変数にバインドされた GPUTexture の format 属性です。 WebGPU は、テクスチャー、バインドグループレイアウトの sampleType、 およびテクスチャー変数のサンプリング型の 互換性を検証します。

texture_multisampled_2d はサンプリング型によってパラメーター化され、 f32、i32、または u32 でなければなりません。

型 次元数 配列化
texture_multisampled_2d<T> 2D いいえ
texture_depth_multisampled_2d 2D いいえ

6.6.4. 外部サンプリングテクスチャー型

外部テクスチャーは、 texture_2d<f32> に似ていますが、 異なる表現を持つ可能性がある、不透明な 2 次元浮動小数点サンプリングテクスチャー型です。 これらの異なる表現を処理する textureLoad または textureSampleBaseClampToEdge 組み込み 関数を使用して読み取ることができます。

WebGPU § 6.4 GPUExternalTextureを参照してください。

型 次元数 配列化
texture_external 2D いいえ

6.6.5. ストレージテクスチャー型

ストレージテクスチャーは、サンプラーを使用せずに 個々のテクセル値へアクセスすることをサポートします。

ストレージテクスチャー型は、ストレージテクスチャー用テクセルフォーマットの いずれかによってパラメーター化されなければなりません。 テクセルフォーマットは、§ 6.6.1 テクセル フォーマットで指定される変換関数を決定します。

ストレージテクスチャーへテクセルを書き込む場合、変換関数の逆を使用して、 シェーダー値を格納されるテクセルへ変換します。

型 次元数 配列化
texture_storage_1d<Format, Access> 1D いいえ
texture_storage_2d<Format, Access> 2D いいえ
texture_storage_2d_array<Format, Access> 2D はい
texture_storage_3d<Format, Access> 3D いいえ

6.6.6. 深度テクスチャー型

深度テクスチャーは、 sampler_comparison と組み合わせて アクセスできます。 サンプラーを使用せずにアクセスすることもできます。 深度テクスチャーでは読み取り アクセスのみが許可されます。

テクスチャーのテクセルフォーマットは、 GPUTextureBindingLayout で定義されます。

型 次元数 配列化
texture_depth_2d 2D いいえ
texture_depth_2d_array 2D はい
texture_depth_cube Cube いいえ
texture_depth_cube_array Cube はい

6.6.7. サンプラー型

サンプラーは、 次の組み合わせを実行することによって、サンプリングテクスチャー または 深度テクスチャーへの アクセスを仲介します:

サンプラー型は次のとおりです:

型 説明
sampler サンプラー。サンプリングテクスチャーへのアクセスを仲介します。
sampler_comparison 比較サンプラー。 深度テクスチャーへのアクセスを仲介します。

サンプラーは WebGPU API で作成されるときにパラメーター化されます。 WGSL モジュールによって変更することはできません。

サンプラーはテクスチャー組み込み関数によってのみ使用できます。

sampler
sampler_comparison

6.7. AllTypes 型

AllTypes 型は、 すべての WGSL 型の集合です。

WGSL ソースに AllTypes 型を記述する方法はありません。

すべての事前宣言済み型と型ジェネレーターの一覧については、 § 6.10 事前宣言済み型と型ジェネレーターの概要を参照してください。

注:型は通常の意味での値ではありません。 シェーダーが実行時に操作するデータではありません。

代わりに、AllTypes 型は、通常の値を含む可能性がある任意の句に型チェック規則を適用できるようにするために存在します。 WGSL は、型を値の一種として定義し、式が型を表せるようにすることで規則を一貫させています。

動機となるケースはテンプレートパラメーターであり、さまざまなコンテキストで 型、列挙子、またはプレーン値を含む、 複数種類のものを表す場合があります。 特に、template_arg_expression 文法規則は、 expression 文法 非終端記号へ展開されます。

6.8. 型エイリアス

型エイリアスは、 既存の型に新しい名前を宣言します。 宣言はモジュールスコープに現れなければならず、そのスコープはプログラム全体です。

型 T が構造体型 S の型 エイリアスとして定義される場合、 属性を含む S のメンバーのすべてのプロパティが T のメンバーへ引き継がれます。

注: エイリアスされる型が値コンストラクター 組み込み関数をサポートしている場合、 型エイリアスがスコープ内にあり、その関数を呼び出すことが他の点でも有効であれば、 元の型指定子名の代わりにエイリアス名を使用してそれらの関数を呼び出せます。

type_alias_decl :

'alias' ident '=' type_specifier

例: 型エイリアス
alias Arr = array<i32, 5>;

alias RTArr = array<vec4<f32>>;

alias single = f32;     // f32 のエイリアスを宣言する
const pi_approx: single = 3.1415;
fn two_pi() -> single {
  return single(2) * pi_approx;
}

6.9. 型指定子文法

§ 8.18 型式を参照してください。

type_specifier :

template_elaborated_ident

template_elaborated_ident :

ident template_list ?

注: 式も、 primary_expression 文法規則を介してtemplate_elaborated_ident に展開し、 また括弧付けを介することで、型を表すことができます。

6.10. 事前宣言済み型と型ジェネレーターの概要

WGSL ソースに記述できる事前宣言済み 型は次のとおりです:

WGSL は、frexp、 modf、およびatomicCompareExchangeWeak 組み込み 関数の戻り値型も事前宣言します。 ただし、それらを WGSL ソースに記述することはできません。

事前宣言済み型ジェネレーターを次の表に示します:

事前宣言済み型ジェネレーター
事前宣言済み型ジェネレーター 相互参照
array § 6.2.9 配列型を参照
atomic § 6.2.8 アトミック型を参照
mat2x2 § 6.2.7 行列型を参照してください。ここには 行列型の事前宣言済みエイリアスも 列挙されています。

注: これらは行列を作成するための 値 コンストラクター式でも使用されます。

mat2x3
mat2x4
mat3x2
mat3x3
mat3x4
mat4x2
mat4x3
mat4x4
ptr § 6.5.3 参照型とポインター型を参照
texture_1d § 6.6.2 サンプリングテクスチャー型を参照
texture_2d
texture_2d_array
texture_3d
texture_cube
texture_cube_array
texture_multisampled_2d § 6.6.3 マルチサンプリングテクスチャー型を参照
texture_storage_1d § 6.6.5 ストレージテクスチャー型を参照
texture_storage_2d
texture_storage_2d_array
texture_storage_3d
vec2 § 6.2.6 ベクトル型を参照してください。ここには ベクトル型の事前宣言済みエイリアスも 列挙されています。

注: これらはベクトルを作成するための 値 コンストラクター式でも使用されます。

vec3
vec4

7. 変数と値の宣言

変数宣言と値宣言は、 データ値に名前を提供します。

値宣言は、 値の名前を作成し、その値は宣言された後は不変です。 値宣言には const、override、let、および 仮引数宣言の 4 種類があり、以下で詳しく説明します(§ 7.2 値宣言を参照)。

変数 宣言は、値を格納するためのメモリー位置に名前を作成します。変数が read_write アクセス モードを持つ場合、そこに格納された値は更新できます。 変数宣言は var の 1 種類ですが、以下で説明するように、 アドレス空間とアクセスモードを さまざまに組み合わせるオプションがあります (§ 7.3 var 宣言を参照)。

注: 値宣言には関連付けられたメモリー位置がありません。 たとえば、その値へのポインターを形成できる WGSL 式はありません。

どの関数定義の外側にも現れる宣言はモジュールスコープにあります。 その名前はプログラム全体でスコープ内です。

関数定義内に現れる宣言は関数スコープにあります。 その名前は宣言の直後の文から、 宣言を直接囲む波括弧で区切られた文リストの終端まで使用できます。 関数スコープ宣言は動的コンテキストです。

注:
変数宣言と値宣言は、全体として似た構文を持ちます。次の非規範的な 図は、変数宣言と値宣言の一般形を示します。ここで [...] は 任意の部分、...* は直前の要素の 0 回以上の繰り返し、...+ は 直前の要素の 1 回以上の繰り返しを表します。具体的な構文規則については、 各要素の対応する節を参照してください。
// 特定の値宣言。
             const    name [: type]  = initializer ;
[attribute]* override name [: type] [= initializer];
             let      name [: type]  = initializer ;

// 一般的な変数形式。
[attribute]* var[<address_space[, access_mode]>] name [: type] [= initializer];

// 特定の変数宣言。
// 関数スコープ。
             var[<function>] name [: type] [= initializer];

// モジュールスコープ。
             var<private>    name [: type] [= initializer];
             var<workgroup>  name : type;
[attribute]+ var<uniform>    name : type;
[attribute]+ var             name : texture_type;
[attribute]+ var             name : sampler_type;
[attribute]+ var<storage[, access_mode]> name : type;

このような各宣言は、明示的に指定された型または初期化子を持たなければなりません。 型と初期化子の両方を指定してもかまいません。 このような各宣言は、関連付けられたデータ値の型を決定します。これは 宣言の実効値型と呼ばれます。 宣言の実効値型は次のとおりです:

各種類の値宣言または変数宣言は、存在する場合には初期化子式の形式と 実効値型に追加の制約を課す場合があります。

変数宣言と値宣言の機能概要。
宣言 可変性 スコープ 実効値型1 初期化子のサポート 初期化子式2 リソースインターフェイスの一部
const 不変 モジュールまたは関数 構築可能(具象または抽象) 必須 const 式 いいえ
override 不変 モジュール 具象スカラー 任意3 const 式またはoverride 式 いいえ4
let 不変 関数 具象構築可能または ポインター型。 さらに、texture_and_sampler_let 機能が サポートされている場合、テクスチャー型またはサンプラー型。 必須 const 式、override 式、または ランタイム 式 いいえ
var<storage, read>
var<storage>
不変 モジュール 具象ホスト共有可能 不可 はい。
storage バッファー
var<storage, read_write>5,6 可変 モジュール 具象ホスト共有可能 不可 はい。
storage バッファー
var<uniform> 不変 モジュール 具象構築可能ホスト共有可能 または固定サイズ バッファー 不可 はい。
uniform バッファー
var<immediate> 不変 モジュール 具象構築可能ホスト共有可能。 ただし配列および配列メンバーを含む構造体を除く 不可 はい。
即時 データ
var5 不変7 モジュール テクスチャー 不可 はい。
テクスチャー リソース
var 不変 モジュール サンプラー 不可 はい。
サンプラー リソース
var<workgroup>6,8 可変 モジュール 具象で、 固定 フットプリントを持つプレーン型または固定サイズバッファー9 不可10 いいえ
var<private> 可変 モジュール 具象構築可能 任意10 const 式またはoverride 式 いいえ
var<function>
var
可変 関数 具象構築可能 任意10 const 式、override 式、または ランタイム 式 いいえ
  1. const 宣言のみが抽象型になることができ、 それも型が明示的に指定されていない場合に限ります。

  2. 式の型は実効値型へ実行可能な変換が可能でなければなりません。

  3. 初期化子が指定されていない場合、パイプライン作成時に 値を提供しなければなりません。

  4. override 宣言はシェーダーインターフェイスの一部ですが、 バインドされたリソースではありません。

  5. read 以外のアクセスモードを持つ ストレージバッファーおよび ストレージ テクスチャーは、頂点シェーダーステージで静的に アクセスすることはできません。 WebGPU createBindGroupLayout() を参照してください。

  6. アトミック型は、 可変なストレージバッファーまたはワークグループ変数にのみ現れることができます。

  7. ストレージテクスチャー内のデータは、 write またはread_write アクセスモードを持つ場合は可変ですが、 textureStore 組み込み関数を介してのみ変更できます。 変数自体は変更できません。

  8. workgroup アドレス空間内の変数は、 コンピュートシェーダーステージでのみ 静的に アクセスできます。

  9. 最外層の配列の 要素数、 またはバッファーのサイズは、 override 式でもかまいません。

  10. 初期化子がない場合、変数は既定で初期化されます。

7.1. 変数と値

変数 宣言は、WGSL モジュール内で唯一の可変データです。 値宣言は 常に不変です。 変数には関連付けられたメモリー位置があるため、 参照値およびポインター値の基礎になることができますが、 値宣言はポインター値または参照値の基礎になることはできません。

一般に、変数を使用することは値宣言を使用するよりもコストが高くなります。 これは、変数を使用するには、その変数に関連付けられたメモリー位置を 読み取る、または書き込むための追加操作が必要になるためです。

一般的に、作者は次の順序で宣言の使用を優先するべきです。 最も優先される選択肢を最初に示します:

これにより、一般にシェーダー全体で最良のパフォーマンスが得られます。

7.2. 値宣言

識別子が値宣言に解決される場合、 その識別子はその値を表します。

WGSL は複数種類の値宣言を提供します。 各種類の宣言の値は、シェーダーライフサイクルの 異なる時点で固定されます。 値宣言の種類と、その値が固定される時点は次のとおりです:

注: 仮引数については§ 11 関数で説明します。

7.2.1. const 宣言

const 宣言は、 シェーダー作成時に固定されるデータ値の名前を指定します。 各 const 宣言には初期化子が必要です。 const 宣言はモジュールスコープまたは関数スコープで宣言できます。 初期化子式はconst 式でなければなりません。 const 宣言の型は、具象または抽象の構築可能型でなければなりません。 実効値型が抽象になり得る宣言は const 宣言だけです。

注: 抽象数値型は WGSL で 記述できないため、型推論を介してのみ使用できます。

例: モジュールスコープの const 宣言
const a = 4;                  // 値 4 の AbstractInt。
const b : i32 = 4;            // 値 4 の i32。
const c : u32 = 4;            // 値 4 の u32。
const d : f32 = 4;            // 値 4 の f32。
const e = vec3(a, a, a);      // 値 (4, 4, 4) の AbstractInt の vec3。
const f = 2.0;                // 値 2 の AbstractFloat。
const g = mat2x2(a, f, a, f); // 次の値を持つ AbstractFloat の mat2x2:
                              // ((4.0, 2.0), (4.0, 2.0))。
                              // AbstractInt の a は AbstractFloat に変換される。
                              // AbstractFloat は AbstractInt に変換できない。
const h = array(a, f, a, f);  // 4 成分を持つ AbstractFloat の配列:
                              // (4.0, 2.0, 4.0, 2.0)。

7.2.2. override 宣言

override 宣言は、 パイプラインでオーバーライド可能な定数値の名前を指定します。 override 宣言はモジュールスコープでのみ宣言されなければなりません。 パイプラインでオーバーライド可能な定数の値は、 パイプライン作成 時に固定されます。 値が指定されている場合は WebGPU パイプライン作成メソッドによって提供された値となり、 それ以外の場合は具象化された初期化子式の値となります。 override 宣言の実効値型は具象 スカラー型でなければなりません。

初期化子式は任意です。 存在する場合、それはoverride 式でなければならず、パイプラインでオーバーライド可能な 定数の既定値を表します。 初期化子が指定されておらず、パイプライン作成時に値が 提供されない場合、パイプライン作成エラーになります。

宣言にid 属性が適用されている場合、リテラル オペランドはパイプライン定数 IDと呼ばれ、0 以上 65535 以下の 一意の整数でなければなりません。 つまり、2 つの override 宣言が同じパイプライン定数 ID を使用してはなりません。

アプリケーションはパイプライン作成 時に override 宣言へ独自の値を指定できます。 パイプライン作成 API は、オーバーライド可能な定数から その定数の型の値への対応付けを受け取ります。 定数はパイプラインでオーバーライド可能な定数の 識別子文字列によって識別されます。これは、指定されている場合はパイプライン定数 IDの 10 進表現、 それ以外の場合は定数の宣言された名前です。

例: モジュール定数、パイプラインでオーバーライド可能
@id(0)    override has_point_light: bool = true;  // アルゴリズム制御
@id(1200) override specular_param: f32 = 2.3;     // 数値制御
@id(1300) override gain: f32;                     // オーバーライド必須
          override width: f32 = 0.0;              // API レベルで
                                                  // 名前 "width" を使用して指定される。
          override depth: f32;                    // API レベルで
                                                  // 名前 "depth" を使用して指定される。
                                                  // オーバーライド必須。
          override height = 2 * depth;            // 既定値は
                                                  // (API レベルで設定されていない場合)、
                                                  // 別のオーバーライド可能な
                                                  // 定数に依存する。

7.2.3. let 宣言

let 宣言は、 文が実行時に実行されるたびに固定される値の名前を指定します。 let 宣言は関数スコープでのみ宣言されなければならず、そのため 動的コンテキストです。 let 宣言には初期化子式が必要です。 値は初期化子の具象化された値です。 let 宣言の実効値型は、具象の構築可能型または ポインター型の いずれかでなければなりません。 texture_and_sampler_let 機能が サポートされている場合、 実効値型はテクスチャー型またはサンプラー型でもかまいません。

注: バッファー型は構築可能ではないため、バッファーへのポインターのみを let 宣言にできます。

例: 関数スコープの let 宣言された定数
// 'blockSize' は i32 値 1024 を表す。
let blockSize: i32 = 1024;

// 'row_size' は u32 値 16u を表す。型は推論される。
let row_size = 16u;

7.3. var 宣言

変数は、 特定の格納可能型の値を 含むことができるメモリーへの名前付き参照です。

変数には 2 つの型が関連付けられます: 格納型(参照されるメモリーに配置できる値の型)と、 参照型(変数自体の型)です。 変数の格納型が T、アドレス空間が AS、アクセスモードが AM である場合、その参照型は ref<AS,T,AM> です。 変数の格納型は常に具象です。

変数宣言は:

識別子が 変数宣言に解決される場合、 その識別子は変数のメモリーに対する参照メモリービューを表す式であり、 その型は変数の参照型です。 § 8.12 変数識別子式を参照してください。

変数宣言のアドレス空間またはアクセスモードが プログラムソースで指定される場合、それらは var キーワードの後にテンプレートリストとして記述されます:

private、storage、 uniform、workgroup、およびhandle アドレス空間内の変数は、 モジュールスコープでのみ 宣言されなければなりません。一方、function アドレス空間内の変数は、 関数スコープでのみ 宣言されなければなりません。 handle と function を除くすべてのアドレス空間では、アドレス空間を指定しなければなりません。 handle アドレス空間を指定してはなりません。 function アドレス空間の指定は任意です。

アクセスモードには常に 既定値があり、storage アドレス空間内の変数を除き、WGSL ソースで指定してはなりません。 § 14.3 アドレス空間を参照してください。

uniform アドレス空間内の変数は、uniform バッファー変数です。 その格納型は、 ホスト共有可能な構築可能型または 固定サイズバッファー 型でなければならず、 アドレス空間レイアウト制約を満たさなければなりません。

storage アドレス空間内の変数は、storage バッファー変数です。 その格納型は ホスト共有可能型でなければならず、 アドレス空間レイアウト制約を満たさなければなりません。 変数はread またはread_write アクセスモードで宣言できます。既定値は read です。

immediate アドレス空間内の変数は、即時データ変数です。 その格納型は、 配列および配列メンバーを含む構造体を除いた、 ホスト共有可能な構築可能型でなければなりません。 各エントリーポイントは、 最大 1 つの即時データ変数へ静的にアクセスしなければなりません。 immediate 変数の値は、WebGPU API コマンドエンコーダーによって記録された setImmediates コマンドを介して設定され、 シェーダー実行中は一定のままです。 変数のサイズは、パイプラインレイアウトのimmediateSize 設定によって制限されます。

AccessibleSlots は、 構造体メンバー間および構造体末尾のパディングバイトを除外します。 シェーダー内で即時データ変数にアクセスする前に、 WebGPU API を介して初期化する必要があるのは、アクセス可能なスロットだけです。

テクスチャーリソースは、 実効値型がテクスチャー型である変数です。 これはモジュールスコープで宣言されます。 基礎となるテクスチャー内の テクセルのグリッドへアクセスするために使用される 不透明ハンドルを保持します。 ハンドル自体はhandle アドレス空間にあり、常に読み取り専用です。 多くの場合、基礎となるテクセルは読み取り専用であり、テクスチャー変数は不変であるといいます。 書き込み専用ストレージテクスチャーおよび読み書き可能ストレージ テクスチャーでは、基礎となるテクセルは可変であり、慣例により テクスチャー変数は可変であるといいます。

サンプラーリソースは、 実効値型がサンプラー型である変数です。 これはモジュールスコープで宣言され、 handle アドレス空間に存在し、 不変です。

§ 13.3.2 リソースインターフェイスで説明されるように、uniform バッファー、storage バッファー、 テクスチャー、およびサンプラーはシェーダーのリソースインターフェイスを形成します。

変数の存続期間は、 シェーダー実行中にメモリー位置が変数に関連付けられている期間です。 モジュールスコープ 変数の存続期間は、シェーダーステージの実行全体です。 各呼び出しについて、private およびfunction アドレス空間の変数には独立した版があります。 関数スコープ変数は 動的コンテキストです。 関数スコープ変数の存続期間は、そのスコープによって決定されます:

2 つのリソース変数は 重複するメモリー位置を持つ場合がありますが、 それらの変数のいずれかが可変である場合は動的エラーです。 存続期間が重複するその他の変数は、重複するメモリー位置を持ちません。 変数の存続期間が終了すると、そのメモリーは別の変数に使用される場合があります。

注: WGSL は、変数の内容が 変数の存続期間中にのみ観測可能であることを保証します。

private、function、 またはworkgroup アドレス空間内の変数が作成されるとき、 初期値を持ちます。 初期化子が指定されていない場合、初期値は既定の 初期値です。 初期値は次のように計算されます:

他のアドレス空間内の変数は、描画コマンド またはディスパッチコマンド内の バインディングによって設定されるリソースです。

次の WGSL スニペットを考えます:

例: 変数の初期値
var i: i32;         // 初期値は 0。推奨されるスタイルではない。
loop {
  var twice: i32 = 2 * i;   // 各反復で再評価される。
  i++;
  if i == 5 { break; }
}
ループ本体は 6 回実行されます。 変数 i は値 0、1、2、3、4、5 を取り、変数 twice は 値 0、2、4、6、8 を取ります。

次の WGSL スニペットを考えます:

例: 変数を複数回読み取る
var x: f32 = 1.0;
let y = x * x + x + 1;
x は変数であるため、それへのすべてのアクセスはロードおよびストア操作になります。 ただし、ブラウザーまたはドライバーのいずれかがこの中間表現を最適化し、 冗長なロードを除去することが期待されます。
例: モジュールスコープの変数宣言
var<private> decibels: f32;
var<workgroup> worklist: array<i32,10>;

struct Params {
  specular: f32,
  count: i32
}

// Uniform バッファー。常に読み取り専用で、より厳しいレイアウト規則を持つ。
@group(0) @binding(2)
var<uniform> param: Params;    // uniform バッファー

// 読み書き用の storage バッファー
@group(0) @binding(0)
var<storage,read_write> pbuf: array<vec2<f32>>;

// テクスチャーとサンプラーは常に "handle" 空間にある。
@group(0) @binding(1)
var filter_params: sampler;
例: バッファーのアクセスモード
// Storage バッファー
@group(0) @binding(0)
var<storage,read> buf1: Buffer;       // 読み取り可能、書き込み不可。
@group(0) @binding(0)
var<storage> buf2: Buffer;            // 読み取り可能、書き込み不可。
@group(0) @binding(1)
var<storage,read_write> buf3: Buffer; // 読み取りと書き込みの両方が可能。

struct ParamsTable {weight: f32}

// Uniform バッファー。常に読み取り専用で、より厳しいレイアウト規則を持つ。
@group(0) @binding(2)
var<uniform> params: ParamsTable;     // 読み取り可能、書き込み不可。
例: 関数スコープの変数と定数
fn f() {
   var<function> count: u32;  // function アドレス空間内の変数。
   var delta: i32;            // function アドレス空間内の別の変数。
   var sum: f32 = 0.0;        // 初期化子を持つ function アドレス空間変数。
   var pi = 3.14159;          // 初期化子から f32 格納型を推論する。
}

7.4. 変数宣言と値宣言の文法概要

variable_or_value_statement :

variable_decl

| variable_decl '=' expression

| 'let' optionally_typed_ident '=' expression

| 'const' optionally_typed_ident '=' expression

variable_decl :

'var' _disambiguate_template template_list ? optionally_typed_ident

optionally_typed_ident :

ident ( ':' type_specifier ) ?

global_variable_decl :

attribute * variable_decl ( '=' expression ) ?

global_value_decl :

'const' optionally_typed_ident '=' expression

| attribute * 'override' optionally_typed_ident ( '=' expression ) ?

8. 式

式は、値がどのように 計算されるかを指定します。

さまざまな種類の値式は、いつ評価されるかと、どの程度表現力を持てるかの間で トレードオフを提供します。 評価が早いほど操作はより制約されますが、その一方で 値を使用できる場所は増えます。このトレードオフにより、値宣言の種類ごとに 異なる柔軟性が生じます。 const 式および override 式は GPU 上での 実行前に評価されるため、最終的な GPU コードには式の計算結果 だけが必要です。 さらに、const 式はシェーダー作成時に評価されるため、 override 式よりも多くの状況で使用できます。たとえば、関数スコープの 変数内の配列のサイズを指定できます。 ランタイム 式は、const 式でも override 式でもない式です。 ランタイム式はシェーダー実行中に GPU 上で計算されます。 ランタイム式を使用できる文法要素は少ないものの、 他のランタイム値など、より広い種類の式から計算できます。

8.1. 早期評価式

WGSL は、実行時より前に評価できる 2 種類の式を定義します:

8.1.1. const 式

シェーダー作成 時に評価できる式をconst 式と呼びます。 式のすべての識別子が次のいずれかに解決される場合、その式は const 式です:

const 式の型は、作成時固定フットプリントを持つ型に解決されなければなりません。

注: 抽象型は const 式の推論型になることができます。

const 式 E は、次の場合に限り評価されます:

注: この評価規則は、短絡評価 演算子 && および || が、静的型を決定するために評価を必要とする部分式がない限り、 右辺の部分式の評価を抑制することを意味します。

const 式は、WebGPU API メソッドを実装する CPU によって評価される場合があります。 したがって、AbstractFloat 値に対する操作の精度要件は、WebAssembly [WASM-CORE-2] や ECMAScript [ECMASCRIPT] など、 一般的な WebGPU ランタイム環境で要求されるものより厳しくありません。 具象浮動小数点型(f32 など)の精度要件は、§ 15.7.4.1 具象浮動小数点式の精度で指定されます。

例: (42) は次のように解析されます:

例: -5 は次のように解析されます:

例: -2147483648 は次のように解析されます:

例: const minint = -2147483648; は次のように解析されます:

例: let minint = -2147483648; は次のように解析されます:

例: false && (10i < i32(5 * 1000 * 1000 * 1000)) は次のように解析されます:

例: false && array<u32, 1 + 2>(0, 1, 2)[0] == 0

8.1.2. override 式

パイプライン作成時に評価できる式をoverride 式と呼びます。 式のすべての識別子が次のいずれかに解決される場合、その式は override 式です:

注: すべてのconst 式は override 式でもあります。

const 式ではない override 式は、パイプライン 作成中にのみ検証または評価され、それも API から提供された 値がoverride 宣言に代入された後に限ります。 override 宣言の値が API を介して代入された場合、 初期化子式が存在しても評価されません。 それ以外の場合、override 式 E は次の場合に限り評価されます:

注: すべての override 式を override 宣言の初期化子として使用できるとは限りません。 このような初期化子は具象スカラー型に解決されなければならないためです。

例: override x = 42; は次のように解析されます:

例: let y = x + 1; は次のように解析されます:

例: vec3(x,x,x) は次のように解析されます:

例: override 式によるシェーダー作成エラー
override a : i32 = 0;
override b = a / 0; // シェーダー作成エラー。
                    // c をオーバーライドしようとするかどうかに関係しない
例: override 式によるパイプライン作成エラー
override a : i32 = 0;
override b = 1 / a;

// b は frag1 シェーダーの一部。frag1 をパイプラインへコンパイルするとき、
// 次の場合があり得る:
// * b がオーバーライドされる場合、エラーは発生しない。
// * a が 0 以外の値にオーバーライドされる場合、エラーは発生しない。
// * a が 0 で b がオーバーライドされない場合、パイプライン作成エラーが発生する。
@fragment
fn frag1() {
  _ = b;
}

// b は frag2 シェーダーの一部ではない。frag2 をパイプラインへコンパイルするとき、
// b がオーバーライドされず、a の値が 0 であってもエラーは発生しない。
@fragment
fn frag2() {
}

8.2. 不定値

限られた場合に、ランタイム式の評価が、 その部分式に対してサポートされていない値を使用して行われることがあります。

そのような場合、その評価結果は式の静的型の不定値となります。 これは、その静的型の実装が任意に選択する値を意味します。

式が評価される一意の動的コンテキストごとに、異なる値が生成される場合があります。 たとえば、評価がループの各反復で 1 回行われる場合、 ループの各反復で異なる値が計算される場合があります。

注: 型が浮動小数点型であり、 実装が NaN 値をサポートする場合、 実行時に生成される不定値は NaN 値である場合があります。

例: 不定値の例
fn fun() {
   var extracted_values: array<i32,2>;
   const v = vec2<i32>(0,1);

   for (var i: i32 = 0; i < 2 ; i++) {
      // ベクトルのインデックス付けに使用されるランタイム式が、
      // ベクトルのインデックス範囲外である場合、ベクトルの成分型の
      // 不定値が生成される。
      let extract = v[i+5];

      // ここで 'extract' は i32 型の任意の値。

      // 後で使用するために保存する。
      extracted_values[i] = extract;

      if extract == extract {
         // これは常に実行される
      }
      if extract < 2 {
         // これは実行される場合もあれば、実行されない場合もある。
         // 元のベクトル成分は 0 と 1 だが、
         // 抽出された値はそのどちらでもない可能性がある。
      }
   }
   if extracted_values[0] == extracted_values[1] {
      // これは実行される場合もあれば、実行されない場合もある。
   }
}

fn float_fun(runtime_index: u32) {
   const v = vec2<f32>(0,1); // 浮動小数点値のベクトル

   // 前の例と同様に、'float_extract' は不定値。
   // 浮動小数点型であるため、NaN の場合がある。
   let float_extract: f32 = v[runtime_index+5];

   if float_extract == float_extract {
      // これは実行されない可能性がある。その理由は:
      //  -  'float_extract' が NaN の場合があり、
      //  -  NaN は他のどの浮動小数点数とも等しくなく、
      //     別の NaN とさえ等しくない。
   }
}

8.3. リテラル値式

スカラーリテラルの型規則
前提条件 結論 説明
true: bool true ブール値。
false: bool false ブール値。
e は接尾辞のない整数リテラル e: AbstractInt 抽象整数リテラル値。
e は接尾辞のない浮動小数点リテラル e: AbstractFloat 抽象浮動小数点リテラル値。
e は i 接尾辞を持つ整数リテラル e: i32 32 ビット符号付き整数リテラル値。
e は u 接尾辞を持つ整数リテラル e: u32 32 ビット符号なし整数リテラル値。
e は f 接尾辞を持つ浮動小数点リテラル e: f32 32 ビット浮動小数点リテラル値。
e は h 接尾辞を持つ浮動小数点リテラル e: f16 16 ビット浮動小数点リテラル値。

8.4. 括弧付き式

括弧付き式の型規則
前提条件 結論 説明
e : T ( e ) : T e に評価されます。
括弧を使用して、式を周囲のテキストから分離します。

8.5. 複合値分解式

この節では、次のための式について説明します:

この説明では、複合値、複合値へのメモリービュー、またはスウィズルビューを 基底と呼びます。

このような式を形成する方法は 2 つあります:

名前付き 成分式

基底 B の式の後にピリオド '.' (U+002D)、続いて成分名を記述します。

  • これは、B がベクトル型または構造体型、ベクトル型または構造体型へのメモリービュー、 あるいはスウィズルビューの場合にサポートされます。

  • 有効な名前は B の型に依存します。

インデックス 式

基底の式の後に '[' (U+005B)、続いてインデックスの式、 続いて ']' (U+005D) を記述します。

構文上、これら 2 つの形式はcomponent_or_swizzle_specifier 文法規則の 使用によって表現されます。

インデックス式のインデックス値 i は、 0 ≤ i < N の場合、範囲内インデックスです。 ここで N は複合型の成分(要素)の数です:

インデックス値が範囲内インデックスでない場合、 範囲外インデックスです。 範囲外インデックスは多くの場合プログラミング上の欠陥であり、多くの場合エラーを引き起こします。 詳細については以下を参照してください。

さらに、ベクトル型は、別のベクトルの成分から新しいベクトル値を作成するためのスウィズル構文をサポートします。

8.5.1. ベクトルアクセス式

ベクトルの成分には、次のいずれかの方法でアクセスできます:

便宜的な名前には . 記法を使用してアクセスします。(例: color.bgra)。

便宜的な文字体系を混在させてはなりません。たとえば、 .rybw は使用できません。

便宜的な文字でベクトルの末尾を超えた成分にアクセスしてはなりません。

便宜的な文字は、必要に応じて文字を重複させることも含め、任意の順序で適用できます。 指定する文字数は 1 以上 4 以下でなければなりません。 つまり、便宜的な文字を使用して生成できるのは、スカラー型または有効なベクトル型だけです。

結果の型は、指定された文字数に依存します。vec4<f32> を想定すると:

アクセサー 結果の型
r f32
rg vec2<f32>
rgb vec3<f32>
rgba vec4<f32>
var a: vec3<f32> = vec3<f32>(1., 2., 3.);
var b: f32 = a.y;          // b = 2.0
var c: vec2<f32> = a.bb;   // c = (3.0, 3.0)
var d: vec3<f32> = a.zyx;  // d = (3.0, 2.0, 1.0)
var e: f32 = a[1];         // e = 2.0
8.5.1.1. ベクトルの単一成分選択
ベクトル分解: 単一成分選択
前提条件 結論 説明
e: vecN<T>
e.x: T
e.r: T
e の最初の成分を選択します

これは単一文字のスウィズルです。

e: vecN<T>
e.y: T
e.g: T
e の 2 番目の成分を選択します

これは単一文字のスウィズルです。

e: vecN<T>
N は 3 または 4
e.z: T
e.b: T
e の 3 番目の成分を選択します

これは単一文字のスウィズルです。

e: vec4<T> e.w: T
e.a: T
e の 4 番目の成分を選択します

これは単一文字のスウィズルです。

e: vecN<T>
i: i32 または u32
T は具象
e[i]: T ベクトルの i 番目の成分を選択します
最初の成分はインデックス i=0 にあります。

i が範囲 [0,N-1] の外側にある場合:

e: vecN<T>
i: i32 または u32
T は抽象
i はconst 式
e[i]: T ベクトルの i 番目の成分を選択します
最初の成分はインデックス i=0 にあります。

i が範囲 [0,N-1] の外側にある場合はシェーダー作成エラーです。

注: 抽象ベクトル値 e がconst 式ではない式によって インデックス付けされる場合、インデックスを適用する前にベクトルが 具象化されます。

8.5.1.2. ベクトルの複数成分選択

この節の式は、内部式に複数文字のスウィズルを適用します:

注: swizzle_assignment 言語拡張が サポートされていない場合、複数文字のスウィズルは代入の左辺に現れることができません: 代入の左辺は参照型でなければなりませんが、 拡張がない場合、複数文字のスウィズル式は常にベクトル型の値を生成します。

ベクトル分解: 複数成分選択
前提条件 結論 説明
e: vecN<T>
I は文字 x、y、z、または w
J は文字 x、y、z、または w
e.IJ: vec2<T>
第 1 成分が e.I、第 2 成分が e.J である 2 成分ベクトルを計算します。
文字 z は N が 3 または 4 の場合にのみ有効です。
文字 w は N が 4 の場合にのみ有効です。
e: vecN<T>
I は文字 r、g、b、または a
J は文字 r、g、b、または a
e.IJ: vec2<T>
第 1 成分が e.I、第 2 成分が e.J である 2 成分ベクトルを計算します。
文字 b は N が 3 または 4 の場合にのみ有効です。
文字 a は N が 4 の場合にのみ有効です。
e: vecN<T>
I は文字 x、y、z、または w
J は文字 x、y、z、または w
K は文字 x、y、z、または w
e.IJK: vec3<T>
第 1 成分が e.I、第 2 成分が e.J、第 3 成分が e.K である 3 成分ベクトルを計算します。
文字 z は N が 3 または 4 の場合にのみ有効です。
文字 w は N が 4 の場合にのみ有効です。
e: vecN<T>
I は文字 r、g、b、または a
J は文字 r、g、b、または a
K は文字 r、g、b、または a
e.IJK: vec3<T>
第 1 成分が e.I、第 2 成分が e.J、第 3 成分が e.K である 3 成分ベクトルを計算します。
文字 b は N が 3 または 4 の場合にのみ有効です。
文字 a は N が 4 の場合にのみ有効です。
e: vecN<T>
I は文字 x、y、z、または w
J は文字 x、y、z、または w
K は文字 x、y、z、または w
L は文字 x、y、z、または w
e.IJKL: vec4<T>
第 1 成分が e.I、第 2 成分が e.J、第 3 成分が e.K、第 4 成分が e.L である 4 成分ベクトルを計算します。
文字 z は N が 3 または 4 の場合にのみ有効です。
文字 w は N が 4 の場合にのみ有効です。
e: vecN<T>
I は文字 r、g、b、または a
J は文字 r、g、b、または a
K は文字 r、g、b、または a
L は文字 r、g、b、または a
e.IJKL: vec4<T>
第 1 成分が e.I、第 2 成分が e.J、第 3 成分が e.K、第 4 成分が e.L である 4 成分ベクトルを計算します。
文字 b は N が 3 または 4 の場合にのみ有効です。
文字 a は N が 4 の場合にのみ有効です。
ベクトルメモリービュー分解: スウィズル代入がサポートされていない場合の複数成分選択
前提条件 結論 説明
swizzle_assignment はサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
I は文字 x、y、z、または w
J は文字 x、y、z、または w
AM は read または read_write

pr.IJ: vec2<T>
e.IJ を計算します。ここで e は評価時に pr が参照するメモリー位置に格納されているベクトルです。

文字 z は N が 3 または 4 の場合にのみ有効です。
文字 w は N が 4 の場合にのみ有効です。

swizzle_assignment はサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
I は文字 r、g、b、または a
J は文字 r、g、b、または a
AM は read または read_write

pr.IJ: vec2<T>
e.IJ を計算します。ここで e は評価時に pr が参照するメモリー位置に格納されているベクトルです。

文字 b は N が 3 または 4 の場合にのみ有効です。
文字 a は N が 4 の場合にのみ有効です。

swizzle_assignment はサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
I は文字 x、y、z、または w
J は文字 x、y、z、または w
K は文字 x、y、z、または w
AM は read または read_write

pr.IJK: vec3<T>
e.IJK を計算します。ここで e は 評価時に pr が参照するメモリー位置に格納されているベクトルです。

文字 z は N が 3 または 4 の場合にのみ有効です。
文字 w は N が 4 の場合にのみ有効です。

swizzle_assignment はサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
I は文字 r、g、b、または a
J は文字 r、g、b、または a
K は文字 r、g、b、または a
AM は read または read_write

pr.IJK: vec3<T>
e.IJK を計算します。ここで e は 評価時に pr が参照するメモリー位置に格納されているベクトルです。

文字 b は N が 3 または 4 の場合にのみ有効です。
文字 a は N が 4 の場合にのみ有効です。

swizzle_assignment はサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
I は文字 x、y、z、または w
J は文字 x、y、z、または w
K は文字 x、y、z、または w
L は文字 x、y、z、または w
AM は read または read_write

pr.IJKL: vec4<T>
e.IJKL を計算します。ここで e は 評価時に pr が参照するメモリー位置に格納されているベクトルです。

文字 z は N が 3 または 4 の場合にのみ有効です。
文字 w は N が 4 の場合にのみ有効です。

swizzle_assignment はサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
I は文字 r、g、b、または a
J は文字 r、g、b、または a
K は文字 r、g、b、または a
L は文字 r、g、b、または a
AM は read または read_write

pr.IJKL: vec4<T>
e.IJKL を計算します。ここで e は 評価時に pr が参照するメモリー位置に格納されているベクトルです。

文字 b は N が 3 または 4 の場合にのみ有効です。
文字 a は N が 4 の場合にのみ有効です。

8.5.1.3. ベクトルメモリービューまたは スウィズルビューからの成分参照

この節の式は、ベクトル全体のメモリービューまたはスウィズルビューから、 メモリー内のベクトルの 単一成分への参照を形成します。

WGSL の型規則により、 このような式は次の場所に現れることができます:

ベクトルの成分への書き込みアクセスは、 そのベクトルに関連付けられたすべてのメモリー位置へアクセスする場合があります。

注: これは、異なる呼び出しが メモリー内のベクトルの異なる成分へアクセスする場合、少なくとも 1 つのアクセスが 書き込みアクセスであれば 同期しなければならないことを意味します。 § 17.11 同期組み込み関数を参照してください。

ベクトルへのメモリービューから成分への参照を取得する
前提条件 結論 説明
r: ref<AS,vecN<T>,AM> または
ptr<AS,vecN<T>,AM>
r.x: ref<AS,T,AM>
r.r: ref<AS,T,AM>
メモリービュー r が参照するベクトルの最初の成分への参照を計算します。
結果の参照の起点変数は、 r の起点変数と同じです。
r: ref<AS,vecN<T>,AM> または
ptr<AS,vecN<T>,AM>
r.y: ref<AS,T,AM>
r.g: ref<AS,T,AM>
メモリービュー r が参照するベクトルの 2 番目の成分への参照を計算します。
結果の参照の起点変数は、 r の起点変数と同じです。
r: ref<AS,vecN<T>,AM> または
ptr<AS,vecN<T>,AM>
N は 3 または 4
r.z: ref<AS,T,AM>
r.b: ref<AS,T,AM>
メモリービュー r が参照するベクトルの 3 番目の成分への参照を計算します。
結果の参照の起点変数は、 r の起点変数と同じです。
r: ref<AS,vec4<T>,AM> または
ptr<AS,vec4<T>,AM>
r.w: ref<AS,T,AM>
r.a: ref<AS,T,AM>
メモリービュー r が参照するベクトルの 4 番目の成分への参照を計算します。
結果の参照の起点変数は、 r の起点変数と同じです。
r: ref<AS,vecN<T>,AM> または
ptr<AS,vecN<T>,AM>
i: i32 または u32
r[i] : ref<AS,T,AM>
メモリービュー r が参照するベクトルの i 番目の成分への参照を計算します。

i が範囲 [0,N-1] の外側にある場合:

結果の参照の起点変数は r の起点変数と同じです。

スウィズルビューから成分への参照を取得する
前提条件 結論 説明
sv : swizzle<AS,S,N,K>
sv.x : ref<AS,S,read_write>
sv.r : ref<AS,S,read_write>
sv をスウィズルビュー (p, « Idx0,...,IdxK−1 ») とします。

結果は、ポインター p のメモリービュー内の インデックス Idx0 の成分への参照です。

結果の参照の起点変数は sv の起点変数と同じです。

sv : swizzle<AS,S,N,K>
sv.y : ref<AS,S,read_write>
sv.g : ref<AS,S,read_write>
sv をスウィズルビュー (p, « Idx0,...,IdxK−1 ») とします。

結果は、ポインター p のメモリービュー内の インデックス Idx1 の成分への参照です。

結果の参照の起点変数は sv の起点変数と同じです。

sv : swizzle<AS,S,N,K>
ここで K ≥ 3
sv.z : ref<AS,S,read_write>
sv.b : ref<AS,S,read_write>
sv をスウィズルビュー (p, « Idx0,...,IdxK−1 ») とします。

結果は、ポインター p のメモリービュー内の インデックス Idx2 の成分への参照です。

結果の参照の起点変数は sv の起点変数と同じです。

sv : swizzle<AS,S,N,K>
ここで K = 4
sv.w : ref<AS,S,read_write>
sv.a : ref<AS,S,read_write>
sv をスウィズルビュー (p, « Idx0,...,IdxK−1 ») とします。

結果は、ポインター p のメモリービュー内の インデックス Idx3 の成分への参照です。

結果の参照の起点変数は sv の起点変数と同じです。

sv : swizzle<AS,S,N,K>
i : i32 または u32
sv[i] : ref<AS,S,read_write>
sv をスウィズルビュー (p, « Idx0,...,IdxK−1 ») とします。

i が [0, K) 内にある場合、式は次の参照です

(*p)[ Idxi ]

注: sv が 無効なスウィズルビューである場合、 結果は無効なメモリー参照です。

i が [0,K) の外側にある場合:

結果の参照の起点変数は sv の起点変数と同じです。

8.5.2. 行列アクセス式

列ベクトルの抽出
前提条件 結論 説明
e: matCxR<T>
i: i32 または u32
T は具象
e[i]: vecR<T> 結果は e の i 番目の列ベクトルです。

i が範囲 [0,C-1] の外側にある場合:

e: matCxR<T>
i: i32 または u32
T は抽象
i はconst 式
e[i]: vecR<T> 結果は e の i 番目の列ベクトルです。

i が範囲 [0,C-1] の外側にある場合はシェーダー作成エラーです。

注: 抽象行列値 e がconst 式ではない式によって インデックス付けされる場合、インデックスを適用する前に行列が 具象化されます。

行列へのメモリービューから列ベクトルへの参照を取得する
前提条件 結論 説明
r: ref<AS,matCxR<T>,AM> または
ptr<AS,matCxR<T>,AM>
i: i32 または u32
r[i] : ref<AS,vecR<T>,AM> メモリービュー r が参照する行列の i 番目の列ベクトルへの参照を計算します。

i が範囲 [0,C-1] の外側にある場合:

結果の参照の起点変数は r の起点変数と同じです。

8.5.3. 配列アクセス式

配列要素の抽出
前提条件 結論 説明
e: array<T,N>
i: i32 または u32
T は具象
e[i] : T 結果は配列値 e の i 番目の要素の値です。

i が範囲 [0,N-1] の外側にある場合:

e: array<T,N>
i: i32 または u32
T は抽象
i はconst 式
e[i] : T 結果は配列値 e の i 番目の要素の値です。

i が範囲 [0,N-1] の外側にある場合はシェーダー作成エラーです。

注: 抽象配列値 e がconst 式ではない式によって インデックス付けされる場合、インデックスを適用する前に配列が 具象化されます。

配列へのメモリービューから配列要素への参照を取得する
前提条件 結論 説明
r: ref<AS,array<T,N>,AM> または
ptr<AS,array<T,N>,AM>
i: i32 または u32
r[i] : ref<AS,T,AM> メモリービュー r が参照する配列の i 番目の要素への参照を計算します。

i が範囲 [0,N-1] の外側にある場合:

結果の参照の起点変数は r の起点変数と同じです。

r: ref<AS,array<T>,AM> または
ptr<AS,array<T>,AM>
i: i32 または u32
r[i] : ref<AS,T,AM> メモリービュー r が参照する ランタイムサイズ配列の i 番目の要素への参照を計算します。

実行時に配列が N 個の要素を持ち、i が範囲 [0,N-1] の外側にある場合、式は無効なメモリー 参照に評価されます。

i が符号付き整数であり、i が 0 未満の場合:

結果の参照の起点変数は r の起点変数と同じです。

8.5.4. 構造体アクセス式

構造体メンバーの抽出
前提条件 結論 説明
S は構造体型
M は型 T を持つ S のメンバーの識別子名
e: S
e.M: T 結果は構造体値 e から取得した、名前 M を持つメンバーの値です。
構造体へのメモリービューから構造体メンバーへの参照を取得する
前提条件 結論 説明
S は構造体型
M は型 T を持つ S のメンバーの識別子名
r: ref<AS,S,AM> または
ptr<AS,S,AM>
r.M: ref<AS,T,AM> 構造体へのメモリービューが与えられた場合、結果は 識別子名 M を持つ構造体メンバーへの参照です。
結果の参照の起点変数は r の起点変数と同じです。

8.6. スウィズルビュー式

スウィズルビュー式は、swizzle_assignment 言語拡張によって有効になります。

スウィズルビューは、次の方法で形成されます:

これらの規則により、スウィズルビューのインデックスリスト部分は シェーダー作成時に完全に決定されます。

この節では、スウィズルインデックス関数 SI を次のように定義します:

次の場合、スウィズル名 Z は K 個のインデックス « Idx0, ..., IdxK−1 » を表すといいます:

注: たとえば、スウィズル wzyx は 4 つのインデックス «3, 2, 1, 0» を表し、スウィズル rb は 2 つのインデックス «0, 2» を表します。 スウィズル rgbz は rgba と xyzw の文字を混在させているため、どのインデックスシーケンスも表しません。

参照からスウィズルビューを形成する
前提条件 結論 説明
swizzle_assignment がサポートされている

r: ref<AS,T,read_write>
T は vecN<S>
スウィズル名 Z は K 個のインデックス I = « Idx0, ..., IdxK−1 » を表す
K は {2,3,4} のいずれか

r.Z : swizzle<AS,S,N,K> 結果はスウィズル ビュー (&r, I) です。

I 内の各インデックスは N 未満でなければなりません。

r が無効なメモリー参照である場合、結果は 無効なスウィズルビューです。

ポインターからスウィズルビューを形成する
前提条件 結論 説明
swizzle_assignment がサポートされている
pointer_composite_access が サポートされている

p: ptr<AS,T,read_write>
T は vecN<S>
スウィズル名 Z は K 個のインデックス I = « Idx0, ..., IdxK−1 » を表す
K は {2,3,4} のいずれか

p.Z : swizzle<AS,S,N,K> 結果はスウィズル ビュー (p, I) です

I 内の各インデックスは N 未満でなければなりません。

p が無効なポインターである場合、結果は無効なスウィズルビューです。

スウィズルビューからスウィズルビューを形成する
前提条件 結論 説明
sv: swizzle<AS,S,N,Kin>
スウィズル名 Z は KZ 個のインデックス IZ = « IZ [0], ..., IZ [KZ −1] » を表す
KZ は {2,3,4} のいずれか
sv.Z : swizzle< AS,S,N,KZ > sv をスウィズルビュー (p, Iin) とします。 定義により、シーケンス Iin は Kin 個の項目を持ちます。

Iout を次のシーケンスとします
« Iin [IZ [0]], ..., Iin [IZ [KZ -1]] »。

式の結果はスウィズルビュー (p, Iout) です。

IZ 内の各インデックスは Kin 未満でなければ なりません。

sv が無効なスウィズルビューである場合、結果は無効なスウィズルビューです。

8.7. 論理式

単項論理演算
前提条件 結論 説明
e: T
T は bool または vecN<bool>
!e: T 論理否定。 e が false のとき結果は true であり、e が true のとき false です。 T がベクトルの場合は成分ごとです。
二項論理式
前提条件 結論 説明
e1: bool
e2: bool
e1 || e2: bool 短絡評価の「or」。e1 または e2 のいずれかが true の場合に true を生成します。 e1 が false の場合にのみ e2 を評価します。
e1: bool
e2: bool
e1 && e2: bool 短絡評価の「and」。e1 と e2 の両方が true の場合に true を生成します。 e1 が true の場合にのみ e2 を評価します。
e1: T
e2: T
T は bool または vecN<bool>
e1 | e2: T 論理「or」。T がベクトルの場合は成分ごとです。e1 と e2 の両方を評価します。
e1: T
e2: T
T は bool または vecN<bool>
e1 & e2: T 論理「and」。T がベクトルの場合は成分ごとです。e1 と e2 の両方を評価します。

8.8. 算術式

単項算術式
前提条件 結論 説明
e: T
T は AbstractInt、AbstractFloat、i32、f32、f16、vecN<AbstractInt>、 vecN<AbstractFloat>、vecN<i32>、vecN<f32>、または vecN<f16>
-e: T 否定。T がベクトルの場合は成分ごとです。 T が整数スカラー型であり、e が 最小の負の値に評価される場合、結果は e です。
二項算術式
前提条件 結論 説明
e1 : T
e2 : T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
e1 + e2 : T 加算。T がベクトルの場合は成分ごとです。

T が浮動小数点型の場合、スカラー定義域は、 次を除くすべての拡張実数の組 (x,y) の集合です:

  • (−∞,+∞)

  • (+∞,−∞)

e1 : T
e2 : T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
e1 - e2 : T 減算。T がベクトルの場合は成分ごとです。

T が浮動小数点型の場合、スカラー定義域は、 次を除くすべての拡張実数の組 (x,y) の集合です:

  • (−∞,−∞)

  • (+∞,+∞)

e1 : T
e2 : T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
e1 * e2 : T 乗算。T がベクトルの場合は成分ごとです。

T が浮動小数点型の場合、スカラー定義域は、 次を除くすべての拡張実数の組 (x,y) の集合です:

  • (0,−∞)

  • (0,+∞)

  • (−∞, 0)

  • (+∞, 0)

e1 : T
e2 : T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
e1 / e2 : T 除算。T がベクトルの場合は成分ごとです。

T が符号付き整数スカラー型の場合、次のように評価されます:

注: 切り捨て動作を保証する必要があるため、実装では 符号なし除算を計算する場合より多くの操作が必要になることがあります。 両方のオペランドが同じ符号であることが分かっている場合は符号なし除算を使用してください。

T が符号なし整数スカラー型の場合、次のように評価されます:

T が浮動小数点型の場合、スカラー定義域は、 次を除くすべての拡張実数の組 (x,y) の集合です:

  • (0,0)

  • (−∞,−∞)

  • (−∞,+∞)

  • (+∞,−∞)

  • (+∞,+∞)

e1 : T
e2 : T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
e1 % e2 : T 剰余。T がベクトルの場合は成分ごとです。

T が符号付き整数スカラー型の場合、e1 と e2 を 1 回ずつ評価し、次のように評価されます:

注: 0 でない場合、結果は e1 と同じ符号を持ちます。

注: 一貫した動作を保証する必要があるため、実装では 符号なし剰余を計算する場合より多くの操作が必要になることがあります。

T が符号なし整数スカラー型の場合、次のように評価されます:

T が浮動小数点型の場合、結果は次に等しくなります:
e1 - e2 * trunc(e1 / e2)。

T が浮動小数点型の場合、スカラー定義域は、 次を除くすべての拡張実数の組 (x,y) の集合です:

  • x / y の定義域外の場合:

    • (0,0)

    • (−∞,−∞)

    • (−∞,+∞)

    • (+∞,−∞)

    • (+∞,+∞)

  • y * trunc(x / y) の定義域外となる追加の場合:

    • y が無限大で、x が有限の場合、 trunc(x / y) は 0 になります。

    • y が 0 で、x が無限大の場合、trunc(x / y) は無限大になります。

スカラーとベクトルが混在するオペランドを持つ二項算術式
前提条件 結論 セマンティクス
S は AbstractInt、AbstractFloat、f32、f16、i32、u32 のいずれか
V は vecN<S>
es: S
ev: V
ev + es: V ev + V(es)
es + ev: V V(es) + ev
ev - es: V ev - V(es)
es - ev: V V(es) - ev
ev * es: V ev * V(es)
es * ev: V V(es) * ev
ev / es: V ev / V(es)
es / ev: V V(es) / ev
ev % es: V ev % V(es)
es % ev: V V(es) % ev
行列算術
前提条件 結論 セマンティクス
e1, e2: matCxR<T>
T は AbstractFloat、f32、または f16
e1 + e2: matCxR<T>
行列加算: 結果は成分ごとに計算され、結果の列 i は e1[i] + e2[i]
e1 - e2: matCxR<T> 行列減算: 結果は成分ごとに計算され、結果の列 i は e1[i] - e2[i]
m: matCxR<T>
s: T
T は AbstractFloat、f32、または f16
m * s: matCxR<T>
成分ごとの スケーリング: (m * s)[i][j] は m[i][j] * s
s * m: matCxR<T>
成分ごとの スケーリング: (s * m)[i][j] は m[i][j] * s
m: matCxR<T>
v: vecC<T>
T は AbstractFloat、f32、または f16
m * v: vecR<T>
線形代数の行列・列ベクトル積: 結果の成分 i は dot(transpose(m)[i],v)
m: matCxR<T>
v: vecR<T>
T は AbstractFloat、f32、または f16
v * m: vecC<T>
線形代数の行ベクトル・行列積:
transpose(transpose(m) * transpose(v))
e1: matKxR<T>
e2: matCxK<T>
T は AbstractFloat、f32、または f16
e1 * e2: matCxR<T>
線形代数の行列積。

8.9. 比較式

比較
前提条件 結論 説明
e1: T
e2: T
S は AbstractInt、AbstractFloat、bool、i32、u32、f32、または f16
T は S または vecN<S>
T がベクトルの場合、TB は vecN<bool>、
それ以外の場合、TB は bool
e1 == e2: TB 等価。T がベクトルの場合は成分ごとです。
e1: T
e2: T
S は AbstractInt、AbstractFloat、bool、i32、u32、f32、または f16
T は S または vecN<S>
T がベクトルの場合、TB は vecN<bool>、
それ以外の場合、TB は bool
e1 != e2: TB 不等価。T がベクトルの場合は成分ごとです。
e1: T
e2: T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
T がベクトルの場合、TB は vecN<bool>、
それ以外の場合、TB は bool
e1 < e2: TB 小なり。T がベクトルの場合は成分ごとです。
e1: T
e2: T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
T がベクトルの場合、TB は vecN<bool>、
それ以外の場合、TB は bool
e1 <= e2: TB 以下。T がベクトルの場合は成分ごとです。
e1: T
e2: T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
T がベクトルの場合、TB は vecN<bool>、
それ以外の場合、TB は bool
e1 > e2: TB 大なり。T がベクトルの場合は成分ごとです。
e1: T
e2: T
S は AbstractInt、AbstractFloat、 i32、u32、f32、または f16
T は S、または vecN<S>
T がベクトルの場合、TB は vecN<bool>、
それ以外の場合、TB は bool
e1 >= e2: TB 以上。T がベクトルの場合は成分ごとです。

8.10. ビット式

単項ビット演算
前提条件 結論 説明
e: T
S は AbstractInt、i32、または u32
T は S または vecN<S>
~e : T e に対するビット単位の補数。 結果の各ビットは、e の対応するビットと反対になります。 T がベクトルの場合は成分ごとです。
二項ビット演算
前提条件 結論 説明
e1: T
e2: T
S は AbstractInt、i32、または u32
T は S または vecN<S>
e1 | e2: T ビット単位 OR。T がベクトルの場合は成分ごとです。
e1: T
e2: T
S は AbstractInt、i32、または u32
T は S または vecN<S>
e1 & e2: T ビット単位 AND。T がベクトルの場合は成分ごとです。
e1: T
e2: T
S は AbstractInt、i32、または u32
T は S または vecN<S>
e1 ^ e2: T ビット単位排他的 OR。T がベクトルの場合は成分ごとです。
ビットシフト式
前提条件 結論 説明
e1: T
e2: TS
S は i32 または u32
T は S または vecN<S>
T が S の場合、TS は u32、それ以外の場合 TS は vecN<u32>
e1 << e2: T 左シフト(シフトされる値は具象):

e1 を左へシフトし、最下位位置に 0 ビットを挿入し、 最上位ビットを破棄します。

シフトするビット数は e2 の値を e1 のビット幅で剰余した値です。
e2 が e1 のビット幅以上の場合:

e1 と e2 の両方がシェーダー実行 開始前に既知である場合、 結果はオーバーフローしてはなりません:

T がベクトルの場合は成分ごとです。

e1: T
e2: TS
T は AbstractInt または vecN<AbstractInt>
T が AbstractInt の場合、TS は u32、それ以外の場合 TS は vecN<u32>
e1 << e2: T 左シフト(シフトされる値は抽象):

e1 を左へシフトし、最下位位置に 0 ビットを挿入し、 最上位ビットを破棄します。

シフトするビット数は e2 の値です。

e1 の最上位 e2+1 ビットは同じビット値を持たなければ なりません。 そうでなければオーバーフローが発生します。

注: この条件は、破棄されるすべての ビットが元の値の符号ビットと同じであり、 かつ最終値の符号ビットとも同じでなければならないことを意味します。

T がベクトルの場合は成分ごとです。

e1: T
e2: TS
S は i32 または u32
T は S または vecN<S>
T が S の場合、TS は u32、それ以外の場合 TS は vecN<u32>
e1 >> e2: T 右シフト(シフトされる値は具象)。

e1 を右へシフトし、最下位ビットを破棄します。

S が符号なし型の場合、最上位位置に 0 ビットを挿入します。

S が符号付き型の場合:

  • e1 が負の場合、挿入される各ビットは 1 であり、 結果も負になります。

  • それ以外の場合、挿入される各ビットは 0 です。

シフトするビット数は e2 の値を e1 のビット幅で剰余した値です。

e2 が e1 のビット幅以上の場合:

T がベクトルの場合は成分ごとです。

e1: T
e2: TS
T は AbstractInt または vecN<AbstractInt>
T が AbstractInt の場合、TS は u32、それ以外の場合 TS は vecN<u32>
e1 >> e2: T 右シフト(抽象)。

e1 を右へシフトし、最下位ビットを破棄します。

e1 が負の場合、挿入される各ビットは 1 であり、 結果も負になります。それ以外の場合、挿入される各ビットは 0 です。

シフトするビット数は e2 の値です。

T がベクトルの場合は成分ごとです。

8.11. 関数呼び出し式

関数呼び出し式は、呼び出される関数が戻り値の型を持つ関数呼び出しを実行します。 呼び出される関数が値を返さない場合は、代わりに関数呼び出し文を 使用するべきです。 § 9.5 関数呼び出し文を参照してください。

8.12. 変数識別子式

変数名から参照を取得する
前提条件 結論 説明
v は、AS アドレス空間で宣言され、 格納型 T およびアクセスモード AM を持つ スコープ内変数に解決される識別子 v: ref<AS,T,AM> 結果は、名前付き変数 v のメモリーへの参照です。

8.13. 仮引数式

関数の仮引数として宣言された識別子の値を取得する
前提条件 結論 説明
a は、型 T を持つスコープ内の仮引数宣言に解決される識別子 a: T 結果は、この関数インスタンスを呼び出す呼び出しサイトで、 対応する関数呼び出しオペランドに提供された値です。

8.14. アドレス取得式

アドレス取得演算子は、 参照を対応するポインターに変換します。

参照からポインターを取得する
前提条件 結論 説明
r: ref<AS,T,AM> &r: ptr<AS,T,AM> 結果は、参照値 r と同じメモリービューに対応する ポインター値です。

r が無効なメモリー参照である場合、結果の ポインターも無効なメモリー参照です。

AS がhandle アドレス空間の場合はシェーダー作成エラーです。

r がベクトル成分への参照である場合はシェーダー作成エラーです。

8.15. 間接参照式

間接参照演算子は、 ポインターを対応する参照に変換します。

ポインターから参照を取得する
前提条件 結論 説明
p: ptr<AS,T,AM> *p: ref<AS,T,AM> 結果は、ポインター値 p と同じメモリービューに対応する 参照値です。

p が無効なメモリー参照である場合、結果の 参照も無効なメモリー参照です。

8.16. 値宣言の識別子式

const、override、または let で宣言された 識別子の値を取得する
前提条件 結論 説明
c は、型 T を持つスコープ内のconst 宣言に解決される識別子 c: T 結果は初期化子式について計算された値です。 この式はconst 式であり、シェーダー作成時に評価されます。
c は、型 T を持つスコープ内のoverride 宣言に解決される識別子 c: T パイプライン作成で定数 IDの値が指定された場合、 結果はその値です。 この値はパイプラインインスタンスごとに異なる場合があります。

それ以外の場合、結果は初期化子式について計算された値です。 パイプラインでオーバーライド可能な定数はモジュールスコープに現れるため、評価は シェーダーの実行開始前に行われます。

注: API 呼び出しで 初期値が指定されず、let 宣言に初期化子式がない場合、 パイプライン作成は失敗します。

c は、型 T を持つスコープ内のlet 宣言に解決される識別子 c: T 結果は初期化子式について計算された値です。 let 宣言は関数本体内に現れ、その初期化子は 制御フローが宣言に到達するたびに評価されます。

8.17. 列挙式

列挙式
前提条件 結論 説明
e は、列挙型 E に属する事前宣言済みの列挙子に解決される識別子 e : E § 6.4.1 事前宣言済み列挙子を参照

8.18. 型式

型式
前提条件 結論 説明
t は事前宣言済みの型に解決される識別子 t : AllTypes § 6.10 事前宣言済み型と型ジェネレーターの概要を参照
a は型エイリアスに解決される識別子。 a : AllTypes さらに、a はそのエイリアス先の型を表します。
s は構造体型の宣言に解決される識別子。 s : AllTypes さらに、s はその構造体型を表します。
tg は型ジェネレーターに解決される識別子

e1: T1
...
eN: TN

tg _template_args_start
e1,
...,
eN
_template_args_end
: AllTypes
各型ジェネレーターは、要求および受け入れるテンプレート パラメーターについて独自の要件を持ち、 テンプレートパラメーターが結果の型をどのように決定するかを定義します。

式 e1 から eN は、型ジェネレーターのテンプレートパラメーターです。

たとえば、型式 vec2<f32> は、2 つのf32 要素からなるベクトルです。

事前宣言済み型ジェネレーターの一覧については、§ 6.10 事前宣言済み型と型ジェネレーターの概要を参照してください。

注: ここにある 2 つの形式の違いは、 eN の後に末尾のカンマがあるかどうかだけです。

tg _template_args_start
e1,
...,
eN,
_template_args_end
: AllTypes

8.19. 式文法の概要

識別子がcall_phrase 内の最初のトークンである場合、それは次のいずれかです:

宣言とスコープの規則により、これらの名前は常に互いに異なることが保証されます。

primary_expression :

template_elaborated_ident

| call_expression

| literal

| paren_expression

call_expression :

call_phrase

注: call_expression 規則は、呼び出し式に型チェックが適用されることを保証するために存在します。
call_phrase :

template_elaborated_ident argument_expression_list

paren_expression :

'(' expression ')'

argument_expression_list :

'(' expression_comma_list ? ')'

expression_comma_list :

expression ( ',' expression ) * ',' ?

component_or_swizzle_specifier :

'[' expression ']' component_or_swizzle_specifier ?

| '.' member_ident component_or_swizzle_specifier ?

| '.' swizzle_name component_or_swizzle_specifier ?

unary_expression :

singular_expression

| '-' unary_expression

| '!' unary_expression

| '~' unary_expression

| '*' unary_expression

| '&' unary_expression

singular_expression :

primary_expression component_or_swizzle_specifier ?

lhs_expression :

core_lhs_expression component_or_swizzle_specifier ?

| '*' lhs_expression

| '&' lhs_expression

core_lhs_expression :

ident

| '(' lhs_expression ')'

| call_expression

multiplicative_expression :

unary_expression

| multiplicative_expression multiplicative_operator unary_expression

multiplicative_operator :

'*'

| '/'

| '%'

additive_expression :

multiplicative_expression

| additive_expression additive_operator multiplicative_expression

additive_operator :

'+'

| '-'

shift_expression :

additive_expression

| unary_expression _shift_left unary_expression

| unary_expression _shift_right unary_expression

relational_expression :

shift_expression

| shift_expression _less_than shift_expression

| shift_expression _greater_than shift_expression

| shift_expression _less_than_equal shift_expression

| shift_expression _greater_than_equal shift_expression

| shift_expression '==' shift_expression

| shift_expression '!=' shift_expression

short_circuit_and_expression :

relational_expression

| short_circuit_and_expression '&&' relational_expression

short_circuit_or_expression :

relational_expression

| short_circuit_or_expression '||' relational_expression

binary_or_expression :

unary_expression

| binary_or_expression '|' unary_expression

binary_and_expression :

unary_expression

| binary_and_expression '&' unary_expression

binary_xor_expression :

unary_expression

| binary_xor_expression '^' unary_expression

bitwise_expression :

binary_and_expression '&' unary_expression

| binary_or_expression '|' unary_expression

| binary_xor_expression '^' unary_expression

expression :

relational_expression

| short_circuit_or_expression '||' relational_expression

| short_circuit_and_expression '&&' relational_expression

| bitwise_expression

8.20. 演算子の優先順位と結合性

この小節全体は非規範的です。

右辺の WGSL 式における演算子の優先順位と結合性は、 その文法の概要から導かれます。右辺式は、次の図に示すように、 演算子をグループ化して整理します:

演算子の優先順位と結合性のグラフ

冗長な記述によって可読性を高めるため、次のグループは他のグループとは結合しません:

また、次のグループは自身とは結合しません:

上記 2 つのグループ区分を結合するには、関係を明示的に設定するための括弧が必要です。 次の例では、これらの規則によって式が無効になる箇所をコメントで示します:

例: 演算子の優先順位の境界的なケース
let a = x & (y ^ (z | w)); // 無効: x & y ^ z | w
let b = (x + y) << (z >= w); // 無効: x + y << z >= w
let c = x < (y > z); // 無効: x < y > z
let d = x && (y || z); // 無効: x && y || z

導出された優先順位は式の暗黙の括弧付けを制御し、より弱い優先順位の演算子と 一緒にある場合、より強く結合する演算子は括弧で囲まれているかのように動作します。 たとえば、加算演算子より強く結合する乗算演算子により、 式 a + b * c から (a + (b * c)) が推論されます。同様に、導出された 結合性は、これらの暗黙の括弧の方向を制御します。たとえば、左から右の結合では 式 a + b + c から ((a + b) + c) が推論される一方、右から左の結合では 式 * * a から (* (* a)) が推論されます。

次の表は、演算子の優先順位、結合性、および結合を、最も強いものから 最も弱いものの順にまとめたものです。結合列には、指定された演算子より強い式が 記載されます。たとえば値が「上記すべて」の場合、その演算子には より強い式のいずれも含めることができます。一方、たとえば値が「単項」の場合、 単項より弱いものの、その行の演算子より強いものをこの演算子と結合するには 括弧が必要になります。この列は、演算子を線形に列挙するために必要です。

右辺式の演算子の優先順位、結合性、および結合。強いものから 弱いものの順
名前 演算子 結合性 結合
括弧付き (...)
基本 a(), a[], a.b 左から右
単項 -a, !a, ~a, *a, &a 右から左 上記すべて
乗算 a*b, a/b, a%b 左から右 上記すべて
加算 a+b, a-b 左から右 上記すべて
シフト a<<b, a>>b 括弧が必要 単項
関係 a<b, a>b, a<=b, a>=b, a==b, a!=b 括弧が必要 上記すべて
二項 AND a&b 左から右 単項
二項 XOR a^b 左から右 単項
二項 OR a|b 左から右 単項
短絡 AND a&&b 左から右 関係
短絡 OR a||b 左から右 関係

9. 文

文は、実行を制御する プログラム断片です。 文は一般に順次実行されますが、 制御フロー文によってプログラムが 非順次の順序で実行される場合があります。

9.1. 複合文

複合文は、 波括弧で囲まれた 0 個以上の文のシーケンスです。 宣言がそれらの文の 1 つである場合、その識別子は 次の文の開始から複合文の終端までスコープ内です。

compound_statement :

attribute * '{' statement * '}'

continuing_compound_statement は、 continuing 文の本体を形成する特殊な形式の複合 文であり、末尾に任意のbreak-if 文を 許可します。

9.2. 代入文

代入は式を評価し、 任意で結果をメモリーに格納します(したがって変数の内容を更新します)。

assignment_statement :

lhs_expression ( '=' | compound_assignment_operator ) expression

| '_' '=' expression

演算子トークンの左側のテキストを左辺と呼び、 演算子トークンの右側の 式を右辺と呼びます。

9.2.1. 単純代入

代入は、 左辺が参照式であり、 演算子が等号('=')トークンである場合、 単純代入です。 この場合、右辺の値が左辺によって参照されるメモリーへ書き込まれます。

前提条件 文 説明
e: T,
T は具象の構築可能型,
r: ref<AS,T,AM>,
AS は書き込み可能なアドレス空間,
アクセスモード AM はwrite またはread_write
r = e r を評価し、次に e を評価し、その後 e について計算された値を r が参照するメモリー 位置へ書き込みます。

注: 参照が無効なメモリー参照である場合、書き込みは 実行されないか、予想とは異なるメモリー位置へ 書き込まれる場合があります。

最も単純な場合、左辺は変数の名前です。 その他の場合については§ 6.5.9 参照値とポインター値の形成を 参照してください。

例: 代入
struct S {
    age: i32,
    weight: f32
}
var<private> person: S;

fn f() {
    var a: i32 = 20;
    a = 30;           // 'a' の内容を 30 に置き換える。

    person.age = 31;  // person 変数の age フィールドに 31 を書き込む。

    var uv: vec2<f32>;
    uv.y = 1.25;      // uv の 2 番目の成分に 1.25 を配置する。

    let uv_x_ptr: ptr<function,f32> = &uv.x;
    *uv_x_ptr = 2.5;  // uv の最初の成分に 2.5 を配置する。

    var sibling: S;
    // 'person' 変数の内容を 'sibling' 変数へコピーする。
    sibling = person;
}

9.2.2. スウィズル代入

この節は、swizzle_assignment 言語拡張が サポートされている場合にのみ適用されます。

代入は、 左辺がスウィズルビューであり、 演算子が等号('=')トークンである場合、 スウィズル 代入です。 この場合、右辺の値を更新ベクトルとして使用して、左辺に対してスウィズルビュー書き込みが実行されます。

前提条件 文 説明
sv : swizzle<AS,S,N,K>
e : vecK<S>
アドレス空間 AS は書き込み可能,
sv = e 慣例により sv = (p, IndexList)

制約:

注: スウィズルビュー式の規則により、 IndexList 内の各インデックスが [0,N-1] 内にあることが保証されます。

次の手順を実行します。

  1. p を評価します。

  2. e を評価し、ベクトル update を生成します。

  3. p が参照するメモリーを読み取り、型 vecN<S> のベクトル old_contents を生成します。

  4. SwizzleViewWrite(p, IndexList, old_contents, update) を実行します

注: スウィズルビューが無効なスウィズルビューである場合、手順 3 と 4 は 範囲外アクセスとなるため、実行されないか、 予想とは異なるメモリー位置へ書き込む場合があります。

注: p の古い内容を 読み取る前に e を評価するのは不自然に見えるかもしれません。 しかし、手順 4 のスウィズル書き込みでは IndexList に列挙されていない ベクトル成分を保持しなければならず、 それらの成分自体が e の評価中に変更されている可能性があります。

例: スウィズル代入の評価順序
var<private> v: array<vec4u,1>;

fn update_and_index() -> u32 {
  v[0] += vec4u(2,4,8,10);
  return 0;
}

fn update_and_rhs() -> vec2u {
  v[0].x = 900;
  v[0].z = 100;
  return vec2u(55,66);
}

fn eval_order_swizzle_assignment() {
  v[0] = vec4u(0,0,0,0);

  // 1. ポインター p を評価する。この評価では
  //    左辺のインデックスを評価し、
  //    副作用として v[0] = vec4u(2,4,8,10) を設定し、
  //    インデックスとして 0 を生成する。
  // 2. 右辺を評価し、
  //     v[0].x = 900
  //     v[0].z = 100
  //    を設定し、vec2u(55,66) を生成する。
  // 3. その後、スウィズル代入は v[0].x と v[0].y だけを更新し、
  //    v[0].z と v[0].w を保持する。

  v[update_and_index()].yx = update_and_rhs();

  // この時点で v[0] は vec4u(66,55,100,10) に等しい。
}

9.2.3. ダミー代入

代入は、 左辺が アンダースコア('_')トークンである場合、 ダミー代入です。 この場合、右辺が評価され、 その後無視されます。

前提条件 文 説明
e: T,
T は構築可能、ポインター型、テクスチャー型、またはサンプラー型
_ = e e を評価します。

注: 結果の値は格納されません。 _ トークンは識別子ではないため、 式内で使用することはできません。

ダミー代入は次の場合に有用です:

例: ダミー代入を使用して不要な関数結果を破棄する
var<private> counter: i32;

fn increment_and_yield_previous() -> i32 {
  let previous = counter;
  counter = counter + 1;
  return previous;
}

fn user() {
  // カウンターをインクリメントするが、結果は使用しない。
  _ = increment_and_yield_previous();
}
例: ダミー代入を使用して、使用せずにバインディングを占有する
struct BufferContents {
    counter: atomic<u32>,
    data: array<vec4<f32>>
}
@group(0) @binding(0) var<storage> buf: BufferContents;
@group(0) @binding(1) var t: texture_2d<f32>;
@group(0) @binding(2) var s: sampler;

@fragment
fn shade_it() -> @location(0) vec4<f32> {
  // buf、t、および s がシェーダーインターフェイスの一部であることを宣言するが、
  // それらを何にも使用しない。
  _ = &buf;
  _ = t;
  _ = s;
  return vec4<f32>();
}

9.2.4. 複合代入

代入は、 左辺が参照式または スウィズルビューであり、 演算子がcompound_assignment_operatorsのいずれかである場合、 複合 代入です。

compound_assignment_operator :

'+='

| '-='

| '*='

| '/='

| '%='

| '&='

| '|='

| '^='

| _shift_right_assign

| _shift_left_assign

各文の型要件、セマンティクス、および動作は、次の点を除き、 複合代入が以下の表のように展開されるものとして定義されます:

文 展開
e1 += e2 e1 = e1 + (e2)
e1 -= e2 e1 = e1 - (e2)
e1 *= e2 e1 = e1 * (e2)
e1 /= e2 e1 = e1 / (e2)
e1 %= e2 e1 = e1 % (e2)
e1 &= e2 e1 = e1 & (e2)
e1 |= e2 e1 = e1 | (e2)
e1 ^= e2 e1 = e1 ^ (e2)
e1 >>= e2 e1 = e1 >> (e2)
e1 <<= e2 e1 = e1 << (e2)

注: 構文上、複合 代入を同時にダミー代入にすることはできません。

注: e1 が参照である場合、それ自体は 1 回評価されますが、 基礎となるメモリーには 2 回アクセスします: 最初の読み取りアクセスで古い 値を取得し、その後書き込みアクセスで 更新された値を格納します。

例: 複合代入
var<private> next_item: i32 = 0;

fn advance_item() -> i32 {
   next_item += 1;   // next_item に 1 を加算する。
   return next_item - 1;
}

fn bump_item() {
  var data: array<f32,10>;
  next_item = 0;
  // advance_item() を 1 回だけ呼び出し、data[0] に 5.0 を加算する。
  data[advance_item()] += 5.0;
  // ここで next_item は 1 になる。
}

fn precedence_example() {
  var value = 1;
  // 複合代入の右辺は、それ自体が 1 つの式である。
  value *= 2 + 3; // value = value * (2 + 3); と同じ
  // 'value' は現在 5 を保持している。
}
注: e1 がスウィズル ビューである場合、指定どおり、e1 は 対応するポインターを計算するために 1 回評価されますが、基礎となるメモリーには 3 回アクセスします:
例: 複合スウィズル代入の評価順序
var<private> v: array<vec4u,1>;

fn update_and_index() -> u32 {
  v[0] += vec4u(2,4,8,10);
  return 0;
}

fn update_and_rhs() -> vec2u {
  v[0].x = 900;
  v[0].z = 100;
  return vec2u(55,66);
}

fn eval_order_compound_swizzle_assignment() {
  v[0] = vec4u(0,0,0,0);

  // 1. ポインター p を評価する。この評価では
  //    左辺のインデックスを評価し、
  //    副作用として v[0] = vec4u(2,4,8,10) を設定し、
  //    インデックスとして 0 を生成する。
  // 2. スウィズル名は .yx なので、IndexList はリスト 1,0 になる。
  //    SwizzleViewRead(p,IndexList) を実行し、
  //    view_contents = vec2u(4,2) を生成する。
  // 3. 右辺を評価し、
  //     v[0].x = 900
  //     v[0].z = 100
  //    を設定し、vec2u(55,66) を生成する。
  // 4. 更新ベクトルを次のように計算する
  //           view_contents + vec2u(55,66)
  //         = vec2u(4,2) + vec2u(55,66)
  //         = vec2u(59,68)
  // 5. その後、スウィズル代入は v[0].x と v[0].y だけを更新し、
  //    v[0].z と v[0].w を保持する。

  v[update_and_index()].yx += update_and_rhs();

  // この時点で v[0] は vec4u(68,59,100,10) に等しい。
}
注: 参照への複合代入は、 代わりに単純代入を使用する別の WGSL コードとして書き換えることができます。 これは、参照を 1 回評価した結果を保持するためにポインターを使用するという考え方です。
たとえば、 e1 がベクトル内部の成分への参照でない場合、
e1+=e2;
は次のように書き換えることができます
{ let p = &(e1); *p = *p + (e2); }
ここで識別子 p は、プログラム内の他のすべての識別子と異なるものを選択します。
e1 がベクトル内部の成分への参照である場合、WGSL ではその場合に アドレスを取得することができないため、上記の手法を 変更する必要があります。 たとえば、ev がベクトルへの参照である場合、文
ev[c] += e2;
は次のように書き換えることができます
{ let p = &(ev); let c0 = c; (*p)[c0] = (*p)[c0] + (e2); }
ここで識別子 c0 と p は、プログラム内の他のすべての 識別子と異なるものを選択します。

9.3. インクリメント文とデクリメント文

インクリメント 文は変数の内容に 1 を加算します。 デクリメント 文は変数の内容から 1 を減算します。

increment_statement :

lhs_expression '++'

decrement_statement :

lhs_expression '--'

式は、具象整数スカラー格納型およびread_write アクセスモードを持つ参照に評価されなければなりません。

前提条件 文 説明
r : ref<AS,T,read_write>,
T は具象整数スカラー
r++ r が参照するメモリーの内容に 1 を加算します。
r += T(1) と同じ
r : ref<AS,T,read_write>,
T は具象整数スカラー
r-- r が参照するメモリーの内容から 1 を減算します。
r -= T(1) と同じ
例: インクリメントとデクリメント
fn f() {
    var a: i32 = 20;
    a++;
    // 現在 a は 21 を含む
    a--;
    // 現在 a は 20 を含む
}

9.4. 制御フロー

制御フロー文によって、プログラムが非順次の順序で実行される場合があります。

9.4.1. If 文

if 文は、条件式の評価に基づいて最大 1 つの複合文を条件付きで実行します。

if 文は、if 節、その後に 0 個以上の else if 節、その後に任意の else 節を持ちます。

if_statement :

attribute * if_clause else_if_clause * else_clause ?

if_clause :

'if' expression compound_statement

else_if_clause :

'else' 'if' expression compound_statement

else_clause :

'else' compound_statement

型規則の 前提条件: 各 if および else if 節の式は必ずbool 型でなければなりません。

if 文は次のように実行されます:

9.4.2. Switch 文

switch 文は、セレクター式の評価に応じて、case 節の集合の 1 つ、 またはdefault 節へ制御を移します。

switch_statement :

attribute * 'switch' expression switch_body

switch_body :

attribute * '{' switch_clause + '}'

switch_clause :

case_clause

| default_alone_clause

case_clause :

'case' case_selectors ':' ? compound_statement

default_alone_clause :

'default' ':' ? compound_statement

case_selectors :

case_selector ( ',' case_selector ) * ',' ?

case_selector :

'default'

| expression

case 節は、'case' トークンに続いて、 カンマ区切りのcase セレクターのリストと、 複合文形式の本体を持つものです。

単独 default 節は、'default' トークンに続いて、複合文形式の本体を持つものです。

default 節は、 次のいずれかです:

各 switch 文は、default 節を正確に 1 つ持たなければなりません。

'default' トークンは、単一のcase_selector リスト内に 2 回以上現れてはなりません。

型規則の 前提条件: 単一の switch 文について、セレクター式とすべての case セレクター式は、同じ具象整数スカラー型でなければなりません。

case_selectors 内の式はconst 式でなければなりません。

同じ switch 文内の異なる 2 つの case セレクター式は、同じ値を持ってはなりません。

セレクター値がcase_selector リスト内の式の値と等しい場合、 制御はそのcase 節の本体へ移ります。 セレクター値がどの case セレクター値とも等しくない場合、制御は default 節の本体へ移ります。

制御が節の本体の終端に到達すると、switch 文の直後の最初の文へ制御が移ります。

節の本体内の文の 1 つが宣言である場合、 それは複合文内の宣言に関する通常のスコープおよび存続期間の規則に従います。 つまり、本体は文のシーケンスであり、その 1 つが宣言である場合、 その宣言のスコープはシーケンス内の次の文の開始から 本体の終端まで続きます。 宣言は到達したときに実行され、 変数または値の新しいインスタンスを作成して初期化します。

例: WGSL Switch
var a : i32;
let x : i32 = generateValue();
switch x {
  case 0: {      // コロンは任意
    a = 1;
  }
  default {      // default は最後に現れる必要はない
    a = 2;
  }
  case 1, 2, {   // 複数のセレクター値を使用できる
    a = 3;
  }
  case 3, {      // 末尾のカンマは任意
    a = 4;
  }
  case 4 {
    a = 5;
  }
}
例: default を組み合わせた WGSL Switch
const c = 2;
var a : i32;
let x : i32 = generateValue();
switch x {
  case 0: {
    a = 1;
  }
  case 1, c {       // const 式を case セレクターで使用できる
    a = 3;
  }
  case 3, default { // default キーワードは他の節とともに使用できる
    a = 4;
  }
}

9.4.3. Loop 文

loop_statement :

attribute * 'loop' attribute * '{' statement * continuing_statement ? '}'

loop 文はループ本体を繰り返し実行します。 ループ本体は複合文として指定されます。 ループ本体の各実行を反復と呼びます。

この繰り返しは、break 文または return 文によって中断できます。

任意で、ループ本体の最後の文を continuing 文にできます。

loop が 無制限の数の反復を実行することになる場合、 動的エラーが発生します。 これによりループの早期終了、その他の非局所的な影響、さらにはデバイスロスが発生する場合があります。

ループ本体内の文の 1 つが宣言である場合、 それは複合文内の宣言に関する通常のスコープおよび存続期間の規則に従います。 つまり、ループ本体は文のシーケンスであり、その 1 つが宣言である場合、 その宣言のスコープはシーケンス内の次の文の開始から ループ本体の終端まで続きます。 宣言は到達するたびに実行されるため、新しい反復ごとに 変数または値の新しいインスタンスが作成され、再初期化されます。

注: loop 文は特殊化された構文であり、おそらく for または while 文を使用することになるでしょう。loop 文は、他の シェーダー言語との最大の違いの 1 つです。

この設計は、コンパイルされたコードで一般的に見られるループのイディオムを直接表現します。 特に、ループ更新文をループ本体の末尾に配置することで、 ループ本体で定義された値を自然に使用できます。

例: for ループ
var a: i32 = 2;
for (var i: i32 = 0; i < 4; i++) {
  a *= 2;
}
例: loop
var a: i32 = 2;
var i: i32 = 0;      // <1>
loop {
  if i >= 4 { break; }

  a = a * 2;

  i++;
}
例: continue を持つ for ループ
var a: i32 = 2;
let step: i32 = 1;
for (var i: i32 = 0; i < 4; i += step) {
  if (i % 2 == 0) { continue; }
  a *= 2;
}
例: continue を持つ loop
var a: i32 = 2;
var i: i32 = 0;
loop {
  if i >= 4 { break; }

  let step: i32 = 1;

  i = i + step;
  if i % 2 == 0 { continue; }

  a = a * 2;
}
例: continue と continuing を持つ loop
var a: i32 = 2;
var i: i32 = 0;
loop {
  if i >= 4 { break; }

  let step: i32 = 1;

  if i % 2 == 0 { continue; }

  a = a * 2;

  continuing {   // <2>
    i = i + step;
  }
}

9.4.4. For 文

for_statement :

attribute * 'for' '(' for_header ')' compound_statement

for_header :

for_init ? ';' expression ? ';' for_update ?

for_init :

variable_or_value_statement

| variable_updating_statement

| func_call_statement

for_update :

variable_updating_statement

| func_call_statement

for 文は、loop 文を含む複合文に対する構文糖です。 一般に、for 文は次の形式を取ります

for ( initializer ; condition ; update_part ) { body }

条件式が存在する場合、for 文は次の形式の loop に脱糖されます:

{
initializer ;
loop {
if !(condition) { break; }
body
continuing { update_part }
}
}
条件式が存在しない場合、for 文は次の形式の loop に脱糖されます:
{
initializer ;
loop {
body
continuing { update_part }
}
}

さらに:

for ループの initializer は、ループの実行前に 1 回実行されます。 宣言が 初期化子に現れる場合、その識別子は body の終端までスコープ内です。 body 内の宣言とは異なり、その宣言は各反復で再初期化されません。

condition、body、update_part はこの順序で実行され、 ループの反復を形成します。 body は複合文の特殊な形式です。 body 内の宣言の識別子は、次の文の開始から body の終端までスコープ内です。 宣言は到達するたびに実行されるため、新しい反復ごとに 変数または定数の新しいインスタンスが作成され、再初期化されます。

例: 条件ありの For から Loop への変換: 変換前
var a: i32 = 2;
for (var i: i32 = 0; i < 4; i++) {
  if a == 0 {
    continue;
  }
  a = a + 2;
}

次のように変換されます:

例: 条件ありの For から Loop への変換: 変換後
var a: i32 = 2;
{ // ループ変数 i のための新しいスコープを導入する
  var i: i32 = 0;
  loop {
    if !(i < 4) {
      break;
    }

    if a == 0 {
      continue;
    }
    a = a + 2;

    continuing {
      i++;
    }
  }
}
例: 条件なしの For から Loop への変換: 変換前
var a: i32 = 2;
for (var i: i32 = 0; ; i++) {
  if a == 0 {
    continue;
  }
  if i == 4 { break; }
  a = a + 2;
}

次のように変換されます:

例: 条件なしの For から Loop への変換: 変換後
var a: i32 = 2;
{ // ループ変数 i のための新しいスコープを導入する
  var i: i32 = 0;
  loop {
    // 注: 脱糖ではここに if 節を導入しない。

    if a == 0 {
      continue;
    }
    if i == 4 { break; }
    a = a + 2;

    continuing {
      i++;
    }
  }
}

for ループが 無制限の数の反復を実行することになる場合、 動的エラーが発生します。 これにより、ループの早期終了、その他の非局所的な影響、さらにはデバイスロスが発生する場合があります。

9.4.5. While 文

while_statement :

attribute * 'while' expression compound_statement

while 文は、条件によってパラメーター化された一種のループです。 各ループ反復の開始時に、 ブール条件が評価されます。 条件が false の場合、while ループは実行を終了します。 それ以外の場合、反復の残りが実行されます。

型規則の 前提条件: 条件はbool 型でなければなりません。

while ループは、loop 文またはfor 文のいずれかに対する構文糖とみなすことができます。 次の文形式は等価です:

while ループが 無制限の数の反復を実行することになる場合、 動的エラーが発生します。 これにより、ループの早期終了、その他の非局所的な影響、さらにはデバイスロスが発生する場合があります。

9.4.6. Break 文

break_statement :

'break'

break 文は、最も近くにある外側のループ本体 またはswitch 文の直後へ 制御を移し、ループまたは switch 文の実行を終了します。

break 文は、loop、for、while、およびswitch 文内でのみ使用しなければなりません。

break 文は、ループのcontinuing 文から 抜けることになる位置に配置してはなりません。 代わりにbreak-if 文を使用してください。

例: continuing 節からの無効な WGSL ループ break
var a: i32 = 2;
var i: i32 = 0;
loop {
  let step: i32 = 1;

  if i % 2 == 0 { continue; }

  a = a * 2;

  continuing {
    i = i + step;
    if i >= 4 { break; } // 無効。代わりに break-if を使用する。
  }
}

9.4.7. Break-If 文

break_if_statement :

'break' 'if' expression ';'

break-if 文はブール条件を評価します。 条件が true の場合、制御は最も近くにある外側のloop 文の本体の直後へ移り、そのループの実行を終了します。

型規則の 前提条件: 条件はbool 型でなければなりません。

注: break-if 文は、 continuing 文の本体内の最後の 文としてのみ現れることができます。

例: continuing 節からの有効な WGSL ループ break-if
var a: i32 = 2;
var i: i32 = 0;
loop {
  let step: i32 = 1;

  if i % 2 == 0 { continue; }

  a = a * 2;

  continuing {
    i = i + step;
    break if i >= 4;
  }
}

9.4.8. Continue 文

continue_statement :

'continue'

continue 文は、最も近くにある外側のloop 内で制御を移します:

continue 文は、loop、for、またはwhile 文内でのみ使用しなければなりません。 continue 文は、外側のcontinuing 文へ制御を移すことになる位置に配置してはなりません。 (continuing 文へ分岐する場合、それは前方分岐です。)

continue 文は、対象のcontinuing 文で使用される宣言を越えて 制御を移すことになる位置に配置してはなりません。

注: continue は、 continuing 文内にネストされた別のループの内部で制御フローを移すために使用する場合に限り、 continuing 文内で使用できます。つまり、continue を使用して 現在実行中の continuing 文の先頭へ制御を移すことはできません。

例: 無効な continue が宣言を迂回する
var i: i32 = 0;
loop {
  if i >= 4 { break; }
  if i % 2 == 0 { continue; } // <3>

  let step: i32 = 2;

  continuing {
    i = i + step;
  }
}

9.4.9. Continuing 文

continuing_statement :

'continuing' continuing_compound_statement

continuing_compound_statement :

attribute * '{' statement * break_if_statement ? '}'

continuing 文は、ループ反復の終端で実行される複合文を指定します。 この構文は任意です。

複合文は、どの複合文のネストレベルにおいてもreturn を含んではなりません。

9.4.10. Return 文

return_statement :

'return' expression ?

return 文は現在の関数の実行を終了します。 関数がエントリーポイントである場合、 現在のシェーダー呼び出しが 終了します。 それ以外の場合、現在の関数呼び出しの呼び出しサイトの評価後にある 次の式または文から評価を続行します。

関数に戻り値の 型がない場合、return 文は 任意です。そのような関数で return 文を指定する場合、値を指定してはなりません。 それ以外の場合、式が存在しなければならず、これを戻り値と呼びます。 この場合、この関数呼び出しの呼び出しサイトは戻り値に評価されます。 戻り値の型は関数の戻り値の型と一致しなければなりません。

9.4.11. Discard 文

discard 文は呼び出しを ヘルパー呼び出しに変換し、 フラグメント出力を破棄します。 discard 文はフラグメントシェーダーステージでのみ使用しなければなりません。

より正確には、discard 文を実行すると次のことが行われます:

discard 文より前に実行された文だけが観測可能な効果を持ちます。

注: discard 文は フラグメントステージ内の関数のいずれからでも実行でき、その効果は同じです: フラグメント出力は破棄されます。

例: discard 文を使用してフラグメントを破棄する
@group(0) @binding(0)
var<storage, read_write> will_emit_color : u32;

fn discard_if_shallow(pos: vec4<f32>) {
  if pos.z < 0.001 {
    // これが実行された場合、ヘルパー呼び出しは共有メモリーへ
    // 書き込まないため、will_emit_color 変数が 1 に設定されることは
    // ない。
    discard;
  }
  will_emit_color = 1;
}

@fragment
fn main(@builtin(position) coord_in: vec4<f32>)
  -> @location(0) vec4<f32>
{
  discard_if_shallow(coord_in);

  // 値を 1 に設定して赤を出力するが、ヘルパー関数が
  // discard 文を実行しなかった場合に限る。
  will_emit_color = 1;
  return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}

9.5. 関数呼び出し文

func_call_statement :

call_phrase

関数呼び出し文は関数呼び出しを実行します。

呼び出された関数がmust_use 属性を持つ場合、シェーダー作成エラーになります。

注: 関数が値を返し、 かつ関数にmust_use 属性がない場合、 その値は無視されます。

9.6. 文の文法概要

statement 規則は、 関数本体内のほとんどの場所で使用できる文に一致します。

statement :

';'

| return_statement ';'

| if_statement

| switch_statement

| loop_statement

| for_statement

| while_statement

| func_call_statement ';'

| variable_or_value_statement ';'

| break_statement ';'

| continue_statement ';'

| 'discard' ';'

| variable_updating_statement ';'

| compound_statement

| assert_statement ';'

variable_updating_statement :

assignment_statement

| increment_statement

| decrement_statement

さらに、特定の文は非常に限定されたコンテキストでのみ使用できます:

9.7. 文の動作解析

9.7.1. 規則

制御フローに影響する一部の文は、特定のコンテキストでのみ有効です。 たとえば、continue はloop、 for、またはwhile の外側では無効です。 さらに、一様性解析(§ 15.2 一様性を参照)では、 制御フローが文から複数の異なる方法で抜けられる場合を知る必要があります。

両方の目的は、文の実行動作を要約するための体系によって実現されます。動作解析は、 各文を、その文の評価が完了した後に実行が進む可能性のある方法の集合へ対応付けます。 値や式の型解析と同様に、動作解析はボトムアップで進みます。まず特定の基本文の 動作を決定し、その後、結合規則を適用してより高水準の構文の動作を決定します。

動作は集合であり、その 要素は次のいずれかです:

これらはそれぞれ、キーワードを介するか、次の文へ進む(「Next」)ことによって、 複合文から抜ける方法に対応します。

s が動作に関する規則を満たし、動作 B を持つことを、 「s: B」と表記します。

各関数について:

各関数には動作を割り当てます。これは、 その本体を通常の文として扱った動作であり、「Return」はすべて「Next」に置き換えます。 上記の規則の結果として、関数の動作は常に {} または {Next} のいずれかです。

動作解析は、各文および関数について空でない動作を決定できなければなりません。

文の動作を解析および検証するための規則
文 前提条件 結果の動作
空文 {Next}
{s} s: B B
s1 s2

注: s1 は多くの場合 セミコロンで終わります。

s1: B1
Next が B1 に含まれる
s2: B2
(B1∖{Next}) ∪ B2
s1: B1
Next が B1 に含まれない
s2: B2
B1
var x:T; {Next}
let x = e; {Next}
var x = e; {Next}
x = e; {Next}
_ = e; {Next}
f(e1, ..., en); f は動作 B を持つ B
return; {Return}
return e; {Return}
discard; {Next}
break; {Break}
break if e; {Break, Next}
continue; {Continue}
const_assert e; {Next}
if e s1 else s2 s1: B1
s2: B2
B1 ∪ B2
loop {s1 continuing {s2}} s1: B1
s2: B2
B1 = {Return}
{Continue, Return} のいずれも B2 に含まれない
{Return}
s1: B1
s2: B2
B1 ≠ {Return}
{Continue, Return} のいずれも B2 に含まれない
Break は (B1 ∪ B2) に含まれない
(B1 ∪ B2)∖{Continue, Next}
s1: B1
s2: B2
B1 ≠ {Return}
{Continue, Return} のいずれも B2 に含まれない
Break は (B1 ∪ B2) に含まれる
(B1 ∪ B2 ∪ {Next})∖{Break, Continue}
switch e {case c1: s1 ... case cn: sn} s1: B1
...
sn: Bn
Break は (B1 ∪ ... ∪ Bn) に含まれない
B1 ∪ ... ∪ Bn
s1: B1
...
sn: Bn
Break は (B1 ∪ ... ∪ Bn) に含まれる
(B1 ∪ ... ∪ Bn ∪ {Next})∖Break

注: ∪ は集合の和集合演算であり、∖ は集合の 差集合演算です。

注: 空文の場合は、 loop の本体が空の場合、または for ループに初期化文または更新文がない場合に 発生します。

この解析の目的では:

各組み込み 関数の動作は {Next} です。 また、上の表に列挙されていない各演算子適用は、同じオペランドを持ち、関数の動作が {Next} である 関数呼び出しであるかのように、同じ動作を持ちます。

関数の動作は、上記の規則を満たさなければなりません。

注: 上記の規則から、ループの動作は {Next}、{Return}、または {Next,Return} のいずれかになります。

注: 式の動作を解析する必要はありません。式は 常に {Next} であるか、以前に解析された関数によって エラーが生成されているためです。

9.7.2. 注記

この節は参考情報であり、非規範的です。

動作解析によって、次のような場合にプログラムが拒否される可能性があります (上記の要件を再掲):

この解析は、コールグラフをボトムアップで解析することにより、線形時間で実行できます (関数呼び出しの動作は関数のコードに依存する可能性があるため)。

9.7.3. 例

この解析の動作を示す例をいくつか示します:

例: 自明なデッドコードは許可される
fn simple() -> i32 {
  var a: i32;
  return 0;  // 動作: {Return}
  a = 1;     // 有効。静的に到達不能なコード。
             //   文の動作: {Next}
             //   全体の動作(逐次文による): {Return}
  return 2;  // 有効。静的に到達不能なコード。動作: {Return}
} // 関数の動作: {Return}
例: 複合文はサポートされる
fn nested() -> i32 {
  var a: i32;
  {             // 複合文の開始。
    a = 2;      // 動作: {Next}
    return 1;   // 動作: {Return}
  }             // 複合文全体の動作は {Return}
  a = 1;        // 有効。静的に到達不能なコード。
                //   文の動作: {Next}
                //   全体の動作(逐次文による): {Return}
  return 2;     // 有効。静的に到達不能なコード。動作: {Return}
}
例: if/then は空の else があるかのように動作する
fn if_example() {
  var a: i32 = 0;
  loop {
    if a == 5 {
      break;      // 動作: {Break}
    }             // if 複合文全体の動作: {Break, Next}、
                  //   if には暗黙の空の else があるため
    a = a + 1;    // 有効。前の文の動作に "Next" が含まれていたため
  }
}
例: if/then/else は両方の側の動作を持つ
fn if_example() {
  var a: i32 = 0;
  loop {
    if a == 5 {
      break;      // 動作: {Break}
    } else {
      continue;   // 動作: {Continue}
    }             // if 複合文全体の動作: {Break, Continue}
    a = a + 1;    // 有効。静的に到達不能なコード。
                  //   文の動作: {Next}
                  //   全体の動作: {Break, Continue}
  }
}
例: if/else if/else はネストされた if/else のように動作する
fn if_example() {
  var a: i32 = 0;
  loop {
    // if e1 s1 else if e2 s2 else s3
    // は次と同一
    // if e1 else { if e2 s2 else s3 }
    if a == 5 {
      break;      // 動作: {Break}
    } else if a == 42 {
      continue;   // 動作: {Continue}
    } else {
      return;     // 動作 {Return}
    }             // if 複合文全体の動作:
                  //   {Break, Continue, Return}
  }               // loop 複合文全体の動作 {Next, Return}
}                 // 関数全体の動作 {Next}
例: switch 内の Break は Next になる
fn switch_example() {
  var a: i32 = 0;
  switch a {
    default: {
      break;   // 動作: {Break}
    }
  }            // 動作: {Next}。switch が Break を Next に置き換えるため
  a = 5;       // 有効。前の文の動作に Next が含まれていたため
}
例: 明らかな無限ループ
fn invalid_infinite_loop() {
  loop { }     // 動作: { }。空であるため無効。
}
例: Discard はループを終了させない
fn invalid_infinite_loop() {
  loop {
    discard; // 動作 { Next }。
  }          // 無効。ループ全体の動作は { }。
}
例: continuing 文を持つ条件付き continue
fn conditional_continue() {
  var a: i32;
  loop {
    if a == 5 { break; } // 動作: {Break, Next}
    if a % 2 == 1 {      // 有効。前の文の動作に Next が含まれるため
      continue;          // 動作: {Continue}
    }                    // 動作: {Continue, Next}
    a = a * 2;           // 有効。前の文の動作に Next が含まれるため
    continuing {         // continuing 文の動作が {Next} なので有効
                         //  次のいずれも含まない:
                         //  {Break, Continue, Return}
      a = a + 1;
    }
  }                      // ループ全体の動作は {Next}、
                         //  "Continue" と "Next" を吸収し、
                         //  その後 "Break" を "Next" に置き換えるため
}
例: continuing 文を持つ冗長な continue
fn redundant_continue_with_continuing() {
  var a: i32;
  loop {
    if a == 5 { break; }
    continue;   // 有効。これは冗長で、次の文へ分岐する。
    continuing {
      a = a + 1;
    }
  }
}
例: ループ本体の末尾にある continue
fn continue_end_of_loop_body() {
  for (var i: i32 = 0; i < 5; i++ ) {
    continue;   // 有効。これは冗長で、
                //   ループ本体の末尾へ分岐する。
  }             // 動作: {Next}、
                //   ループが "Continue" を吸収し、
                //   "for" ループは常に "Next" を追加するため
}
for ループは、条件付き break を持つ loop に脱糖されます。前の例で示したように、 条件付き break の動作は {Break, Next} であり、これによってループの動作に "Next" が追加されます。
例: 戻り値の型を持つ関数では return が必須
fn missing_return () -> i32 {
  var a: i32 = 0;
  if a == 42 {
    return a;       // 動作: {Return}
  }                 // 動作: {Next, Return}
}                   // エラー: Next は戻り値の型を持つ関数の
                    //   本体では無効
例: continue はループ内になければならない
fn continue_out_of_loop () {
  var a: i32 = 0;
  if a > 0  {
    continue;       // 動作: {Continue}
  }                 // 動作: {Next, Continue}
}                   // エラー: Continue は関数本体では無効
continue を break に置き換えた場合も、同じ理由で 同じ例は無効になります。

10. アサーション

アサーションは、 ブール条件が満たされていることを保証する検査です。

global_assert :

const_assert ';'

WGSL は 1 種類のアサーションを定義します: const アサーションです。

const_assert :

'const_assert' expression

型規則の 前提条件: 式はbool 型でなければなりません。

10.1. Const アサーション文

const アサーション文は、式が false に評価された場合に シェーダー作成エラーを生成するアサーションです。 式はconst 式でなければなりません。 この文はシェーダー内の静的アクセス条件を満たすことができますが、 それ以外ではコンパイル済みシェーダーに影響を与えません。 const アサーションは モジュールスコープ、 または関数スコープの文として現れることができます。

assert_statement :

const_assert

例: 静的アサーションの例
const x = 1;
const y = 2;
const_assert x < y; // モジュールスコープで有効。
const_assert(y != 0); // 括弧は任意。

fn foo() {
  const z = x + y - 2;
  const_assert z > 0; // 関数内で有効。
  let a  = 3;
  const_assert a != 0; // 無効。式は const 式でなければならない。
}

11. 関数

関数は、呼び出されたときに計算処理を実行します。

関数は次のいずれかの方法で呼び出されます:

WGSL の関数は、使用箇所より後のソースに記述することも含め、任意の順序で定義できます。 そのため、関数プロトタイプや前方宣言は不要であり、それらを記述する方法もありません。

関数には 2 種類あります:

11.1. ユーザー定義関数の宣言

関数 宣言は、次を指定することによってユーザー定義関数を作成します:

関数宣言はモジュールスコープでのみ行われなければなりません。 関数名はプログラム全体でスコープ内です。

注: 各ユーザー定義関数にはオーバーロードが 1 つだけあります。

仮引数宣言は、関数を呼び出すときに提供しなければならない値について、 識別子名と型を指定します。 エントリーポイント関数の 仮引数は属性を持つことができます。 § 11.2 関数呼び出しを参照してください。 識別子のスコープは関数本体です。 同じ関数の 2 つの仮引数は同じ名前を持ってはなりません。

注: 一部の組み込み関数では、パラメーターに 抽象数値 型を使用できる場合があります。 ただし、この機能は現在ユーザー宣言関数ではサポートされていません。

戻り値の型を指定する場合、 構築可能でなければなりません。

WGSL は、関数宣言に適用できる次の属性を定義します:

function_decl :

attribute * function_header compound_statement

function_header :

'fn' ident '(' param_list ? ')' ( '->' attribute * template_elaborated_ident ) ?

param_list :

param ( ',' param ) * ',' ?

param :

attribute * ident ':' type_specifier

例: 単純な関数
// add_two 関数を宣言する。
// 2 つの仮引数 i と b を持つ。
// 戻り値の型は i32。
// return 文を含む本体を持つ。
fn add_two(i: i32, b: f32) -> i32 {
  return i + 2;  // 仮引数は本体内で使用できる。
}

// コンピュートシェーダーのエントリーポイント関数 'main'。
// 指定された戻り値の型を持たない。
// add_two 関数を呼び出し、結果の値を
// 名前付き値 'six' に格納する。
@compute @workgroup_size(1)
fn main() {
   let six: i32 = add_two(4, 5.0);
}

11.2. 関数呼び出し

関数呼び出しは、 関数を呼び出す文または式です。

関数呼び出しを含む関数を呼び出し元関数、または呼び出し元と呼びます。 呼び出される関数を呼び出される関数、または呼び出し先と呼びます。

関数呼び出しは:

関数呼び出しは、呼び出される関数の仮引数と同じ数の引数値を提供しなければなりません。 各引数値は、位置に対応する仮引数と同じ型に評価されなければなりません。

要約すると、関数を呼び出す場合:

  1. 呼び出し元関数の実行が中断されます。

  2. 呼び出される関数が 戻るまで実行されます。

  3. 呼び出し元関数の実行が再開されます。

呼び出された関数は次のように戻ります:

詳細には、関数呼び出しが実行されると次の手順が発生します:

  1. 関数呼び出しの引数値が評価されます。 相対的な評価順序は左から右です。

  2. 呼び出し元関数の実行が中断されます。 すべての関数スコープ 変数および定数は現在の値を保持します。

  3. 呼び出された関数がユーザー定義の場合、 呼び出された関数内の各関数スコープ変数にメモリーが割り当てられます。

  4. 呼び出された関数の仮引数の値は、 関数呼び出しの引数値を位置によって対応付けることで決定されます。 たとえば、呼び出された関数の最初の仮引数には、 呼び出しサイトの最初の引数の値が設定されます。

  5. 制御は呼び出された関数へ移ります。 呼び出された関数がユーザー定義の場合、実行は 本体の最初の文から進みます。

  6. 呼び出された関数は、戻るまで実行されます。

  7. 制御は呼び出し元関数へ戻され、呼び出された関数の実行の中断が解除されます。 呼び出された関数が値を返す場合、その値が 関数呼び出し式の値として提供されます。

関数呼び出しの位置を呼び出しサイトと呼びます。具体的には、 call_phrase 文法規則の解析済みインスタンス内にある最初のトークンの位置です。 呼び出しサイトは動的 コンテキストです。 そのため、同じテキスト上の位置が複数の呼び出しサイトを表す場合があります。

注: クワッド内のすべての呼び出しが破棄された場合、 フラグメントシェーダー内の関数呼び出しが 戻らない可能性があります。 その場合、制御は呼び出し元関数へ戻されません。

11.3. const 関数

const 属性を付けて宣言された関数は、 シェーダー作成時に評価できます。 これらの関数をconst 関数と呼びます。 これらの関数の呼び出しはconst 式の一部にできます。

関数がconst 式ではない式、または const 宣言ではない 宣言を含む場合、シェーダー作成エラーです。

注: const 属性は ユーザー宣言関数には適用できません。

例: const 関数
const first_one = firstLeadingBit(1234 + 4567); // 12 に評価される
                                                // firstLeadingBit は AbstractInt を
                                                // 操作できないため、first_one の型は
                                                // i32

@id(1) override x : i32;
override y = firstLeadingBit(x); // const 式は
                                 // override 式で使用できる。
                                 // firstLeadingBit(x) はこの
                                 // コンテキストでは const 式ではない。

fn foo() {
  var a : array<i32, firstLeadingBit(257)>; // const 関数は、すべての
                                            // パラメーターが const 式である場合、
                                            // const 式で使用できる。
}

11.4. 関数の制限

注: あらゆる種類の宣言間で循環が許可されないため、 再帰は禁止されています。

例: 有効および無効なポインター引数
fn bar(p : ptr<function, f32>) {
}

fn baz(p : ptr<private, i32>) {
}

fn bar2(p : ptr<function, f32>) {
  let a = &*&*(p);

  bar(p); // 有効
  bar(a); // 有効
}

fn baz2(p : ptr<storage, f32>) {
}

struct S {
  x : i32
}

@group(0) @binding(0)
var<storage> ro_storage : f32;
@group(0) @binding(1)
var<storage, read_write> rw_storage : f32;

var usable_priv : i32;
var unusable_priv : array<i32, 4>;
fn foo() {
  var usable_func : f32;
  var unusable_func : S;
  var i32_func : i32;

  let a_priv = &usable_priv;
  let b_priv = a_priv;
  let c_priv = &*&usable_priv;
  let d_priv = &(unusable_priv.x);
  let e_priv = d_priv;

  let a_func = &usable_func;
  let b_func = &unusable_func;
  let c_func = &(*b_func)[0];
  let d_func = c_func;
  let e_func = &*a_func;

  baz(&usable_priv); // 有効。変数のアドレス取得。
  baz(a_priv);       // 有効。実質的に変数のアドレス取得。
  baz(b_priv);       // 有効。実質的に変数のアドレス取得。
  baz(c_priv);       // 有効。実質的に変数のアドレス取得。
  baz(d_priv);       // 有効。メモリービューが変更されている。
  baz(e_priv);       // 有効。メモリービューが変更されている。
  baz(&i32_func);    // 無効。アドレス空間が一致しない。

  bar(&usable_func); // 有効。変数のアドレス取得。
  bar(c_func);       // 有効。メモリービューが変更されている。
  bar(d_func);       // 有効。メモリービューが変更されている。
  bar(e_func);       // 有効。実質的に変数のアドレス取得。

  baz2(&ro_storage); // 有効。変数のアドレス取得。
  baz2(&rw_storage); // 無効。アクセスモードが一致しない。
}

11.4.1. エイリアス解析

11.4.1.1. ルート識別子

メモリー位置は、 関数の実行中にメモリービューまたはスウィズルビューを使用してアクセスできます。 関数内では、各メモリー ビューに特定のルート識別子があり、 その関数内でそのメモリーへのアクセスを最初に提供する変数または仮引数に名前を付けます。 同様に、スウィズル ビューのルート 識別子は、スウィズルビューのポインターのルート識別子です。

参照型または ポインター型のローカルで派生した式は、 特定のルート識別子に新しい名前を導入する場合がありますが、 各式には静的に決定可能なルート識別子があります。

ポインターまたは参照型の式 E が与えられた場合、 ルート識別子は、 次のように見つかる起点変数またはポインター型の仮 引数です:

11.4.1.2. エイリアシング

ルート識別子の起点変数は、関数の呼び出しサイトに 依存する動的な概念ですが、WGSL モジュールを 静的に解析することで、各ルート識別子について考えられるすべての起点変数の集合を決定できます。

2 つのルート識別子は、同じ 起点 変数を持つ場合、エイリアスするといいます。 WGSL 関数の実行は、一方のアクセスが書き込みで、 他方が読み取りまたは書き込みである場合、エイリアスするルート識別子を介して メモリーにアクセスする可能性があってはなりません。 これは、コールグラフの葉から 上方向(すなわちトポロジカル順序)にプログラムを解析することで決定されます。 各関数について、解析では次の集合を記録します:

関数の各呼び出しサイトでは、次のいずれかが 発生した場合、シェーダー作成エラーです:

例: エイリアス解析
var<private> x : i32 = 0;

fn f1(p1 : ptr<function, i32>, p2 : ptr<function, i32>) {
  *p1 = *p2;
}

fn f2(p1 : ptr<function, i32>, p2 : ptr<function, i32>) {
  f1(p1, p2);
}

fn f3() {
  var a : i32 = 0;
  f2(&a, &a);  // 無効。同じルート識別子を持つ 2 つのポインターパラメーターを
               // 一方または複数が書き込まれる場合に渡すことはできない
               // (サブ関数によって書き込まれる場合も含む)。
}

fn f4(p1 : ptr<function, i32>, p2 : ptr<function, i32>) -> i32 {
  return *p1 + *p2;
}

fn f5() {
  var a : i32 = 0;
  let b = f4(&a, &a); // 有効。f4 の p1 と p2 はどちらも読み取り専用。
}

fn f6(p : ptr<private, i32>) {
  x = *p;
}

fn f7(p : ptr<private, i32>) -> i32 {
  return x + *p;
}

fn f8() {
  let a = f6(&x); // 無効。x はグローバル変数として書き込まれ、
                  // パラメーターとして読み取られる。
  let b = f7(&x); // 有効。x はパラメーターとしても変数としても
                  // 読み取られるだけである。
}

12. 属性

属性はオブジェクトを変更します。 WGSL は、属性を適用するための統一された構文を提供します。 属性は、API とのインターフェイスの指定など、さまざまな目的で使用されます。

一般に、言語の観点からは、型およびセマンティックチェックの目的では 属性を無視できます。 さらに、属性名はコンテキスト依存名であり、 一部の属性パラメーターもコンテキスト依存名です。

attribute :

'@' ident_pattern_token argument_expression_list ?

| align_attr

| binding_attr

| blend_src_attr

| builtin_attr

| const_attr

| diagnostic_attr

| group_attr

| id_attr

| interpolate_attr

| invariant_attr

| location_attr

| must_use_attr

| size_attr

| workgroup_size_attr

| subgroup_size_attr

| vertex_attr

| fragment_attr

| compute_attr

属性の説明で明示的に許可されていない限り、属性はオブジェクトまたは型ごとに 2 回以上指定してはなりません。

12.1. align

align_attr :

'@' 'align' '(' expression ',' ? ')'

align 属性
説明 メモリー内での構造体メンバーの配置を制約します。

構造体型のメンバーにのみ適用しなければなりません。

この属性は、包含する構造体型の値がメモリー内にどのように現れるかに影響します: 構造体自体とその構成メンバーが現れることのできるバイトアドレスを 制約します。

align(n) が型 T を持つ S のメンバーに 適用され、 S がアドレス空間 AS 内の変数の格納型になり得て、 AS がuniform でない場合、 n は次を満たさなければなりません:
n = k × RequiredAlignOf(T,AS) となる正の整数 k が存在する。

アラインメントとサイズの規則は相互再帰的です。 ただし、上記の制約はネストされた型の必要アラインメントに依存し、 型には有限のネスト深度があるため、適切に定義されています。

uniform または storage バッファーにバインドされたメモリーの開始アドレスのアラインメントが 属性で指定された値より低い場合、結果のアラインメントは その 2 つの最小値になります。 実装は変数のベースアドレスを基準としてのみ 属性を満たします。

§ 14.4 メモリーレイアウトを参照してください。

パラメーター i32 またはu32 に解決されるconst 式でなければなりません。
正でなければなりません。
2 のべき乗でなければなりません。

12.2. binding

binding_attr :

'@' 'binding' '(' expression ',' ? ')'

binding 属性
説明 バインドグループ内のリソースのバインディング番号を指定します。 § 13.3.2 リソースインターフェイスを参照してください。

リソース変数にのみ適用しなければなりません。

パラメーター i32 またはu32 に解決されるconst 式でなければなりません。
0 以上でなければなりません。

12.3. blend_src

blend_src_attr :

'@' 'blend_src' '(' expression ',' ? ')'

blend_src 属性
説明 機能 dual_source_blending が有効な場合のフラグメント出力の一部を指定します。 § 13.3.1.3 入出力ロケーションを参照してください。

location 属性を持つ構造体型のメンバーにのみ適用しなければなりません。 数値スカラー または数値 ベクトル型のオブジェクトの宣言にのみ適用しなければなりません。 シェーダー ステージ入力に含めてはなりません。 フラグメント シェーダーステージを除き、シェーダーステージ出力に含めてはなりません。

パラメーター 値が 0 または 1 の i32 またはu32 に解決されるconst 式でなければなりません。

12.4. builtin

builtin_attr :

'@' 'builtin' '(' builtin_value_name ',' ? ')'

builtin 属性
説明 関連付けられたオブジェクトが、指定されたトークンによって示される組み込み値であることを指定します。 § 13.3.1.1 組み込み入力と出力を参照してください。

エントリーポイント関数のパラメーター、エントリーポイントの戻り値の型、または構造体のメンバーにのみ適用しなければなりません。

パラメーター 組み込み値の組み込み値 名トークンでなければなりません。

12.5. const

const_attr :

'@' 'const'

const 属性
説明 関数をconst 関数として使用できることを指定します。 この属性はユーザー定義関数に適用してはなりません。

関数宣言にのみ適用しなければなりません。

注: この属性は、 どの組み込み関数をconst 式で使用できるかを記述するための 表記上の規約として使用されます。

パラメーター なし

12.6. diagnostic

diagnostic_attr :

'@' 'diagnostic' diagnostic_control

diagnostic_control :

'(' severity_control_name ',' diagnostic_rule_name ',' ? ')'

diagnostic 属性
説明 範囲診断フィルターを指定します。§ 2.3 診断を参照してください。

構文形式には複数のdiagnostic 属性を指定できますが、 それらは異なるトリガールールを指定しなければなりません。

パラメーター 最初のパラメーターはseverity_control_name です。

2 番目のパラメーターは、トリガールールを指定するdiagnostic_rule_name トークンです。

12.7. group

group_attr :

'@' 'group' '(' expression ',' ? ')'

group 属性
説明 リソースのバインディンググループを指定します。 § 13.3.2 リソースインターフェイスを参照してください。

リソース変数にのみ適用しなければなりません。

パラメーター i32 またはu32 に解決されるconst 式でなければなりません。
0 以上でなければなりません。

12.8. id

id_attr :

'@' 'id' '(' expression ',' ? ')'

id 属性
説明 パイプラインでオーバーライド可能な定数の代替名として 数値識別子を指定します。

スカラー型のoverride 宣言にのみ適用しなければなりません。

パラメーター i32 またはu32 に解決されるconst 式でなければなりません。
0 以上でなければなりません。

12.9. interpolate

interpolate_attr :

'@' 'interpolate' '(' interpolate_type_name ',' ? ')'

| '@' 'interpolate' '(' interpolate_type_name ',' interpolate_sampling_name ',' ? ')'

interpolate_type_name :

ident_pattern_token

interpolate 属性
説明 ユーザー定義 IO をどのように補間しなければならないかを指定します。 § 13.3.1.4 補間を参照してください。

location 属性が適用された宣言にのみ適用しなければなりません。

存在する場合、この属性はユーザー定義の頂点出力 およびフラグメント入力に対してのみ意味を持ちます。

パラメーター 最初のパラメーターは、補間型の 補間型名トークンでなければなりません。

2 番目のパラメーターが存在する場合、補間サンプリングの 補間サンプリング名トークンでなければなりません。

12.10. invariant

invariant_attr :

'@' 'invariant'

invariant 属性
説明 頂点 シェーダーのposition 組み込み出力値に 適用すると、結果の計算は異なる プログラム間、および同じエントリーポイントの異なる呼び出し間で不変になります。 つまり、異なるエントリーポイント内の 2 つの position 出力について データフローと制御フローが一致する場合、結果の値が同じであることが 保証されます。 position 組み込み入力値には影響しません。

position 組み込み値にのみ適用しなければなりません。

注: この属性は HLSL の precise 修飾子、および GLSL の invariant 修飾子に対応します。

パラメーター なし

12.11. location

location_attr :

'@' 'location' '(' expression ',' ? ')'

location 属性
説明 エントリーポイントのユーザー定義 IO の一部を指定します。 § 13.3.1.3 入出力ロケーションを参照してください。

エントリーポイント関数のパラメーター、エントリーポイントの 戻り値の型、または構造体型のメンバーにのみ適用しなければなりません。 数値スカラー または数値 ベクトル型のオブジェクトの宣言にのみ適用しなければなりません。 コンピュートシェーダー ステージ入力に含めてはなりません。

パラメーター i32 またはu32 に解決されるconst 式でなければなりません。
0 以上でなければなりません。

12.12. must_use

must_use_attr :

'@' 'must_use'

must_use 属性
説明 この関数の呼び出しは式として使用しなければならないことを指定します。 つまり、この関数の呼び出しは関数呼び出し文の全体であってはなりません。

戻り値の型を持つ 関数の宣言にのみ適用しなければなりません。

注: 多くの関数は値を返し、 副作用を持ちません。 このような関数を関数呼び出し文の唯一の内容として呼び出すことは、多くの場合プログラミング上の欠陥です。 これらの性質を持つ組み込み関数は @must_use として宣言されます。 ユーザー定義関数も @must_use 属性を持つことができます。

注: 意図的に @must_use 規則を回避するには、ダミー代入を使用するか、 関数呼び出しを初期化子として使用して値を 宣言してください。

パラメーター なし

12.13. size

size_attr :

'@' 'size' '(' expression ',' ? ')'

size 属性
説明 構造体メンバー用に予約されるバイト数を指定します。

この数は、メンバーの型のバイトサイズ以上でなければなりません:

size(n) が型 T のメンバーに適用される場合、SizeOf(T) ≤ n。

§ 14.4 メモリーレイアウトを参照してください。

構造体型のメンバーにのみ適用しなければなりません。 メンバー型は作成時固定 フットプリントを持たなければなりません。

パラメーター i32 またはu32 に解決されるconst 式でなければなりません。
正でなければなりません。

12.14. subgroup_size

subgroup_size_attr :

'@' 'subgroup_size' '(' expression ',' ? ')'

subgroup_size 属性
説明 コンピュートシェーダー呼び出しのサブグループサイズを指定します。

コンピュートシェーダーのエントリーポイント関数にのみ適用しなければなりません。

要件 subgroup_size_control 拡張が 有効な場合にのみ使用しなければなりません。
パラメーター i32 またはu32 に解決されるconst 式またはoverride 式でなければなりません。

値が 2 のべき乗でない場合:

エントリーポイントの workgroup_size の x 次元が subgroup_size 値の倍数でない場合、 パイプライン作成エラーになります。

値が subgroupMaxSize より大きいか、subgroupMinSize より小さい場合、 パイプライン作成エラーになります。

値が subgroupMinSize と subgroupMaxSize の間であっても、レジスター圧力 または特定のハードウェア制限によって、パイプライン作成で未分類エラーが発生する場合があります。

12.15. workgroup_size

workgroup_size_attr :

'@' 'workgroup_size' '(' expression ',' ? ')'

| '@' 'workgroup_size' '(' expression ',' expression ',' ? ')'

| '@' 'workgroup_size' '(' expression ',' expression ',' expression ',' ? ')'

workgroup_size 属性
説明 コンピュートシェーダーのワークグループグリッドの x、y、z 次元を指定します。

最初のパラメーターは x 次元を指定します。 2 番目のパラメーターが指定されている場合は y 次元を指定し、指定されていない場合は 1 とみなされます。 3 番目のパラメーターが指定されている場合は z 次元を指定し、指定されていない場合は 1 とみなされます。

コンピュートシェーダーのエントリーポイント関数にのみ適用しなければなりません。 その他のオブジェクトには適用してはなりません。

パラメーター 1 個、2 個、または 3 個のパラメーターを取ります。

各パラメーターはconst 式またはoverride 式でなければなりません。 すべてのパラメーターは、i32 またはu32 のいずれかの同じ型でなければなりません。

指定されたパラメーターのいずれかが、0 以下の値に評価される const 式である場合、シェーダー作成エラーになります。

指定されたパラメーターのいずれかが 0 以下の値に評価される、 WebGPU API で指定された上限を超える、またはパラメーター値の積が WebGPU API で指定された上限を超える場合、パイプライン作成エラーになります (WebGPU § 3.6.2 制限を参照)。

12.16. シェーダーステージ属性

以下のシェーダーステージ 属性は、 関数を特定のシェーダーステージのエントリー ポイントとして指定します。 これらの属性は関数宣言にのみ適用しなければならず、 1 つの関数には最大 1 つだけ存在できます。 パラメーターは取りません。

12.16.1. vertex

vertex_attr :

'@' 'vertex'

vertex 属性は、関数をレンダー パイプラインの頂点シェーダー ステージのエントリーポイントとして宣言します。

12.16.2. fragment

fragment_attr :

'@' 'fragment'

fragment 属性は、関数をレンダー パイプラインのフラグメントシェーダー ステージのエントリーポイントとして宣言します。

12.16.3. compute

compute_attr :

'@' 'compute'

compute 属性は、関数をコンピュートパイプラインのコンピュートシェーダー ステージのエントリーポイントとして宣言します。

13. エントリーポイント

エントリーポイントは、 特定のシェーダー ステージの処理を実行するユーザー定義 関数です。

13.1. シェーダーステージ

WebGPU は描画またはディスパッチコマンドの形式で GPU に処理を発行します。 これらのコマンドは、シェーダーステージの 入力、出力、および アタッチされたリソースの集合のコンテキストで パイプラインを実行します。

パイプラインは、 GPU 上で実行される処理を、一連の ステージとして記述し、その一部はプログラム可能です。 WebGPU では、描画コマンドまたはディスパッチコマンドの実行をスケジュールする前にパイプラインを作成します。 パイプラインには GPUComputePipeline と GPURenderPipeline の 2 種類があります。

ディスパッチコマンドは、 GPUComputePipeline を使用して、 制御可能な並列度を持つ論理的な 点のグリッド上でコンピュートシェーダー ステージを実行し、 バッファーおよび画像リソースを読み取り、場合によっては更新します。

描画コマンドはGPURenderPipeline を使用して、 他の固定機能ステージの中に 2 つのプログラム可能なステージを含む 多段階処理を実行します:

WebGPU 仕様では、パイプラインについてさらに詳しく説明しています。

WGSL は、パイプラインの プログラム可能部分に対応する 3 つのシェーダー ステージを定義します:

各シェーダーステージには、別の箇所で説明される独自の機能と制約があります。

13.2. エントリーポイント宣言

エントリーポイントを作成するには、 シェーダーステージ属性を持つユーザー定義 関数を宣言します。

WebGPU API でパイプラインを構成する場合、 エントリーポイントの関数名は WebGPU GPUProgrammableStage オブジェクトの entryPoint 属性に対応します。

エントリーポイントの仮 引数は、そのステージのシェーダーステージ入力を表します。 構造体型を使用してユーザー定義入力同士を、任意で組み込み 入力とともにグループ化できます。 各パラメーターはシェーダーステージ入力でなければならないか、 各構造体メンバーがシェーダーステージ入力である構造体型で宣言されなければなりません。

指定されている場合、エントリーポイントの戻り値の 型とその属性は、そのステージのシェーダーステージ出力を表します。 構造体型を使用してユーザー定義出力同士を、任意で組み込み 出力とともにグループ化できます。 存在する場合、戻り値の型とその属性は シェーダーステージ出力でなければならないか、 各構造体メンバーがシェーダーステージ出力である構造体型でなければなりません。

注: コンピュートエントリーポイントは戻り値の型を持ちません。

例: エントリーポイント
@vertex
fn vert_main() -> @builtin(position) vec4<f32> {
  return vec4<f32>(0.0, 0.0, 0.0, 1.0);
}

@fragment
fn frag_main(@builtin(position) coord_in: vec4<f32>) -> @location(0) vec4<f32> {
  return vec4<f32>(coord_in.x, coord_in.y, 0.0, 1.0);
}

@compute @workgroup_size(1)
fn comp_main() { }

シェーダーステージ内の関数の集合は、次の和集合です:

和集合は安定するまで繰り返し適用されます。 有限回の手順で安定します。

13.2.1. エントリーポイントの関数属性

WGSL は、エントリーポイント宣言に適用できる次の属性を定義します:

例: workgroup_size 属性
@compute @workgroup_size(8,4,1)
fn sorter() { }

@compute @workgroup_size(8u)
fn reverser() { }

// パイプラインでオーバーライド可能な定数を使用する。
@id(42) override block_width = 12u;
@compute @workgroup_size(block_width)
fn shuffler() { }

// エラー: workgroup_size はコンピュートシェーダーで指定しなければならない
@compute
fn bad_shader() { }

13.3. シェーダーインターフェイス

シェーダーインターフェイスは、シェーダーがシェーダーステージの外部にあるデータへ 読み取りまたは書き込みのためにアクセスする際に介するオブジェクトと、 シェーダーの構成に使用されるパイプラインでオーバーライド可能な定数の集合です。 インターフェイスには次が含まれます:

宣言 D は、次の場合にシェーダーによって静的にアクセスされるといいます:

注:静的アクセスは、次を考慮して再帰的に定義されます:

これで、シェーダーのインターフェイスを次で構成されるものとして正確に定義できます:

13.3.1. ステージ間入出力インターフェイス

シェーダーステージ入力 は、パイプラインの上流からシェーダーステージに提供されるデータです。 各データは組み込み入力値またはユーザー定義入力のいずれかです。

シェーダーステージ 出力は、パイプライン下流の後続処理にシェーダーが提供するデータです。 各データは組み込み出力値またはユーザー定義出力のいずれかです。

IO 属性は、 オブジェクトをシェーダーステージ入力またはシェーダーステージ出力として確立するため、 または入力や出力のプロパティをさらに記述するために使用されます。 IO 属性は次のとおりです:

13.3.1.1. 組み込み入力と出力

組み込み入力 値は、システムが生成した制御情報へのアクセスを提供します。 エントリーポイントは、同じ組み込み 値名を持つ 2 つの組み込み入力を持ってはなりません。

名前 X、型 TX を持つステージ S の組み込み入力には、 シェーダーステージ S の エントリーポイントの仮引数を介して、 次の 2 つの方法のいずれかでアクセスします:

  1. パラメーターが属性 builtin(X) を持ち、型が TX である。

  2. パラメーターが構造体型を持ち、その構造体メンバーの 1 つが属性 builtin(X) を持ち、型が TX である。

逆に、エントリーポイントのパラメーターまたはパラメーターのメンバーがbuiltin 属性を持つ場合、 対応する builtin はエントリーポイントのシェーダーステージの入力でなければなりません。

組み込み出力 値は、シェーダーがパイプライン内の後続処理段階へ 制御情報を伝えるために使用されます。 エントリーポイントは、同じ組み込み 値名を持つ 2 つの組み込み出力を持ってはなりません。

名前 Y、型 TY を持つステージ S の組み込み出力は、 シェーダーステージ S の エントリーポイントの戻り値を介して、次の 2 つの方法のいずれかで設定されます:

  1. エントリーポイントの戻り値の型 が属性 builtin(Y) を持ち、型が TY である。

  2. エントリーポイントの戻り値の 型が構造体型を持ち、その構造体メンバーの 1 つが属性 builtin(Y) を持ち、型が TY である。

逆に、エントリーポイントの戻り値の型または戻り値の型のメンバーがbuiltin 属性を持つ場合、 対応する builtin はエントリーポイントのシェーダーステージの出力でなければなりません。

注: position 組み込み値は、 頂点シェーダーの出力であると同時に、フラグメントシェーダーへの入力でもあります。

組み込み入力値と組み込み出力値を総称して組み込み値と呼びます。

次の表は、利用可能な組み込み値をまとめたものです。 各項目は組み込み値の組み込み値名トークンです。 各項目については後続の節で詳しく説明します。

組み込み入力値と出力値
名前 ステージ 方向 型 拡張
vertex_index vertex input u32
instance_index vertex input u32
clip_distances vertex output array<f32, N> (N ≤ 8) clip_distances
position vertex output vec4<f32>
fragment input vec4<f32>
front_facing fragment input bool
frag_depth fragment output f32
primitive_index fragment input u32 primitive_index
sample_index fragment input u32
sample_mask fragment input u32
fragment output u32
local_invocation_id compute input vec3<u32>
local_invocation_index compute input u32
global_invocation_id compute input vec3<u32>
global_invocation_index compute input u32 linear_indexing
workgroup_id compute input vec3<u32>
workgroup_index compute input u32 linear_indexing
num_workgroups compute input vec3<u32>
subgroup_invocation_id compute input u32 subgroups
fragment
subgroup_size compute input u32 subgroups
fragment
subgroup_id compute input u32 subgroups and subgroup_id
num_subgroups compute input u32 subgroups and subgroup_id
例: 組み込み値の宣言
 struct VertexOutput {
   @builtin(position) my_pos: vec4<f32>,
   @builtin(clip_distances) my_clip_distances: array<f32, 8>,
 }

 @vertex
 fn vs_main(
   @builtin(vertex_index) my_index: u32,
   @builtin(instance_index) my_inst_index: u32,
 ) -> VertexOutput {}

 struct FragmentOutput {
   @builtin(frag_depth) depth: f32,
   @builtin(sample_mask) mask_out: u32
 }

 @fragment
 fn fs_main(
   @builtin(front_facing) is_front: bool,
   @builtin(position) coord: vec4<f32>,
   @builtin(sample_index) my_sample_index: u32,
   @builtin(sample_mask) mask_in: u32,
 ) -> FragmentOutput {}

 @compute @workgroup_size(64)
 fn cs_main(
   @builtin(local_invocation_id) local_id: vec3<u32>,
   @builtin(local_invocation_index) local_index: u32,
   @builtin(global_invocation_id) global_id: vec3<u32>,
) {}
13.3.1.1.1. clip_distances
名前 clip_distances
ステージ vertex
型 array<f32, N>
方向 出力
説明 配列内の各値は、ユーザー定義クリップ平面までの距離を表します。クリップ距離が 0 の場合、頂点は平面上にあり、正の距離は頂点がクリップ 半空間の内側にあることを、負の距離は頂点がクリップ半空間の外側にあることを意味します。clip_distances の配列 サイズは ≤ 8 でなければなりません。 WebGPU § 23.2.4 プリミティブクリッピングを参照してください。
13.3.1.1.2. frag_depth
名前 frag_depth
ステージ fragment
型 f32
方向 出力
説明 ビューポート深度範囲内の、更新されたフラグメント深度。

WebGPU § 3.3 座標系を参照してください。

fragment_depth 機能がサポートされている場合、 builtin 属性には、深度モードを指定するための任意の 2 番目の パラメーターを指定できます:

フラグメントの元の深度は、そのフラグメントの RasterizationPoint の depth プロパティです。

シェーダーが深度モードの約束に違反する深度値を返した場合、代わりに 不定の深度値が使用されることがあります。

@fragment
fn main() -> @builtin(frag_depth, greater) f32 {
    return 1.0f;
}
13.3.1.1.3. front_facing
名前 front_facing
ステージ fragment
型 bool
方向 入力
説明 現在のフラグメントが前面プリミティブ上にある場合は True。 それ以外の場合は False。
13.3.1.1.4. global_invocation_id
名前 global_invocation_id
ステージ compute
型 vec3<u32>
方向 入力
説明 現在の呼び出しのグローバル呼び出し ID、すなわち コンピュート シェーダーグリッド内での位置です。global_invocation_id の値は、 workgroup_id * workgroup_size + local_invocation_id に等しくなります。
13.3.1.1.5. global_invocation_index
名前 global_invocation_index
ステージ compute
型 u32;
方向 入力
説明 現在の呼び出しのグローバル呼び出しインデックス、すなわち コンピュートシェーダーグリッド内での線形位置です。global_invocation_index の値は次に等しくなります:

global_invocation_id.x +
(global_invocation_id.y * workgroup_size.x * num_workgroups.x) +
(global_invocation_id.z * workgroup_size.x * num_workgroups.x * workgroup_size.y * num_workgroups.y)

注: ディスパッチされる ワークグループ数によってこの値がu32 型の範囲を超える場合、ディスパッチは失敗します:
  • dispatchWorkgroups の場合、GPUComputePassEncoder は無効化されます。

  • dispatchWorkgroupsIndirect の場合、ディスパッチは実行されません。

13.3.1.1.6. instance_index
名前 instance_index
ステージ vertex
型 u32
方向 入力
説明 現在の API レベルの描画コマンド内における現在の頂点のインスタンスインデックス。

最初のインスタンスのインデックスは、直接指定されたか間接的に指定されたかにかかわらず、 描画の firstInstance 引数に等しくなります。 描画内の追加のインスタンスごとに、インデックスは 1 ずつ増加します。

13.3.1.1.7. local_invocation_id
名前 local_invocation_id
ステージ compute
型 vec3<u32>
方向 入力
説明 現在の呼び出しのローカル呼び出し ID、すなわち ワークグループ グリッド内での位置です。
13.3.1.1.8. local_invocation_index
名前 local_invocation_index
ステージ compute
型 u32
方向 入力
説明 現在の呼び出しのローカル呼び出しインデックスであり、 ワークグループグリッド内における呼び出しの位置を線形化したインデックスです。
13.3.1.1.9. num_workgroups
名前 num_workgroups
ステージ compute
型 vec3<u32>
方向 入力
説明 API によってディスパッチされたコンピュート シェーダーのディスパッチサイズ、 vec3<u32>(group_count_x, group_count_y, group_count_z)。
13.3.1.1.10. position
名前 position
ステージ vertex
型 vec4<f32>
方向 出力
説明 クリップ空間座標における、現在の頂点のクリップ位置。

出力値 (x,y,z,w) は、WebGPU の正規化デバイス座標で (x/w, y/w, z/w) に対応します。

WebGPU § 3.3 座標系およびWebGPU § 23.2.4 プリミティブクリッピングを参照してください。

w 座標が 0 の場合、動的エラー が発生します。

名前 position
ステージ fragment
型 vec4<f32>
方向 入力
説明
現在のフラグメントラスタライズ点の入力位置。

rp をフラグメントのRasterizationPoint とします。
vp を描画コマンドに対して有効な [[viewport]] とします。
そして fp を、計算されたフラグメントラスタライズ点の入力位置とします。

概略的には:

fp.xy = rp.destination.position
fp.z = rp.depth
fp.w = rp.perspectiveDivisor

より詳しくは:

  • fp.x と fp.y は、フレームバッファー内にある 現在のフラグメントラスタライズ点の位置の、補間された x 座標と y 座標です。

    フレームバッファーは、左上が (0.0,0.0)、 右下が (vp.width, vp.height) の 2 次元ピクセルグリッドです。 各ピクセルは x 次元および y 次元のそれぞれで 1.0 単位の範囲を持ち、 ピクセル中心は整数座標から (0.5,0.5) オフセットした位置にあります。

  • fp.z は、現在のフラグメントラスタライズ 点の補間された深度です。 たとえば:

    • 正規化デバイス座標における深度 0 は fp.z = vp.minDepth に対応し、

    • 正規化デバイス座標における深度 1 は fp.z = vp.maxDepth に対応します。

  • fp.w はフラグメントラスタライズ点の透視除数であり、 1.0 ÷ vertex_w の補間値です。 ここで vertex_w は頂点 シェーダーのposition 出力の w 成分です。

WebGPU § 3.3 座標系およびWebGPU § 23.2.5 ラスタライズを参照してください。

13.3.1.1.11. primitive_index
名前 primitive_index
ステージ fragment
型 u32
方向 入力
説明 現在の描画操作の開始以降、現在のインスタンスについて処理されたプリミティブ数に基づく プリミティブごとのインデックス。0 から始まり、各 点、線、または三角形プリミティブが処理されるたびに 1 ずつ増加します。描画される各インスタンス間で 0 にリセットされます。 プリミティブ再開値を使用してストリッププリミティブを再開しても、 プリミティブインデックスには影響しません。このインデックスは、プリミティブのすべてのフラグメントで一様です。
13.3.1.1.12. sample_index
名前 sample_index
ステージ fragment
型 u32
方向 入力
説明 現在のフラグメントラスタライズ点のサンプルインデックス。 値は 0 以上、 sampleCount-1 以下です。ここで sampleCount は GPU レンダーパイプラインに指定されたサンプル count です。 この属性が適用されている場合、フラグメントシェーダーの効果が sample_index の値に基づいて変化するなら、フラグメントシェーダーは サンプルごとに 1 回呼び出されます。

WebGPU § 10.3 GPURenderPipelineを参照してください。

13.3.1.1.13. sample_mask
名前 sample_mask
ステージ fragment
型 u32
方向 入力
説明 現在のフラグメントのサンプルカバレッジビットマスク。

ビットは半開区間 [0, sampleCount) のサンプルインデックスによって索引付けされます。 ここで sampleCount は GPU レンダーパイプラインに指定されたサンプル count です。

サンプルがレンダリングされているプリミティブによって覆われている場合にのみ、ビットは 1 に設定されます。 インデックスが sampleCount 以上のビットは常に 0 に設定されます。

ビットマスクには、次の 2 つの可能な値があります:

  • ビットマスクには、フラグメントによって覆われるすべてのサンプルについて 1 ビットが設定されます。 この場合、ビットマスクはフラグメントの RasterizationPoint coverageMask に等しくなります。

  • ビットマスクには 1 ビットだけが設定され、現在のフラグメントシェーダー呼び出しによって 処理されているサンプルに対応します。 つまり、sample_index 組み込み入力を使用した場合と同様に、ビットマスクは (1 << sample_index) です。

注: sampleCount = 1 の場合、 これら 2 つの場合は同じです。

注: これは sampleCount > 1 の場合の 既知の移植性上の問題です。 一部のデバイスは完全なカバレッジマスクを生成します。他のデバイスは単一ビットマスクを生成します。

WebGPU § 23.2.10 サンプル単位シェーディングおよびWebGPU § 23.2.11 サンプル マスキングを参照してください。

名前 sample_mask
ステージ fragment
型 u32
方向 出力
説明 現在のフラグメントのサンプルカバレッジマスク制御。この変数に最後に 書き込まれた値がシェーダー出力マスクになります。書き込まれた値の 0 ビットにより、カラーアタッチメント内の対応するサンプルが 破棄されます。

WebGPU § 23.2.11 サンプルマスキングを参照してください。

13.3.1.1.14. vertex_index
名前 vertex_index
ステージ vertex
型 u32
方向 入力
説明 現在の API レベルの描画コマンド内における現在の頂点のインデックスで、 描画のインスタンス化とは無関係です。

非インデックス描画の場合、最初の頂点のインデックスは、直接指定されたか間接的に指定されたかにかかわらず、 描画の firstVertex 引数に等しくなります。 描画インスタンス内の追加の頂点ごとにインデックスは 1 ずつ増加します。

インデックス描画の場合、インデックスは 頂点のインデックスバッファーエントリーに、直接指定されたか 間接的に指定されたかにかかわらず描画の baseVertex 引数を加えた値に等しくなります。

13.3.1.1.15. workgroup_id
名前 workgroup_id
ステージ compute
型 vec3<u32>
方向 入力
説明 現在の呼び出しのワークグループ ID、すなわち、 全体のコンピュートシェーダーグリッド内における ワークグループの位置です。

同じワークグループ内のすべての呼び出しは、同じワークグループ ID を持ちます。

ワークグループ ID の範囲は (0,0,0) から (group_count_x - 1, group_count_y - 1, group_count_z - 1) です。

13.3.1.1.16. workgroup_index
名前 workgroup_index
ステージ compute
型 u32
方向 入力
説明 現在の呼び出しのワークグループインデックス、すなわち、 全体のコンピュートシェーダーグリッド内における ワークグループの線形位置です。

同じワークグループ内のすべての呼び出しは、同じワークグループインデックスを持ちます。

注: ディスパッチされた ワークグループ数によってこの値がu32 型の範囲を超える場合、ディスパッチは失敗します:
  • dispatchWorkgroups の場合、GPUComputePassEncoder は無効化されます。

  • dispatchWorkgroupsIndirect の場合、ディスパッチは実行されません。

13.3.1.1.17. subgroup_invocation_id
名前 subgroup_invocation_id
ステージ compute または fragment
型 u32
方向 入力
説明 現在の呼び出しのサブグループ呼び出し ID。

ID は [0, subgroup_size - 1] の範囲内です。

compute シェーダーでは、ID は 0 から始まり密です。 つまり、コンピュートシェーダーが実行を開始したとき、各サブグループ内で:

  • 1 つの呼び出しが subgroup_invocation_id = 0 を持ち、かつ

  • サブグループに subgroup_invocation_id = k を持つ呼び出しがある場合、 すべての 0 ≤ j < k について、サブグループには subgroup_invocation_id = j を持つ呼び出しがあります。

注: フラグメントシェーダーでのサブグループ呼び出しのインデックス付けは 密でない場合があります。実装は より小さい番号の ID の一部をヘルパー呼び出しに割り当てる場合があります。

13.3.1.1.18. subgroup_size
名前 subgroup_size
ステージ compute または fragment
型 u32
方向 入力
説明 現在の呼び出しのサブグループのサブグループサイズ。

subgroup_size 属性を持つコンピュートシェーダーでは、この値は 指定された属性値に等しくなります。

13.3.1.1.19. subgroup_id
名前 subgroup_id
ステージ compute
型 u32
方向 入力
説明 現在の呼び出しのワークグループ内における、 現在の呼び出しのサブグループのサブグループ ID。

ID は [0, num_subgroups - 1] の範囲内です。

13.3.1.1.20. num_subgroups
名前 num_subgroups
ステージ compute
型 u32
方向 入力
説明 現在の呼び出しのワークグループ内の サブグループの数。
13.3.1.2. ユーザー定義の入力と出力

ユーザー定義データは、パイプラインの開始時に入力として渡したり、 パイプラインのステージ間で渡したり、パイプラインの終端から出力したりできます。

各ユーザー定義 入力データおよび ユーザー定義 出力データは、次を満たさなければなりません:

compute シェーダーはユーザー定義の 入力または出力を持ってはなりません。

13.3.1.3. 入出力ロケーション

各入出力ロケーションには、最大 16 バイトの値を格納できます。 型のバイトサイズは、§ 14.4.1 アラインメントとサイズの SizeOf 列を使用して定義されます。 たとえば、浮動小数点値の 4 成分ベクトルは 1 つのロケーションを占有します。

IO ロケーションはlocation 属性によって指定されます。

各ユーザー定義入力および出力には、明示的に指定された IO ロケーションがなければなりません。 エントリーポイント IO 内の各構造体メンバーは、組み込み値 (§ 13.3.1.1 組み込み入力と出力を参照)であるか、ロケーションが割り当てられているかの いずれかでなければなりません。

WGSL モジュールで定義された各エントリーポイントについて、inputs をそのシェーダーステージ入力の集合 (すなわち、仮引数のロケーション、または構造体型の仮引数のメンバーのロケーション)とします。
WGSL モジュールで定義された各構造体型 S(シェーダーステージの入力または 出力で使用されるものだけではありません)について、 members をlocation 属性を持つ S のメンバーの集合とします。

注: ロケーション番号は入力と 出力で別々です: エントリーポイントのシェーダーステージ入力のロケーション番号は、 エントリーポイントのシェーダーステージ出力のロケーション番号と競合しません。

注: エントリーポイントの出力内でロケーションの 重複を防ぐための追加規則は必要ありません。 出力が構造体の場合、上記の最初の規則が重複を防ぎます。 それ以外の場合、出力はスカラーまたはベクトルであり、割り当てられるロケーションは 1 つだけです。

注: エントリーポイントで使用可能なロケーション数は WebGPU API によって定義されます。

例: location 属性の適用
struct A {
  @location(0) x: f32,
  // ロケーションは 16 バイトだが、x と y はロケーションを共有できない
  @location(1) y: f32
}

// in1 はロケーション 0 と 1 を占有する。
// in2 はロケーション 2 を占有する。
// 戻り値はロケーション 0 を占有する。
@fragment
fn fragShader(in1: A, @location(2) in2: f32) -> @location(0) vec4<f32> {
 // ...
}

ユーザー定義 IO は、同じ構造体内で組み込み値と混在させることができます。たとえば、

例: 組み込み値とユーザー定義 IO の混在
// 組み込み入力とユーザー定義入力を混在させる。
struct MyInputs {
  @location(0) x: vec4<f32>,
  @builtin(front_facing) y: bool,
  @location(1) @interpolate(flat) z: u32
}

struct MyOutputs {
  @builtin(frag_depth) x: f32,
  @location(0) y: vec4<f32>
}

@fragment
fn fragShader(in1: MyInputs) -> MyOutputs {
  // ...
}
例: 無効なロケーション割り当て
struct A {
  @location(0) x: f32,
  // 無効。x と y はロケーションを共有できない。
  @location(0) y: f32
}

struct B {
  @location(0) x: f32
}

struct C {
  // 無効。ユーザー定義 IO を持つ構造体はネストできない。
  b: B
}

struct D {
  x: vec4<f32>
}

@fragment
// 無効。location は構造体型に適用できない。
fn fragShader1(@location(0) in1: D) {
  // ...
}

@fragment
// 無効。in1 と in2 はロケーションを共有できない。
fn fragShader2(@location(0) in1: f32, @location(0) in2: f32) {
  // ...
}

@fragment
// 無効。location は構造体に適用できない。
fn fragShader3(@location(0) in1: vec4<f32>) -> @location(0) D {
  // ...
}
13.3.1.4. 補間

作成者はinterpolate 属性を使用して、 ユーザー定義 IO データをどのように補間するかを制御できます。 WGSL では、補間の 2 つの側面、すなわち補間の型と 補間のサンプリングを制御できます。

補間型は、次の 補間型名トークンのいずれかでなければなりません:

perspective

値は透視補正を行う方法で補間されます。

linear

値は透視補正を行わない線形な方法で補間されます。

flat

値は補間されません。

補間 サンプリングは、次の 補間サンプリング名トークンのいずれかでなければなりません:

center

補間はピクセルの中心で行われます。

centroid

補間は、現在のプリミティブ内でフラグメントによって覆われる すべてのサンプルの内部にある点で行われます。 この値はプリミティブ内のすべてのサンプルで同じです。

sample

補間はサンプルごとに行われます。 この属性が適用されると、fragment シェーダーは サンプルごとに 1 回呼び出されます。

first

値はプリミティブの最初の頂点によって提供されます。

either

値はプリミティブの最初の頂点または最後の頂点によって提供されます。 値が最初と最後のどちらの頂点から来るかは実装依存です。

スカラー型またはベクトル浮動小数点型のユーザー定義 IO について:

スカラー型またはベクトル整数型のユーザー定義vertex 出力およびfragment 入力は、常に補間型 flat を指定しなければなりません。

ステージ間インターフェイス検証は、 レンダー パイプライン内で、 各ユーザー定義fragment 入力の補間プロパティが、 同じlocation 割り当てを持つ頂点出力の補間プロパティと一致することを検査します。 一致しない場合、パイプライン作成エラーが発生します。

13.3.2. リソースインターフェイス

リソースは、 シェーダーステージの外部のデータへのアクセスを提供するオブジェクトであり、 override 宣言でも、即時データ変数でも、 シェーダーステージ入力または出力でもありません。 リソースはシェーダーのすべての呼び出しによって共有されます。

リソースには 4 種類あります:

シェーダーの リソースインターフェイスは、 シェーダーステージ内の関数によって静的にアクセスされる モジュールスコープのリソース変数の集合です。

各リソース変数は、group およびbinding 属性の両方を指定して宣言しなければなりません。 シェーダーのステージと組み合わせることで、これらはシェーダーのパイプライン上における リソースのバインディングアドレスを識別します。 WebGPU § 8.3 GPUPipelineLayoutを参照してください。

即時データ変数は group またはbinding 属性を使用しません。

シェーダー内の異なる 2 つのリソース変数は、 ペアとして考えたとき、同じgroup 値およびbinding 値を持っては なりません。

13.3.3. リソースレイアウトの互換性

WebGPU は、シェーダーのリソースインターフェイスが、そのシェーダーを使用するパイプラインのレイアウトと 一致することを要求します。

リソースインターフェイス内の WGSL 変数が、互換性のない WebGPU バインディングメンバーまたはバインディング型に バインドされている場合、パイプライン作成エラーです。 互換性は次の表で定義されます。

WebGPU バインディング型の互換性
WGSL リソース WebGPU バインディングメンバー WebGPU バインディング型
uniform バッファー buffer GPUBufferBindingType "uniform"
storage バッファー (read_write アクセス) "storage"
storage バッファー (read アクセス) "read-only-storage"
sampler sampler GPUSamplerBindingType "filtering"
"non-filtering"
sampler_comparison "comparison"
サンプル済みテクスチャー、 深度 テクスチャー、または マルチサンプルテクスチャー texture GPUTextureSampleType "float"
"unfilterable-float"
"sint"
"uint"
"depth"
書き込み専用ストレージテクスチャー storageTexture GPUStorageTextureAccess "write-only"
読み書きストレージテクスチャー "read-write"
読み取り専用ストレージテクスチャー "read-only"
外部テクスチャー externalTexture (該当なし)

インターフェイス検証要件については、WebGPU API 仕様を参照してください。

13.3.4. バッファーバインディングによるランタイムサイズ配列の要素数の決定

storage バッファー 変数がランタイムサイズ配列を含む場合、その配列内の要素数は 対応する resource のサイズから決定されます:

より詳しくは、型 RAT のランタイムサイズ配列のNRuntime は:

truncate((EBBS − array_offset) ÷ array_stride)。ここで:

シェーダーは arrayLength 組み込み関数を介してNRuntime を計算できます。

注: このアルゴリズムには曖昧さがありません: ランタイムサイズ配列がより大きな型の一部である場合、構造体の最後の要素としてのみ現れることができ、 その構造体自体を外側の配列または構造体の一部にすることはできません。

NRuntime は 対応するバッファーバインディングのサイズによって決定され、そのサイズは描画 またはディスパッチコマンドごとに異なる場合があります。

WebGPU の検証規則により、1 ≤ NRuntime が保証されます。

次のコード例では:
例: 単純なランタイムサイズ配列の要素数
@group(0) @binding(1) var<storage> weights: array<f32>;

次の表は、対応する実効バッファーバインディングサイズに基づく、 weights 変数のNRuntime の例を示します。

単純なランタイムサイズ配列の要素数の例
実効バッファーバインディングサイズ weights 変数の NRuntime 計算
1024 256 truncate( 1024 ÷ 4 )
1025 256 truncate( 1025 ÷ 4 )
1026 256 truncate( 1026 ÷ 4 )
1027 256 truncate( 1027 ÷ 4 )
1028 257 truncate( 1028 ÷ 4 )
次のコード例では:
例: 複雑なランタイムサイズ配列の要素数
struct PointLight {                          //             align(16) size(32)
  position : vec3f,                          // offset(0)   align(16) size(12)
  // -- 暗黙のメンバーアラインメントパディング -- // offset(12)            size(4)
  color : vec3f,                             // offset(16)  align(16) size(12)
  // -- 暗黙の構造体サイズパディング --      // offset(28)            size(4)
}

struct LightStorage {                        //             align(16)
  pointCount : u32,                          // offset(0)   align(4)  size(4)
  // -- 暗黙のメンバーアラインメントパディング -- // offset(4)             size(12)
  point : array<PointLight>,                 // offset(16)  align(16) elementsize(32)
}

@group(0) @binding(1) var<storage> lights : LightStorage;

次の表は、lights 変数の point メンバーについてのNRuntime の例を示します。

複雑なランタイムサイズ配列の要素数の例
実効バッファーバインディングサイズ lights 変数の point メンバーの NRuntime 計算
1024 31 truncate( ( 1024 - 16 ) ÷ 32) )
1025 31 truncate( ( 1025 - 16 ) ÷ 32) )
1039 31 truncate( ( 1039 - 16 ) ÷ 32) )
1040 32 truncate( ( 1040 - 16 ) ÷ 32) )

14. メモリー

WGSL では、格納可能型の値を 後で取得するためにメモリーへ格納できます。 この節では、メモリーの構造と、メモリーへアクセスする操作のセマンティクスについて説明します。 メモリーに配置できる値の型、および メモリーアクセスの実行に使用される型については、§ 6.5 メモリービューを参照してください。

14.1. メモリー位置

メモリーは、個別のメモリー位置の集合から構成されます。 各メモリー位置のサイズは 8 ビットです。 メモリーに影響する操作は、1 つ以上のメモリー位置の集合と相互作用します。 複合値に対するメモリー操作は、 パディングのメモリー位置へアクセスしません。 したがって、操作によってアクセスされるメモリー位置の集合は連続していない場合があります。

2 つのメモリー位置の集合は、それらのメモリー位置集合の共通部分が空でない場合、 重複するといいます。

14.2. メモリーアクセスモード

メモリーアクセスは、 メモリー位置に作用する操作です。

1 つの操作で、読み取り、書き込み、または読み書きの両方を行うことができます。

特定のメモリー位置では、特定の種類のアクセスだけがサポートされる場合があり、 これはメモリーのアクセス モードとして表されます。

アクセスモード
アクセスモード サポートされるアクセス
read 読み取りアクセスをサポートしますが、書き込みはサポートしません。
write 書き込みアクセスをサポートしますが、読み取りはサポートしません。
read_write 読み取りアクセスと書き込みアクセスの両方をサポートします。

WGSL は列挙子 read、 write、および read_write を事前宣言します。

14.3. アドレス空間

メモリー位置はアドレス空間に分割されます。 各アドレス空間には、可変性、可視性、格納できる値、 およびそのアドレス空間で変数を使用する方法を決定する固有のプロパティがあります。 詳細については、§ 7 変数宣言と値宣言を参照してください。

特定のメモリー ビューのアクセスモードは、多くの場合コンテキストによって決定されます:

storage アドレス空間は、read および read_write アクセス モードの両方をサポートします。 その他の各アドレス空間は 1 つのアクセスモードだけをサポートします。 各アドレス空間のデフォルトアクセスモードを次の 表に示します。

アドレス空間
アドレス空間 呼び出し間での共有 デフォルトアクセスモード 注記
function 同じ呼び出しのみ read_write
private 同じ呼び出しのみ read_write
workgroup 同じコンピュートシェーダーのワークグループ内の呼び出し read_write 最外配列の要素数は、 パイプラインでオーバーライド可能な定数である場合があります。
uniform 同じシェーダーステージ内の呼び出し read uniform バッファー変数用
storage 同じシェーダーステージ内の呼び出し read storage バッファー変数用
immediate 同じシェーダーステージ内の呼び出し read 即時 データ変数用。
各エントリーポイントは、 最大 1 つの immediate 変数に静的にアクセスできます。
handle 同じシェーダーステージ内の呼び出し read サンプラー およびテクスチャー 変数用。

WGSL は handle アドレス空間を除く各アドレス空間について、 列挙子を事前宣言します。

workgroup アドレス空間の変数は、 コンピュートシェーダーステージ内でのみ静的に アクセスしなければなりません。

storage アドレス空間の変数(storage バッファー)は、 アクセスモードがread の場合に限り、頂点シェーダーステージによって静的に アクセスできます。 格納型が write またはread_write アクセスモードを持つストレージテクスチャー である変数は、頂点シェーダーステージによって静的に アクセスできません。 WebGPU createBindGroupLayout()を参照してください。

注: 各アドレス空間は異なるパフォーマンス 特性を持つ場合があります。

WGSL ソースで変数宣言またはポインター型を記述する場合:

14.4. メモリーレイアウト

WGSL における型のレイアウトはアドレス空間に依存しません。 ただし厳密には、そのレイアウトを観測できるのはホスト共有可能な バッファーだけです。 uniform バッファー変数およびstorage バッファー変数は、 メモリー内のバイト列として編成された大量のデータを共有するために使用されます。 バッファーは CPU と GPU の間、パイプライン内の異なるシェーダーステージ間、 または異なるパイプライン間で共有されます。

バッファーデータは再フォーマットや変換を行わずに共有されるため、 バッファーの生成側と消費側でメモリーレイアウト、すなわち バッファー内のバイトが型付き WGSL 値としてどのように編成されるかについて合意していない場合、 動的エラーです。 これらのバイトは、共通のベース 位置を基準とする値のメモリー 位置です。

バッファー変数の格納型は、 以下で説明するように、完全に具体化されたメモリーレイアウトを持つ ホスト共有可能型でなければなりません。

各バッファー変数は、 uniform または storage アドレス空間のいずれかで宣言しなければなりません。

型のメモリーレイアウトが重要になるのは、次を含む式を評価するときだけです:

8 ビットのバイトはホスト共有可能メモリーの最も基本的な単位です。 この節で定義される用語は、8 ビットバイトの個数を表します。

次の表記を使用します。ここで T はホスト共有可能または固定フットプリント型、 S はホスト共有可能または固定フットプリント構造体型、 A はホスト共有可能または固定フットプリントの配列、もしくはランタイムサイズ配列です:

14.4.1. アラインメントとサイズ

各ホスト共有可能または固定フットプリントデータ型 T はサイズを持ちます。 バッファー型を除き、 各ホスト共有可能型または固定フットプリント型はアラインメントを持ちます。

型のアラインメントは、 その型の値をメモリー内のどこに配置できるかを示す制約であり、整数として表されます: 型のアラインメントは、その型の値の先頭メモリー位置のバイトアドレスを 余りなく割り切らなければなりません。 アラインメントにより、値へのアクセスにより効率的なハードウェア命令を使用できるようになったり、 特定のアドレス空間におけるより厳しいハードウェア要件を満たしたりできます。 (アドレス空間レイアウト制約を参照)。

注: 各アラインメント値は、構成上常に 2 のべき乗です。

型または構造体メンバーのバイトサイズは、 型または構造体メンバーの値を格納する目的で ホスト共有可能メモリーに予約される連続バイト数です。 サイズには型の末尾にあるアドレス指定不能なパディングが含まれる場合があります。 そのため、値のロードおよびストアでアクセスされるメモリー位置の数は、 値のサイズより少ない場合があります。

ホスト共有可能および固定フットプリント型のアラインメントとサイズは、 次の表で再帰的に定義されます:

ホスト共有可能型および固定フットプリント型のアラインメントとサイズ
ホスト共有可能型または固定フットプリント型 T AlignOf(T) SizeOf(T)
bool
注記を参照してください。
4 4
i32、u32、またはf32 4 4
f16 2 2
atomic<T> 4 4
vec2<T>, T はbool、i32、u32、またはf32 8 8
vec2<f16> 4 4
vec3<T>, T はbool、i32、u32、 またはf32 16 12
vec3<f16> 8 6
vec4<T>, T はbool、i32、u32、 またはf32 16 16
vec4<f16> 8 8
matCxR (列優先)

(一般形)

AlignOf(vecR) SizeOf(array<vecR, C>)
mat2x2<f32> 8 16
mat2x2<f16> 4 8
mat3x2<f32> 8 24
mat3x2<f16> 4 12
mat4x2<f32> 8 32
mat4x2<f16> 4 16
mat2x3<f32> 16 32
mat2x3<f16> 8 16
mat3x3<f32> 16 48
mat3x3<f16> 8 24
mat4x3<f32> 16 64
mat4x3<f16> 8 32
mat2x4<f32> 16 32
mat2x4<f16> 8 16
mat3x4<f32> 16 48
mat3x4<f16> 8 24
mat4x4<f32> 16 64
mat4x4<f16> 8 32
struct S、 メンバー M1...MN を持つ max(AlignOfMember(S,1), ... , AlignOfMember(S,N))
roundUp(AlignOf(S), justPastLastMember)

ここで justPastLastMember = OffsetOfMember(S,N) + SizeOfMember(S,N)
array<E, N>
AlignOf(E) N × roundUp(AlignOf(E), SizeOf(E))
array<E>
AlignOf(E) NRuntime × roundUp(AlignOf(E),SizeOf(E))

ここで NRuntime は T の実行時に決定される要素数
buffer<N> 該当なし N
buffer 該当なし アタッチされた WebGPU GPUBuffer のサイズ

注: buffer 型は他のいかなる型にも 含めることができないため、そのアラインメントは関係ありません。

注: 多くの GPU は、潜在的なデータ競合を導入せずに 1 バイトの書き込みを実装できません。 bool 値が 4 バイトを占有し、4 バイトアラインメントを持つと指定することで、 実装はデータ競合を導入せずにメモリー内で隣接するブール値をサポートできます。

14.4.2. 構造体メンバーのレイアウト

構造体の内部レイアウトは、 そのメンバーのサイズとアラインメントから計算されます。 デフォルトでは、メンバーのアラインメント要件を満たしながら、 メンバーは順序どおり、重複なく、密に配置されます。

このデフォルトの内部レイアウトは、次のレイアウト属性を使用して上書きできます:

構造体型 S の i 番目のメンバーにはサイズとアラインメントがあり、 それぞれ SizeOfMember(S, i) およびAlignOfMember(S, i) と表記します。 メンバーのサイズとアラインメントは、§ 14.4.4 値の内部レイアウトで説明するように、 構造体の先頭から各メンバーまでのバイトオフセットを計算するために使用されます。

S の i 番目のメンバーが属性size(k) を持つ場合、 SizeOfMember(S, i) は k です。 それ以外の場合、メンバーの型を T とすると、 SizeOf(T) です。
S の i 番目のメンバーが属性align(k) を持つ場合、 AlignOfMember(S, i) は k です。 それ以外の場合、メンバーの型を T とすると、 AlignOf(T) です。

構造体メンバーにsize 属性が適用されている場合、その 値はメンバー型のサイズ以上でなければなりません:

SizeOfMember(S, i) ≥ SizeOf(T)
ここで T は S の i 番目のメンバーの型です。

最初の構造体メンバーの、構造体の先頭からのバイトオフセットは常に 0 です:

OffsetOfMember(S, 1) = 0

後続の各メンバーは、メンバー型のアラインメントを満たし、 かつ前のメンバーとの重複を避ける最小のオフセットに配置されます。 各メンバーインデックス i > 1 について:

OffsetOfMember(S, i) = roundUp(AlignOfMember(S, i ), OffsetOfMember(S, i-1) + SizeOfMember(S, i-1))
例: 暗黙のメンバーサイズとアラインメントを使用する構造体のレイアウト
struct A {                                     //             align(8)  size(24)
    u: f32,                                    // offset(0)   align(4)  size(4)
    v: f32,                                    // offset(4)   align(4)  size(4)
    w: vec2<f32>,                              // offset(8)   align(8)  size(8)
    x: f32                                     // offset(16)  align(4)  size(4)
    // -- 暗黙の構造体サイズパディング --      // offset(20)            size(4)
}

struct B {                                     //             align(16) size(160)
    a: vec2<f32>,                              // offset(0)   align(8)  size(8)
    // -- 暗黙のメンバーアラインメントパディング -- // offset(8)             size(8)
    b: vec3<f32>,                              // offset(16)  align(16) size(12)
    c: f32,                                    // offset(28)  align(4)  size(4)
    d: f32,                                    // offset(32)  align(4)  size(4)
    // -- 暗黙のメンバーアラインメントパディング -- // offset(36)            size(4)
    e: A,                                      // offset(40)  align(8)  size(24)
    f: vec3<f32>,                              // offset(64)  align(16) size(12)
    // -- 暗黙のメンバーアラインメントパディング -- // offset(76)            size(4)
    g: array<A, 3>,    // element stride 24       offset(80)  align(8)  size(72)
    h: i32                                     // offset(152) align(4)  size(4)
    // -- 暗黙の構造体サイズパディング --      // offset(156)           size(4)
}

@group(0) @binding(0)
var<storage,read_write> storage_buffer: B;
例: 明示的なメンバーサイズとアラインメントを持つ構造体のレイアウト
struct A {                                     //             align(8)  size(32)
    u: f32,                                    // offset(0)   align(4)  size(4)
    v: f32,                                    // offset(4)   align(4)  size(4)
    w: vec2<f32>,                              // offset(8)   align(8)  size(8)
    @size(16) x: f32                           // offset(16)  align(4)  size(16)
}

struct B {                                     //             align(16) size(208)
    a: vec2<f32>,                              // offset(0)   align(8)  size(8)
    // -- 暗黙のメンバーアラインメントパディング -- // offset(8)             size(8)
    b: vec3<f32>,                              // offset(16)  align(16) size(12)
    c: f32,                                    // offset(28)  align(4)  size(4)
    d: f32,                                    // offset(32)  align(4)  size(4)
    // -- 暗黙のメンバーアラインメントパディング -- // offset(36)            size(12)
    @align(16) e: A,                           // offset(48)  align(16) size(32)
    f: vec3<f32>,                              // offset(80)  align(16) size(12)
    // -- 暗黙のメンバーアラインメントパディング -- // offset(92)            size(4)
    g: array<A, 3>,    // element stride 32       offset(96)  align(8)  size(96)
    h: i32                                     // offset(192) align(4)  size(4)
    // -- 暗黙の構造体サイズパディング --      // offset(196)           size(12)
}

@group(0) @binding(0)
var<uniform> uniform_buffer: B;

14.4.3. 配列レイアウトの例

例: 固定サイズ配列のレイアウト例
// 次の配列:
//   - アラインメントは 4 = AlignOf(f32)
//   - 要素ストライドは 4 = roundUp(AlignOf(f32),SizeOf(f32)) = roundUp(4,4)
//   - サイズは 32 = stride * number_of_elements = 4 * 8
var small_stride: array<f32, 8>;

// 次の配列:
//   - アラインメントは 16 = AlignOf(vec3<f32>) = 16
//   - 要素ストライドは 16 = roundUp(AlignOf(vec3<f32>), SizeOf(vec3<f32>))
//                          = roundUp(16,12)
//   - サイズは 128 = stride * number_of_elements = 16 * 8
var bigger_stride: array<vec3<f32>, 8>;
例: ランタイムサイズ配列のレイアウト例
// 次の配列:
//   - アラインメントは 4 = AlignOf(f32)
//   - 要素ストライドは 4 = roundUp(AlignOf(f32),SizeOf(f32)) = 4
// B が描画またはディスパッチコマンドのバインディングの
// 実効バッファーバインディングサイズの場合、要素数は:
//   N_runtime = floor(B / element stride) = floor(B / 4)
@group(0) @binding(0)
var<storage> weights: array<f32>;

// 次の配列:
//   - アラインメントは 16 = AlignOf(vec3<f32>) = 16
//   - 要素ストライドは 16 = roundUp(AlignOf(vec3<f32>), SizeOf(vec3<f32>))
//                          = roundUp(16,12)
// B が描画またはディスパッチコマンドのバインディングの
// 実効バッファーバインディングサイズの場合、要素数は:
//   N_runtime = floor(B / element stride) = floor(B / 16)
var<storage> directions: array<vec3<f32>>;

14.4.4. 値の内部レイアウト

この節では、値全体の配置が仮定されている場合に、 ホスト共有可能値の内部がバッファーのバイト位置にどのように配置されるかを説明します。 これらのレイアウトは値の型と、 構造体メンバー上のalign およびsize 属性に依存します。 これらの規則は、以下で説明する非不透明型に適用されます。 buffer 型の値には内部 構造がなく、これらの規則による制約を受けません。

値が配置されるバッファーバイトオフセットは、型のアラインメント要件を満たさなければなりません: 型 T の値がバッファーオフセット k に 配置される場合、ある 0 以上の整数 c について k = c × AlignOf(T) です。

データはアドレス空間に関係なく同一に現れます。

注: bool 型はホスト共有可能ではありません。 WGSL は bool 値のサイズと アラインメントが 4 バイトであると指定しますが、 bool 値の内部レイアウトは指定しません。

型 u32 またはi32 の値 V が、 ホスト共有バッファーのバイトオフセット k に配置される場合:

注: i32 は 2 の補数表現を使用するため、符号ビットは ビット位置 31 にあることを思い出してください。

64 ビット整数のレイアウト: WebGPU API の一部の機能は、64 ビットの 符号なし整数値をバッファーに書き込みます。そのような値 V が ホスト共有バッファーのバイトオフセット k に現れる場合:

注: WGSL には具象の64 ビット整数型はありません。

型 f32 の値 V は、 IEEE-754 binary32 形式で表現されます。 符号ビット 1 個、指数ビット 8 個、小数部ビット 23 個を持ちます。 V がホスト共有バッファーのバイトオフセット k に配置される場合:

型 f16 の値 V は、 IEEE-754 binary16 形式で表現されます。 符号ビット 1 個、指数ビット 5 個、小数部ビット 10 個を持ちます。 V がホスト共有バッファーのバイトオフセット k に配置される場合:

注: 上記の規則は、 ホスト共有バッファー内の数値が リトルエンディアン形式で格納されることを意味します。

アトミック 型 atomic<T> の値 V がホスト共有バッファーに配置される場合、 基礎となる型 T の値と同じ内部レイアウトを持ちます。

ベクトル型 vecN<T> の値 V が ホスト共有バッファーのバイトオフセット k に配置される場合:

行列型 matCxR<T> の値 V が ホスト共有バッファーのバイトオフセット k に配置される場合:

配列型 A の値が ホスト共有メモリーバッファーのバイトオフセット k に配置される場合:

構造体型 S の値が、ホスト共有メモリーバッファーのバイトオフセット k に配置される場合:

14.4.5. アドレス空間レイアウト制約

storage およびuniform アドレス空間には、 この節で説明する異なるレイアウト制約があります。

uniform を除くすべてのアドレス空間は、 storage アドレス空間と同じ 制約を持ちます。

変数によって直接または間接的に参照されるすべての構造体型および配列型は、 その変数のアドレス空間の制約に従わなければなりません。 アドレス空間制約への違反はシェーダー作成エラーになります。

この節では、RequiredAlignOf(S, C) を、 ホスト共有可能型または固定フットプリント型 S の値を アドレス空間 C で使用するときのバイトオフセットのアラインメント要件として定義します。

アドレス空間 C におけるホスト共有可能型または固定フットプリント型のアラインメント要件
ホスト共有可能型または固定フットプリント型 S、 S が C に現れることができると仮定 RequiredAlignOf(S, C),
uniform_buffer_standard_layout がサポートされているか、 C がuniform ではない
RequiredAlignOf(S, C),
uniform_buffer_standard_layout がサポートされておらず、 C がuniform
bool、i32、u32、f32、 またはf16 AlignOf(S) AlignOf(S)
atomic<T> AlignOf(S) AlignOf(S)
vecN<T> AlignOf(S) AlignOf(S)
matCxR<T> AlignOf(S) AlignOf(S)
array<T, N> AlignOf(S) roundUp(16, AlignOf(S))
array<T> AlignOf(S)
C がuniform の場合、 buffer_view 組み込み関数の結果である場合を除き許可されない
roundUp(16, AlignOf(S))
buffer_view 組み込み関数の結果である場合を除き許可されない
struct S AlignOf(S) roundUp(16, AlignOf(S))

型 T の構造体メンバーは、アドレス空間 C について、 構造体の先頭からのバイトオフセットがRequiredAlignOf(T, C) の倍数でなければなりません:

OffsetOfMember(S, i) = k × RequiredAlignOf(T, C)
ここで k は 0 以上の整数で、構造体 S の i 番目のメンバーの 型は T

要素型 T の配列は、アドレス空間 C について RequiredAlignOf(T, C) の倍数である要素ストライドを持たなければなりません:

StrideOf(array<T, N>) = k × RequiredAlignOf(T, C)
StrideOf(array<T>) = k × RequiredAlignOf(T, C)
ここで k は正の整数

uniform_buffer_standard_layout が サポートされていない場合、 uniform アドレス空間では次が必要です:

注: 次の例は、uniform バッファーのレイアウト要件を 満たすために、構造体メンバー上でalign およびsize 属性を 使用する方法を示します。 特に、これらの手法を使用して、std140 レイアウトを持つ GLSL バッファーを WGSL へ機械的に変換できます。

例: uniform アドレス空間のオフセット要件を満たす
struct S {
  x: f32
}
struct Invalid {
  a: S,
  b: f32 // 無効: a と b の間のオフセットは 4 バイトだが、少なくとも 16 でなければならない
}
@group(0) @binding(0) var<uniform> invalid: Invalid;

struct Valid {
  a: S,
  @align(16) b: f32 // 有効: a と b の間のオフセットは 16 バイト
}
@group(0) @binding(1) var<uniform> valid: Valid;
例: uniform アドレス空間のストライド要件を満たす
struct small_stride {
  a: array<f32,8> // stride 4
}
// 無効。ストライドは 16 の倍数でなければならない
@group(0) @binding(0) var<uniform> invalid: small_stride;

struct wrapped_f32 {
  @size(16) elem: f32
}
struct big_stride {
  a: array<wrapped_f32,8> // stride 16
}
@group(0) @binding(1) var<uniform> valid: big_stride;     // 有効

14.5. メモリーモデル

一般に、WGSL はVulkan メモリーモデルに従います。 この節の残りでは、WGSL プログラムが Vulkan メモリーモデルへどのように対応するかを説明します。

注: Vulkan メモリーモデルは、 形式的 Alloy モデルをテキストで表現したものです。

14.5.1. メモリー操作

WGSL における読み取りアクセスは、 Vulkan メモリーモデルのメモリー読み取り操作に相当します。 WGSL における書き込みアクセスは、 Vulkan メモリーモデルのメモリー書き込み操作に相当します。

読み取りアクセスは、 呼び出しが次のいずれかを実行するときに発生します:

書き込みアクセスは、 呼び出しが次のいずれかを実行するときに発生します:

アトミック読み取り・変更・書き込み組み込み関数は、 読み取り アクセスと書き込み アクセスの両方である 1 つのメモリー操作を実行します。

読み取りアクセスと書き込みアクセスは、その他の状況では発生しません。 読み取りアクセスと書き込みアクセスは、Vulkan メモリーモデルでは総称してメモリー操作と呼ばれます。

メモリー ビューを介するメモリー操作は、通常、そのメモリー ビューに関連付けられた位置の集合だけにアクセスします。 例外として、ベクトルの成分への書き込みアクセスは、そのベクトルに関連付けられた すべてのメモリー位置へアクセスする場合があります。

スウィズル ビューを介するメモリー操作は、基礎となるベクトルに関連付けられたすべてのメモリー位置へアクセスします。 詳細については、スウィズルビュー読み取り およびスウィズルビュー 書き込みを参照してください。

例: メモリー位置へのアクセス
struct S {
  a : f32,
  b : u32,
  c : f32
}

@group(0) @binding(0)
var<storage> v : S;

fn foo() {
  let x = v.b; // v.a または v.c のメモリー位置にはアクセスしない。
}

14.5.2. メモリーモデル参照

各モジュールスコープのリソース変数は、 一意のgroup とbinding のペアについて メモリーモデル参照を形成します。 その他の各変数(すなわち、function、 private、 およびworkgroup アドレス空間の変数)は、 その変数の存続期間中、一意のメモリーモデル参照を形成します。

14.5.3. スコープ付き操作

呼び出しがスコープ付き操作を実行するとき、1 つまたは 2 つの呼び出し集合に影響します。 これらの集合がメモリースコープと実行スコープです。メモリースコープは、操作によって影響を受けるメモリー内容の 更新を認識する呼び出しの集合を指定します。 同期組み込み関数の場合、これはさらに、 関数より前にプログラム順序付けされた、影響を受けるすべてのメモリー操作が、 関数より後にプログラム順序付けされた影響を受ける操作から可視になることを意味します。 実行スコープは、 操作に参加できる呼び出しの集合を指定します (§ 15.6 集合操作を参照)。

アトミック組み込み関数は、メモリースコープが次のアトミック操作に対応します:

同期組み込み関数は、 実行およびメモリースコープが Workgroup の制御バリアに対応します。

暗黙および明示的な微分は、暗黙のクワッド 実行スコープを持ちます。

注: 生成されたシェーダーで Vulkan メモリーモデルが 有効でない場合、QueueFamily の代わりに Device スコープを使用するべきです。

14.5.4. メモリーセマンティクス

すべてのアトミック組み込み関数は Relaxed メモリーセマンティクスを使用し、したがってストレージクラス セマンティクスは使用しません。

注: WGSL のアドレス空間は SPIR-V のストレージ クラスに相当します。

workgroupBarrier は AcquireRelease メモリーセマンティクスおよび WorkgroupMemory セマンティクスを使用します。 storageBarrier は AcquireRelease メモリーセマンティクスおよび UniformMemory セマンティクスを使用します。 textureBarrier は AcquireRelease メモリーセマンティクスおよび ImageMemory セマンティクスを使用します。

注: workgroupBarrier と storageBarrier の組み合わせは AcquireRelease 順序付けセマンティクス、および WorkgroupMemory と UniformMemory の両方のメモリー セマンティクスを使用します。

注: MakeAvailable または MakeVisible セマンティクスを使用するアトミック組み込み関数または同期組み込み関数はありません。

14.5.5. プライベートと非プライベート

storage または workgroup アドレス空間のすべての非アトミックな読み取りアクセスは、 非プライベートとみなされ、 Workgroup スコープの NonPrivatePointer | MakePointerVisible メモリーオペランドを持つ 読み取り操作に対応します。

storage または workgroup アドレス空間のすべての非アトミックな書き込みアクセスは、 非プライベートとみなされ、 Workgroup スコープの NonPrivatePointer | MakePointerAvailable メモリーオペランドを持つ書き込み操作に対応します。

handle アドレス空間のすべての非アトミックな読み取りアクセスは、 非プライベートとみなされ、 Workgroup スコープの NonPrivateTexel | MakeTexelVisible メモリーオペランドを持つ 読み取り操作に対応します。

handle アドレス空間のすべての非アトミックな書き込みアクセスは、 非プライベートとみなされ、 Workgroup スコープの NonPrivateTexel | MakeTexelAvailable メモリーオペランドを持つ 書き込み操作に対応します。

15. 実行

§ 1.1 概要では、シェーダーがどのように呼び出され、呼び出しに分割されるかを説明しています。 この節では、呼び出しが個別および集合的にどのように実行されるかに関する 追加の制約について説明します。

15.1. 呼び出し内のプログラム順序

WGSL モジュール内の各文は、実行中に 0 回以上実行される場合があります。 特定の呼び出しについて、特定の文の各実行は一意の 動的文 インスタンスを表します。

文に式が含まれる場合、文のセマンティクスによって次が決定されます:

式のネストは、評価を完了するために満たさなければならないデータ依存関係を定義します。 すなわち、ネストされた式は、それを包含する式を評価する前に評価されなければなりません。 WGSL における式のオペランドの評価順序は左から右です。 たとえば、foo() + bar() は bar() より前に foo() を評価しなければなりません。 § 8 式を参照してください。

WGSL モジュール内の文は、制御フロー順に実行されます。 § 9 文および§ 11.2 関数呼び出しを参照してください。

15.2. 一様性

集合操作 (例: バリア、微分、または暗黙に計算された微分に依存するテクスチャー操作)は、 GPU 上で同時に実行される異なる呼び出し間の協調を必要とします。 すべての呼び出しが同時に、すなわち一様制御フローで実行する場合、 操作は正しく移植可能に実行されます。

逆に、呼び出しの厳密な部分集合だけが操作を実行する場合、 すなわち非一様制御フローでは、不正または移植不能な動作が発生します。 非公式には、非一様な制御依存関係の結果として、一部の呼び出しは集合操作に到達するものの、 他の呼び出しは到達しないか、同時には到達しません。 非一様な制御依存関係は、非一様値に動作が依存する制御フロー 文から生じます。

たとえば、異なる呼び出しが if、break-if、while、またはfor の条件について異なる値を計算する場合、 switch のセレクターについて異なる値を計算する場合、 または短絡二項演算子(&& または ||)の左オペランドについて異なる値を計算する場合、 非一様な制御依存関係が生じます。

これらの非一様値は、多くの場合、静的に一様であることが証明されていない 特定のソースまでたどることができます。 これらのソースには、次が含まれますが、これらに限定されません:

正しく移植可能な動作を保証するため、WGSL 実装は静的な一様性解析を実行し、 各集合操作が一様 制御フローで実行されることを証明しようとします。 後続の小節でこの解析について説明します。

一様性違反は、 一様性 解析が、特定の集合操作が一様 制御フローで実行されることを証明できない場合にトリガーされます。

15.2.1. 用語と概念

次の定義は単なる参考情報であり、次の小節の解析が何を計算しているのかを 直感的に説明することを目的としています。 実際にこれらの概念を定義し、プログラムが有効であるか、一様性規則に違反するかを 決定するのは解析です。

特定の呼び出しグループについて:

15.2.2. 一様性解析の概要

残りの小節では、集合操作が一様制御フローでのみ実行されることを検証する 静的解析を規定します。 subgroup_uniformity 機能がサポートされている場合、 複数の一様性 スコープがあります。 この解析は各スコープについて 1 回実行されます。

注: 解析はスコープごとに 1 回実行されるものとして 説明されていますが、 実装は各スコープを含む単一の解析を実行してもかまいません。 ワークグループおよび描画 一様性スコープは、異なるシェーダーステージで動作し、シェーダーステージ内で 最大の一様性スコープを表すため、実質的に同等です。

解析は動的 エラーが発生しないと仮定します。 動的 エラーを持つシェーダーステージは、一様性解析の結果に関係なく、 すでに移植不能です。

注:この解析には次の望ましい性質があります:

各関数は、次の 2 つを保証しようとして解析されます:

これら 2 つの検査のいずれかが失敗すると、一様性違反が トリガーされます。

この処理の一部として、解析は関数についてのメタデータを計算し、 続いてその呼び出し元を解析するのに役立てます。 これは、最初にコールグラフを構築し、関数を葉から上方向へ、 すなわち標準ライブラリー以外の関数を呼び出さない関数からエントリーポイントへ向かって解析しなければならないことを意味します。 こうすることで、関数を解析するとき、そのすべての呼び出し先のメタデータがすでに計算済みになります。 言語では再帰が禁止されているため、循環に陥る危険はありません。

注: 同じことを別の言い方で表すと、 「(場合によっては間接的に)呼び出し先である」という半順序によって順序付けされた関数を トポロジカルソートし、その順序で解析します。

さらに、各関数呼び出しについて、解析は、その呼び出しが一様制御フローにあることを 証明できない場合にトリガーされるトリガールールの集合があれば、 それを計算して伝播します。 これを呼び出しの潜在トリガー集合と呼びます。 この集合の要素は、次の可能性から選ばれます:

15.2.3. 関数の一様性要件の解析

各関数は 2 段階で解析されます。

第 1 段階では関数の構文を走査し、次の小節の規則に基づいて その過程で有向グラフを構築します。 第 2 段階ではそのグラフを探索し、この関数を呼び出す際の制約を計算し、 場合によっては一様性違反をトリガーします。

注:4 つの特殊ノード RequiredToBeUniform.error、 RequiredToBeUniform.warning、 RequiredToBeUniform.info、およびMayBeNonUniform を除き、 各ノードは次の文のいずれかの真偽値を捉えるものと理解できます:

エッジは、そのソースノードに対応する文から ターゲットノードに対応する文への含意として理解できます。

たとえば、一様性要件の 1 つとして、workgroupBarrier 組み込み関数は 一様制御フロー内でのみ呼び出されなければなりません。 これを表現するため、RequiredToBeUniform.error から workgroupBarrier の呼び出しサイトに対応するノードへのエッジを追加します。 これを理解する 1 つの方法は、RequiredToBeUniform.error が命題 True に対応すると考えることであり、その場合 RequiredToBeUniform.error -> X は、 X が真であるということと同じです。

逆に、何かの一様性を保証できないこと (例: スレッド ID を保持する変数)を表現するため、その対応するノードから MayBeNonUniform へのエッジを追加します。 これを理解する 1 つの方法は、MayBeNonUniform が命題 False に対応すると考えることであり、その場合 X -> MayBeNonUniform は、 X が偽であるということと同じです。

この解釈の帰結として、RequiredToBeUniform.error から到達可能なすべてのノードは、 プログラムが有効であるために一様であることを要求される何かに対応し、 MayBeNonUniform に 到達可能なすべてのノードは、一様性を保証できない何かに対応します。 したがって、RequiredToBeUniform.error からMayBeNonUniform へのパスが 1 つでもある場合、 一様性違反となり、一様性違反がトリガーされます。

ノード RequiredToBeUniform.warning およびRequiredToBeUniform.info も同様に使用されますが、 代わりに警告または情報診断をいつトリガーするべきかの判断に役立ちます:

§ 2.3 診断で説明されているように、より高い重大度の診断も生成されている場合、 より低い重大度の診断は破棄される場合があります。

各関数について、2 つのタグが計算されます:

関数の各仮 引数について、1 つまたは 2 つのタグが計算されます:

呼び出しサイトタグの値
呼び出しサイトタグ 説明
CallSiteRequiredToBeUniform.S,
ここで S は重大度 error、warning、またはinfo のいずれかです。
関数は一様制御フローからのみ呼び出さなければなりません。 それ以外の場合、重大度 S の診断がトリガーされます。

潜在トリガー集合に関連付けられます。

CallSiteNoRestriction 関数は非一様制御フローから呼び出してもかまいません。
関数タグの値
関数タグ 説明
ReturnValueMayBeNonUniform 関数の戻り値は 非一様である可能性があります。
NoRestriction 関数は非一様性を導入しません。
パラメータータグの値
パラメータータグ 説明
ParameterRequiredToBeUniform.S,
ここで S は重大度 error、warning、またはinfo のいずれかです。
パラメーターは一様値でなければなりません。 パラメーター型がポインターの場合、メモリービューは一様でなければなりませんが、 その内容まで必ず一様である必要はありません。 それ以外の場合、重大度 S の診断がトリガーされます。

潜在トリガー集合に関連付けられます。

ParameterContentsRequiredToBeUniform.S,
ここで S は重大度 error、warning、またはinfo のいずれかです。
ポインターパラメーターが指すメモリーに格納された値は一様値でなければなりません。 それ以外の場合、重大度 S の診断がトリガーされます。

潜在トリガー集合に関連付けられます。

ParameterNoRestriction パラメーター値には一様性要件がありません。
パラメーター 戻りタグの値
パラメーター戻りタグ 説明
ParameterReturnContentsRequiredToBeUniform 戻り値が 一様値になるためには、パラメーターが一様値でなければなりません。 パラメーターがポインターの場合、そのポインターが指すメモリーに格納された値も 一様でなければなりません。
ParameterReturnNoRestriction パラメーター値には一様性要件がありません。
ポインター パラメータータグの値
ポインターパラメータータグ 説明
PointerParameterMayBeNonUniform 関数呼び出しの後、ポインターパラメーターが指すメモリーに格納された値は 非一様である可能性があります。
PointerParameterNoRestriction ポインターパラメーターが指すメモリーに格納された値の一様性は、 関数呼び出しの影響を受けません。

次のアルゴリズムは、特定の関数についてこれらのタグを計算する方法を説明します:

注: この時点でグラフ全体を破棄できます。 上記のタグだけを記憶しておけば、この関数の呼び出し元を解析できます。 ただし、グラフには、より有益な診断を提供するために使用できる情報が含まれています。 たとえば、ある関数内の値が一様であることを証明できず、 それが別の関数での一様性違反のトリガーに寄与する場合があります。 有益な診断では、非一様値とともに、診断の トリガー位置にある関数呼び出しも説明します。

15.2.4. ポインターの脱糖

function アドレス空間内のポインター型の各パラメーターは、 初期値がパラメーターを間接参照したものと等価であるローカル変数宣言として脱糖されます。 つまり、function アドレス空間のポインターは、ローカル 変数宣言へのエイリアスとして扱われます。 初期値の代入により、i番目のパラメーターについてparam_i_contents へのエッジが生成されます (つまり、V(e) はparam_i_contents です)。

実効値型がポインター型である各let 宣言 L は、次のように脱糖されます:

この脱糖により、ポインターのルート識別子が各使用箇所で直接現れるため、 後続の解析が簡単になります。

注: 一様性解析の目的では、型チェックは、 この脱糖の前と後の両方で行われるものとして説明されます。

例: 一様性解析におけるポインター
fn foo(p : ptr<function, array<f32, 4>>, i : i32) -> f32 {
  let p1 = p;
  var x = i;
  let p2 = &((*p1)[x]);
  x = 0;
  *p2 = 5;
  return (*p1)[x];
}

// これは解析用の foo の等価なバージョンです。
fn foo_for_analysis(p : ptr<function, array<f32, 4>>, i : i32) -> f32 {
  var p_var = *p;            // p 用の変数を導入する。
  let p1 = &p_var;           // p1 に p 用の変数を使用する
  var x = i;
  let x_tmp1 = x;            // x の値を取得する
  let p2 = &(p_var[x_tmp1]); // p1 の初期化子を置換する
  x = 0;
  *(&(p_var[x_tmp1])) = 5;   // p2 の初期化子を置換する
  return (*(&p_var))[x];     // p1 の初期化子を置換する
}

15.2.5. 関数スコープ変数の値解析

特定の文における各関数スコープ変数の値は、 そこに到達する代入、および場合によってはその初期値の観点から解析できます。

代入は、次の場合に完全 代入です:

それ以外の場合、代入は部分代入です。

完全参照は、 次のいずれかである参照 型の式です:

完全ポインターは、 次のいずれかであるポインター型の式です:

注: この解析の目的では、 ポインター型の仮引数が完全ポインターである場合を考慮する必要はありません。

完全参照、および同様に 完全ポインターは、 対応する起点変数 x の すべてのメモリー位置に対するメモリービューです。

完全 参照でない参照は、部分参照です。 したがって、部分参照は次のいずれかです:

注: 部分参照でも、完全参照とまったく同じメモリー位置、 すなわち変数宣言によって使用されるすべての位置を覆う場合があります。 これは、格納型がメンバーを 1 つだけ持つ構造体型である場合、 または格納型が要素を 1 つ持つ配列型である場合に発生します。

メンバーを 1 つ持つ構造体型と、その型を格納する変数を考えます:

struct S { member: i32; }
fn foo () {
   var v: S;
}

この場合、v は完全参照で、v.member は部分参照です。 それらのメモリービューは同じメモリー 位置を覆いますが、v の格納型は S であり、 v.s の格納型は i32 です。

要素を 1 つ持つ配列でも同様の状況が発生します:

fn foo () {
   var arr: array<i32,1>;
}

この場合、arr は完全参照で、arr[0] は部分参照です。 それらのメモリービューは同じメモリー 位置を覆いますが、arr の格納型は array<i32,1> であり、 arr[0] の格納型は i32 です。

解析を簡単にするため、あらゆる種類の部分参照を介する代入は、 関連付けられた起点変数内の すべてのメモリー位置を変更しないものとして扱われます。 これにより解析は保守的になり、厳密には必要でないより多くのプログラムについて一様性違反がトリガーされる可能性があります。

完全スウィズルビューは、 次を満たすスウィズルビュー sv = (p, IndexList) に評価される式です:

注: 完全スウィズルビューを介して代入すると、 メモリー内の基礎となるベクトルのすべての要素が上書きされます。

部分スウィズル ビューは、完全スウィズルビューではないスウィズルビュー型の式です。

注: 完全スウィズルビューは、 基礎となるポインター式の完全性と IndexList だけに依存し、 どちらもシェーダー作成時に既知であるため、シェーダー作成時に判定できます。 これはスウィズルビュー式を連鎖させる場合でも成り立ちます。

完全 参照または完全スウィズルビューを介する代入は、完全代入です。

部分参照または部分スウィズルビューを介する代入は、部分代入です。

後続の節の一様性規則が、RHSValue として使用される 関数スコープ変数の値を参照する場合、それは RHSValue 式の評価より前の変数の値を意味します。 後続の節の一様性規則が、LHSValue として使用される 関数スコープ変数の値を参照する場合、それはその式が現れる文の実行後の変数の値を意味します。

制御フロー文または部分代入によって、 変数への複数の代入がその変数の使用箇所に到達する場合があります。 解析では、各制御フロー出口に到達する代入の集合の和集合を取ることで、 制御フロー文から出る複数の代入を結合します。

次の表は、代入を結合する規則について説明します。 一様性グラフでは、各結合は結果ノードから値のソースを表すノードへのエッジです。 任意の変数 x を用いて記述します。次の 表記を使用します:

関数スコープ変数への複数の代入を結合する規則。
文 結果 結果からのエッジ
var x; Vin(next) V(0)
var x = e;
Vin(next) V(e)

注: これは x への完全代入です。

x = e;
r = e;
ここで r は変数 x への完全参照
sv = e;
ここで sv は起点変数 x を持つ完全スウィズルビュー
r = e;
ここで r は変数 x への部分参照
Vout(S) V(e), Vout(prev)

注: これは x への部分代入です。

注: 部分代入には以前の値が含まれます。 代入は格納された成分の一部だけを書き込むか、 書き込まれる値の型が起点変数の格納型と異なります。

sv = e;
ここで sv は起点変数 x を持つ部分スウィズルビュー
s1 s2
ここで Next は s1 の動作に含まれます。

注: s1 は多くの場合 セミコロンで終わります。

Vin(s2) Vout(s1)
if e s1 else s2
ここで Next は s1 と s2 の両方の動作に含まれます
Vin(next) Vout(s1), Vout(s2)
if e s1 else s2
ここで Next は s1 の動作に含まれますが、s2 には含まれません
Vin(next) Vout(s1)
if e s1 else s2
ここで Next は s2 の動作に含まれますが、s1 には含まれません
Vin(next) Vout(s2)
loop { s1 continuing { s2 } } Vin(s1) Vout(prev),
s1 の動作が {Next,Continue} と交差する場合は Vout(s2)
loop { s1 continuing { s2 } } Vin(s2) Next が s1 の動作に含まれる場合は Vout(s1)、
動作が {Continue} で s2 へ 制御を移す s1 内のすべての si について Vout(si)
loop { s1 continuing { s2 } } Vin(next) Break が s1 の動作に含まれる場合は Vout(s2)、
動作が {Break} で next へ 制御を移す s1 内のすべての si について Vout(si)
switch e {
case _: s1
case _: s2
...
case _: s3
}
Vin(si) Vout(prev)
switch e {
case _: s1
case _: s2
...
case _: s3
}
Vin(next) Next または Break を含む動作を持つ すべての si について Vout(si)、
および
動作が {Break} で next へ 制御を移す sj 内のすべての文について Vout(sj)

その他のすべての文(関数呼び出しを除く)について、Vin(next) は Vout(prev) と等価です。

注: 文の動作解析と同じ脱糖が適用されます。

15.2.6. 文の一様性規則

文を解析する規則は、文そのものと、その開始時の制御フローに対応するノード (以下では "CF" と表記します)の両方を引数として受け取り、次の両方を返します:

以下の表で、(CF1, S) => CF2 は「制御フロー CF1 から開始して S の解析を実行し、 必要な変更をグラフに適用し、結果の制御フローノードを CF2 と命名する」ことを意味します。 同様に、(CF1, E) => V は「制御フロー CF1 から開始して式 E の解析を実行し、 必要な変更をグラフに適用し、結果の値ノードを V と命名する」ことを意味します (式の解析については次の節を参照)。 この式の評価は、代入の左辺の一部ではないすべての式に使用され、 RHSValue と呼ばれます。

代入の 左辺の一部である式、 すなわちLHSValue については同様の規則集合があり、 LHSValue: (CF, E) => L と表記します。値の一様性に対応するノードを計算する代わりに、 代入先の変数の一様性に対応するノードを計算します。

注: LHSValue にはインクリメント文および デクリメント 文内の式が含まれます。

注: RHSValue には、代入文の右辺の一部である式、 または代入、インクリメント、もしくはデクリメント文の一部ではない式が含まれます。

複数のエッジを作成する必要がある場合、X -> Y, X -> Z の省略形として X -> {Y, Z} を使用します。

ループを解析する際には、次のパターンを使用します:

文の一様性規則
文 新しいノード 再帰解析 結果の制御フローノード 新しいエッジ
空文 CF
{s} (CF, s) => CF' CF'
s1 s2,
s1 の動作に Next を含む

注: s1 は多くの場合 セミコロンで終わります。

(CF, s1) => CF1
(CF1, s2) => CF2
CF2
s1 s2,
s1 の動作に Next を含まない

注: s1 は多くの場合 セミコロンで終わります。

(CF, s1) => CF1

注: s2 は静的に 到達不能であり、再帰的に解析されません。 s2 は一様性解析に寄与しません。

CF1
if e s1 else s2
動作 {Next}
(CF, e) => V
(V, s1) => CF1
(V, s2) => CF2
CF
if e s1 else s2
その他の動作
CFend CFend CFend -> {CF1, CF2}
loop {s1}
s1 の動作に Return を含まない
CF' (CF', s1) => CF1 CF CF' -> {CF1, CF},
s1 の動作が {Next,Continue} と交差する場合
CF' -> CF,
s1 の動作が {Next,Continue} と交差しない場合
loop {s1}
s1 の動作に Return を含む
CF' (CF', s1) => CF1 CF1 CF' -> {CF1, CF}
s1 の動作が {Next,Continue} と交差する場合
CF' -> CF
s1 の動作が {Next,Continue} と交差しない場合
loop {s1 continuing {s2}}
s1 の動作が {Break}
(CF, s1) => CF1 CF

注: ループは 1 回の 反復だけを実行するため、追加のエッジは必要ありません。

loop {s1 continuing {s2}}
s1 の動作が {Return} または {Break,Return}
(CF, s1) => CF1 CF1
loop {s1 continuing {s2}}
s1 の動作が {Next,Continue} と交差する
CF' (CF', s1) => CF1
(CF1, s2) => CF2
CF
s1 の動作に Return が含まれない場合
CF' -> {CF2, CF}
CF'
s1 の動作に Return が含まれる場合
switch e case _: s_1 .. case _: s_n
動作 {Next}
(CF, e) => V
(V, s_1) => CF_1
...
(V, s_n) => CF_n
CF
switch e case _: s_1 .. case _: s_n
その他の 動作
CFend CFend CFend -> {CF_1, ..., CF_n}
var x: T; CF

注: x がfunction アドレス空間の変数の場合、CF は 値解析でゼロ値の初期化子として使用されます。

break;
continue;
break if e; CFend (CF, e) => V CFend CFend -> V

注: CFend から V へのエッジは、 条件値が非一様である場合、この break if 文から生じる制御フローも 非一様であるという事実を捉えます。

return; CF function アドレス空間の各ポインターパラメーター i について、 Value_return_i_contents -> Vin(prev)(§ 15.2.5 関数スコープ 変数の値解析を参照)
return e; (CF, e) => V CF Value_return -> V

function アドレス空間の各ポインターパラメーター i について、 Value_return_i_contents -> Vin(prev)(§ 15.2.5 関数スコープ 変数の値解析を参照)

e1 = e2; LHSValue: (CF, e1) => LV
(CF, e2) => RV
CF LV -> RV

注: LV は 値解析から得られる結果値です。

_ = e (CF, e) => V CF
let x = e; (CF, e) => V CF
var x = e; (CF, e) => V CF

注: x がfunction アドレス空間の変数の場合、 V は値 解析で結果値として使用されます。

f()
引数なしの関数呼び出し文
関数呼び出し解析を呼び出す: (CF, f()) => Result CF
f(e1,...,eN)
引数ありの関数呼び出し文
関数呼び出し解析を呼び出す: (CF, f(e1,...,eN)) => Result CF

この解析の目的では:

性能を最大化するため、実装は多くの場合、 非一様制御 フローの量を最小化しようとします。 ただし、呼び出しが一様であると言える点は、 多くの要因によって異なります。WGSL の静的解析では、文の動作が {Next} である場合、 if、switch、およびloop 文の終端で 一様制御フローへ戻ると保守的に仮定します。 これは前の表で、結果の制御フローノードが 入力制御フローノードと同じであるものとしてモデル化されています。

15.2.7. 関数呼び出しの一様性規則

最も複雑な規則は関数呼び出しに関するものです:

注: Vout(call) の定義については、§ 15.2.5 関数スコープ変数の値解析を参照してください。

ほとんどの組み込み関数は次のタグを持ちます:

例外は次のとおりです:

注: WGSL 実装は、 関数呼び出しより前の制御フローが特定のスコープについて一様である場合、 関数呼び出しの後も一様であることを保証します。

15.2.8. 式の一様性規則

式を解析する規則は、式そのものと、その開始時の制御フローに対応するノード (以下では "CF" と表記します)の両方を引数として受け取り、次を返します:

RHSValue 式の一様性規則
式 新しいノード 再帰解析 結果の値ノード 新しいエッジ
e1 || e2 (CF, e1) => V1
(V1, e2) => V2
V2
e1 && e2
リテラル CF
関数スコープ変数 "x" に解決される識別子で、 その識別子がメモリービュー式 MVE のルート識別子として現れ、 型チェック中に MVE に対してロード規則が呼び出される Result X はこの式を含む文への入力時点における "x" の値に対応するノード Result Result -> {CF, X}

注: X は "x" の Vout(prev) と等価です
(§ 15.2.5 関数スコープ変数の値解析を参照)

関数スコープ変数 "x" に解決される識別子で、 その識別子がスウィズル ビュー式 SVE のルート識別子として現れ、 型チェック中に SVE に対してスウィズルビューロード規則が呼び出される
関数スコープ変数 "x" に解決される識別子で、 "x" が脱糖されたポインターパラメーター i であり、 その識別子がメモリービュー 式 MVE のルート識別子として現れ、 型チェック中に MVE に対してロード規則が呼び出されない param_i
関数スコープ変数 "x" に解決される識別子で、 "x" が脱糖されたポインターパラメーター i であり、 その識別子がスウィズル ビュー式 SVE のルート識別子として現れ、 型チェック中に SVE に対してスウィズルビューロード規則が呼び出される
関数スコープ変数 "x" に解決される識別子で、 その識別子がメモリービュー 式 MVE のルート識別子として現れ、 型チェック中に MVE に対してロード規則が呼び出されない CF
関数スコープ変数 "x" に解決される識別子で、 その識別子がスウィズル ビュー式 SVE のルート識別子として現れ、 型チェック中に SVE に対してスウィズルビューロード規則が呼び出されない
const 宣言、override 宣言、 let 宣言、または非組み込みの仮引数である 非ポインター型 "x" に解決される識別子 Result X は "x" に対応するノード Result Result -> {CF, X}
storage、workgroup、 またはprivate アドレス空間内の、 読み取り専用でないアクセスモードを持つポインター型の仮 引数に解決される識別子で、 その識別子がメモリービュー 式 MVE のルート識別子として現れ、 型チェック中に MVE に対してロード規則が呼び出される MayBeNonUniform
storage、workgroup、 またはprivate アドレス空間内の、 読み取り専用でないアクセスモードを持つポインター型の仮 引数に解決される識別子で、 その識別子がスウィズルビュー式 SVE のルート識別子として現れ、 型チェック中に SVE に対してスウィズルビューロード規則が呼び出される
storage、workgroup、 またはprivate アドレス空間内の、 読み取り専用でないアクセスモードを持つポインター型の仮 引数に解決される識別子で、 その識別子がメモリービュー 式 MVE のルート識別子として現れ、 型チェック中に MVE に対してロード規則が呼び出されない CF
storage、workgroup、 またはprivate アドレス空間内の、 読み取り専用でないアクセスモードを持つポインター型の仮 引数に解決される識別子で、 その識別子がスウィズルビュー式 SVE のルート識別子として現れ、 型チェック中に SVE に対してスウィズルビューロード規則が呼び出されない
function 以外のアドレス空間内の、 読み取り専用アクセスモードを持つポインター型の仮 引数に解決される識別子 CF
一様な組み込み値 "x" に解決される識別子 CF
非一様な組み込み値 "x" に解決される識別子 MayBeNonUniform
読み取り専用のモジュールスコープ変数 "x" に解決される識別子 CF
読み取り専用でないモジュールスコープ 変数 "x" に解決される識別子で、 その識別子がメモリービュー式 MVE のルート識別子として現れ、 型チェック中に MVE に対してロード規則が呼び出される MayBeNonUniform
読み取り専用でないモジュールスコープ 変数 "x" に解決される識別子で、 その識別子がスウィズル ビュー式 SVE のルート識別子として現れ、 型チェック中に SVE に対してスウィズルビューロード規則が呼び出される
読み取り専用でないモジュールスコープ 変数 "x" に解決される識別子で、 その識別子がメモリービュー式 MVE のルート識別子として現れ、 型チェック中に MVE に対してロード規則が呼び出されない CF
読み取り専用でないモジュールスコープ 変数 "x" に解決される識別子で、 その識別子がスウィズル ビュー式 SVE のルート識別子として現れ、 型チェック中に SVE に対してスウィズルビューロード規則が呼び出されない
( e ) (CF, e) => V V
op e,
ここで op は単項演算子
e.field, ここで field は構造体メンバー名
e.swiz, ここで swiz はスウィズル名
e1 op e2,
ここで op は短絡しない二項 演算子
Result (CF, e1) => V1
(CF, e2) => V2
Result Result -> {V1, V2}
e2[e1]
f()
引数なしの関数呼び出し式
関数呼び出し解析を呼び出す:
(CF, f()) => Result
Result
f(e1,...,eN)
引数ありの関数呼び出し式
関数呼び出し解析を呼び出す: (CF, f(e1,...,eN)) => Result Result

次の組み込み入力変数は一様であるとみなされます:

サブグループ 一様性スコープでは、次の組み込み 入力変数も一様であるとみなされます:

その他すべて(組み込み 値を参照)は非一様であるとみなされます。

注: 解析では複合型の成分を個別に解析しないため、 作成者は一様な組み込み値を他の非一様入力と一緒にまとめることを避けるべきです。

LHSValue 式の一様性規則
式 新しいノード 再帰解析 結果の変数ノード 新しいエッジ
関数スコープ変数 "x" に解決される識別子 Result X はこの式を含む文の出力時点における "x" の値に対応するノード。 Result Result -> {CF, X}

注: X は "x" の Vin(next) と等価です
(§ 15.2.5 関数スコープ変数の値解析を参照)

const 宣言、override 宣言、 let 宣言、または仮引数 "x" に解決される識別子 X は "x" に対応するノード X
モジュールスコープ変数 "x" に解決される識別子 MayBeNonUniform
e.field, ここで field は構造体メンバー名 LHSValue: (CF, e) => L1 L1
e.swiz, ここで swiz はスウィズル名
*e
&e
e2[e1] (CF, e1) => V1
LHSValue: (CF, e2) => L2
L2 L2 -> V1
f()
引数なしの関数呼び出し式
関数呼び出し解析を呼び出す:
LHSValue: (CF, f()) => Result
Result
f(e1,...,eN)
引数ありの関数呼び出し式
関数呼び出し解析を呼び出す: LHSValue: (CF, f(e1,...,eN)) => Result Result

15.2.9. 制御フロー内のすべての点の一様性への注釈付け

この小節全体は非規範的です。

実装者が、シェーダー全体の制御フロー内の各点について、 それが一様かどうか(したがって、そこで一様性を要求する関数を呼び出すことが有効かどうか)を示す 診断モードを開発者へ提供したい場合、次を推奨します:

これらの到達可能性解析で訪問されないノードは、解析によって一様であることを証明できます (したがって、そこで微分関数などを呼び出しても安全です)。

注: 呼び出しに遭遇したときにグラフへ どのエッジを追加するかを知るため、ボトムアップ解析は依然として必要です。

15.2.10. 例

後続の例のグラフでは、ノードについて次の規約を使用します:

15.2.10.1. 無効な textureSample 関数呼び出し

この例は、textureSample 組み込み関数呼び出しの無効な使用を示します。 この関数呼び出しは、非一様値 (すなわち組み込み値 position)に条件が依存する if 文内で行われます。 無効な依存関係の連鎖は赤色で強調されています。

例: 無効な textureSample を使用する WGSL
@group(0) @binding(0) var t : texture_2d<f32>;
@group(0) @binding(1) var s : sampler;

@fragment
fn main(@builtin(position) pos : vec4<f32>) {
  if (pos.x < 0.5) {
    // 無効な textureSample 関数呼び出し。
    _ = textureSample(t, s, pos.xy);
  }
}
一様性グラフ

この例は、if 文の後の制御フローの一様性が、 if 文より前の一様性と同じであることも示しています (CF_return がCF_start に接続されています)。 つまり、if 文の後では制御フローは再び一様になります (エントリーポイントの開始時には一様制御フローとして開始することが保証されるためです)。 textureSample 関数呼び出しを if 文の外へ移動していれば、 プログラムは有効でした。 同様に、if 文の条件が一様値 (たとえば各呼び出しがuniform バッファーから同じ値を読み取る場合)であれば、 プログラムも有効でした。

15.2.10.2. 関数スコープ変数の一様性

この例は、関数スコープ変数の値に依存する、有効なバリア関数呼び出しと無効な関数呼び出しの両方を示します。 x の値は変更可能なモジュールスコープ変数 a から導出されるため、 workgroupBarrier は無効です。 x の値は変更不可能なモジュールスコープ変数 b から導出されるため、 storageBarrier は有効です。 この例は、関数スコープ変数の存続期間における異なる一様性の期間を分離する、 値解析の能力を強調しています。 またこの例は、最初のif 文の終端後に制御フローが再び一様になることも明確に示しています。 グラフのその部分が 2 番目の if 文から独立していることから、これが分かります。

例: 関数変数を使用する WGSL
@group(0) @binding(0) var<storage, read_write> a : i32;
@group(0) @binding(1) var<uniform> b : i32;

@compute @workgroup_size(16,1,1)
fn main() {
  var x : i32;
  x = a;
  if x > 0 {
    // 無効なバリア関数呼び出し。
    workgroupBarrier();
  }
  x = b;
  if x < 0 {
    // 有効なバリア関数呼び出し。
    storageBarrier();
  }
}
一様性グラフ

注: サブグラフは理解しやすくするためだけに 例へ含まれています。

15.2.10.3. 複合値解析の制限

一様性解析の制限の 1 つは、複合値の成分を個別に追跡しないことです。 つまり、非一様な成分値が 1 つでもあると、解析は複合値全体を非一様として扱います。 この例は、この問題と、シェーダー作成者がこの制限を回避するために使用できる 可能な回避策を示します。

例: 無効な複合値 WGSL
struct Inputs {
  // workgroup_id は一様な組み込み値。
  @builtin(workgroup_id) wgid : vec3<u32>,
  // local_invocation_index は非一様な組み込み値。
  @builtin(local_invocation_index) lid : u32
}

@compute @workgroup_size(16,1,1)
fn main(inputs : Inputs) {
  // この比較は常に一様だが、
  // 解析ではそれを判定できない。
  if inputs.wgid.x == 1 {
    workgroupBarrier();
  }
}
無効な一様性グラフ

この解析上の制限を回避する最も簡単な方法は、複合値を分割し、 一様であることが既知の値を、非一様であることが既知の値から分離することです。 以下の代替 WGSL では、2 つの組み込み値を別々の パラメーターに分割することで一様性解析を満たします。 これは、グラフ内にRequiredToBeUniform.S から MayBeNonUniform への パスがないことから分かります。

例: 有効な代替 WGSL
@compute @workgroup_size(16,1,1)
fn main(@builtin(workgroup_id) wgid : vec3<u32>,
        @builtin(local_invocation_index) lid : u32) {
  // 一様性解析は、この比較が常に一様であることを
  // 正しく判定できるようになった。
  if wgid.x == 1 {
    // 有効なバリア関数呼び出し。
    workgroupBarrier();
  }
}
有効な代替一様性グラフ
15.2.10.4. ループ内の一様性

この例では、ループ内に無効な workgroupBarrier 関数呼び出しがあります。 非一様な組み込み値 local_invocation_index は、 ループ内でバリアより後に現れるにもかかわらず、最終的な原因です。 これは、後続の反復でワークグループ内の一部の呼び出しが ループを早期に抜ける一方で、他の呼び出しがバリアを実行しようとするためです。 解析は、ループ本体の開始時の制御(CF_loop_body)が ループ本体の終端の制御フロー(CF_after_if)に依存するエッジとして、 反復間の依存関係をモデル化します。

例: ループ一様性 WGSL
@compute @workgroup_size(16,1,1)
fn main(@builtin(local_invocation_index) lid : u32) {
  for (var i = 0u; i < 10; i++) {
    workgroupBarrier();
    if (lid + i) > 7 {
      break;
    }
  }
}
一様性グラフ
15.2.10.5. ユーザー定義関数呼び出し

この例は最初の例を変更したものですが、 ユーザー定義関数呼び出しを使用します。 解析は scale の両方のパラメーターのパラメーター戻りタグを ParameterReturnContentsRequiredToBeUniform に設定します。 これにより、main 内で scale 関数呼び出しの戻り値と position 組み込み値の間にパスが生じます。 そのパスは、RequiredToBeUniform.S から MayBeNonUniform への 全体として無効なパスの部分パスです。

例: ユーザー定義関数呼び出しの一様性 WGSL
fn scale(in1 : f32, in2 : f32) -> f32 {
  let v = in1 / in2;
  return v;
}

@group(0) @binding(0) var t : texture_2d<f32>;
@group(0) @binding(1) var s : sampler;

@fragment
fn main(@builtin(position) pos : vec4<f32>) {
  let tmp = scale(pos.x, 0.5);
  if tmp > 1.0 {
    _ = textureSample(t, s, pos.xy);
  }
}
scale の一様性グラフ
main の一様性グラフ

注: サブグラフは理解しやすくするためだけに 例へ含まれています。

15.3. コンピュートシェーダーとワークグループ

ワークグループは、 コンピュートシェーダーステージのエントリーポイントを同時に実行し、 workgroup アドレス空間内のシェーダー変数へのアクセスを共有する 呼び出しの集合です。

コンピュートシェーダーのワークグループグリッドは、 次を満たす整数座標 (i,j,k) を持つ点の集合です:

ここで (workgroup_size_x, workgroup_size_y, workgroup_size_z) は、 エントリーポイントのworkgroup_size 属性に指定された 値です。

ワークグループグリッド内の各点について、ワークグループ内には正確に 1 つの呼び出しがあります。

呼び出しのローカル 呼び出し IDは、その呼び出しに対応するワークグループグリッド点の 座標 3 つ組 (i,j,k) です。

呼び出しがローカル呼び出し IDを持つ場合、その ローカル呼び出し インデックスは次のとおりです:

i + (j × workgroup_size_x) + (k × workgroup_size_x × workgroup_size_y)

ワークグループに W 個の呼び出しがある場合、 そのワークグループの各呼び出し I は、一意のローカル呼び出しインデックス L(I) を持ち、 0 ≤ L(I) < W を満たし、 その範囲全体が網羅されることに注意してください。

コンピュートシェーダーは、WebGPU 実装が キューからディスパッチコマンドを取り出し、GPU 上で指定された処理を開始すると実行を開始します。 ディスパッチコマンドはディスパッチサイズを指定します。 これは整数の 3 つ組 (group_count_x, group_count_y, group_count_z) であり、 以下で説明するように、実行されるワークグループ数を示します。

特定のディスパッチに対するコンピュートシェーダー グリッドは、次を満たす整数座標 (CSi,CSj,CSk) を持つ点の集合です:

ここで workgroup_size_x、 workgroup_size_y、および workgroup_size_z は、上記のコンピュートシェーダーエントリーポイントの場合と同じです。

コンピュートシェーダーのディスパッチによって実行される処理は、 コンピュートシェーダーグリッド内の各点について、エントリーポイントの呼び出しを正確に 1 回実行することです。

呼び出しのグローバル 呼び出し IDは、その呼び出しに対応するコンピュートシェーダーグリッド点の 座標 3 つ組です。

呼び出しはワークグループに編成され、各呼び出しの グローバル呼び出し ID (CSi, CSj, CSk) は、 ワークグループ IDによって識別される 1 つのワークグループへ対応付けられます:

( ⌊ CSi ÷ workgroup_size_x ⌋, ⌊ CSj ÷ workgroup_size_y ⌋, ⌊ CSk ÷ workgroup_size_z ⌋)

さらに、そのワークグループ内の 1 つの呼び出しが、ローカル呼び出し IDによって識別されます:

( CSi mod workgroup_size_x , CSj mod workgroup_size_y , CSk mod workgroup_size_z ).

注: ワークグループ ID の範囲は (0,0,0) から (group_count_x - 1, group_count_y - 1, group_count_z - 1) です。

linear_indexing 機能がサポートされている場合、 ワークグループがワークグループ ID (WGi, WGj, WGk) を持つとき、その ワークグループインデックスは:

WGi + ( WGj × group_count_x ) + ( WGk × group_count_x × group_count_y )

linear_indexing 機能がサポートされている場合、 呼び出しがグローバル呼び出し ID (CSi, CSj, CSk) を持つとき、その グローバル呼び出し インデックスは:

CSi + ( CSj × workgroup_size_x × group_count_x ) + ( CSk × workgroup_size_x × group_count_x × workgroup_size_y × group_count_y )

WebGPU は次について何も保証しません:

15.4. フラグメントシェーダーとヘルパー呼び出し

フラグメントシェーダーステージの呼び出しは、 X および Y 次元で隣接する位置を持つ呼び出しの 2x2 グリッドに分割されます。 これらの各グリッドをクワッドと呼びます。 クワッドは一部の集合操作で協調できます(§ 15.6.2 微分を参照)。 呼び出しのクワッド 呼び出し IDはクワッド内の一意の ID であり、次のとおりです:

注: クワッド ID にアクセスする組み込み値はありません。

通常、フラグメント処理は、 ラスタライズによって生成される 各RasterizationPoint について、 フラグメントシェーダーの呼び出しを 1 つ作成します。 グラフィックスプリミティブの境界などでは、 クワッドを完全に埋めるのに十分な RasterizationPoint がない場合があります。 クワッドに RasterizationPoint に対応する呼び出しが 1、2、または 3 個しかない場合、 フラグメント処理はクワッド内の未使用の各位置について ヘルパー呼び出しを作成します。

ヘルパー呼び出しの観測可能な効果は限定されています。 これらは微分の計算を支援し、 サブグループ操作に参加する場合があります。 そのため、ヘルパー呼び出しには次の制限があります:

クワッド内のすべての呼び出しがヘルパー呼び出しになった場合 (たとえばdiscard 文を実行したため)、クワッドの実行が終了される場合があります。 ただし、このような終了は非一様制御フローを生成するものとはみなされません。

15.5. サブグループ

サブグループは、 compute またはfragment シェーダーステージのエントリーポイントを同時に 実行し、データを効率的に共有して結果を集合的に計算できる呼び出しの集合です。 compute または fragment シェーダーの各呼び出しは、正確に 1 つのサブグループに属します。 compute シェーダーでは、各サブグループは特定のワークグループの部分集合です。 fragment シェーダーでは、サブグループに複数の描画コマンドからの呼び出しが含まれる場合があります。 各クワッドは単一の サブグループ内に含まれます。

サブグループサイズは、 サブグループ内の呼び出しの最大数です。 シェーダー内では、この値にはsubgroup_size 組み込み値を介してアクセスできます。 サブグループサイズは、ディスパッチコマンド内、したがってワークグループ内では一様 値ですが、描画コマンド内では一様値でない場合があります。 すべてのサブグループサイズは [4, 128] の範囲内の 2 のべき乗であり、特定のデバイス向けに コンパイルされたシェーダーの値は、WebGPU § 4.3 GPUAdapter の [subgroupMinSize, subgroupMaxSize] の範囲内になります。 実際のサイズは、シェーダー、デバイスのプロパティ、およびデバイスコンパイラーに依存します。 各デバイスは、可能なサブグループサイズ範囲の部分集合(単一の値の場合もあります)をサポートします。 デバイスコンパイラーは、さまざまなヒューリスティックを用いて、サポートされるサイズから 1 つを選択します。 各サブグループに含まれる呼び出し数は、報告されたサブグループサイズより少ない場合があります (たとえば、起動された呼び出し数がサブグループサイズより少ない場合)。

呼び出しのサブグループ呼び出し IDは、サブグループ内の一意の ID です。 この ID にはsubgroup_invocation_id 組み込み値を介してアクセスでき、範囲 [0, subgroup_size - 1] 内にあります。

subgroup_id 機能がサポートされている場合、compute シェーダー内のサブグループ IDは、ワークグループ内の サブグループに対する一意の ID です。 この ID にはsubgroup_id 組み込み値を介してアクセスでき、 範囲 [0, num_subgroups - 1] 内にあります。

サブグループ値(すなわち subgroup_invocation_id および subgroup_id)とlocal_invocation_index の間には、定義された関係はありません。 移植不能なコードを避けるため、シェーダー作成者は、これら 2 つの値の間に特定の 対応付けがあると仮定するべきではありません。

同じサブグループ内の呼び出しが異なる制御フローパスを実行する場合、 サブグループの実行は分岐したといいます。 これは非一様制御フローの特殊な場合です。 分岐はサブグループ操作のセマンティクスに影響します。 サブグループ操作を同時に実行するサブグループ内の呼び出しは、その操作についてアクティブです。 サブグループ内のその他の呼び出しは、その操作について非アクティブ です。 サブグループサイズがサブグループ内の呼び出し数を超える場合、 追加の仮想的な呼び出しは非アクティブとみなされます。 ヘルパー呼び出しは、 操作内でアクティブまたは非アクティブになる場合があります。 つまり、一部のデバイスではヘルパー呼び出しがサブグループ操作に参加する場合がありますが、 他のデバイスでは参加しない場合があります。

注: 非一様制御フローで 動作する場合、基盤となるデバイス間にはかなりの移植性の違いがあり、 デバイスコンパイラーはそのようなコードを積極的に最適化することがよくあります。 その結果、サブグループにはシェーダー作成者が予想したものとは異なるアクティブ 呼び出しの集合が含まれる場合があります。

15.6. 集合操作

15.6.1. バリア

バリアは、プログラム内のメモリー操作を順序付ける同期組み込み関数です。 制御バリアは、 同じワークグループ内のすべての呼び出しによって、 同時に実行されたかのように実行されます。 したがって、制御バリアはcompute シェーダー内の一様制御フローでのみ実行しなければなりません。

15.6.2. 微分

偏微分は、 軸に沿った値の変化率です。 同じクワッド内のフラグメントシェーダー呼び出しは協調して、 近似的な偏微分を計算します。

微分を計算する組み込み関数は次のとおりです:

フラグメント座標の偏微分は、次の組み込み関数の動作の一部として 暗黙的に計算されます:

これらでは、微分はサンプリングするテクセルのミップレベルを決定するのに役立ち、 textureSampleCompare の場合は、サンプリングして参照値と比較するテクセルの ミップレベルを決定するのに役立ちます。

呼び出しで指定された値の偏微分は、 § 17.6 微分組み込み 関数で説明される組み込み関数によって計算されます:

隣接する呼び出しが協調して微分を計算するため、これらの 関数はフラグメントシェーダー内の一様制御フローでのみ呼び出すべきです。 これらの関数の各呼び出しについて、一様性解析が、 呼び出しが一様制御フローで行われることを証明できない場合、 derivative_uniformity 診断がトリガーされます。

これらの関数の 1 つが非一様制御フローで呼び出された場合、結果は不定 値です。

注: 微分は暗黙的なクワッド操作の一種です。 その使用にsubgroups 拡張は必要ありません。

15.6.3. サブグループ操作

サブグループ組み込み関数は、サブグループ内の呼び出し間での効率的な 通信と計算を可能にします。 サブグループ操作は、単一命令複数スレッド(SIMT)操作です。

サブグループ内のアクティブな呼び出しは、 結果を決定するために通信します。 したがって、すべての呼び出しがアクティブなとき (すなわち、サブグループレベルの一様制御フロー内)にこれらの関数が呼び出されると、 移植性が最大になります。

15.6.4. クワッド操作

クワッド組み込み関数は、呼び出しのクワッドに対して動作します。 これらはクワッド内のデータ通信に有用です。

クワッド内のアクティブな呼び出しは、 結果を決定するために通信します。 したがって、すべての呼び出しがアクティブなとき (すなわち、クワッドレベルの一様制御フロー内)にこれらの関数が呼び出されると、 移植性が最大になります。

15.7. 浮動小数点評価

WGSL の浮動小数点機能は、浮動小数点に関するIEEE-754 標準に基づいていますが、 GPU が行う妥協を反映して機能が縮小されており、移植性のための追加のガードレールも備えています。

15.7.1. IEEE-754 の概要

WGSL の浮動小数点型は、IEEE-754 の二進浮動小数点型に基づいています。

IEEE-754 の二進浮動小数点型は、 拡張実数の数直線を 次のように近似します:

浮動小数点型の有限範囲は、 区間 [low, high] です。 ここで low はその型で最小の有限値、high はその型で最大の有限値です。

対象となる IEEE-754 浮動小数点型は次のとおりです:

次のアルゴリズムは、浮動小数点値のビット表現を、それに対応する拡張実数値または NaN に対応付けます:

アルゴリズム: 浮動小数点ビット表現の解釈

入力: Bits、二進浮動小数点型の値に対するビット表現。

出力: F、Bits によって表される浮動小数点値。

手順:

浮動小数点演算の定義域は、 演算が適切に定義される拡張 実数入力の集合です。

丸めは、拡張実数値 x を、浮動小数点型の値 x' に対応付けます。 x が浮動小数点型に含まれる場合、丸めは x をそれ自身へ対応付けます: x = x'。 x が型の有限範囲外にある場合、丸めはオーバーフローする場合があります。 それ以外の場合、x' は x より上の最小の浮動小数点値、または x より下の最大の浮動小数点値のいずれかです。 丸めモードによって、どちらを選択するかが決定されます。

一般に、NaN を入力とする演算は NaN を出力します。 例外には次が含まれます:

IEEE-754 は 5 種類の例外を定義します:

15.7.2. IEEE-754 との相違点

WGSL はIEEE-754 標準に従いますが、次の相違点があります:

15.7.3. 浮動小数点の丸めとオーバーフロー

オーバーフローする計算は、無限大または最も近い有限値へ丸められる場合があります。 結果は、オーバーフローした中間結果値の大きさと、 評価がシェーダーモジュール作成中、パイプライン作成中、またはシェーダー 実行中のいずれで発生するかによって異なります。

浮動小数点型 T について、MAX(T) を T の最大の正の有限値、 2EMAX(T) を T で表現可能な最大の 2 のべき乗として定義します。 特に、EMAX(f32) = 127、EMAX(f16) = 15 です。

X を、浮動小数点計算から得られる無限精度の中間結果とします。 式の最終値は、次のように中間結果値 X' と X'' を介して 2 段階で決定されます:

X から、丸めによって T の X' を計算します:

X' から、式の最終値 X'' を計算するか、プログラムエラーを検出します:

15.7.4. 浮動小数点精度

x を、無限精度で計算した場合の演算の正確な実数値または無限大の結果とします。 浮動小数点型 T に対する演算の正しく 丸められた結果は次のとおりです:

つまり、結果は上または下に丸められる場合があります: WGSL は丸めモードを指定しません。

注: 浮動小数点型には正および負の 無限大が含まれるため、 正しく丸められた結果は有限または無限大になる場合があります。

注: 無限精度で計算した場合の演算結果には、 double の精度を超える精度が必要になる場合があります。 そのような場合の例は、x - y で x=1.0 かつ y=1.17e-38 (最小の正の正規単精度浮動小数点数)の場合です。 これらの数の指数は 126 単位離れています。IEEE-754 binary64(倍精度) 形式の仮数は 52 ビットしかないため、 減算を行うと y のすべての有効ビットが失われます。 丸めモードによっては、この場合や、y が小さいがゼロではない多くの他の場合に、 WGSL 式 x - y が x と同じ値を生成する場合があります。 [ECMASCRIPT] は、IEEE-754 の roundTiesToEven 丸めモードに相当するものを使用することに注意してください。

浮動小数点数 x の最終桁単位、ULP は、 [Muller2005]に従い、次のように定義されます:

演算の精度は、次の 5 つの 可能性のいずれかで示されます:

演算の精度が入力範囲について指定されている場合、 その範囲外の入力値について精度は未定義です。

許容される結果が結果型の有限範囲外にある場合、 § 15.7.3 浮動小数点の丸めと オーバーフローの規則が適用されます。

15.7.4.1. 具象浮動小数点式の精度
具象浮動小数点演算の精度
式 f32 の精度 f16 の精度
x + y 正しく丸められる
x - y 正しく丸められる
x * y 正しく丸められる
x / y |y| が範囲 [2-126, 2126] 内の場合 2.5 ULP |y| が範囲 [2-14, 214] 内の場合 2.5 ULP
x % y x - y * trunc(x/y) から継承
-x 正しく丸められる
x == y 正しい結果
x != y 正しい結果
x < y 正しい結果
x <= y 正しい結果
x > y 正しい結果
x >= y 正しい結果
具象浮動小数点組み込み関数の精度
組み込み関数 f32 の精度 f16 の精度
abs(x) 正しく丸められる
acos(x) 次のうち悪い方:
  • 絶対誤差 6.77×10-5

  • atan2(sqrt(1.0 - x * x), x) から継承

次のうち悪い方:
  • 絶対誤差 3.91×10-3

  • atan2(sqrt(1.0 - x * x), x) から継承

acosh(x) log(x + sqrt(x * x - 1.0)) から継承
asin(x) 次のうち悪い方:
  • 絶対誤差 6.81×10-5

  • atan2(x, sqrt(1.0 - x * x)) から継承

次のうち悪い方:
  • 絶対誤差 3.91×10-3

  • atan2(x, sqrt(1.0 - x * x)) から継承

asinh(x) log(x + sqrt(x * x + 1.0)) から継承
atan(x) 4096 ULP 5 ULP
atan2(y, x) |x| が範囲 [2-126, 2126] 内で、かつ y が有限かつ正規の場合 4096 ULP |x| が範囲 [2-14, 214] 内で、かつ y が 有限かつ正規の場合 5 ULP
atanh(x) log( (1.0 + x) / (1.0 - x) ) * 0.5 から継承
ceil(x) 正しく丸められる
clamp(x,low,high) 正しく丸められる。

無限精度の結果は、min(max(x,low),high) または 3 値の中央値を取る定式化のいずれかとして計算されます。 low > high の場合、これらは異なる場合があります。

x と low または high のいずれかが非正規の場合、結果は任意の非正規値になる場合があります。 これは、非正規入力に対する min および max 関数の可能な結果に由来します。

cos(x) x が区間 [-π, π] 内の場合、絶対誤差は最大 2-11 x が区間 [-π, π] 内の場合、絶対誤差は最大 2-7
cosh(x) (exp(x) + exp(-x)) * 0.5 から継承
cross(x, x) (x[i] * y[j] - x[j] * y[i]) から継承。 ここで i ≠ j
degrees(x) x * 57.295779513082322865 から継承
determinant(m:mat2x2<T>)
determinant(m:mat3x3<T>)
determinant(m:mat4x4<T>)
無限 ULP。
注:WebGPU 実装は、実用上有用な determinant 関数を提供するべきです。

理想的な数学では、行列式は加算、減算、乗算演算で計算されます。

しかし、GPU は浮動小数点演算を使用し、行列式の GPU 実装は、 オーバーフローや誤差に対する堅牢性よりも速度と単純さを優先します。

たとえば、単純な 2x2 行列式の計算でさえ (m[0][0] * m[1][1] - m[1][0] * m[0][1])、 桁落ちへの対策がありません。 2x2 行列式により厳しい誤差上限を与えることは、比較的新しい研究の対象です[Jeannerod2013]。 行列サイズが大きくなるにつれて、課題は急速に複雑になります。

WGSL の行列式に有限の誤差上限がないことは、 基盤となる実装にも同じく上限がないことを反映しています。

distance(x, y) length(x - y) から継承
dot(x, y) x[i] * y[i] の総和から継承
dpdx(x)
dpdxCoarse(x)
dpdxFine(x)
dpdy(x)
dpdyCoarse(x)
dpdyFine(x)
fwidth(x)
fwidthCoarse(x)
fwidthFine(x)
無限 ULP。
注:WebGPU 実装は、実用上有用な微分関数を 提供するべきです。

微分は GPU 上で異なる呼び出しの値同士の差 (fwidth の場合は絶対値の差)として実装されます。

WGSL の微分に有限の誤差上限がないことは、 基盤となる実装にも同じく上限がないことを反映しています。

exp(x) 3 + 2 * |x| ULP 1 + 2 * |x| ULP
exp2(x) 3 + 2 * |x| ULP 1 + 2 * |x| ULP
faceForward(x, y, z) select(-x, x, dot(z, y) < 0.0) から継承
floor(x) 正しく丸められる
fma(x, y, z) x * y + z から継承
fract(x) x - floor(x) から継承
frexp(x) x がゼロまたは正規の場合、正しく丸められる。
inverseSqrt(x) 2 ULP
ldexp(x, y) 正しく丸められる
length(x) ベクトルの場合は sqrt(dot(x, x))、 スカラーの場合は sqrt(x*x) から継承。
log(x) x が区間 [0.5, 2.0] 内の場合、絶対誤差は最大 2-21。
x が区間 [0.5, 2.0] 外の場合 3 ULP。
x が区間 [0.5, 2.0] 内の場合、絶対誤差は最大 2-7。
x が区間 [0.5, 2.0] 外の場合 3 ULP。
log2(x) x が区間 [0.5, 2.0] 内の場合、絶対誤差は最大 2-21。
x が区間 [0.5, 2.0] 外の場合 3 ULP。
x が区間 [0.5, 2.0] 内の場合、絶対誤差は最大 2-7。
x が区間 [0.5, 2.0] 外の場合 3 ULP。
max(x, y) 正しく丸められる

x と y の両方が非正規の場合、 結果はいずれかの入力になる場合があります。

min(x, y) 正しく丸められる。

x と y の両方が非正規の場合、 結果はいずれかの入力になる場合があります。

mix(x, y, z) x * (1.0 - z) + y * z から継承
modf(x) 正しく丸められる
normalize(x) x / length(x) から継承
pack4x8snorm(x) 正しく丸められた中間結果 値。正しい結果。
pack4x8unorm(x) 正しく丸められた中間結果 値。正しい結果。
pack2x16snorm(x) 正しく丸められた中間結果 値。正しい結果。
pack2x16unorm(x) 正しく丸められた中間結果 値。正しい結果。
pack2x16float(x) 正しく丸められた中間結果 値。正しい結果。
pow(x, y) exp2(y * log2(x)) から継承
quantizeToF16(x) 正しく丸められる
radians(x) x * 0.017453292519943295474 から継承
reflect(x, y) x - 2.0 * dot(x, y) * y から継承
refract(x, y, z) z * x - (z * dot(y, x) + sqrt(k)) * y から継承。
ここで k = 1.0 - z * z * (1.0 - dot(y, x) * dot(y, x))
k < 0.0 の場合、 結果は正確に 0.0
round(x) 正しく丸められる
sign(x) 正しく丸められる
sin(x) x が区間 [-π, π] 内の場合、絶対誤差は最大 2-11 x が区間 [-π, π] 内の場合、絶対誤差は最大 2-7
sinh(x) (exp(x) - exp(-x)) * 0.5 から継承
saturate(x) 正しく丸められる
smoothstep(edge0, edge1, x) t * t * (3.0 - 2.0 * t) から継承。
ここで t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0)
sqrt(x) 1.0 / inverseSqrt(x) から継承
step(edge, x) 正しく丸められる
tan(x) sin(x) / cos(x) から継承
tanh(x) 次のうち悪い方:
  • 絶対誤差 1.0×10-5

  • sinh(x) / cosh(x) から継承

transpose(x) 正しく丸められる
trunc(x) 正しく丸められる
unpack4x8snorm(x) 3 ULP 該当なし
unpack4x8unorm(x) 3 ULP 該当なし
unpack2x16snorm(x) 3 ULP 該当なし
unpack2x16unorm(x) 3 ULP 該当なし
unpack2x16float(x) 正しく丸められる 該当なし
subgroupBroadcast(x, i) 正しく丸められる
subgroupBroadcastFirst(x) 正しく丸められる
subgroupAdd(x) サブグループ内のすべてのアクティブな呼び出しについての x の総和から継承
subgroupExclusiveAdd(x) サブグループ内で、サブグループ呼び出し IDが現在の 呼び出しの ID より小さいすべてのアクティブな呼び出しについての x の総和から継承。
subgroupInclusiveAdd(x) サブグループ内で、サブグループ呼び出し IDが現在の 呼び出しの ID 以下であるすべてのアクティブな呼び出しについての x の総和から継承。
subgroupMul(x) サブグループ内のすべてのアクティブな呼び出しについての x の積から継承
subgroupExclusiveMul(x) サブグループ内で、サブグループ呼び出し IDが i 番目の 呼び出しの ID より小さいすべてのアクティブな呼び出しについての xi の積から継承
subgroupInclusiveMul(x) サブグループ内で、サブグループ呼び出し IDが i 番目の呼び出しの ID 以下であるすべてのアクティブな呼び出しについての xi の積から継承
subgroupMax(x) サブグループ内のすべてのアクティブな呼び出しについての max(x) から継承
subgroupMin(x) サブグループ内のすべてのアクティブな呼び出しについての min(x) から継承
subgroupShuffle(x, id) 正しく丸められる
subgroupShuffleDown(x, delta) 正しく丸められる
subgroupShuffleUp(x, delta) 正しく丸められる
subgroupShuffleXor(x, mask) 正しく丸められる
quadBroadcast(x, id) 正しく丸められる
quadSwapDiagonal(x) 正しく丸められる
quadSwapX(x) 正しく丸められる
quadSwapY(x) 正しく丸められる
15.7.4.2. AbstractFloat 式の精度

AbstractFloat 演算の精度は次のとおりです:

注:ULP で定量化した場合、特定の絶対誤差上限は 基礎となる浮動小数点型に大きく依存します。

AbstractFloat 値の ULP は、 AbstractFloat がIEEE-754 binary64 型と同一であると仮定します。

f32 値の 1 ULP は、IEEE-754 binary64 値の 1 ULP より 229 倍大きくなります。 これは、binary64 形式の仮数が f32 型の仮数より 29 ビット長いためです。

たとえば、演算の真の結果値が x で、x' として計算されたとします。 その誤差 x-x' が f32 で 3 ULP の場合、同じ絶対誤差 x-x' は、 AbstractFloat では 3·229 ULP です。

15.7.5. 再結合と融合

再結合は、 正確に計算すれば答えが同じになるように式内の演算を並べ替えることです。たとえば:

ただし、浮動小数点で計算すると結果は同じでない場合があります。 再結合された結果は近似によって不正確になる場合があり、または中間結果の計算時にオーバーフローや NaN を引き起こす場合があります。

実装は演算を再結合してもかまいません。

変換後の式が元の定式化と同等以上の精度である場合、 実装は演算を融合してもかまいません。 たとえば、一部の融合積和実装は、 乗算の後に加算を行うよりも高精度になる場合があります。

15.7.6. 浮動小数点変換

この節では、変換元または変換先のいずれかが浮動小数点型であるスカラー変換の詳細について説明します。

この節では、浮動小数点型は次のいずれでもかまいません:

注: WGSL のf32 型は IEEE-754 のbinary32 形式に対応し、 WGSL のf16 型は IEEE-754 のbinary16 形式に対応することを思い出してください。

スカラー浮動小数点から整数への変換 アルゴリズムは次のとおりです:

浮動小数点スカラー値 X を整数スカラー型 T に変換するには:

注: 言い換えると、NaN でない場合の 浮動小数点から整数への変換では、 値を対象型の範囲内にクランプしてから、ゼロ方向へ丸めます。 このクランプ要件は、WGSL が意味のある結果を必須とする一方、 C および C++ では未定義動作となり、 IEEE-754 では無効な演算例外と NaN 結果を 必須とする箇所の 1 つです。

注: たとえば:

浮動小数点への数値スカラー変換 アルゴリズムは次のとおりです:

アルゴリズム: 浮動小数点への数値スカラー変換

入力:

出力: XOut、X を型 T に変換した結果、または エラーを生成します。

手順:

注: 整数値は、隣接する 2 つの 表現可能な浮動小数点値の間に位置する場合があります。 特に、f32 型は 23 個の明示的な 小数部ビットを使用します。 さらに、浮動小数点値が正規範囲内(指数がいずれの極値でもない)にある場合、 仮数は小数部ビットに、ビット位置 23 の最上位位置にある追加の 1 ビットを加えた集合です。 したがって、たとえば整数 228 と 1+228 は、どちらも同じ浮動小数点値に対応付けられます。 最下位の 1 ビットの差は浮動小数点形式では表現できません。 この種の衝突は、大きさが少なくとも 225 の隣接整数のペアで発生します。

注: 元の型がi32 またはu32 のいずれかで、 変換先型がf32 の場合、 元の値は常に変換先型の範囲内です。

注: 変換元型が、 変換先の浮動小数点型より指数ビットと仮数ビットが少ない浮動小数点型である場合、 元の値は常に変換先型の範囲内です。

15.7.7. 浮動小数点式と組み込み関数の定義域

前の節では、浮動小数点式がその定義域外で評価された場合の期待される動作について説明しています。

§ 8.8 算術式および§ 17.5 数値組み込み関数は、それぞれ浮動小数点式と 組み込み関数の定義域を定義します。 特定の演算について制限が記載されていない場合、定義域は全域です。つまり、定義域にはすべての有限および 無限大の入力が含まれます。 それ以外の場合は、明示的な定義域が記載されます。

WGSL 演算がIEEE-754 で定義された演算に対応する多くの場合、 両者は同じ定義域を持ちます。 たとえば WGSL と IEEE-754 の acos 演算はいずれも定義域 [−1,1] を持ちます。

明示的に定義域が記載された成分ごとの WGSL 演算については、スカラーの場合だけが説明されます。ベクトルの場合は成分ごとのセマンティクスから推論されます。

一部の WGSL 演算は、他の WGSL 式を用いて実装される場合があります。 § 15.7.4 浮動小数点精度では、これらを継承元の精度を持つものとして記載しています。 これらの演算の定義域を記載する場合、次のいずれかです:

たとえば、2 要素ベクトル a と b に対する dot(a,b) 関数の 精度は、式 a[0] * b[0] + a[1] * b[1] から継承されます。 これは浮動小数点乗算を 2 回、浮動小数点加算を 1 回使用します。

16. キーワードとトークンの概要

16.1. キーワードの概要

16.2. 予約語

予約語は、 将来の使用のために予約されているトークンです。 WGSL モジュールに予約語を含めてはなりません。

次は予約語です:

_reserved :

| 'NULL'

| 'Self'

| 'abstract'

| 'active'

| 'alignas'

| 'alignof'

| 'as'

| 'asm'

| 'asm_fragment'

| 'async'

| 'attribute'

| 'auto'

| 'await'

| 'become'

| 'cast'

| 'catch'

| 'class'

| 'co_await'

| 'co_return'

| 'co_yield'

| 'coherent'

| 'column_major'

| 'common'

| 'compile'

| 'compile_fragment'

| 'concept'

| 'const_cast'

| 'consteval'

| 'constexpr'

| 'constinit'

| 'crate'

| 'debugger'

| 'decltype'

| 'delete'

| 'demote'

| 'demote_to_helper'

| 'do'

| 'dynamic_cast'

| 'enum'

| 'explicit'

| 'export'

| 'extends'

| 'extern'

| 'external'

| 'fallthrough'

| 'filter'

| 'final'

| 'finally'

| 'friend'

| 'from'

| 'fxgroup'

| 'get'

| 'goto'

| 'groupshared'

| 'highp'

| 'impl'

| 'implements'

| 'import'

| 'inline'

| 'instanceof'

| 'interface'

| 'layout'

| 'lowp'

| 'macro'

| 'macro_rules'

| 'match'

| 'mediump'

| 'meta'

| 'mod'

| 'module'

| 'move'

| 'mut'

| 'mutable'

| 'namespace'

| 'new'

| 'nil'

| 'noexcept'

| 'noinline'

| 'nointerpolation'

| 'non_coherent'

| 'noncoherent'

| 'noperspective'

| 'null'

| 'nullptr'

| 'of'

| 'operator'

| 'package'

| 'packoffset'

| 'partition'

| 'pass'

| 'patch'

| 'pixelfragment'

| 'precise'

| 'precision'

| 'premerge'

| 'priv'

| 'protected'

| 'pub'

| 'public'

| 'readonly'

| 'ref'

| 'regardless'

| 'register'

| 'reinterpret_cast'

| 'require'

| 'resource'

| 'restrict'

| 'self'

| 'set'

| 'shared'

| 'sizeof'

| 'smooth'

| 'snorm'

| 'static'

| 'static_assert'

| 'static_cast'

| 'std'

| 'subroutine'

| 'super'

| 'target'

| 'template'

| 'this'

| 'thread_local'

| 'throw'

| 'trait'

| 'try'

| 'type'

| 'typedef'

| 'typeid'

| 'typename'

| 'typeof'

| 'union'

| 'unless'

| 'unorm'

| 'unsafe'

| 'unsized'

| 'use'

| 'using'

| 'varying'

| 'virtual'

| 'volatile'

| 'wgsl'

| 'where'

| 'with'

| 'writeonly'

| 'yield'

16.3. 構文トークン

構文トークンは、 次の目的で使用される特殊なコードポイントの並びです:

構文トークンは次のとおりです:

17. 組み込み関数

特定の関数は、実装によって提供される事前宣言済みの関数であり、 したがって WGSL モジュール内で常に使用できます。 これらを組み込み 関数と呼びます。

組み込み関数はすべて同じ名前を持つ関数のファミリーですが、 仮引数の数、順序、および型によって区別されます。 これらの異なる関数バリエーションのそれぞれをオーバーロードと呼びます。

注: 各ユーザー定義関数には オーバーロードが 1 つだけあります。

各オーバーロードは、以下で次によって説明されます:

組み込み関数を呼び出す場合、関数のすべての引数は 関数の評価が開始される前に評価されます。 § 11.2 関数呼び出しを参照してください。

17.1. コンストラクター組み込み関数

値コンストラクター 組み込み関数は、指定された型の 値を明示的に作成します。

WGSL は、すべての事前宣言済み型、およびすべての 構築可能な構造体型に対する値コンストラクターを提供します。 このようなコンストラクター組み込み関数は、型またはその型の型エイリアスと同じ綴りを持ちます。 このような組み込み関数が使用される箇所では、識別子は型または型エイリアスのスコープ内になければならず、 その識別子は 別の宣言に解決されてはなりません。

注: frexp、 modf、およびatomicCompareExchangeWeak が返す構造体型は、 WGSL モジュール内に記述できません。

注: その型の値宣言は、 WGSL テキストのその文で有効である必要があります。

WGSL は 2 種類の値コンストラクターを提供します:

17.1.1. ゼロ値組み込み関数

各具象かつ構築可能な T は、 一意のゼロ値を持ち、 対応する組み込み関数は WGSL で型の後に空の括弧の組を付けて記述されます: T ()。 抽象数値 型にもゼロ値がありますが、それらへアクセスする組み込み関数はありません。

ゼロ値は次のとおりです:

注: WGSL にはアトミック型、 ランタイムサイズ配列、バッファー、 またはその他の構築可能でない型に対するゼロ組み込み関数はありません。

オーバーロード
@const @must_use fn T() -> T
パラメーター化 T は具象の構築可能型です。
説明 型 T のゼロ値を 構築します。

注: AbstractInt のゼロで埋められたベクトルは、 vec2()、vec3()、および vec4() として記述できます。

例: ゼロ値のベクトル
vec2<f32>()                 // 2 つの f32 成分からなるゼロ値ベクトル。
vec2<f32>(0.0, 0.0)         // 同じ値を明示的に記述したもの。

vec3<i32>()                 // 3 つの i32 成分からなるゼロ値ベクトル。
vec3<i32>(0, 0, 0)          // 同じ値を明示的に記述したもの。
例: ゼロ値の配列
array<bool, 2>()               // 2 つのブール値からなるゼロ値配列。
array<bool, 2>(false, false)   // 同じ値を明示的に記述したもの。
例: ゼロ値の構造体
struct Student {
  grade: i32,
  GPA: f32,
  attendance: array<bool,4>
}

fn func() {
  var s: Student;

  // Student のゼロ値
  s = Student();

  // 同じ値を明示的に記述したもの。
  s = Student(0, 0.0, array<bool,4>(false, false, false, false));

  // 同じ値をゼロ値メンバーで記述したもの。
  s = Student(i32(), f32(), array<bool,4>());
}

17.1.2. 値コンストラクター組み込み関数

以下の小節で定義される組み込み関数は、次の方法で構築可能な値を作成します:

ベクトル形式と行列形式は、成分型が一致する成分と部分ベクトルのさまざまな組み合わせから、 ベクトル値と行列値を構築します。 対象型の次元を指定しつつ成分型を指定する必要がない、ベクトルおよび行列を構築するためのオーバーロードがあります。 成分型はコンストラクター引数から推論されます。

17.1.2.1. array
オーバーロード
@const @must_use fn array<T, N>(e1 : T, ..., eN : T) -> array<T, N>
パラメーター化 T は具象かつ構築可能
説明 要素から配列を構築します。

注: array<T,N> は、その要素数が コンストラクターへの引数の数と等しく、したがってシェーダー作成時に完全に決定されるため、構築可能です。

オーバーロード
@const @must_use fn array(e1 : T, ..., eN : T) -> array<T, N>
パラメーター化 T は構築可能
説明 要素から配列を構築します。

成分型は要素の型から推論されます。 配列のサイズは要素数によって決定されます。

17.1.2.2. bool
オーバーロード
@const @must_use fn bool(e : T) -> bool
パラメーター化 T はスカラー 型です。
説明 bool 値を構築します。

T がbool の場合、 これは恒等演算です。
それ以外の場合、これはブール値への強制変換です。 e がゼロ値(浮動小数点型の場合は -0.0 も含む)なら 結果は false、それ以外の場合は true です。

17.1.2.3. f16
オーバーロード
@const @must_use fn f16(e : T) -> f16
パラメーター化 T はスカラー型
説明 f16 値を構築します。

T がf16 の場合、これは 恒等演算です。
T が数値スカラー(f16 を除く)の場合、e はf16 に変換されます(無効な 変換を含む)。
T がbool の場合、 e が true なら結果は 1.0h、それ以外は 0.0h です。

17.1.2.4. f32
オーバーロード
@const @must_use fn f32(e : T) -> f32
パラメーター化 T は具象スカラー型
説明 f32 値を構築します。

T がf32 の場合、これは 恒等演算です。
T が数値スカラー(f32 を除く)の場合、e はf32 に変換されます(無効な 変換を含む)。
T がbool の場合、 e が true なら結果は 1.0f、それ以外は 0.0f です。

17.1.2.5. i32
オーバーロード
@const @must_use fn i32(e : T) -> i32
パラメーター化 T はスカラー型
説明 i32 値を構築します。

T がi32 の場合、これは 恒等演算です。
T がu32 の場合、これは ビットの再解釈です(すなわち、結果は e と同じビットパターンを持つi32 の一意の値です)。
T が浮動小数点型の場合、 e はゼロ方向に丸めながら、変換されてi32 になります。
T がbool の場合、 e が true なら結果は 1i、それ以外は 0i です。
T がAbstractInt の場合、e をi32 で表現できれば恒等演算であり、 それ以外の場合はシェーダー作成 エラーを生成します。

17.1.2.6. mat2x2
オーバーロード
@const @must_use fn mat2x2<T>(e : mat2x2<S>) -> mat2x2<T>
@const @must_use fn mat2x2(e : mat2x2<S>) -> mat2x2<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 2x2 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat2x2<T>(v1 : vec2<T>, v2 : vec2<T>) -> mat2x2<T>
@const @must_use fn mat2x2(v1 : vec2<T>, v2 : vec2<T>) -> mat2x2<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 2x2 列優先行列を構築します。
オーバーロード
@const @must_use fn mat2x2<T>(e1 : T, e2 : T, e3 : T, e4 : T) -> mat2x2<T>
@const @must_use fn mat2x2(e1 : T, e2 : T, e3 : T, e4 : T) -> mat2x2<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 2x2 列優先行列を構築します。

mat2x2(vec2(e1,e2), vec2(e3,e4)) と同じです。

17.1.2.7. mat2x3
オーバーロード
@const @must_use fn mat2x3<T>(e : mat2x3<S>) -> mat2x3<T>
@const @must_use fn mat2x3(e : mat2x3<S>) -> mat2x3<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 2x3 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat2x3<T>(v1 : vec3<T>, v2 : vec3<T>) -> mat2x3<T>
@const @must_use fn mat2x3(v1 : vec3<T>, v2 : vec3<T>) -> mat2x3<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 2x3 列優先行列を構築します。
オーバーロード
@const @must_use fn mat2x3<T>(e1 : T, ..., e6 : T) -> mat2x3<T>
@const @must_use fn mat2x3(e1 : T, ..., e6 : T) -> mat2x3<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 2x3 列優先行列を構築します。

mat2x3(vec3(e1,e2,e3), vec3(e4,e5,e6)) と同じです。

17.1.2.8. mat2x4
オーバーロード
@const @must_use fn mat2x4<T>(e : mat2x4<S>) -> mat2x4<T>
@const @must_use fn mat2x4(e : mat2x4<S>) -> mat2x4<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 2x4 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat2x4<T>(v1 : vec4<T>, v2 : vec4<T>) -> mat2x4<T>
@const @must_use fn mat2x4(v1 : vec4<T>, v2 : vec4<T>) -> mat2x4<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 2x4 列優先行列を構築します。
オーバーロード
@const @must_use fn mat2x4<T>(e1 : T, ..., e8 : T) -> mat2x4<T>
@const @must_use fn mat2x4(e1 : T, ..., e8 : T) -> mat2x4<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 2x4 列優先行列を構築します。

mat2x4(vec4(e1,e2,e3,e4), vec4(e5,e6,e7,e8)) と同じです。

17.1.2.9. mat3x2
オーバーロード
@const @must_use fn mat3x2<T>(e : mat3x2<S>) -> mat3x2<T>
@const @must_use fn mat3x2(e : mat3x2<S>) -> mat3x2<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 3x2 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat3x2<T>(v1 : vec2<T>,
                              v2 : vec2<T>,
                              v3 : vec2<T>) -> mat3x2<T>
@const @must_use fn mat3x2(v1 : vec2<T>,
                           v2 : vec2<T>,
                           v3 : vec2<T>) -> mat3x2<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 3x2 列優先行列を構築します。
オーバーロード
@const @must_use fn mat3x2<T>(e1 : T, ..., e6 : T) -> mat3x2<T>
@const @must_use fn mat3x2(e1 : T, ..., e6 : T) -> mat3x2<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 3x2 列優先行列を構築します。

mat3x2(vec2(e1,e2), vec2(e3,e4), vec2(e5,e6)) と同じです。

17.1.2.10. mat3x3
オーバーロード
@const @must_use fn mat3x3<T>(e : mat3x3<S>) -> mat3x3<T>
@const @must_use fn mat3x3(e : mat3x3<S>) -> mat3x3<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 3x3 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat3x3<T>(v1 : vec3<T>,
                              v2 : vec3<T>,
                              v3 : vec3<T>) -> mat3x3<T>
@const @must_use fn mat3x3(v1 : vec3<T>,
                           v2 : vec3<T>,
                           v3 : vec3<T>) -> mat3x3<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 3x3 列優先行列を構築します。
オーバーロード
@const @must_use fn mat3x3<T>(e1 : T, ..., e9 : T) -> mat3x3<T>
@const @must_use fn mat3x3(e1 : T, ..., e9 : T) -> mat3x3<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 3x3 列優先行列を構築します。

mat3x3(vec3(e1,e2,e3), vec3(e4,e5,e6), vec3(e7,e8,e9)) と同じです。

17.1.2.11. mat3x4
オーバーロード
@const @must_use fn mat3x4<T>(e : mat3x4<S>) -> mat3x4<T>
@const @must_use fn mat3x4(e : mat3x4<S>) -> mat3x4<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 3x4 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat3x4<T>(v1 : vec4<T>,
                              v2 : vec4<T>,
                              v3 : vec4<T>) -> mat3x4<T>
@const @must_use fn mat3x4(v1 : vec4<T>,
                           v2 : vec4<T>,
                           v3 : vec4<T>) -> mat3x4<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 3x4 列優先行列を構築します。
オーバーロード
@const @must_use fn mat3x4<T>(e1 : T, ..., e12 : T) -> mat3x4<T>
@const @must_use fn mat3x4(e1 : T, ..., e12 : T) -> mat3x4<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 3x4 列優先行列を構築します。

mat3x4(vec4(e1,e2,e3,e4), vec4(e5,e6,e7,e8), vec4(e9,e10,e11,e12)) と同じです。

17.1.2.12. mat4x2
オーバーロード
@const @must_use fn mat4x2<T>(e : mat4x2<S>) -> mat4x2<T>
@const @must_use fn mat4x2(e : mat4x2<S>) -> mat4x2<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 4x2 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat4x2<T>(v1 : vec2<T>,
                              v2 : vec2<T>,
                              v3 : vec2<T>,
                              v4: vec2<T>) -> mat4x2<T>
@const @must_use fn mat4x2(v1 : vec2<T>,
                           v2 : vec2<T>,
                           v3 : vec2<T>,
                           v4: vec2<T>) -> mat4x2<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 4x2 列優先行列を構築します。
オーバーロード
@const @must_use fn mat4x2<T>(e1 : T, ..., e8 : T) -> mat4x2<T>
@const @must_use fn mat4x2(e1 : T, ..., e8 : T) -> mat4x2<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 4x2 列優先行列を構築します。

mat4x2(vec2(e1,e2), vec2(e3,e4), vec2(e5,e6), vec2(e7,e8)) と同じです。

17.1.2.13. mat4x3
オーバーロード
@const @must_use fn mat4x3<T>(e : mat4x3<S>) -> mat4x3<T>
@const @must_use fn mat4x3(e : mat4x3<S>) -> mat4x3<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 4x3 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat4x3<T>(v1 : vec3<T>,
                              v2 : vec3<T>,
                              v3 : vec3<T>,
                              v4 : vec3<T>) -> mat4x3<T>
@const @must_use fn mat4x3(v1 : vec3<T>,
                           v2 : vec3<T>,
                           v3 : vec3<T>,
                           v4 : vec3<T>) -> mat4x3<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 4x3 列優先行列を構築します。
オーバーロード
@const @must_use fn mat4x3<T>(e1 : T, ..., e12 : T) -> mat4x3<T>
@const @must_use fn mat4x3(e1 : T, ..., e12 : T) -> mat4x3<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 4x3 列優先行列を構築します。

mat4x3(vec3(e1,e2,e3), vec3(e4,e5,e6), vec3(e7,e8,e9), vec3(e10,e11,e12)) と同じです。

17.1.2.14. mat4x4
オーバーロード
@const @must_use fn mat4x4<T>(e : mat4x4<S>) -> mat4x4<T>
@const @must_use fn mat4x4(e : mat4x4<S>) -> mat4x4<S>
パラメーター化 T はf16 またはf32
S はAbstractFloat、f16、またはf32
説明 4x4 列優先行列のコンストラクターです。

T が S と一致しない場合、変換が行われます。

オーバーロード
@const @must_use fn mat4x4<T>(v1 : vec4<T>,
                              v2 : vec4<T>,
                              v3 : vec4<T>,
                              v4 : vec4<T>) -> mat4x4<T>
@const @must_use fn mat4x4(v1 : vec4<T>,
                           v2 : vec4<T>,
                           v3 : vec4<T>,
                           v4 : vec4<T>) -> mat4x4<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 列ベクトルから 4x4 列優先行列を構築します。
オーバーロード
@const @must_use fn mat4x4<T>(e1 : T, ..., e16 : T) -> mat4x4<T>
@const @must_use fn mat4x4(e1 : T, ..., e16 : T) -> mat4x4<T>
パラメーター化 T はAbstractFloat、f16、またはf32
説明 要素から 4x4 列優先行列を構築します。

mat4x4(vec4(e1,e2,e3,e4), vec4(e5,e6,e7,e8), vec4(e9,e10,e11,e12), vec4(e13,e14,e15,e16)) と同じです。

17.1.2.15. 構造体
オーバーロード
@const @must_use fn S(e1 : T1, ..., eN : TN) -> S
パラメーター化 S は、型 T1 ... TN のメンバーを持つ構築可能な構造体型です。
説明 メンバーから型 S の構造体を構築します。
17.1.2.16. u32
オーバーロード
@const @must_use fn u32(e : T) -> u32
パラメーター化 T はスカラー型
説明 u32 値を構築します。

T がu32 の場合、これは 恒等演算です。
T がi32 の場合、これは ビットの再解釈です(すなわち、結果は e と同じビットパターンを持つu32 の一意の値です)。
T が浮動小数点型の場合、 e はゼロ方向に丸めながら、変換されてu32 になります。
T がbool の場合、 e が true なら結果は 1u、それ以外は 0u です。
T がAbstractInt の場合、e をu32 で表現できれば恒等演算であり、それ以外の場合はシェーダー作成 エラーを生成します。

注: AbstractInt からのオーバーロードは、u32(4*1000*1000*1000) のような式が、 そうでなければ i32 型でオーバーフローする u32 値を作成できるようにするため存在します。このオーバーロードが存在しない場合、オーバーロード解決は u32(i32) オーバーロードを選択し、AbstractInt 式は自動的に i32 へ変換され、オーバーフローによりシェーダー作成エラーが発生します。

17.1.2.17. vec2
オーバーロード
@const @must_use fn vec2<T>(e : T) -> vec2<T>
@const @must_use fn vec2(e : S) -> vec2<S>
パラメーター化 T は具象スカラー
S はスカラー
説明 e を両方の成分とする 2 成分ベクトルを構築します。
オーバーロード
@const @must_use fn vec2<T>(e : vec2<S>) -> vec2<T>
@const @must_use fn vec2(e : vec2<S>) -> vec2<S>
パラメーター化 T は具象スカラー
S はスカラー
説明 e.x と e.y を成分とする 2 成分ベクトルの成分ごとの構築です。

T が S と一致しない場合は変換が使用され、成分は T(e.x) と T(e.y) になります。

オーバーロード
@const @must_use fn vec2<T>(e1 : T, e2 : T) -> vec2<T>
@const @must_use fn vec2(e1 : T, e2 : T) -> vec2<T>
パラメーター化 T はスカラー
説明 e1 と e2 を成分とする 2 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec2() -> vec2<T>
パラメーター化 T は AbstractInt
説明 値 vec2(0,0) を返します。
17.1.2.18. vec3
オーバーロード
@const @must_use fn vec3<T>(e : T) -> vec3<T>
@const @must_use fn vec3(e : S) -> vec3<S>
パラメーター化 T は具象スカラー
S はスカラー
説明 e をすべての成分とする 3 成分ベクトルを構築します。
オーバーロード
@const @must_use fn vec3<T>(e : vec3<S>) -> vec3<T>
@const @must_use fn vec3(e : vec3<S>) -> vec3<S>
パラメーター化 T は具象スカラー
S はスカラー
説明 e.x、e.y、および e.z を成分とする 3 成分ベクトルの成分ごとの構築です。

T が S と一致しない場合は変換が使用され、成分は T(e.x)、T(e.y)、および T(e.z) になります。

オーバーロード
@const @must_use fn vec3<T>(e1 : T, e2 : T, e3 : T) -> vec3<T>
@const @must_use fn vec3(e1 : T, e2 : T, e3 : T) -> vec3<T>
パラメーター化 T はスカラー
説明 e1、e2、および e3 を成分とする 3 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec3<T>(v1 : vec2<T>, e1 : T) -> vec3<T>
@const @must_use fn vec3(v1 : vec2<T>, e1 : T) -> vec3<T>
パラメーター化 T はスカラー
説明 v1.x、v1.y、および e1 を成分とする 3 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec3<T>(e1 : T, v1 : vec2<T>) -> vec3<T>
@const @must_use fn vec3(e1 : T, v1 : vec2<T>) -> vec3<T>
パラメーター化 T はスカラー
説明 e1、v1.x、および v1.y を成分とする 3 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec3() -> vec3<T>
パラメーター化 T は AbstractInt
説明 値 vec3(0,0,0) を返します。
17.1.2.19. vec4
オーバーロード
@const @must_use fn vec4<T>(e : T) -> vec4<T>
@const @must_use fn vec4(e : S) -> vec4<S>
パラメーター化 T は具象スカラー
S はスカラー
説明 e をすべての成分とする 4 成分ベクトルを構築します。
オーバーロード
@const @must_use fn vec4<T>(e : vec4<S>) -> vec4<T>
@const @must_use fn vec4(e : vec4<S>) -> vec4<S>
パラメーター化 T は具象スカラー
S はスカラー
説明 e.x、e.y、e.z、 および e.w を成分とする 4 成分ベクトルの成分ごとの構築です。

T が S と一致しない場合は変換が使用され、成分は T(e.x)、T(e.y)、T(e.z)、および T(e.w) になります。

オーバーロード
@const @must_use fn vec4<T>(e1 : T, e2 : T, e3 : T, e4 : T) -> vec4<T>
@const @must_use fn vec4(e1 : T, e2 : T, e3 : T, e4 : T) -> vec4<T>
パラメーター化 T はスカラー
説明 e1、e2、e3、および e4 を成分とする 4 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec4<T>(e1 : T, v1 : vec2<T>, e2 : T) -> vec4<T>
@const @must_use fn vec4(e1 : T, v1 : vec2<T>, e2 : T) -> vec4<T>
パラメーター化 T はスカラー
説明 e1、v1.x、v1.y、 および e2 を成分とする 4 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec4<T>(e1 : T, e2 : T, v1 : vec2<T>) -> vec4<T>
@const @must_use fn vec4(e1 : T, e2 : T, v1 : vec2<T>) -> vec4<T>
パラメーター化 T はスカラー
説明 e1、e2、v1.x、 および v1.y を成分とする 4 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec4<T>(v1 : vec2<T>, v2 : vec2<T>) -> vec4<T>
@const @must_use fn vec4(v1 : vec2<T>, v2 : vec2<T>) -> vec4<T>
パラメーター化 T はスカラー
説明 v1.x、v1.y、 v2.x、および v2.y を成分とする 4 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec4<T>(v1 : vec2<T>, e1 : T, e2 : T) -> vec4<T>
@const @must_use fn vec4(v1 : vec2<T>, e1 : T, e2 : T) -> vec4<T>
パラメーター化 T はスカラー
説明 v1.x、v1.y、e1、 および e2 を成分とする 4 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec4<T>(v1 : vec3<T>, e1 : T) -> vec4<T>
@const @must_use fn vec4(v1 : vec3<T>, e1 : T) -> vec4<T>
パラメーター化 T はスカラー
説明 v1.x、v1.y、 v1.z、および e1 を成分とする 4 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec4<T>(e1 : T, v1 : vec3<T>) -> vec4<T>
@const @must_use fn vec4(e1 : T, v1 : vec3<T>) -> vec4<T>
パラメーター化 T はスカラー
説明 e1、v1.x、v1.y、 および v1.z を成分とする 4 成分ベクトルの成分ごとの構築です。
オーバーロード
@const @must_use fn vec4() -> vec4<T>
パラメーター化 T は AbstractInt
説明 値 vec4(0,0,0,0) を返します。

17.2. ビット再解釈組み込み関数

17.2.1. bitcast

bitcast 組み込み関数は、ある型の値のビット表現を 別の型の値として再解釈するために使用されます。

内部レイアウト規則については、§ 14.4.4 値の内部レイアウトで説明されています。

オーバーロード
@const @must_use fn bitcast<T>(e : T) -> T
パラメーター化 T は具象数値スカラーまたは具象数値ベクトル
説明 恒等変換。
T がベクトルの場合は成分ごと。
結果は e です。
オーバーロード
@const @must_use fn bitcast<T>(e : S) -> T
パラメーター化 S は i32、u32、または f32
T は S ではなく、i32、u32、または f32
説明 T としてのビットの再解釈。
結果は e のビットを T 値として再解釈したものです。
オーバーロード
@const @must_use fn bitcast<vecN<T>>(e : vecN<S>) -> vecN<T>
パラメーター化 S は i32、u32、または f32
T は S ではなく、i32、u32、または f32
説明 T としてのビットの成分ごとの 再解釈。
結果は e のビットを vecN<T> 値として再解釈したものです。
オーバーロード
@const @must_use fn bitcast<u32>(e : AbstractInt) -> u32
@const @must_use fn bitcast<vecN<u32>>(e : vecN<AbstractInt>) -> vecN<u32>
パラメーター化
説明 e をu32 として表現できる場合は恒等演算であり、 それ以外の場合はシェーダー作成エラーを生成します。 すなわち、u32(e) と同じ結果を生成します。

e がベクトルの場合は成分ごとです。

オーバーロード
@const @must_use fn bitcast<T>(e : vec2<f16>) -> T
パラメーター化 T は i32、u32、または f32
説明 T としてのビットの成分ごとの 再解釈。
結果は、内部レイアウト規則に従って、e の 32 ビットを T 値として 再解釈したものです。
オーバーロード
@const @must_use fn bitcast<vec2<T>>(e : vec4<f16>) -> vec2<T>
パラメーター化 T は i32、u32、または f32
説明 T としてのビットの成分ごとの 再解釈。
結果は、内部レイアウト規則に従って、e の 64 ビットを T 値として 再解釈したものです。
オーバーロード
@const @must_use fn bitcast<vec2<f16>>(e : T) -> vec2<f16>
パラメーター化 T は i32、u32、または f32
説明 f16 としてのビットの成分ごとの 再解釈。
結果は、内部レイアウト規則に従って、e の 32 ビットを f16 値として再解釈したものです。
オーバーロード
@const @must_use fn bitcast<vec4<f16>>(e : vec2<T>) -> vec4<f16>
パラメーター化 T は i32、u32、または f32
説明 vec2<f16> としてのビットの成分ごとの 再解釈。
結果は、内部レイアウト規則に従って、e の 64 ビットを f16 値として再解釈したものです。

17.3. 論理組み込み関数

17.3.1. all

オーバーロード
@const @must_use fn all(e: vecN<bool>) -> bool
説明 e の各成分が true の場合に true を返します。
オーバーロード
@const @must_use fn all(e: bool) -> bool
説明 e を返します。

17.3.2. any

オーバーロード
@const @must_use fn any(e: vecN<bool>) -> bool
説明 e のいずれかの成分が true の場合に true を返します。
オーバーロード
@const @must_use fn any(e: bool) -> bool
説明 e を返します。

17.3.3. select

オーバーロード
@const @must_use fn select(f: T,
                           t: T,
                           cond: bool) -> T
パラメーター化 T はスカラーまたはベクトル
説明 cond が true の場合は t、それ以外の場合は f を返します。
オーバーロード
@const @must_use fn select(f: vecN<T>,
                           t: vecN<T>,
                           cond: vecN<bool>) -> vecN<T>
パラメーター化 T はスカラー
説明 成分ごとの 選択。結果の成分 i は select(f[i], t[i], cond[i]) として評価されます。

17.4. 配列組み込み関数

17.4.1. arrayLength

オーバーロード
@must_use fn arrayLength(p: ptr<AS, array<E>, AM>) -> u32
パラメーター化 E はランタイムサイズ配列の要素型です。
AS はstorage、uniform、 またはworkgroup のいずれかです。
アクセスモード AM はread またはread_write であり、AS に対して有効でなければなりません。

注: p が bufferView または bufferArrayView 組み込み関数の結果から導出される場合に限り、 AS はuniform またはworkgroup にできます。

説明 NRuntime、すなわち ランタイムサイズ配列内の要素数を返します。

§ 13.3.4 バッファー バインディングによるランタイムサイズ配列の要素数の決定を参照してください

p がbufferView または bufferArrayView 組み込み関数から導出される場合、 NRuntime は § 17.14 バッファービュー組み込み 関数の解析で決定されるバッファーのサイズに基づきます。

例: ランタイムサイズ配列の要素数の取得
struct PointLight {
  position : vec3f,
  color : vec3f,
}

struct LightStorage {
  pointCount : u32,
  point : array<PointLight>,
}

@group(0) @binding(1) var<storage> lights : LightStorage;

fn num_point_lights() -> u32 {
  return arrayLength( &lights.point );
}

17.5. 数値組み込み関数

17.5.1. abs

オーバーロード
@const @must_use fn abs(e: T ) -> T
パラメーター化 S は AbstractInt、AbstractFloat、i32、u32、f32、または f16
T は S、または vecN<S>
説明 e の絶対値。 T がベクトルの場合は成分ごとです。

e が浮動小数点型の場合、結果は符号ビットを正にした e です。 e が符号なし整数スカラー型の場合、結果は e です。 e が符号付き整数スカラー型で、最大の 負の値に評価される場合、結果は e です。

17.5.2. acos

オーバーロード
@const @must_use fn acos(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の逆余弦(cos-1)の主値をラジアンで返します。
すなわち、cos(x) = e となる 0 ≤ x ≤ π の x を近似します。

T がベクトルの場合は成分ごとです。

スカラー定義域 区間 [−1, 1]

17.5.3. acosh

オーバーロード
@const @must_use fn acosh(x: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 x の逆双曲線余弦(cosh-1)を双曲角として返します。
すなわち、cosh(a) = x となる 0 ≤ a ≤ +∞ の a を近似します。

T がベクトルの場合は成分ごとです。

スカラー定義域 区間 [1, +∞]

17.5.4. asin

オーバーロード
@const @must_use fn asin(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の逆正弦(sin-1)の主値をラジアンで返します。
すなわち、sin(x) = e となる -π/2 ≤ x ≤ π/2 の x を近似します。

T がベクトルの場合は成分ごとです。

スカラー定義域 区間 [−1, 1]

17.5.5. asinh

オーバーロード
@const @must_use fn asinh(y: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 y の逆双曲線正弦(sinh-1)を双曲角として返します。
すなわち、sinh(y) = a となる a を近似します。

T がベクトルの場合は成分ごとです。

17.5.6. atan

オーバーロード
@const @must_use fn atan(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の逆正接(tan-1)の主値をラジアンで返します。
すなわち、tan(x) = e となる − π/2 ≤ x ≤ π/2 の x を近似します。

T がベクトルの場合は成分ごとです。

17.5.7. atanh

オーバーロード
@const @must_use fn atanh(t: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 t の逆双曲線正接(tanh-1)を双曲角として返します。
すなわち、tanh(a) = t となる a を近似します。

T がベクトルの場合は成分ごとです。

スカラー定義域 区間 [−1, 1]

17.5.8. atan2

オーバーロード
@const @must_use fn atan2(y: T,
                          x: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 正接が y÷x である区間 [-π, π] 内の角度をラジアンで返します。

結果によって選択される象限は、y と x の符号に依存します。 たとえば、この関数は次のように実装できます:

  • x > 0 の場合は atan(y/x)

  • (x < 0) かつ (y > 0) の場合は atan(y/x) + π

  • (x < 0) かつ (y < 0) の場合は atan(y/x) - π

注: 結果の誤差には上限がありません:
  • abs(x) が非常に小さい場合、たとえばその型で非正規の場合、

  • 原点 (x,y) = (0,0) の場合、または

  • y が非正規または無限大の場合。

T がベクトルの場合は成分ごとです。

17.5.9. ceil

オーバーロード
@const @must_use fn ceil(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の天井値を返します。 T がベクトルの場合は成分ごとです。

17.5.10. clamp

オーバーロード
@const @must_use fn clamp(e: T,
                          low: T,
                          high: T) -> T
パラメーター化 S は AbstractInt、AbstractFloat、i32、u32、f32、または f16
T は S、または vecN<S>
説明 e の値を範囲内に制限します。

T が整数型の場合、結果は min(max(e, low), high) です。

T が浮動小数点型の場合、結果は min(max(e, low), high)、または 3 つの値 e、 low、high の中央値のいずれかです。

T がベクトルの場合は成分ごとです。

low が high より大きい場合:

17.5.11. cos

オーバーロード
@const @must_use fn cos(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 ラジアン単位の e の余弦を返します。 T がベクトルの場合は成分ごとです。
スカラー定義域 区間 (−∞, +∞)

17.5.12. cosh

オーバーロード
@const @must_use fn cosh(a: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 双曲角である a の双曲線余弦を返します。 純粋な数学関数 (ea + e−a)÷2 を近似しますが、 必ずしもその方法で計算されるわけではありません。

T がベクトルの場合は成分ごとです

17.5.13. countLeadingZeros

オーバーロード
@const @must_use fn countLeadingZeros(e: T) -> T
パラメーター化 T は i32、u32、vecN<i32>、または vecN<u32>
説明 T がスカラー型の場合、e の最上位ビットから始まる 連続した 0 ビットの数。
T がベクトルの場合は成分ごとです。
一部の言語では "clz" とも呼ばれます。

17.5.14. countOneBits

オーバーロード
@const @must_use fn countOneBits(e: T) -> T
パラメーター化 T は i32、u32、vecN<i32>、または vecN<u32>
説明 e の表現内の 1 ビットの数。
"population count" とも呼ばれます。
T がベクトルの場合は成分ごとです。

17.5.15. countTrailingZeros

オーバーロード
@const @must_use fn countTrailingZeros(e: T) -> T
パラメーター化 T は i32、u32、vecN<i32>、または vecN<u32>
説明 T がスカラー型の場合、e の最下位ビットから始まる 連続した 0 ビットの数。
T がベクトルの場合は成分ごとです。
一部の言語では "ctz" とも呼ばれます。

17.5.16. cross

オーバーロード
@const @must_use fn cross(a: vec3<T>,
                          b: vec3<T>) -> vec3<T>
パラメーター化 T は AbstractFloat、f32、または f16
説明 e1 と e2 の外積を返します。
定義域 可能な実装によって与えられる線形項から暗黙的に導かれます:
  • a[1] × b[2] − a[2] × b[1]

  • a[2] × b[0] − a[0] × b[2]

  • a[0] × b[1] − a[1] × b[0]

17.5.17. degrees

オーバーロード
@const @must_use fn degrees(e1: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 ラジアンを度に変換し、e1 × 180 ÷ π を近似します。 T がベクトルの場合は成分ごとです

17.5.18. determinant

オーバーロード
@const @must_use fn determinant(e: matCxC<T>) -> T
パラメーター化 T は AbstractFloat、f32、または f16
説明 e の行列式を返します。
定義域 行列式の標準的な数学的定義における線形項から暗黙的に導かれます。

17.5.19. distance

オーバーロード
@const @must_use fn distance(e1: T,
                             e2: T) -> S
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e1 と e2 の間の距離を返します(たとえば length(e1 - e2))。

定義域は、 減算 e1−e2 が有効なすべてのベクトル (e1,e2) です。 すなわち、ある成分 i について e1[i] と e2[i] が 同じ無限大値である場合を除く、すべてのベクトルの集合です。

17.5.20. dot

オーバーロード
@const @must_use fn dot(e1: vecN<T>,
                        e2: vecN<T>) -> T
パラメーター化 T は AbstractInt、AbstractFloat、i32、u32、f32、または f16
説明 e1 と e2 のドット積を返します。
定義域 項 e1[i] × e2[i] の総和の線形項から暗黙的に導かれます。

17.5.21. dot4U8Packed

オーバーロード
@const @must_use fn dot4U8Packed(e1: u32,
                                 e2: u32) -> u32
説明 e1 と e2 は、4 つの 8 ビット符号なし整数 成分を持つベクトルとして解釈されます。 これら 2 つのベクトルの符号なし整数ドット積を返します。

17.5.22. dot4I8Packed

オーバーロード
@const @must_use fn dot4I8Packed(e1: u32,
                                 e2: u32) -> i32
説明 e1 と e2 は、4 つの 8 ビット符号付き整数 成分を持つベクトルとして解釈されます。 これら 2 つのベクトルの符号付き整数ドット積を返します。各成分は乗算を行う前に i32 へ符号拡張され、その後、加算演算は WGSL i32 で行われます(結果は数学的に -65024 から 65536 の範囲内であることが保証され、この範囲は i32 で表現可能な数の範囲内にあるため、加算はオーバーフローしません)。

17.5.23. exp

オーバーロード
@const @must_use fn exp(e1: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e1 の自然指数関数(たとえば ee1)を返します。 T がベクトルの場合は成分ごとです。

17.5.24. exp2

オーバーロード
@const @must_use fn exp2(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 2 の e 乗(たとえば 2e)を返します。 T がベクトルの場合は成分ごとです。

17.5.25. extractBits(符号付き)

オーバーロード
@const @must_use fn extractBits(e: T,
                                offset: u32,
                                count: u32) -> T
パラメーター化 T は i32 または vecN<i32>
説明 整数から符号拡張付きでビットを読み取ります。

T がスカラー型の場合:

  • w は T のビット幅
  • o = min(offset, w)
  • c = min(count, w - o)
  • c が 0 の場合、結果は 0。
  • それ以外の場合、結果のビット 0..c - 1 は e のビット o..o + c - 1 からコピーされます。 結果のその他のビットは、結果のビット c - 1 と同じです。
T がベクトルの場合は成分ごとです。

count + offset が w より大きい場合:

17.5.26. extractBits(符号なし)

オーバーロード
@const @must_use fn extractBits(e: T,
                                offset: u32,
                                count: u32) -> T
パラメーター化 T は u32 または vecN<u32>
説明 整数から符号拡張なしでビットを読み取ります。

T がスカラー型の場合:

  • w は T のビット幅
  • o = min(offset, w)
  • c = min(count, w - o)
  • c が 0 の場合、結果は 0。
  • それ以外の場合、結果のビット 0..c - 1 は e のビット o..o + c - 1 からコピーされます。 結果のその他のビットは 0 です。
T がベクトルの場合は成分ごとです。

count + offset が w より大きい場合:

17.5.27. faceForward

オーバーロード
@const @must_use fn faceForward(e1: T,
                                e2: T,
                                e3: T) -> T
パラメーター化 T は vecN<AbstractFloat>、vecN<f32>、または vecN<f16>
説明 dot(e2, e3) が負の場合は e1、それ以外の場合は -e1 を返します。
定義域 定義域の制限は dot(e2,e3) 演算から生じます。これは項 e2[i] × e3[i] の総和の線形項から暗黙的に導かれます。

17.5.28. firstLeadingBit(符号付き)

オーバーロード
@const @must_use fn firstLeadingBit(e: T) -> T
パラメーター化 T は i32 または vecN<i32>
説明 スカラー T の場合、結果は:
  • e が 0 または -1 の場合は -1。
  • それ以外の場合、e の符号ビットと異なる e 内の最上位ビットの位置。

T がベクトルの場合は成分ごとです。

注: 符号付き整数は 2 の補数表現を使用するため、 符号ビットは最上位ビット位置に現れます。

17.5.29. firstLeadingBit(符号なし)

オーバーロード
@const @must_use fn firstLeadingBit(e: T) -> T
パラメーター化 T は u32 または vecN<u32>
説明 スカラー T の場合、結果は:
  • e がゼロの場合は T(-1)。
  • それ以外の場合、e 内の最上位の 1 ビットの位置。
T がベクトルの場合は成分ごとです。

17.5.30. firstTrailingBit

オーバーロード
@const @must_use fn firstTrailingBit(e: T) -> T
パラメーター化 T は i32、u32、vecN<i32>、または vecN<u32>
説明 スカラー T の場合、結果は:
  • e がゼロの場合は T(-1)。
  • それ以外の場合、e 内の最下位の 1 ビットの位置。
T がベクトルの場合は成分ごとです。

17.5.31. floor

オーバーロード
@const @must_use fn floor(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の床値を返します。 T がベクトルの場合は成分ごとです。

17.5.32. fma

オーバーロード
@const @must_use fn fma(e1: T,
                        e2: T,
                        e3: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e1 * e2 + e3 を返します。 T がベクトルの場合は成分ごとです。

注: fma という名前は "fused multiply add" の略です。

注: IEEE-754 の fusedMultiplyAdd 演算は、中間結果を 無制限の範囲と精度で計算したかのように求め、最終結果だけを変換先型の値へ丸めます。 しかし、fma に対する§ 15.7.4 浮動小数点精度規則は、 対象型への通常の乗算の後に通常の加算を行う実装を許可します。 この場合、中間結果値はオーバーフローしたり精度を失ったりする場合があり、 演算全体はまったく "fused" ではありません。

定義域 式 e2 × e2 + e3 の線形項から暗黙的に導かれます。

17.5.33. fract

オーバーロード
@const @must_use fn fract(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e - floor(e) として計算された e の小数部分を返します。
T がベクトルの場合は成分ごとです。

注: 有効な結果は閉区間 [0, 1.0] 内です。 たとえば、e が非常に小さい負数の場合、fract(e) は 1.0 になる場合があります。

17.5.34. frexp

オーバーロード
@const @must_use fn frexp(e: T) -> __frexp_result_f32
パラメーター化 T は f32
説明 e を小数部と指数部に分割します。
  • e がゼロの場合、小数部はゼロです。

  • e がゼロでなく正規の場合、e = fraction * 2exponent であり、 小数部は範囲 [0.5, 1.0) または (-1.0, -0.5] 内です。

  • それ以外の場合、e は非正規、NaN、または無限大です。結果の 小数部と指数部は不定値です。

次のように定義される __frexp_result_f32 組み込み構造体を返します:

struct __frexp_result_f32 {
  fract : f32, // 小数部分
  exp : i32    // 指数部分
}

注: frexp という名前は "fraction and exponent" と覚えることができます。

例: frexp の使用
// 結果型を推論する
let fraction_and_exponent = frexp(1.5);
// fraction_only を 0.75 に設定する
let fraction_only = frexp(1.5).fract;

注: 値を型 __frexp_result_f32 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn frexp(e: T) -> __frexp_result_f16
パラメーター化 T は f16
説明 e を小数部と指数部に分割します。
  • e がゼロの場合、小数部はゼロです。

  • e がゼロでなく正規の場合、e = fraction * 2exponent であり、 小数部は範囲 [0.5, 1.0) または (-1.0, -0.5] 内です。

  • それ以外の場合、e は非正規、NaN、または無限大です。結果の 小数部と指数部は不定値です。

次のように定義されたものとして __frexp_result_f16 組み込み構造体を返します:

struct __frexp_result_f16 {
  fract : f16, // 小数部分
  exp : i32    // 指数部分
}

注: frexp という名前は "fraction and exponent" と覚えることができます。

注: 値を型 __frexp_result_f16 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn frexp(e: T) -> __frexp_result_abstract
パラメーター化 T は AbstractFloat
説明 e を小数部と指数部に分割します。
  • e がゼロの場合、小数部はゼロです。

  • e がゼロでなく正規の場合、e = fraction * 2exponent であり、 小数部は範囲 [0.5, 1.0) または (-1.0, -0.5] 内です。

  • e が非正規の場合、小数部と指数部の 誤差には上限がありません。 小数部は任意の AbstractFloat 値、指数部は任意の AbstractInt 値であってもかまいません。

注: 無限大または NaN となる AbstractFloat 式は シェーダー作成エラーを引き起こします。

次のように定義される __frexp_result_abstract 組み込み構造体を返します:

struct __frexp_result_abstract {
  fract : AbstractFloat, // 小数部分
  exp : AbstractInt      // 指数部分
}

注: frexp という名前は "fraction and exponent" と覚えることができます。

例: 抽象 frexp の使用
// 結果型を推論する
const fraction_and_exponent = frexp(1.5);
// fraction_only を 0.75 に設定する
const fraction_only = frexp(1.5).fract;

注: 値を型 __frexp_result_abstract で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn frexp(e: T) -> __frexp_result_vecN_f32
パラメーター化 T は vecN<f32>
説明 e の成分 ei を小数部と指数部に分割します。
  • ei がゼロの場合、小数部はゼロです。

  • ei がゼロでなく正規の場合、ei = fraction * 2exponent であり、 小数部は範囲 [0.5, 1.0) または (-1.0, -0.5] 内です。

  • それ以外の場合、ei は NaN または無限大です。結果の小数部と指数部は 不定値です。

次のように定義される __frexp_result_vecN_f32 組み込み構造体を返します:

struct __frexp_result_vecN_f32 {
  fract : vecN<f32>, // 小数部分
  exp : vecN<i32>    // 指数部分
}

注: frexp という名前は "fraction and exponent" と覚えることができます。

注: 値を型 __frexp_result_vecN_f32 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn frexp(e: T) -> __frexp_result_vecN_f16
パラメーター化 T は vecN<f16>
説明 e の成分 ei を小数部と指数部に分割します。
  • ei がゼロの場合、小数部はゼロです。

  • ei がゼロでなく正規の場合、ei = fraction * 2exponent であり、 小数部は範囲 [0.5, 1.0) または (-1.0, -0.5] 内です。

  • それ以外の場合、ei は NaN または無限大です。結果の小数部と指数部は 不定値です。

次のように定義されたものとして __frexp_result_vecN_f16 組み込み構造体を 返します:

struct __frexp_result_vecN_f16 {
  fract : vecN<f16>, // 小数部分
  exp : vecN<i32>    // 指数部分
}

注: frexp という名前は "fraction and exponent" と覚えることができます。

注: 値を型 __frexp_result_vecN_f16 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn frexp(e: T) -> __frexp_result_vecN_abstract
パラメーター化 T は vecN<AbstractFloat>
説明 e の成分 ei を小数部と指数部に分割します。
  • ei がゼロの場合、小数部はゼロです。

  • ei がゼロでなく正規の場合、ei = fraction * 2exponent であり、 小数部は範囲 [0.5, 1.0) または (-1.0, -0.5] 内です。

  • ei が非正規の場合、小数部と指数部の 誤差には上限がありません。 小数部は任意の AbstractFloat 値、指数部は任意の AbstractInt 値であってもかまいません。

注: 無限大または NaN となる AbstractFloat 式は シェーダー作成エラーを引き起こします。

次のように定義される __frexp_result_vecN_abstract 組み込み構造体を返します:

struct __frexp_result_vecN_abstract {
  fract : vecN<AbstractFloat>, // 小数部分
  exp : vecN<AbstractInt>      // 指数部分
}

注: frexp という名前は "fraction and exponent" と覚えることができます。

注: 値を型 __frexp_result_vecN_abstract で明示的に宣言することはできませんが、 値はその型を推論できます。

17.5.35. insertBits

オーバーロード
@const @must_use fn insertBits(e: T,
                              newbits: T,
                              offset: u32,
                              count: u32) -> T
パラメーター化 T は i32、u32、vecN<i32>、または vecN<u32>
説明 整数内のビットを設定します。

T がスカラー型の場合:

  • w は T のビット幅
  • o = min(offset, w)
  • c = min(count, w - o)
  • c が 0 の場合、結果は e です。
  • それ以外の場合、 結果のビット o..o + c - 1 は newbits のビット 0..c - 1 からコピーされます。 結果のその他のビットは e からコピーされます。
T がベクトルの場合は成分ごとです。

count + offset が w より大きい場合:

17.5.36. inverseSqrt

オーバーロード
@const @must_use fn inverseSqrt(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 sqrt(e) の逆数を返します。 T がベクトルの場合は成分ごとです。
スカラー定義域 区間 [0, +∞]

17.5.37. ldexp

オーバーロード
@const @must_use fn ldexp(e1: T,
                          e2: I) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
I は AbstractInt、i32、vecN<AbstractInt>、または vecN<i32>
T がベクトルである場合に限り I もベクトルです
I も抽象であり、その逆も成り立つ場合に限り、 T は抽象になれます

注: いずれかのパラメーターが具象の場合、 他方のパラメーターは (該当する場合)自動変換によって 具象 型となり、結果も 具象 型になります。

説明 次を除き、e1 * 2e2 を返します:

ここで bias は浮動小数点形式の指数バイアスです:

  • f16 では 15

  • f32 では 127

  • AbstractFloat がIEEE-754 binary64 の場合、AbstractFloat では 1023

x がゼロまたはその型の有限な正規値の場合:

x = ldexp(frexp(x).fract, frexp(x).exp)

T がベクトルの場合は成分ごとです。

注: ldexp という名前は "load exponent" と覚えることができます。 この名前は PDP-11 の浮動小数点ユニットにある対応する命令から 取られた可能性があります。

17.5.38. length

オーバーロード
@const @must_use fn length(e: T) -> S
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の長さを返します。
T がスカラーの場合、e の絶対値に評価されます。
T がベクトル型の場合、 sqrt(e[0]2 + e[1]2 + ...) に評価されます。

注: スカラーの場合は sqrt(e * e) として評価される場合があり、 不必要にオーバーフローしたり精度を失ったりする可能性があります。

17.5.39. log

オーバーロード
@const @must_use fn log(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の自然対数を返します。 T がベクトルの場合は成分ごとです。
スカラー定義域 区間 [0, +∞]

17.5.40. log2

オーバーロード
@const @must_use fn log2(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の底 2 の対数を返します。 T がベクトルの場合は成分ごと です。
スカラー定義域 区間 [0, +∞]

17.5.41. max

オーバーロード
@const @must_use fn max(e1: T,
                        e2: T) -> T
パラメーター化 S は AbstractInt、AbstractFloat、i32、u32、f32、または f16
T は S、または vecN<S>
説明 e1 が e2 より小さい場合は e2、それ以外の場合は e1 を返します。 T がベクトルの場合は成分ごと です。

e1 と e2 が浮動小数点値の場合:

  • e1 と e2 の両方が非正規の場合、 結果はいずれかの値であってもかまいません。

17.5.42. min

オーバーロード
@const @must_use fn min(e1: T,
                        e2: T) -> T
パラメーター化 S は AbstractInt、AbstractFloat、i32、u32、f32、または f16
T は S、または vecN<S>
説明 e2 が e1 より小さい場合は e2、それ以外の場合は e1 を返します。 T がベクトルの場合は成分ごと です。

e1 と e2 が浮動小数点値の場合:

  • e1 と e2 の両方が非正規の場合、 結果はいずれかの値であってもかまいません。

17.5.43. mix

オーバーロード
@const @must_use fn mix(e1: T,
                        e2: T,
                        e3: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e1 と e2 の線形ブレンド(たとえば e1 * (T(1) - e3) + e2 * e3)を返します。 T がベクトルの場合は成分ごと です。
定義域 次の式の線形項から暗黙的に導かれます: e1[i] × (1 − e3[i]) + e2[i] × e3[i]。 e2[i] × e2[i] + e3[i]。
オーバーロード
@const @must_use fn mix(e1: T2,
                        e2: T2,
                        e3: T) -> T2
パラメーター化 T は AbstractFloat、f32、または f16
T2 は vecN<T>
説明 e1 と e2 の成分ごとの線形ブレンドを返し、 各成分にスカラーのブレンド係数 e3 を使用します。
mix(e1, e2, T2(e3)) と同じです。
定義域 次の式の線形項から暗黙的に導かれます: e1[i] × (1 − e3) + e2[i] × e3。

17.5.44. modf

オーバーロード
@const @must_use fn modf(e: T) -> __modf_result_f32
パラメーター化 T は f32
説明 e を小数部分と整数部分に分割します。

整数部分は trunc(e) であり、小数部分 は e - trunc(e) です。

次のように定義される __modf_result_f32 組み込み構造体を返します:

struct __modf_result_f32 {
  fract : f32, // 小数部分
  whole : f32  // 整数部分
}
例: modf の使用
// 結果型を推論する
let fract_and_whole = modf(1.5);
// fract_only を 0.5 に設定する
let fract_only = modf(1.5).fract;
// whole_only を 1.0 に設定する
let whole_only = modf(1.5).whole;

注: 値を型 __modf_result_f32 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn modf(e: T) -> __modf_result_f16
パラメーター化 T は f16
説明 e を小数部分と整数部分に分割します。

整数部分は trunc(e) であり、小数部分 は e - trunc(e) です。

次のように定義されたものとして __modf_result_f16 組み込み構造体を返します:

struct __modf_result_f16 {
  fract : f16, // 小数部分
  whole : f16  // 整数部分
}

注: 値を型 __modf_result_f16 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn modf(e: T) -> __modf_result_abstract
パラメーター化 T は AbstractFloat
説明 e を小数部分と整数部分に分割します。

整数部分は trunc(e) であり、小数部分 は e - trunc(e) です。

次のように定義される __modf_result_abstract 組み込み構造体を返します:

struct __modf_result_abstract {
  fract : AbstractFloat, // 小数部分
  whole : AbstractFloat  // 整数部分
}
例: 抽象 modf の使用
// 結果型を推論する
const fract_and_whole = modf(1.5);
// fract_only を 0.5 に設定する
const fract_only = modf(1.5).fract;
// whole_only を 1.0 に設定する
const whole_only = modf(1.5).whole;

注: 値を型 __modf_result_abstract で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn modf(e: T) -> __modf_result_vecN_f32
パラメーター化 T は vecN<f32>
説明 e の成分を小数部分と整数部分に分割します。

整数部分と小数部分の i 番目の成分は、 modf(e[i]) の整数部分と小数部分 にそれぞれ等しくなります。

次のように定義される __modf_result_vecN_f32 組み込み構造体を返します:

struct __modf_result_vecN_f32 {
  fract : vecN<f32>, // 小数部分
  whole : vecN<f32>  // 整数部分
}

注: 値を型 __modf_result_vecN_f32 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn modf(e: T) -> __modf_result_vecN_f16
パラメーター化 T は vecN<f16>
説明 e の成分を小数部分と整数部分に分割します。

整数部分と小数部分の i 番目の成分は、 modf(e[i]) の整数部分と小数部分 にそれぞれ等しくなります。

次のように定義されたものとして __modf_result_vecN_f16 組み込み構造体を返します:

struct __modf_result_vecN_f16 {
  fract : vecN<f16>, // 小数部分
  whole : vecN<f16>  // 整数部分
}

注: 値を型 __modf_result_vecN_f16 で明示的に宣言することはできませんが、 値はその型を推論できます。

オーバーロード
@const @must_use fn modf(e: T) -> __modf_result_vecN_abstract
パラメーター化 T は vecN<AbstractFloat>
説明 e の成分を小数部分と整数部分に分割します。

整数部分と小数部分の i 番目の成分は、 modf(e[i]) の整数部分と小数部分 にそれぞれ等しくなります。

次のように定義される __modf_result_vecN_abstract 組み込み構造体を返します:

struct __modf_result_vecN_abstract {
  fract : vecN<AbstractFloat>, // 小数部分
  whole : vecN<AbstractFloat>  // 整数部分
}

注: 値を型 __modf_result_vecN_abstract で明示的に宣言することはできませんが、 値はその型を推論できます。

17.5.45. normalize

オーバーロード
@const @must_use fn normalize(e: vecN<T> ) -> vecN<T>
パラメーター化 T は AbstractFloat、f32、または f16
説明 e と同じ方向の単位ベクトルを返します。

定義域はゼロベクトルを除くすべてのベクトルです。

17.5.46. pow

オーバーロード
@const @must_use fn pow(e1: T,
                        e2: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e1 の e2 乗を返します。 T がベクトルの場合は成分ごと です。
スカラー定義域 次を除く、すべての拡張実数の組 (x,y) の集合:
  • x < 0。

  • x が 1 で y が無限大。

  • x が無限大で y が 0。

この規則は、結果が exp2(y * log2(x)) として計算される場合があることに由来します。

17.5.47. quantizeToF16

オーバーロード
@const @must_use fn quantizeToF16(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 32 ビット浮動小数点値 e を、e が IEEE-754 binary16 値へ変換され、その後 IEEE-754 binary32 値へ戻されたかのように量子化します。

e が binary16 の有限範囲外にある場合:

中間の binary16 値はゼロへフラッシュされる場合があります。すなわち、中間の binary16 値が非正規の場合、最終結果はゼロになる場合があります。

§ 15.7.6 浮動小数点変換を参照してください。

T がベクトルの場合は成分ごとです。

注: vec2<f32> の場合は unpack2x16float(pack2x16float(e)) と同じです。

17.5.48. radians

オーバーロード
@const @must_use fn radians(e1: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 度をラジアンに変換し、e1 × π ÷ 180 を近似します。 T がベクトルの場合は成分ごと です

17.5.49. reflect

オーバーロード
@const @must_use fn reflect(e1: T,
                            e2: T) -> T
パラメーター化 T は vecN<AbstractFloat>、vecN<f32>、または vecN<f16>
説明 入射ベクトル e1 と表面の向き e2 に対して、反射方向 e1 - 2 * dot(e2, e1) * e2 を返します。

17.5.50. refract

オーバーロード
@const @must_use fn refract(e1: T,
                            e2: T,
                            e3: I) -> T
パラメーター化 T は vecN<I>
I は AbstractFloat、f32、または f16
説明 入射ベクトル e1、表面法線 e2、および屈折率の比 e3 に対して、 k = 1.0 - e3 * e3 * (1.0 - dot(e2, e1) * dot(e2, e1)) とします。 k < 0.0 の場合は屈折ベクトル 0.0 を返し、それ以外の場合は屈折 ベクトル e3 * e1 - (e3 * dot(e2, e1) + sqrt(k)) * e2 を返します。入射ベクトル e1 と法線 e2 は、 スネルの法則に従う望ましい結果を得るために正規化されているべきです。そうでない場合、結果は 期待される物理的挙動に従わない場合があります。

17.5.51. reverseBits

オーバーロード
@const @must_use fn reverseBits(e: T) -> T
パラメーター化 T は i32、u32、vecN<i32>、または vecN<u32>
説明 e のビットを反転します: 結果の位置 k のビットは、 e の位置 31 -k のビットと等しくなります。
T がベクトルの場合は成分ごと です。

17.5.52. round

オーバーロード
@const @must_use fn round(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 結果は、浮動小数点値としての e に最も近い整数 k です。
e が整数 k と k + 1 のちょうど中間にある場合、 k が偶数なら結果は k、k が奇数なら結果は k + 1 です。
T がベクトルの場合は成分ごと です。

17.5.53. saturate

オーバーロード
@const @must_use fn saturate(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 clamp(e, 0.0, 1.0) を返します。 T がベクトルの場合は成分ごと です。

17.5.54. sign

オーバーロード
@const @must_use fn sign(e: T) -> T
パラメーター化 S は AbstractInt、AbstractFloat、i32、f32、または f16
T は S、または vecN<S>
説明 結果は次のとおりです:
  • e > 0 の場合は 1
  • e = 0 の場合は 0
  • e < 0 の場合は -1

T がベクトルの場合は成分ごとです。

17.5.55. sin

オーバーロード
@const @must_use fn sin(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 ラジアン単位の e の正弦を返します。 T がベクトルの場合は成分ごと です。
スカラー定義域 区間 (−∞, +∞)

17.5.56. sinh

オーバーロード
@const @must_use fn sinh(a: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 双曲角である a の双曲線正弦を返します。 純粋な数学関数 (ea − e−a)÷2 を近似しますが、必ずしもその方法で計算されるわけではありません。

T がベクトルの場合は成分ごとです。

17.5.57. smoothstep

オーバーロード
@const @must_use fn smoothstep(edge0: T,
                               edge1: T,
                               x: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 0 と 1 の間の滑らかなエルミート補間を返します。 T がベクトルの場合は成分ごと です。

スカラー T の場合、結果は t * t * (3.0 - 2.0 * t)、
ここで t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0) です。

定性的には:

  • edge0 < edge1 の場合、この関数は x が edge0 未満では 0 で、その後滑らかに増加し、 x が edge1 に達すると、それ以降は 1 のままです。

  • edge0 > edge1 の場合、この関数は x が edge1 未満では 1 で、その後滑らかに減少し、 x が edge0 に達すると、それ以降は 0 のままです。

edge0 = edge1 の場合:

17.5.58. sqrt

オーバーロード
@const @must_use fn sqrt(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の平方根を返します。 T がベクトルの場合は成分ごと です。
スカラー定義域 区間 [0, +∞]

17.5.59. step

オーバーロード
@const @must_use fn step(edge: T,
                         x: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 edge ≤ x の場合は 1.0、それ以外の場合は 0.0 を返します。 T がベクトルの場合は成分ごと です。

17.5.60. tan

オーバーロード
@const @must_use fn tan(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 ラジアン単位の e の正接を返します。 T がベクトルの場合は成分ごと です。
スカラー定義域 区間 (−∞, +∞)

17.5.61. tanh

オーバーロード
@const @must_use fn tanh(a: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 双曲角である a の双曲線正接を返します。 純粋な数学関数 (ea − e−a) ÷ (ea + e−a) を近似しますが、必ずしもその方法で計算されるわけではありません。

T がベクトルの場合は成分ごとです。

17.5.62. transpose

オーバーロード
@const @must_use fn transpose(e: matRxC<T>) -> matCxR<T>
パラメーター化 T は AbstractFloat、f32、または f16
説明 e の転置を返します。

17.5.63. trunc

オーバーロード
@const @must_use fn trunc(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 truncate(e)、すなわち絶対値が e の絶対値以下である最も近い整数を返します。 T がベクトルの場合は成分ごと です。

17.6. 微分組み込み関数

§ 15.6.2 微分を参照してください。

これらの関数の呼び出しは:

17.6.1. dpdx

オーバーロード
@must_use fn dpdx(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 ウィンドウ x 座標に関する e の偏微分。 結果は dpdxFine(e) または dpdxCoarse(e) のいずれかと同じです。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.2. dpdxCoarse

オーバーロード
@must_use fn dpdxCoarse(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 局所差分を使用して、ウィンドウ x 座標に関する e の偏微分を返します。 これにより、dpdxFine(e) より一意の位置が少なくなる場合があります。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.3. dpdxFine

オーバーロード
@must_use fn dpdxFine(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 ウィンドウ x 座標に関する e の偏微分を返します。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.4. dpdy

オーバーロード
@must_use fn dpdy(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 ウィンドウ y 座標に関する e の偏微分。 結果は dpdyFine(e) または dpdyCoarse(e) のいずれかと同じです。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.5. dpdyCoarse

オーバーロード
@must_use fn dpdyCoarse(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 局所差分を使用して、ウィンドウ y 座標に関する e の偏微分を返します。 これにより、dpdyFine(e) より一意の位置が少なくなる場合があります。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.6. dpdyFine

オーバーロード
@must_use fn dpdyFine(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 ウィンドウ y 座標に関する e の偏微分を返します。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.7. fwidth

オーバーロード
@must_use fn fwidth(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 abs(dpdx(e)) + abs(dpdy(e)) を返します。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.8. fwidthCoarse

オーバーロード
@must_use fn fwidthCoarse(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 abs(dpdxCoarse(e)) + abs(dpdyCoarse(e)) を返します。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.6.9. fwidthFine

オーバーロード
@must_use fn fwidthFine(e: T) -> T
パラメーター化 T は f32 または vecN<f32>
説明 abs(dpdxFine(e)) + abs(dpdyFine(e)) を返します。

非一様制御フロー内で呼び出された場合、不定値を返します。

17.7. テクスチャー組み込み関数

パラメーター値は、それぞれのテクスチャー型に対して有効でなければなりません。

17.7.1. textureDimensions

テクスチャー、またはテクスチャーのミップレベルのテクセル単位の次元を返します。

パラメーター化 オーバーロード
ST はi32、u32、またはf32
F はテクセル フォーマット
A はアクセス モード

T は texture_1d<ST> または texture_storage_1d<F,A>
@must_use fn textureDimensions(t: T) -> u32
ST はi32、u32、またはf32

T は texture_1d<ST>

L はi32、またはu32

@must_use fn textureDimensions(t: T,
                               level: L) -> u32
ST はi32、u32、またはf32
F はテクセル フォーマット
A はアクセス モード

T は texture_2d<ST>、texture_2d_array<ST>、 texture_cube<ST>、 texture_cube_array<ST>、texture_multisampled_2d<ST>、 texture_depth_2d、texture_depth_2d_array、 texture_depth_cube、 texture_depth_cube_array、texture_depth_multisampled_2d、 texture_storage_2d<F,A>、texture_storage_2d_array<F,A>、 または texture_external
@must_use fn textureDimensions(t: T) -> vec2<u32>
ST はi32、u32、またはf32

T は texture_2d<ST>、texture_2d_array<ST>、 texture_cube<ST>、 texture_cube_array<ST>、texture_depth_2d、 texture_depth_2d_array、 texture_depth_cube、または texture_depth_cube_array

L はi32、またはu32

@must_use fn textureDimensions(t: T,
                               level: L) -> vec2<u32>
ST はi32、u32、またはf32
F はテクセル フォーマット
A はアクセス モード

T は texture_3d<ST> または texture_storage_3d<F,A>
@must_use fn textureDimensions(t: T) -> vec3<u32>
ST はi32、u32、またはf32

T は texture_3d<ST>

L はi32、またはu32

@must_use fn textureDimensions(t: T,
                               level: L) -> vec3<u32>

パラメーター:

t サンプリング、 マルチサンプリング、深度、 ストレージ、または外部 テクスチャー。
level ミップレベル。レベル 0 はテクスチャーのフルサイズ版を含みます。
省略した場合、レベル 0 の次元が返されます。

戻り値:

テクスチャーの座標次元。

すなわち、結果は論理テクセルアドレスの座標に対する整数境界を提供し、 ミップレベル数、配列サイズ、およびサンプル数は除外されます。

キューブに基づくテクスチャーでは、結果はキューブの各面の次元です。 キューブの面は正方形であるため、結果の x 成分と y 成分は等しくなります。

level が範囲 [0, textureNumLevels(t)) 外の場合、戻り値の型の不定 値 が返される場合があります。

17.7.2. textureGather

テクスチャーギャザー 操作は 2D、2D 配列、キューブ、またはキューブ配列テクスチャーから読み取り、 次のように 4 成分ベクトルを計算します:

4 つのテクセルは、 WebGPU サンプラーディスクリプターで説明されるサンプリング領域を形成します。

パラメーター化 オーバーロード
C はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureGather(component: C,
                           t: texture_2d<ST>,
                           s: sampler,
                           coords: vec2<f32>) -> vec4<ST>
C はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureGather(component: C,
                           t: texture_2d<ST>,
                           s: sampler,
                           coords: vec2<f32>,
                           offset: vec2<i32>) -> vec4<ST>
C はi32、またはu32
A はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureGather(component: C,
                           t: texture_2d_array<ST>,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> vec4<ST>
C はi32、またはu32
A はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureGather(component: C,
                           t: texture_2d_array<ST>,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A,
                           offset: vec2<i32>) -> vec4<ST>
C はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureGather(component: C,
                           t: texture_cube<ST>,
                           s: sampler,
                           coords: vec3<f32>) -> vec4<ST>
C はi32、またはu32
A はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureGather(component: C,
                           t: texture_cube_array<ST>,
                           s: sampler,
                           coords: vec3<f32>,
                           array_index: A) -> vec4<ST>
@must_use fn textureGather(t: texture_depth_2d,
                           s: sampler,
                           coords: vec2<f32>) -> vec4<f32>
@must_use fn textureGather(t: texture_depth_2d,
                           s: sampler,
                           coords: vec2<f32>,
                           offset: vec2<i32>) -> vec4<f32>
@must_use fn textureGather(t: texture_depth_cube,
                           s: sampler,
                           coords: vec3<f32>) -> vec4<f32>
A はi32、またはu32
@must_use fn textureGather(t: texture_depth_2d_array,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> vec4<f32>
A はi32、またはu32
@must_use fn textureGather(t: texture_depth_2d_array,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A,
                           offset: vec2<i32>) -> vec4<f32>
A はi32、またはu32
@must_use fn textureGather(t: texture_depth_cube_array,
                           s: sampler,
                           coords: vec3<f32>,
                           array_index: A) -> vec4<f32>

パラメーター:

component 深度以外のテクスチャーにのみ適用されます。
選択されたテクセルから読み取るチャンネルのインデックス。
指定される場合、component 式は必ずconst 式(たとえば 1)でなければなりません。
その値は 0 以上 3 以下でなければなりません。 この範囲外の値はシェーダー作成 エラーになります。
t 読み取り元のサンプリングまたは深度テクスチャー。
s サンプラー型。
coords テクスチャー座標。
array_index 0 ベースのテクスチャー配列インデックス。
この値は範囲 [0, textureNumLayers(t) - 1] にクランプされます。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、テクスチャーのラップモードを適用する前に 適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず -8 以上 7 以下でなければなりません。この範囲外の値はシェーダー作成エラーになります。

戻り値:

上記のように、選択されたテクセルの指定されたチャンネルから抽出された成分を持つ 4 成分ベクトル。

例: 2D テクスチャーのテクセルから成分をギャザーする
@group(0) @binding(0) var t: texture_2d<f32>;
@group(0) @binding(1) var dt: texture_depth_2d;
@group(0) @binding(2) var s: sampler;

fn gather_x_components(c: vec2<f32>) -> vec4<f32> {
  return textureGather(0,t,s,c);
}
fn gather_y_components(c: vec2<f32>) -> vec4<f32> {
  return textureGather(1,t,s,c);
}
fn gather_z_components(c: vec2<f32>) -> vec4<f32> {
  return textureGather(2,t,s,c);
}
fn gather_depth_components(c: vec2<f32>) -> vec4<f32> {
  return textureGather(dt,s,c);
}

17.7.3. textureGatherCompare

テクスチャーギャザー 比較操作は、深度テクスチャー内の 4 つのテクセルに対して深度比較を実行し、 次のように結果を単一のベクトルに収集します:

パラメーター化 オーバーロード
@must_use fn textureGatherCompare(t: texture_depth_2d,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  depth_ref: f32) -> vec4<f32>
@must_use fn textureGatherCompare(t: texture_depth_2d,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  depth_ref: f32,
                                  offset: vec2<i32>) -> vec4<f32>
A はi32、またはu32
@must_use fn textureGatherCompare(t: texture_depth_2d_array,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  array_index: A,
                                  depth_ref: f32) -> vec4<f32>
A はi32、またはu32
@must_use fn textureGatherCompare(t: texture_depth_2d_array,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  array_index: A,
                                  depth_ref: f32,
                                  offset: vec2<i32>) -> vec4<f32>
@must_use fn textureGatherCompare(t: texture_depth_cube,
                                  s: sampler_comparison,
                                  coords: vec3<f32>,
                                  depth_ref: f32) -> vec4<f32>
A はi32、またはu32
@must_use fn textureGatherCompare(t: texture_depth_cube_array,
                                  s: sampler_comparison,
                                  coords: vec3<f32>,
                                  array_index: A,
                                  depth_ref: f32) -> vec4<f32>

パラメーター:

t 読み取り元の深度テクスチャー。
s 比較サンプラー。
coords テクスチャー座標。
array_index 0 ベースのテクスチャー配列インデックス。
この値は範囲 [0, textureNumLayers(t) - 1] にクランプされます。
depth_ref サンプリングされた深度値と比較する参照値。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、テクスチャーのラップモードを適用する前に 適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず -8 以上 7 以下でなければなりません。この範囲外の値はシェーダー作成エラーになります。

戻り値:

上記のように、選択されたテクセルの比較結果を持つ 4 成分ベクトル。

例: 深度比較のギャザー
@group(0) @binding(0) var dt: texture_depth_2d;
@group(0) @binding(1) var s: sampler;

fn gather_depth_compare(c: vec2<f32>, depth_ref: f32) -> vec4<f32> {
  return textureGatherCompare(dt,s,c,depth_ref);
}

17.7.4. textureLoad

サンプリングやフィルタリングを行わずに、テクスチャーから単一のテクセルを読み取ります。

パラメーター化 オーバーロード
C はi32、またはu32
L はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureLoad(t: texture_1d<ST>,
                         coords: C,
                         level: L) -> vec4<ST>
C はi32、またはu32
L はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureLoad(t: texture_2d<ST>,
                         coords: vec2<C>,
                         level: L) -> vec4<ST>
C はi32、またはu32
A はi32、またはu32
L はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureLoad(t: texture_2d_array<ST>,
                        coords: vec2<C>,
                        array_index: A,
                        level: L) -> vec4<ST>
C はi32、またはu32
L はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureLoad(t: texture_3d<ST>,
                         coords: vec3<C>,
                         level: L) -> vec4<ST>
C はi32、またはu32
S はi32、またはu32
ST はi32、u32、またはf32
@must_use fn textureLoad(t: texture_multisampled_2d<ST>,
                         coords: vec2<C>,
                         sample_index: S)-> vec4<ST>
C はi32、またはu32
L はi32、またはu32
@must_use fn textureLoad(t: texture_depth_2d,
                         coords: vec2<C>,
                         level: L) -> f32
C はi32、またはu32
A はi32、またはu32
L はi32、またはu32
@must_use fn textureLoad(t: texture_depth_2d_array,
                         coords: vec2<C>,
                         array_index: A,
                         level: L) -> f32
C はi32、またはu32
S はi32、またはu32
@must_use fn textureLoad(t: texture_depth_multisampled_2d,
                         coords: vec2<C>,
                         sample_index: S)-> f32
C はi32、またはu32
@must_use fn textureLoad(t: texture_external,
                         coords: vec2<C>) -> vec4<f32>
C はi32、またはu32
AM はread またはread_write
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
@must_use fn textureLoad(t : texture_storage_1d<F, AM>,
                         coords : C) -> vec4<CF>
C はi32、またはu32
AM はread またはread_write
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
@must_use fn textureLoad(t : texture_storage_2d<F, AM>,
                         coords : vec2<C>) -> vec4<CF>
C はi32、またはu32
AM はread またはread_write
A はi32 またはu32
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
@must_use fn textureLoad(t : texture_storage_2d_array<F, AM>,
                         coords : vec2<C>,
                         array_index : A) -> vec4<CF>
C はi32、またはu32
AM はread またはread_write
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
@must_use fn textureLoad(t : texture_storage_3d<F, AM>,
                         coords : vec3<C>) -> vec4<CF>

パラメーター:

t サンプリング、 マルチサンプリング、 深度、 ストレージ、または 外部 テクスチャー
coords 0 ベースのテクセル座標。
array_index 0 ベースのテクスチャー配列インデックス。
level ミップレベル。レベル 0 はテクスチャーのフルサイズ版を含みます。
sample_index マルチサンプリングテクスチャーの 0 ベースのサンプルインデックス。

戻り値:

フィルタリングされていないテクセルデータ。

論理テクセル アドレスは、次の場合に無効です:

論理テクセルアドレスが無効な場合、組み込み関数は次のいずれかを返します:

17.7.5. textureNumLayers

配列化テクスチャーのレイヤー(要素)数を返します。

パラメーター化 オーバーロード
F はテクセル フォーマット
A はアクセス モード
ST はi32、u32、またはf32

T は texture_2d_array<ST>、texture_cube_array<ST>、 texture_depth_2d_array、texture_depth_cube_array、 または texture_storage_2d_array<F,A>
@must_use fn textureNumLayers(t: T) -> u32

パラメーター:

t サンプリング、 深度、 または ストレージ テクスチャーの配列テクスチャー。

戻り値:

テクスチャーがキューブに基づく場合、キューブ配列テクスチャー内のキューブ数を返します。

それ以外の場合、配列テクスチャー内のレイヤー(テクセルの均質なグリッド)の数を返します。

17.7.6. textureNumLevels

テクスチャーのミップレベル数を返します。

パラメーター化 オーバーロード
ST はi32、u32、またはf32

T は texture_1d<ST>、texture_2d<ST>、 texture_2d_array<ST>、texture_3d<ST>、 texture_cube<ST>、texture_cube_array<ST>、 texture_depth_2d、texture_depth_2d_array、 texture_depth_cube、または texture_depth_cube_array
@must_use fn textureNumLevels(t: T) -> u32

パラメーター:

t サンプリングまたは深度テクスチャー。

戻り値:

テクスチャーのミップレベル 数。

17.7.7. textureNumSamples

マルチサンプリングテクスチャー内のテクセルあたりのサンプル数を返します。

パラメーター化 オーバーロード
ST はi32、u32、またはf32

T は texture_multisampled_2d<ST> または texture_depth_multisampled_2d
@must_use fn textureNumSamples(t: T) -> u32

パラメーター:

t マルチサンプリングテクスチャー。

戻り値:

マルチサンプリングテクスチャーのサンプル数。

17.7.8. textureSample

テクスチャーをサンプリングします。

必ず fragment シェーダーステージでのみ使用しなければなりません。

一様性 解析が、この関数の呼び出しが一様制御フロー内にあることを証明できない場合、 derivative_uniformity 診断がトリガーされます。

パラメーター化 オーバーロード
@must_use fn textureSample(t: texture_1d<f32>,
                           s: sampler,
                           coords: f32) -> vec4<f32>
@must_use fn textureSample(t: texture_2d<f32>,
                           s: sampler,
                           coords: vec2<f32>) -> vec4<f32>
@must_use fn textureSample(t: texture_2d<f32>,
                           s: sampler,
                           coords: vec2<f32>,
                           offset: vec2<i32>) -> vec4<f32>
A はi32、またはu32
@must_use fn textureSample(t: texture_2d_array<f32>,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> vec4<f32>
A はi32、またはu32
@must_use fn textureSample(t: texture_2d_array<f32>,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A,
                           offset: vec2<i32>) -> vec4<f32>
T は texture_3d<f32>、または texture_cube<f32>
@must_use fn textureSample(t: T,
                           s: sampler,
                           coords: vec3<f32>) -> vec4<f32>
@must_use fn textureSample(t: texture_3d<f32>,
                           s: sampler,
                           coords: vec3<f32>,
                           offset: vec3<i32>) -> vec4<f32>
A はi32、またはu32
@must_use fn textureSample(t: texture_cube_array<f32>,
                           s: sampler,
                           coords: vec3<f32>,
                           array_index: A) -> vec4<f32>
@must_use fn textureSample(t: texture_depth_2d,
                           s: sampler,
                           coords: vec2<f32>) -> f32
@must_use fn textureSample(t: texture_depth_2d,
                           s: sampler,
                           coords: vec2<f32>,
                           offset: vec2<i32>) -> f32
A はi32、またはu32
@must_use fn textureSample(t: texture_depth_2d_array,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> f32
A はi32、またはu32
@must_use fn textureSample(t: texture_depth_2d_array,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A,
                           offset: vec2<i32>) -> f32
@must_use fn textureSample(t: texture_depth_cube,
                           s: sampler,
                           coords: vec3<f32>) -> f32
A はi32、またはu32
@must_use fn textureSample(t: texture_depth_cube_array,
                           s: sampler,
                           coords: vec3<f32>,
                           array_index: A) -> f32

パラメーター:

t サンプリングするサンプリングまたは深度 テクスチャー。
s サンプラー型。
coords サンプリングに使用されるテクスチャー座標。
array_index サンプリングする 0 ベースのテクスチャー配列インデックス。
この値は範囲 [0, textureNumLayers(t) - 1] にクランプされます。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、テクスチャーのラップモードを適用する前に 適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず -8 以上 7 以下でなければなりません。この範囲外の値はシェーダー作成エラーになります。

戻り値:

サンプリングされた値。

非一様制御フロー内で呼び出された場合、不定 値になります。

17.7.9. textureSampleBias

ミップレベルにバイアスを加えてテクスチャーをサンプリングします。

必ず fragment シェーダーステージでのみ使用しなければなりません。

一様性 解析が、この関数の呼び出しが一様制御フロー内にあることを証明できない場合、 derivative_uniformity 診断がトリガーされます。

パラメーター化 オーバーロード
@must_use fn textureSampleBias(t: texture_2d<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               bias: f32) -> vec4<f32>
@must_use fn textureSampleBias(t: texture_2d<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               bias: f32,
                               offset: vec2<i32>) -> vec4<f32>
A はi32、またはu32
@must_use fn textureSampleBias(t: texture_2d_array<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               array_index: A,
                               bias: f32) -> vec4<f32>
A はi32、またはu32
@must_use fn textureSampleBias(t: texture_2d_array<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               array_index: A,
                               bias: f32,
                               offset: vec2<i32>) -> vec4<f32>
T は texture_3d<f32>、または texture_cube<f32>
@must_use fn textureSampleBias(t: T,
                               s: sampler,
                               coords: vec3<f32>,
                               bias: f32) -> vec4<f32>
@must_use fn textureSampleBias(t: texture_3d<f32>,
                               s: sampler,
                               coords: vec3<f32>,
                               bias: f32,
                               offset: vec3<i32>) -> vec4<f32>
A はi32、またはu32
@must_use fn textureSampleBias(t: texture_cube_array<f32>,
                               s: sampler,
                               coords: vec3<f32>,
                               array_index: A,
                               bias: f32) -> vec4<f32>

パラメーター:

t サンプリングするサンプリングテクスチャー。
s サンプラー型。
coords サンプリングに使用されるテクスチャー座標。
array_index サンプリングする 0 ベースのテクスチャー配列インデックス。
この値は範囲 [0, textureNumLayers(t) - 1] にクランプされます。
bias サンプリング前にミップレベルへ適用するバイアス。
この値は範囲 [-16.0, 15.99] にクランプされます。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、テクスチャーのラップモードを適用する前に 適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず -8 以上 7 以下でなければなりません。この範囲外の値はシェーダー作成エラーになります。

戻り値:

サンプリングされた値。

17.7.10. textureSampleCompare

深度 テクスチャーをサンプリングし、サンプリングされた深度値を参照値と比較します。

必ず fragment シェーダーステージでのみ使用しなければなりません。

一様性 解析が、この関数の呼び出しが一様制御フロー内にあることを証明できない場合、 derivative_uniformity 診断がトリガーされます。

パラメーター化 オーバーロード
@must_use fn textureSampleCompare(t: texture_depth_2d,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  depth_ref: f32) -> f32
@must_use fn textureSampleCompare(t: texture_depth_2d,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  depth_ref: f32,
                                  offset: vec2<i32>) -> f32
A はi32、またはu32
@must_use fn textureSampleCompare(t: texture_depth_2d_array,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  array_index: A,
                                  depth_ref: f32) -> f32
A はi32、またはu32
@must_use fn textureSampleCompare(t: texture_depth_2d_array,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  array_index: A,
                                  depth_ref: f32,
                                  offset: vec2<i32>) -> f32
@must_use fn textureSampleCompare(t: texture_depth_cube,
                                  s: sampler_comparison,
                                  coords: vec3<f32>,
                                  depth_ref: f32) -> f32
A はi32、またはu32
@must_use fn textureSampleCompare(t: texture_depth_cube_array,
                                  s: sampler_comparison,
                                  coords: vec3<f32>,
                                  array_index: A,
                                  depth_ref: f32) -> f32

パラメーター:

t サンプリングする深度 テクスチャー。
s sampler_comparison 型。
coords サンプリングに使用されるテクスチャー座標。
array_index サンプリングする 0 ベースのテクスチャー配列インデックス。
この値は範囲 [0, textureNumLayers(t) - 1] にクランプされます。
depth_ref サンプリングされた深度値と比較する参照値。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、テクスチャーのラップモードを適用する前に 適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず -8 以上 7 以下でなければなりません。この範囲外の値はシェーダー作成エラーになります。

戻り値:

範囲 [0.0..1.0] 内の値。

サンプリングされた各テクセルは、sampler_comparison によって定義された比較 演算子を使用して参照値と比較され、その結果、各テクセルについて 0 または 1 の値になります。

サンプラーがバイリニアフィルタリングを使用する場合、返される値は これらの値をフィルタリングした平均であり、それ以外の場合は単一の テクセルの比較結果が返されます。

非一様制御フロー内で呼び出された場合、不定 値になります。

17.7.11. textureSampleCompareLevel

深度 テクスチャーをサンプリングし、サンプリングされた深度値を参照値と比較します。

パラメーター化 オーバーロード
@must_use fn textureSampleCompareLevel(t: texture_depth_2d,
                                       s: sampler_comparison,
                                       coords: vec2<f32>,
                                       depth_ref: f32) -> f32
@must_use fn textureSampleCompareLevel(t: texture_depth_2d,
                                       s: sampler_comparison,
                                       coords: vec2<f32>,
                                       depth_ref: f32,
                                       offset: vec2<i32>) -> f32
A はi32、またはu32
@must_use fn textureSampleCompareLevel(t: texture_depth_2d_array,
                                       s: sampler_comparison,
                                       coords: vec2<f32>,
                                       array_index: A,
                                       depth_ref: f32) -> f32
A はi32、またはu32
@must_use fn textureSampleCompareLevel(t: texture_depth_2d_array,
                                       s: sampler_comparison,
                                       coords: vec2<f32>,
                                       array_index: A,
                                       depth_ref: f32,
                                       offset: vec2<i32>) -> f32
@must_use fn textureSampleCompareLevel(t: texture_depth_cube,
                                       s: sampler_comparison,
                                       coords: vec3<f32>,
                                       depth_ref: f32) -> f32
A はi32、またはu32
@must_use fn textureSampleCompareLevel(t: texture_depth_cube_array,
                                       s: sampler_comparison,
                                       coords: vec3<f32>,
                                       array_index: A,
                                       depth_ref: f32) -> f32

パラメーター:

t サンプリングする深度 テクスチャー。
s sampler_comparison 型。
coords サンプリングに使用されるテクスチャー座標。
array_index サンプリングする 0 ベースのテクスチャー配列インデックス。
この値は範囲 [0, textureNumLayers(t) - 1] にクランプされます。
depth_ref サンプリングされた深度値と比較する参照値。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、テクスチャーのラップモードを適用する前に 適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず -8 以上 7 以下でなければなりません。この範囲外の値はシェーダー作成エラーになります。

戻り値:

範囲 [0.0..1.0] 内の値。

textureSampleCompareLevel 関数は textureSampleCompare と同じですが、 次の点が異なります:

17.7.12. textureSampleGrad

明示的な勾配を使用してテクスチャーをサンプリングします。

パラメーター化 オーバーロード
@must_use fn textureSampleGrad(t: texture_2d<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               ddx: vec2<f32>,
                               ddy: vec2<f32>) -> vec4<f32>
@must_use fn textureSampleGrad(t: texture_2d<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               ddx: vec2<f32>,
                               ddy: vec2<f32>,
                               offset: vec2<i32>) -> vec4<f32>
A は i32、または u32
@must_use fn textureSampleGrad(t: texture_2d_array<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               array_index: A,
                               ddx: vec2<f32>,
                               ddy: vec2<f32>) -> vec4<f32>
A は i32、または u32
@must_use fn textureSampleGrad(t: texture_2d_array<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               array_index: A,
                               ddx: vec2<f32>,
                               ddy: vec2<f32>,
                               offset: vec2<i32>) -> vec4<f32>
T は texture_3d<f32>、または texture_cube<f32>
@must_use fn textureSampleGrad(t: T,
                               s: sampler,
                               coords: vec3<f32>,
                               ddx: vec3<f32>,
                               ddy: vec3<f32>) -> vec4<f32>
@must_use fn textureSampleGrad(t: texture_3d<f32>,
                               s: sampler,
                               coords: vec3<f32>,
                               ddx: vec3<f32>,
                               ddy: vec3<f32>,
                               offset: vec3<i32>) -> vec4<f32>
A は i32、または u32
@must_use fn textureSampleGrad(t: texture_cube_array<f32>,
                               s: sampler,
                               coords: vec3<f32>,
                               array_index: A,
                               ddx: vec3<f32>,
                               ddy: vec3<f32>) -> vec4<f32>

パラメーター:

t サンプリングするサンプリングテクスチャー。
s サンプラー。
coords サンプリングに使用されるテクスチャー座標。
array_index サンプリングする 0 ベースのテクスチャー配列インデックス。
この値は必ず範囲 [0, textureNumLayers(t) - 1] にクランプされます。
ddx サンプリング位置の計算に使用される x 方向の微分ベクトル。
ddy サンプリング位置の計算に使用される y 方向の微分ベクトル。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、任意の テクスチャーラップモードを適用する前に適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず少なくとも -8、かつ最大 7 でなければなりません。範囲外の値は シェーダー作成エラーになります。

戻り値:

サンプリングされた値。

17.7.13. textureSampleLevel

明示的なミップレベルを使用してテクスチャーをサンプリングします。

パラメーター化 オーバーロード
@must_use fn textureSampleLevel(t: texture_1d<f32>,
                                s: sampler,
                                coords: f32,
                                level: f32) -> vec4<f32>
@must_use fn textureSampleLevel(t: texture_2d<f32>,
                                s: sampler,
                                coords: vec2<f32>,
                                level: f32) -> vec4<f32>
@must_use fn textureSampleLevel(t: texture_2d<f32>,
                                s: sampler,
                                coords: vec2<f32>,
                                level: f32,
                                offset: vec2<i32>) -> vec4<f32>
A は i32、または u32
@must_use fn textureSampleLevel(t: texture_2d_array<f32>,
                                s: sampler,
                                coords: vec2<f32>,
                                array_index: A,
                                level: f32) -> vec4<f32>
A は i32、または u32
@must_use fn textureSampleLevel(t: texture_2d_array<f32>,
                                s: sampler,
                                coords: vec2<f32>,
                                array_index: A,
                                level: f32,
                                offset: vec2<i32>) -> vec4<f32>
T は texture_3d<f32>、または texture_cube<f32>
@must_use fn textureSampleLevel(t: T,
                                s: sampler,
                                coords: vec3<f32>,
                                level: f32) -> vec4<f32>
@must_use fn textureSampleLevel(t: texture_3d<f32>,
                                s: sampler,
                                coords: vec3<f32>,
                                level: f32,
                                offset: vec3<i32>) -> vec4<f32>
A は i32、または u32
@must_use fn textureSampleLevel(t: texture_cube_array<f32>,
                                s: sampler,
                                coords: vec3<f32>,
                                array_index: A,
                                level: f32) -> vec4<f32>
L は i32、または u32
@must_use fn textureSampleLevel(t: texture_depth_2d,
                                s: sampler,
                                coords: vec2<f32>,
                                level: L) -> f32
L は i32、または u32
@must_use fn textureSampleLevel(t: texture_depth_2d,
                                s: sampler,
                                coords: vec2<f32>,
                                level: L,
                                offset: vec2<i32>) -> f32
A は i32、または u32
L は i32、または u32
@must_use fn textureSampleLevel(t: texture_depth_2d_array,
                                s: sampler,
                                coords: vec2<f32>,
                                array_index: A,
                                level: L) -> f32
A は i32、または u32
L は i32、または u32
@must_use fn textureSampleLevel(t: texture_depth_2d_array,
                                s: sampler,
                                coords: vec2<f32>,
                                array_index: A,
                                level: L,
                                offset: vec2<i32>) -> f32
L は i32、または u32
@must_use fn textureSampleLevel(t: texture_depth_cube,
                                s: sampler,
                                coords: vec3<f32>,
                                level: L) -> f32
A は i32、または u32
L は i32、または u32
@must_use fn textureSampleLevel(t: texture_depth_cube_array,
                                s: sampler,
                                coords: vec3<f32>,
                                array_index: A,
                                level: L) -> f32

パラメーター:

t サンプリングするサンプリングまたは深度テクスチャー。
s サンプラー型。
coords サンプリングに使用されるテクスチャー座標。
array_index サンプリングする 0 ベースのテクスチャー配列インデックス。
この値は必ず範囲 [0, textureNumLayers(t) - 1] にクランプされます。
level ミップレベル。レベル 0 にはテクスチャーのフルサイズ版が含まれます。 level が f32 である関数では、フォーマットが テクスチャーフォーマット機能に従ってフィルター可能である場合、端数値によって 2 つのレベル間を補間してもよいです。
offset テクスチャーをサンプリングする前に、非正規化テクスチャー座標へ適用される任意のテクセルオフセット。 このオフセットは、任意の テクスチャーラップモードを適用する前に適用されます。
offset 式は必ずconst 式(たとえば vec2<i32>(1, 2))でなければなりません。
各 offset 成分は必ず少なくとも -8、かつ最大 7 でなければなりません。範囲外の値は シェーダー作成エラーになります。

戻り値:

サンプリングされた値。

17.7.14. textureSampleBaseClampToEdge

テクスチャービューをそのベースレベルでサンプリングし、 テクスチャー座標を以下で説明するように端へクランプします。

パラメーター化 オーバーロード
T は texture_2d<f32> または texture_external
@must_use fn textureSampleBaseClampToEdge(t: T,
                                          s: sampler,
                                          coords: vec2<f32>) -> vec4<f32>

パラメーター:

t サンプリングするサンプリングまたは外部テクスチャー。
s サンプラー型。
coords サンプリングに使用されるテクスチャー座標。

サンプリング前に、指定された座標は必ず 次の矩形へクランプされます

[ half_texel, 1 - half_texel ]

ここで

half_texel = vec2(0.5) / vec2<f32>(textureDimensions(t))

注: 半テクセル調整により、 サンプラーの アドレッシング および フィルター モードに関係なく、 ラップは発生しません。 すなわち、端の近くでサンプリングすると、サンプリングされるテクセルは その端またはそれに隣接する位置にあり、反対側の端から選択されることはありません。

戻り値:

サンプリングされた値。

17.7.15. textureStore

単一のテクセルをテクスチャーへ書き込みます。

パラメーター化 オーバーロード
F はテクセル フォーマット
C は i32、または u32
AM は write または read_write
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
fn textureStore(t: texture_storage_1d<F,AM>,
                coords: C,
                value: vec4<CF>)
F はテクセル フォーマット
C は i32、または u32
AM は write または read_write
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
fn textureStore(t: texture_storage_2d<F,AM>,
                coords: vec2<C>,
                value: vec4<CF>)
F はテクセル フォーマット
C は i32、または u32
AM は write または read_write
A は i32、または u32
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
fn textureStore(t: texture_storage_2d_array<F,AM>,
                coords: vec2<C>,
                array_index: A,
                value: vec4<CF>)
F はテクセル フォーマット
C は i32、または u32
AM は write または read_write
CF はストレージテクセルフォーマット F に依存します。 テクセルフォーマットからチャンネルフォーマットへの対応については、テクセルフォーマット 表を参照してください。
fn textureStore(t: texture_storage_3d<F,AM>,
                coords: vec3<C>,
                value: vec4<CF>)

パラメーター:

t 書き込み専用ストレージテクスチャーまたは 読み書き可能ストレージテクスチャー
coords 0 ベースのテクセル座標。
array_index 0 ベースのテクスチャー配列インデックス。
value 新しいテクセル値。 value は逆チャンネル伝達関数を使用して変換されます。

注:

論理テクセル アドレスは、次の場合に無効です:

論理テクセルアドレスが無効な場合、組み込み関数は実行されません。

17.8. アトミック組み込み関数

アトミック組み込み関数は、アトミック オブジェクトの読み取り/書き込み/読み取り・変更・書き込みに使用できます。これらは § 6.2.8 アトミック型 に対して許可される唯一の操作です。

すべてのアトミック組み込み関数は relaxed メモリー 順序付けを使用します。これは、同期および順序付けの保証が、同じメモリー位置に作用する アトミック操作間にのみ適用されることを意味します。アトミックと非アトミックのメモリーアクセス間、または 異なるメモリー位置に作用するアトミックアクセス間には、同期 または順序付けの保証は適用されません。

アトミック組み込み関数は使用してはならず、vertex シェーダーステージでは使用できません。

すべてのアトミック組み込み関数における atomic_ptr パラメーターのアドレス空間 AS は 必ず storage または workgroup のいずれかでなければなりません。

別途指定されない限り、T は必ず u32 または i32 のいずれかでなければなりません。

17.8.1. atomicLoad

fn atomicLoad(atomic_ptr: ptr<AS, atomic<T>, read_write>) -> T

atomic_ptr が指す値をアトミックにロードして返します。 オブジェクトを変更 しません。

17.8.2. atomicStore

fn atomicStore(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T)

atomic_ptr が指すアトミックオブジェクトに値 v をアトミックに格納します。

17.8.3. アトミック読み取り・変更・書き込み算術および論理関数

各関数は次の手順をアトミックに実行します:

  1. atomic_ptr が指す元の値をロードします。

  2. 関数名に対応する演算(たとえば max)を値 v とともに実行して 新しい値を取得します。

  3. atomic_ptr を使用して新しい値を格納します。

各関数は、演算前にアトミックオブジェクトへ格納されていた元の値を返します。

17.8.3.1. atomicAdd
fn atomicAdd(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに対して 値 v を用いた加算演算をアトミックに実行し、演算前にアトミックオブジェクトへ格納されていた 元の値を返します。

例: 関数としてのアトミック加算の動作
// すべての操作はアトミックに実行される
fn atomicAdd(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = old + v;
  return old;
}
17.8.3.2. atomicSub
fn atomicSub(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに対して 値 v を用いた減算演算をアトミックに実行し、演算前にアトミックオブジェクトへ格納されていた 元の値を返します。

例: 関数としてのアトミック減算の動作
// すべての操作はアトミックに実行される
fn atomicSub(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = old - v;
  return old;
}
17.8.3.3. atomicMax
fn atomicMax(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに対して 値 v を用いた最大値演算をアトミックに実行し、演算前にアトミックオブジェクトへ格納されていた 元の値を返します。

例: 関数としてのアトミック最大値演算の動作
// すべての操作はアトミックに実行される
fn atomicMax(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = max(old, v);
  return old;
}
17.8.3.4. atomicMin
fn atomicMin(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに対して 値 v を用いた最小値演算をアトミックに実行し、演算前にアトミックオブジェクトへ格納されていた 元の値を返します。

例: 関数としてのアトミック最小値演算の動作
// すべての操作はアトミックに実行される
fn atomicMin(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = min(old, v);
  return old;
}
17.8.3.5. atomicAnd
fn atomicAnd(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに対して 値 v を用いたビット単位 AND 演算をアトミックに実行し、演算前にアトミックオブジェクトへ格納されていた 元の値を返します。

例: 関数としてのアトミックビット単位 AND の動作
// すべての操作はアトミックに実行される
fn atomicAnd(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = old & v;
  return old;
}
17.8.3.6. atomicOr
fn atomicOr(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに対して 値 v を用いたビット単位 OR 演算をアトミックに実行し、演算前にアトミックオブジェクトへ格納されていた 元の値を返します。

例: 関数としてのアトミックビット単位 OR の動作
// すべての操作はアトミックに実行される
fn atomicOr(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = old | v;
  return old;
}
17.8.3.7. atomicXor
fn atomicXor(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに対して 値 v を用いたビット単位 XOR 演算をアトミックに実行し、演算前にアトミックオブジェクトへ格納されていた 元の値を返します。

例: 関数としてのアトミックビット単位 XOR の動作
// すべての操作はアトミックに実行される
fn atomicXor(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = old ^ v;
  return old;
}

17.8.4. atomicExchange

fn atomicExchange(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T

atomic_ptr が指すアトミックオブジェクトに値 v をアトミックに格納し、 演算前にアトミックオブジェクトへ格納されていた元の値を返します。

例: 関数としてのアトミック交換の動作
// すべての操作はアトミックに実行される
fn atomicExchange(atomic_ptr: ptr<AS, atomic<T>, read_write>, v : T) -> T {
  let old = *atomic_ptr;
  *atomic_ptr = v;
  return old;
}

17.8.5. atomicCompareExchangeWeak

fn atomicCompareExchangeWeak(
      atomic_ptr: ptr<AS, atomic<T>, read_write>,
      cmp: T,
      v: T) -> __atomic_compare_exchange_result<T>

struct __atomic_compare_exchange_result<T> {
  old_value : T,   // アトミックに格納されていた古い値
  exchanged : bool // 交換が行われた場合は true
}

注: 値を 型 __atomic_compare_exchange_result で明示的に宣言することはできませんが、値はその型を推論できます。

次の手順をアトミックに実行します:

  1. atomic_ptr が指す元の値をロードします。

  2. 等価演算を使用して、元の値と値 cmp を比較します。

  3. 等価比較の結果が true である場合にのみ値 v を格納します。

2 メンバーの構造体を返します。最初のメンバー old_value は 演算前のアトミックオブジェクトの元の値であり、2 番目のメンバー exchanged は 比較が成功したかどうかを表します。

例: 関数としてのアトミック比較交換の動作
// すべての操作はアトミックに実行される
fn atomicCompareExchangeWeak(atomic_ptr: ptr<AS, atomic<T>, read_write>, cmp : T, v : T) ->
  _atomic_compare_exchange_result<T> {
  let old = *atomic_ptr;
  // この比較は見かけ上失敗する場合がある。
  let comparison = old == cmp;
  if comparison {
    *atomic_ptr = v;
  }
  return __atomic_compare_exchange_result<T>(old, comparison);
}

注: 等価比較は 一部の実装では見かけ上失敗する場合があります。つまり、 結果構造体の exchanged メンバーは、old_value メンバーが cmp と等しい場合でも false になることがあります。

17.8.6. アトミック格納最小値および最大値関数

これらの関数はすべて atomic_vec2u_min_max 言語機能を必要とします。

これらの関数は値を返しません。

17.8.6.1. atomicStoreMin
fn atomicStoreMin(atomic_ptr: ptr<storage, atomic<vec2<u32>>, read_write>,
                  v: vec2<u32>)

atomic_ptr が指すアトミックオブジェクトに対して 64 ビット符号なし整数の最小値演算をアトミックに実行し、 値 v を使用します。

次の手順をアトミックに実行します:

  1. atomic_ptr が参照するメモリーから元の vec2u 値 old をロードします。

  2. 64 ビット符号なし整数値を計算します:

    • old64 = 232 × old[1] + old[0]

    • v64 = 232 × v[1] + v[0]

  3. old64 と v64 の最小値として値 new64 を計算します。

  4. 型 vec2<u32> の値 new を計算します。ここで:

    • new[0] は new64 の下位 32 ビットを含み、

    • new[1] は new64 の上位 32 ビットを含みます。

  5. new を atomic_ptr が参照するメモリーへ格納します。

17.8.6.2. atomicStoreMax
fn atomicStoreMax(atomic_ptr: ptr<storage, atomic<vec2<u32>>, read_write>, v: vec2<u32>)

atomic_ptr が指すアトミックオブジェクトに対して 64 ビット符号なし整数の最大値演算をアトミックに実行し、 値 v を使用します。

次の手順をアトミックに実行します:

  1. atomic_ptr が参照するメモリーから元の vec2u 値 old をロードします。

  2. 64 ビット符号なし整数値を計算します:

    • old64 = 232 × old[1] + old[0]

    • v64 = 232 × v[1] + v[0]

  3. old64 と v64 の最大値として値 new64 を計算します。

  4. 型 vec2<u32> の値 new を計算します。ここで:

    • new[0] は new64 の下位 32 ビットを含み、

    • new[1] は new64 の上位 32 ビットを含みます。

  5. new を atomic_ptr が参照するメモリーへ格納します。

17.9. データパッキング組み込み関数

データパッキング組み込み関数は、WGSL の型に直接対応しない データフォーマットを使用して値をエンコードするために使用できます。 これにより、プログラムは多数の密にパックされた値をメモリーへ書き込むことができ、 シェーダーのメモリー帯域幅要求を削減できます。

各組み込み関数は、複数の入力値にチャンネル伝達関数の逆を適用し、その後 その結果を 単一の出力値へ結合します。

注: unorm 値をパックする場合、正規化された浮動 小数点値は区間 [0.0, 1.0] にあります。

注: snorm 値をパックする場合、正規化された浮動 小数点値は区間 [-1.0, 1.0] にあります。

17.9.1. pack4x8snorm

オーバーロード
@const @must_use fn pack4x8snorm(e: vec4<f32>) -> u32
説明 4 つの正規化浮動小数点値を 8 ビット符号付き整数に変換し、その後それらを 1 つの u32 値へ結合します。

入力の成分 e[i] は 8 ビット 2 の補数整数 値 ⌊ 0.5 + 127 × min(1, max(-1, e[i])) ⌋ へ変換され、その後結果のビット 8 × i から 8 × i + 7 に配置されます。

17.9.2. pack4x8unorm

オーバーロード
@const @must_use fn pack4x8unorm(e: vec4<f32>) -> u32
説明 4 つの正規化浮動小数点値を 8 ビット符号なし整数に変換し、その後それらを 1 つの u32 値へ 結合します。

入力の成分 e[i] は 8 ビット符号なし整数値 ⌊ 0.5 + 255 × min(1, max(0, e[i])) ⌋ へ変換され、その後結果のビット 8 × i から 8 × i + 7 に配置されます。

17.9.3. pack4xI8

オーバーロード
@const @must_use fn pack4xI8(e: vec4<i32>) -> u32
説明 e の各成分の下位 8 ビットを u32 値へパックし、使用されないすべてのビットを破棄します。

入力の成分 e[i] は結果のビット 8 × i から 8 × i + 7 に対応付けられます。

17.9.4. pack4xU8

オーバーロード
@const @must_use fn pack4xU8(e: vec4<u32>) -> u32
説明 e の各成分の下位 8 ビットを u32 値へパックし、使用されないすべてのビットを破棄します。

入力の成分 e[i] は結果のビット 8 × i から 8 × i + 7 に対応付けられます。

17.9.5. pack4xI8Clamp

オーバーロード
@const @must_use fn pack4xI8Clamp(e: vec4<i32>) -> u32
説明 e の各成分を範囲 [-128, 127] にクランプし、その後各 成分の下位 8 ビットを u32 値へパックします。

入力の成分 e[i] は結果のビット 8 × i から 8 × i + 7 に対応付けられます。

17.9.6. pack4xU8Clamp

オーバーロード
@const @must_use fn pack4xU8Clamp(e: vec4<u32>) -> u32
説明 e の各成分を範囲 [0, 255] にクランプし、その後各 成分の下位 8 ビットを u32 値へパックします。

入力の成分 e[i] は結果のビット 8 × i から 8 × i + 7 に対応付けられます。

17.9.7. pack2x16snorm

オーバーロード
@const @must_use fn pack2x16snorm(e: vec2<f32>) -> u32
説明 2 つの正規化浮動小数点値を 16 ビット符号付き整数に変換し、その後それらを 1 つの u32 値へ結合します。
入力の成分 e[i] は 16 ビット 2 の補数整数値へ変換されます ⌊ 0.5 + 32767 × min(1, max(-1, e[i])) ⌋。その後、結果のビット 16 × i から 16 × i + 15 に配置されます。

17.9.8. pack2x16unorm

オーバーロード
@const @must_use fn pack2x16unorm(e: vec2<f32>) -> u32
説明 2 つの正規化浮動小数点値を 16 ビット符号なし整数に変換し、その後 それらを 1 つの u32 値へ結合します。
入力の成分 e[i] は 16 ビット符号なし整数値へ変換されます ⌊ 0.5 + 65535 × min(1, max(0, e[i])) ⌋。その後、結果のビット 16 × i から 16 × i + 15 に配置されます。

17.9.9. pack2x16float

オーバーロード
@const @must_use fn pack2x16float(e: vec2<f32>) -> u32
説明 2 つの浮動小数点値を半精度浮動小数点数へ変換し、その後それらを 1 つの u32 値へ結合します。
入力の成分 e[i] は IEEE-754 binary16 値へ変換され、その後 結果のビット 16 × i から 16 × i + 15 に配置されます。 § 15.7.6 浮動小数点変換を参照してください。

e[0] または e[1] のいずれかが binary16 の有限範囲外にある場合:

17.10. データアンパッキング組み込み関数

データアンパッキング組み込み関数は、 WGSL の型に直接対応しないデータフォーマットの値をデコードするために使用できます。 これにより、プログラムは多数の密にパックされた値をメモリーから読み取ることができ、 シェーダーのメモリー帯域幅要求を削減できます。

各組み込み関数は入力値をチャンネルへ分解し、その後それぞれにチャンネル伝達関数 を適用します。

注: unorm 値をアンパックする場合、正規化された 浮動小数点結果は区間 [0.0, 1.0] にあります。

注: snorm 値をアンパックする場合、正規化された 浮動小数点結果は区間 [-1.0, 1.0] にあります。

17.10.1. unpack4x8snorm

オーバーロード
@const @must_use fn unpack4x8snorm(e: u32) -> vec4<f32>
説明 32 ビット値を 4 つの 8 ビットチャンクへ分解し、その後 各チャンクを符号付き正規化浮動小数点値として再解釈します。
結果の成分 i は max(v ÷ 127, -1) です。ここで v は、 e のビット 8×i から 8×i + 7 を 2 の補数の符号付き 整数として解釈した値です。

17.10.2. unpack4x8unorm

オーバーロード
@const @must_use fn unpack4x8unorm(e: u32) -> vec4<f32>
説明 32 ビット値を 4 つの 8 ビットチャンクへ分解し、その後 各チャンクを符号なし正規化浮動小数点値として再解釈します。
結果の成分 i は v ÷ 255 です。ここで v は、 e のビット 8×i から 8×i + 7 を符号なし整数として解釈した値です。

17.10.3. unpack4xI8

オーバーロード
@const @must_use fn unpack4xI8(e: u32) -> vec4<i32>
説明 e は 4 つの 8 ビット符号付き整数成分を持つベクトルとして解釈されます。 e を符号拡張して vec4<i32> へアンパックします。

17.10.4. unpack4xU8

オーバーロード
@const @must_use fn unpack4xU8(e: u32) -> vec4<u32>
説明 e は 4 つの 8 ビット符号なし整数成分を持つベクトルとして解釈されます。 e をゼロ拡張して vec4<u32> へアンパックします。

17.10.5. unpack2x16snorm

オーバーロード
@const @must_use fn unpack2x16snorm(e: u32) -> vec2<f32>
説明 32 ビット値を 2 つの 16 ビットチャンクへ分解し、その後 各チャンクを符号付き正規化浮動小数点値として再解釈します。
結果の成分 i は max(v ÷ 32767, -1) です。ここで v は、 e のビット 16×i から 16×i + 15 を 2 の補数の 符号付き整数として解釈した値です。

17.10.6. unpack2x16unorm

オーバーロード
@const @must_use fn unpack2x16unorm(e: u32) -> vec2<f32>
説明 32 ビット値を 2 つの 16 ビットチャンクへ分解し、その後 各チャンクを符号なし正規化浮動小数点値として再解釈します。
結果の成分 i は v ÷ 65535 です。ここで v は、 e のビット 16×i から 16×i + 15 を符号なし整数として解釈した値です。

17.10.7. unpack2x16float

オーバーロード
@const @must_use fn unpack2x16float(e: u32) -> vec2<f32>
説明 32 ビット値を 2 つの 16 ビットチャンクへ分解し、各チャンクを 浮動小数点値として再解釈します。
結果の成分 i は v の f32 表現です。 ここで v は e のビット 16×i から 16×i + 15 を IEEE-754 binary16 値として解釈したものです。 § 15.7.6 浮動小数点変換を参照してください。

17.11. 同期組み込み関数

すべての同期関数は、Acquire/Release メモリー順序付けを伴う制御バリアを実行します。 すなわち、すべての同期関数、および影響を受けるメモリー操作とアトミック 操作は、同期関数に対してプログラム順序で順序付けられます。 さらに、同期関数より前にプログラム順序付けされた影響対象のメモリー操作とアトミック操作は、 同期関数より後にプログラム順序付けされた影響対象のメモリー操作またはアトミック操作が ワークグループのメンバーによって実行される前に、 ワークグループ内の他のすべてのスレッドから可視でなければなりません。

すべての同期関数は Workgroup メモリースコープを使用します。
すべての同期関数は Workgroup 実行スコープを持ちます。
すべての同期関数は必ず compute シェーダーステージでのみ使用しなければなりません。 すべての同期関数は必ず 一様制御 フロー内でのみ呼び出されなければなりません。

17.11.1. storageBarrier

オーバーロード
fn storageBarrier()
説明 storage アドレス 空間内のメモリー操作とアトミック操作に影響する制御 バリア同期関数を実行します。

17.11.2. textureBarrier

オーバーロード
fn textureBarrier()
説明 handle アドレス空間内の メモリー操作に影響する制御 バリア同期関数を実行します。

17.11.3. workgroupBarrier

オーバーロード
fn workgroupBarrier()
説明 workgroup アドレス 空間内のメモリー操作とアトミック操作に影響する制御 バリア同期関数を実行します。

17.11.4. workgroupUniformLoad

オーバーロード
@must_use fn workgroupUniformLoad(p : ptr<workgroup, T>) -> T
パラメーター化 T は具象の構築可能型です。
説明 p が指す値をワークグループ内のすべての呼び出しへ返します。 戻り値は一様です。 p は必ず一様値でなければなりません。

workgroup アドレス 空間内のメモリー操作とアトミック操作に影響する制御バリア同期関数を実行します。

オーバーロード
@must_use fn workgroupUniformLoad(p : ptr<workgroup, atomic<T>, read_write>) -> T
説明 p が指す値をアトミックにロードし、ワークグループ内のすべての呼び出しへ 返します。 戻り値は一様です。 p は必ず一様値でなければなりません。

workgroup アドレス 空間内のメモリー操作とアトミック操作に影響する制御バリア同期関数を実行します。

17.12. サブグループ組み込み関数

§ 15.6.3 サブグループ操作を参照してください。

これらの関数の呼び出しは:

注: compute シェーダーステージでは、一様制御フローのスコープは ワークグループです。 fragment シェーダーステージでは、一様制御フローのスコープは 描画コマンドです。 これらのスコープはいずれもサブグループより大きくなります。

17.12.1. subgroupAdd

オーバーロード
@must_use fn subgroupAdd(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 リダクション操作。

サブグループ内のすべてのアクティブな呼び出しにおける e の合計を返します。

17.12.1.1. subgroupExclusiveAdd
オーバーロード
@must_use fn subgroupExclusiveAdd(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 排他的プレフィックススキャン操作。

サブグループ内で、 サブグループ呼び出し ID が現在の 呼び出しの id より小さいすべてのアクティブな呼び出しにおける e の合計を返します。

アクティブな呼び出しの中で最小の id を持つ呼び出しに返される値は T(0) です。

17.12.1.2. subgroupInclusiveAdd
オーバーロード
@must_use fn subgroupInclusiveAdd(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 包含的プレフィックススキャン操作。

サブグループ内で、 サブグループ呼び出し ID が現在の呼び出しの id 以下である すべてのアクティブな呼び出しにおける e の合計を返します。

注: subgroupExclusiveAdd(x) + x と等価です。

17.12.2. subgroupAll

オーバーロード
@must_use fn subgroupAll(e : bool) -> bool
説明 アクティブなすべての呼び出しについて e が true である場合、サブグループ内で true を返します。

17.12.3. subgroupAnd

オーバーロード
@must_use fn subgroupAnd(e : T) -> T
前提条件 T は i32、u32、vecN<i32>、または vecN<u32>
説明 リダクション操作。

アクティブなすべての 呼び出しにおける e のビット単位 AND(&)を、サブグループ内で返します。

17.12.4. subgroupAny

オーバーロード
@must_use fn subgroupAny(e : bool) -> bool
説明 アクティブな呼び出しのいずれかについて e が true である場合、サブグループ内で true を返します。

17.12.5. subgroupBallot

オーバーロード
@must_use fn subgroupBallot(pred : bool) -> vec4<u32>
説明 pred が true であるアクティブな呼び出しについて、 サブグループ内の ビットマスクを返します。

戻り値の x 成分には呼び出し 0 から 31 が含まれます。
戻り値の y 成分には呼び出し 32 から 63 が含まれます。
戻り値の z 成分には呼び出し 64 から 95 が含まれます。
戻り値の w 成分には呼び出し 96 から 127 が含まれます。

各成分内で、ID はビット位置の昇順です (たとえば ID 32 は y 成分のビット位置 0 にあります)。

17.12.6. subgroupBroadcast

オーバーロード
@must_use fn subgroupBroadcast(e : T, id : I) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
I は u32 または i32
説明 サブグループ呼び出し ID が id と一致する呼び出しの e の値を、サブグループ内のすべてのアクティブな呼び出しへサブグループ内で返します。

id は必ず範囲 [0, 128) のconst 式でなければなりません。

id がアクティブな 呼び出しを選択しない場合、動的 エラーです。

注: id の非定数版が必要な場合は、 代わりに subgroupShuffle を使用してください。

17.12.6.1. subgroupBroadcastFirst
オーバーロード
@must_use fn subgroupBroadcastFirst(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 アクティブな 呼び出しの中で最小のサブグループ呼び出し ID を持つ呼び出しの e の値を、 サブグループ内のすべてのアクティブな 呼び出しへ返します。

17.12.7. subgroupElect

オーバーロード
@must_use fn subgroupElect() -> bool
説明 現在の呼び出しが、アクティブな呼び出しの中で最小のサブグループ呼び出し ID を持つ場合、サブグループ内で true を返します。

17.12.8. subgroupMax

オーバーロード
@must_use fn subgroupMax(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 リダクション操作。

アクティブなすべての呼び出しにおける e の最大値を、 サブグループ内で返します。

17.12.9. subgroupMin

オーバーロード
@must_use fn subgroupMin(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 リダクション操作。

アクティブなすべての呼び出しにおける e の最小値を、 サブグループ内で返します。

17.12.10. subgroupMul

オーバーロード
@must_use fn subgroupMul(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 リダクション操作。

アクティブなすべての呼び出しにおける e の積を、 サブグループ内で返します。

17.12.10.1. subgroupExclusiveMul
オーバーロード
@must_use fn subgroupExclusiveMul(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 排他的プレフィックススキャン操作。

アクティブな呼び出しのうち、 サブグループ内でサブグループ呼び出し ID が 現在の呼び出しの id より小さいすべての呼び出しにおける e の積を返します。

アクティブな呼び出しの中で最小の id を持つ呼び出しに返される値は T(1) です。

17.12.10.2. subgroupInclusiveMul
オーバーロード
@must_use fn subgroupInclusiveMul(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 包含的プレフィックススキャン操作。

アクティブな呼び出しのうち、 サブグループ内でサブグループ呼び出し ID が 現在の呼び出しの id 以下であるすべての呼び出しにおける e の積を返します。

注: subgroupExclusiveMul(x) * x と等価です。

17.12.11. subgroupOr

オーバーロード
@must_use fn subgroupOr(e : T) -> T
前提条件 T は i32、u32、vecN<i32>、または vecN<u32>
説明 リダクション操作。

アクティブなすべての 呼び出しにおける e のビット単位 OR(|)を、サブグループ内で返します。

17.12.12. subgroupShuffle

オーバーロード
@must_use fn subgroupShuffle(e : T, id : I) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
I は u32 または i32
説明 サブグループ呼び出し ID が id と一致する呼び出しから e を返します。

id が範囲 [0, 128) 外にある場合:

id が アクティブな 呼び出しを選択しない場合、不定値が返されます。

17.12.12.1. subgroupShuffleDown
オーバーロード
@must_use fn subgroupShuffleDown(e : T, delta : u32) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 現在の呼び出しについて、サブグループ呼び出し ID が subgroup_invocation_id + delta と一致する呼び出しから e を返します。

delta が 127 より大きい場合:

delta が一様値でない場合、subgroup_uniformity 診断がトリガーされます。 subgroup_invocation_id + delta がアクティブな呼び出しを選択しない場合、または delta が サブグループ内で 一様値ではない場合、不定値が返されます。

17.12.12.2. subgroupShuffleUp
オーバーロード
@must_use fn subgroupShuffleUp(e : T, delta : u32) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 現在の呼び出しについて、サブグループ呼び出し ID が subgroup_invocation_id - delta と一致する呼び出しから e を返します。

delta が 127 より大きい場合:

delta が一様値でない場合、subgroup_uniformity 診断がトリガーされます。 subgroup_invocation_id - delta がアクティブな呼び出しを選択しない場合、または delta が サブグループ内で一様値ではない場合、不定値が返されます。

17.12.12.3. subgroupShuffleXor
オーバーロード
@must_use fn subgroupShuffleXor(e : T,  mask : u32) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 現在の呼び出しについて、サブグループ呼び出し ID が subgroup_invocation_id ^ mask と一致する呼び出しから e を返します。

mask が 127 より大きい場合:

mask が一様値でない場合、subgroup_uniformity 診断がトリガーされます。 mask がアクティブな呼び出しを選択しない場合、または mask が サブグループ内で一様値ではない場合、不定値が返されます。

17.12.13. subgroupXor

オーバーロード
@must_use fn subgroupXor(e : T) -> T
前提条件 T は i32、u32、vecN<i32>、または vecN<u32>
説明 リダクション操作。

アクティブなすべての 呼び出しにおける e のビット単位 XOR(^)を、サブグループ内で返します。

17.13. クアッド操作

§ 15.6.4 クアッド操作を参照してください。

これらの関数の呼び出しは:

注: compute シェーダーステージでは、一様制御フローのスコープは ワークグループです。 fragment シェーダーステージでは、一様制御フローのスコープは 描画コマンドです。 これらのスコープはいずれもクアッドより大きくなります。

17.13.1. quadBroadcast

オーバーロード
@must_use fn quadBroadcast(e : T, id : I) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
I は u32 または i32
説明 クアッド呼び出し ID が id と一致する呼び出しの e の値を、クアッド内のすべてのアクティブな呼び出しへ返します。

id は必ず範囲 [0, 4) のconst 式でなければなりません。

id が アクティブな 呼び出しを選択しない場合、不定値が返されます。

注: subgroupBroadcast とは異なり、現在 非定数の代替手段はありません。

17.13.2. quadSwapDiagonal

オーバーロード
@must_use fn quadSwapDiagonal(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 クアッド内で反対側の座標を持つ呼び出しから e の値を返します。 すなわち:
  • ID 0 と 3 が交換されます。

  • ID 1 と 2 が交換されます。

17.13.3. quadSwapX

オーバーロード
@must_use fn quadSwapX(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 同じ X 次元を共有するクアッド内の呼び出しから e の値を返します。 すなわち:
  • ID 0 と 1 が交換されます。

  • ID 2 と 3 が交換されます。

17.13.4. quadSwapY

オーバーロード
@must_use fn quadSwapY(e : T) -> T
前提条件 T は具象数値スカラーまたは具象数値ベクトル
説明 同じ Y 次元を共有するクアッド内の呼び出しから e の値を返します。 すなわち:
  • ID 0 と 2 が交換されます。

  • ID 1 と 3 が交換されます。

17.14. バッファービュー組み込み関数

これらの関数はすべて buffer_view 言語機能を必要とします。

これらの関数はバッファーへのポインターを操作します。 bufferView および bufferArrayView はバッファー内の不透明データを 別のホスト共有可能データ型として再解釈します。 結果のポインターは、その後ほかのポインターと同様に使用できます。

ArrayOffset(T) を次のように定義します:

MinTypeSize(T) を次のように定義します:

関数呼び出しへのバッファーポインター引数は仮引数の型へ自動 変換される場合があるため、実装は必ず プロシージャ間解析を使用して、無効なメモリー参照の両方をチェックし、 正しい結果を保証します。 バッファービュー組み込み関数で使用されるバッファーサイズは、その呼び出しで使用される特定の起点変数について遭遇した最小の バッファーサイズです。 これは動的な概念であるため、実装は必ず組み込み関数の特定のインスタンスについてこの値が正しく決定されることを保証します。 サイズは次の最小値になります:

注: 実装が unrestricted_pointer_parameters 言語機能をサポートしない場合、 組み込み関数への引数のルート識別子は 起点 変数でなければなりません。

注: バッファーサイズは、関数へ 渡される際に大きくすることはできません。

17.14.1. bufferView

オーバーロード
@must_use fn bufferView<T>(p : ptr<AS, buffer, AM>, offset: I) -> ptr<AS, T, AM>
前提条件 AS は storage、uniform、または workgroup のいずれかです。
AM は AS に有効なアクセスモードです。

T はホスト共有可能型です。
T はしてはならず、アトミックまたはバッファー型であっても、それらを含んでもなりません。
T は必ず AS のアドレス空間レイアウト制約を満たさなければなりません。

I は u32 または i32 です。

説明 p の先頭から offset バイトのメモリー ビューを型 T として再解釈します。 すなわち、p に関連付けられたメモリー位置が 範囲 [0, bufferLength(p)) にある場合、結果に関連付けられたメモリー位置は、格納型 T で範囲 [offset, bufferLength(p)) にあります。

I が i32 の場合:

MinTypeSize(T) + offset > bufferLength(p) の場合、無効な ポインターが返されます。

offset % RequiredAlignOf(T, AS) != 0 の場合:

注: これは uniform_buffer_standard_layout 言語機能と相互作用します。

オーバーロード
@must_use fn bufferView<T>(p : ptr<AS, buffer<N>, AM>, offset: I) -> ptr<AS, T, AM>
前提条件 AS は storage、uniform、または workgroup のいずれかです。
AM は AS に有効なアクセスモードです。

T はホスト共有可能型です。
T はしてはならず、アトミックまたはバッファー型であっても、それらを含んでもなりません。
T は必ず AS のアドレス空間レイアウト制約を満たさなければなりません。

I は u32 または i32 です。

説明 p の先頭から offset バイトのメモリー ビューを型 T として再解釈します。 すなわち、p に関連付けられたメモリー位置が 範囲 [0, bufferLength(p)) にある場合、結果に関連付けられたメモリー位置は、格納型 T で範囲 [offset, bufferLength(p)) にあります。

I が i32 の場合:

MinTypeSize(T) + offset > N の場合、無効なメモリー参照が返されます。

offset % RequiredAlignOf(T, AS) != 0 の場合:

注: これは uniform_buffer_standard_layout 言語機能と相互作用します。

例: WGSL bufferView の使用
requires buffer_view;

@group(0) @binding(0) var<storage> in : buffer;
@group(0) @binding(1) var<storage, read_write> out : buffer;

struct S {
  a : mat3x3f,
  b : vec2f,
}

fn foo(offsets : array<u32, 4>) {
  // データの一部を vec4u として読み書きする。
  let p1 = bufferView<vec4u>(&in, offsets[0]);
  *bufferView<vec4u>(&out, offsets[1]) = *p1;

  // 構造体を介してほかのデータの一部を読み書きする。
  let p2 = bufferView<array<S, 2>>(&in, offsets[2]);
  let v = (*p2)[1].a;
  *bufferView<mat3x3f>(&out, offsets[3]) = v;
}

17.14.2. bufferArrayView

オーバーロード
@must_use fn bufferArrayView<T>(p : ptr<AS, buffer, AM>,
                                offset: OI, size: SI) -> ptr<AS, T, AM>
前提条件 AS は storage、uniform、または workgroup のいずれかです。
AM は AS に有効なアクセスモードです。

T は固定フットプリントを持たないホスト共有可能型です。
T はしてはならず、アトミック またはバッファー型であっても、それらを含んでもなりません。
T は必ず AS のアドレス空間レイアウト制約を満たさなければなりません。

OI は u32 または i32 です。
SI は u32 または i32 です。

説明 p の先頭から offset バイトの位置から size バイト分のメモリー ビューを型 T として再解釈します。 すなわち、p に関連付けられたメモリー位置が 範囲 [0, bufferLength(p)) にある場合、結果に関連付けられたメモリー位置は、格納 型 T で範囲 [offset, offset + size) にあります。

OI が i32 の場合:

SI が i32 の場合:

MinTypeSize(T) > size の場合、無効なメモリー参照が返されます。

offset + size > bufferLength(p) の場合、無効なメモリー参照が返されます。

offset % RequiredAlignOf(T, AS) != 0 の場合:

注: これは uniform_buffer_standard_layout 言語機能と相互作用します。

(size - ArrayOffset(T)) % StrideOf(array<E>) != 0 の場合:

オーバーロード
@must_use fn bufferArrayView<T>(p : ptr<AS, buffer<N>, AM>,
                                offset: OI, size: SI) -> ptr<AS, T, AM>
前提条件 AS は storage、uniform、または workgroup のいずれかです。
AM は AS に有効なアクセスモードです。

T は固定フットプリントを持たないホスト共有可能型です。
T はしてはならず、アトミック またはバッファー型であっても、それらを含んでもなりません。
T は必ず AS のアドレス空間レイアウト制約を満たさなければなりません。

OI は u32 または i32 です。
SI は u32 または i32 です。

説明 p の先頭から offset バイトの位置から size バイト分のメモリー ビューを型 T として再解釈します。 すなわち、p に関連付けられたメモリー位置が 範囲 [0, bufferLength(p)) にある場合、結果に関連付けられたメモリー位置は、格納 型 T で範囲 [offset, offset + size) にあります。

OI が i32 の場合:

SI が i32 の場合:

MinTypeSize(T) > size の場合、無効なメモリー参照が返されます。

offset + size > N の場合、無効なメモリー参照が返されます。

MinTypeSize(T) > N の場合:

offset % RequiredAlignOf(T, AS) != 0 の場合:

注: これは uniform_buffer_standard_layout 言語機能と相互作用します。

(size - ArrayOffset(T)) % StrideOf(array<E>) != 0 の場合:

例: WGSL bufferArrayView の使用
requires buffer_view;

const stride = 32;
const N = 4;
const size = 2048;
const_assert stride * N < size;

struct strided_u32 {
  @size(stride) a : u32,
}

@group(0) @binding(0) var<uniform> in : buffer<size>;
@group(0) @binding(1) var<storage, read_write> out: array<u32, N>;

fn foo(offsets : u32) {
  // in からストライド付き配列を読み取り、ストライドなしで out へコピーする。
  var tmp : array<u32, N>;
  let view = bufferArrayView<array<strided_u32>>(&in, offset, stride * N);
  for (var i = 0; i < N; i++) {
    tmp[i] = (*view)[i];
  }
  out = tmp;
}

17.14.3. bufferLength

オーバーロード
@must_use fn bufferLength(p : ptr<AS, buffer,    AM>) -> u32
@must_use fn bufferLength(p : ptr<AS, buffer<N>, AM>) -> u32
前提条件 AS は storage、uniform、または workgroup のいずれかです。
AM は AS に有効なアクセスモードです。
説明 プロシージャ間解析中に遭遇した、p が指すバッファーの最小サイズ、または ランタイムサイズバッファーのみが遭遇した場合は WebGPU GPUBuffer のサイズを返します。
例: bufferLength の値
requires buffer_view;
requires unrestricted_pointer_parameters;

@group(0) @binding(0) var<storage> b1 : buffer<2048>;
@group(0) @binding(0) var<storage> b2 : buffer<4096>;

fn foobar(p : ptr<storage, buffer>) -> u32 {
  return bufferLength(p);
}
fn bar(p : ptr<storage, buffer<1024>>) -> u32 {
  return foobar(p);
}
fn foo(p : ptr<storage, buffer<256>>) -> u32 {
  return bufferLength(p);
}

@compute @workgroup_size(1)
fn main() {
  let len1 = bufferLength(&b1); // 2048
  let len2 = bufferLength(&b2); // 4096

  let len3 = foo(&b1); // 256
  let len4 = foo(&b2); // 256

  let len5 = bar(&b1); // 1024
  let len6 = bar(&b2); // 1024

  let len7 = foobar(&b1); // 2048
  let len8 = foobar(&b2); // 4096
}

18. 再帰下降構文解析用の文法

この節は非規範的です。

WGSL 文法は LALR(1) パーサーに適した形式で規定されています。 実装では代わりに再帰下降パーサーを使用したい場合があります。

規範的な文法は再帰下降パーサーで直接使用できません。これは、 その規則のいくつかが左再帰であるためです。 文法規則は、定義される非終端記号がその生成規則の 1 つの先頭に現れる場合、 直接左再帰です。

以下は WGSL 文法ですが、機械的に次のように変換されています:

ただし、これは LL(1) ではありません。 一部の非終端記号では、複数の生成規則が共通の先読み集合を持ちます。 たとえば、attribute 非終端記号のすべての生成規則は attr トークンで始まります。 より微妙な例は global_decl で、3 つの生成規則が attribute * 句で始まりますが、その後 fn、override、var トークンによって区別されます。

簡潔にするため、多くのトークン定義は繰り返していません。 仕様の本文にあるトークン定義を使用してください。

additive_operator:

'+'

| '-'

argument_expression_list:

'(' ( expression ( ',' expression )* ',' ? )? ')'

assignment_statement/0.1:

compound_assignment_operator

| '='

attribute:

compute_attr

| const_attr

| fragment_attr

| interpolate_attr

| invariant_attr

| must_use_attr

| vertex_attr

| workgroup_size_attr

| '@' ident_pattern_token ( '(' ( expression ( ',' expression )* ',' ? )? ')' )?

| '@' 'align' '(' expression ',' ? ')'

| '@' 'binding' '(' expression ',' ? ')'

| '@' 'blend_src' '(' expression ',' ? ')'

| '@' 'builtin' '(' builtin_value_name ',' ? ')'

| '@' 'diagnostic' diagnostic_control

| '@' 'group' '(' expression ',' ? ')'

| '@' 'id' '(' expression ',' ? ')'

| '@' 'location' '(' expression ',' ? ')'

| '@' 'size' '(' expression ',' ? ')'

| '@' 'subgroup_size' '(' expression ',' ? ')'

bitwise_expression.post.unary_expression:

'&' unary_expression ( '&' unary_expression )*

| '^' unary_expression ( '^' unary_expression )*

| '|' unary_expression ( '|' unary_expression )*

bool_literal:

'false'

| 'true'

builtin_value_name: ident_pattern_token
call_expression.post.ident:

template_elaborated_ident.post.ident '(' ( expression ( ',' expression )* ',' ? )? ')'

case_selector:

expression

| 'default'

component_or_swizzle_specifier:

'.' member_ident component_or_swizzle_specifier ?

| '.' swizzle_name component_or_swizzle_specifier ?

| '[' expression ']' component_or_swizzle_specifier ?

compound_assignment_operator:

shift_left_assign

| shift_right_assign

| '%='

| '&='

| '*='

| '+='

| '-='

| '/='

| '^='

| '|='

compound_statement:

attribute * '{' statement * '}'

compute_attr:

'@' 'compute'

const_attr:

'@' 'const'

core_lhs_expression:

ident

| ident call_expression.post.ident

| '(' lhs_expression ')'

decimal_int_literal:

/0[iu]?/

| /[1-9][0-9]*[iu]?/

diagnostic_control:

'(' ident_pattern_token ',' diagnostic_rule_name ',' ? ')'

diagnostic_rule_name:

ident_pattern_token

| ident_pattern_token '.' ident_pattern_token

expression:

unary_expression bitwise_expression.post.unary_expression

| unary_expression relational_expression.post.unary_expression

| unary_expression relational_expression.post.unary_expression '&&' unary_expression relational_expression.post.unary_expression ( '&&' unary_expression relational_expression.post.unary_expression )*

| unary_expression relational_expression.post.unary_expression '||' unary_expression relational_expression.post.unary_expression ( '||' unary_expression relational_expression.post.unary_expression )*

float_literal:

decimal_float_literal

| hex_float_literal

for_init:

ident call_expression.post.ident

| variable_or_value_statement

| variable_updating_statement

for_update:

ident call_expression.post.ident

| variable_updating_statement

fragment_attr:

'@' 'fragment'

global_assert:

'const_assert' ';'

global_decl:

attribute * 'fn' ident '(' ( attribute * ident ':' type_specifier ( ',' param )* ',' ? )? ')' ( '->' attribute * ident template_elaborated_ident.post.ident )? attribute * '{' statement * '}'

| attribute * 'var' ( _template_args_start expression ( ',' expression )* ',' ? _template_args_end )? optionally_typed_ident ( '=' expression )? ';'

| global_value_decl ';'

| 'alias' ident '=' ident template_elaborated_ident.post.ident ';'

| 'struct' ident '{' attribute * member_ident ':' type_specifier ( ',' attribute * member_ident ':' type_specifier )* ',' ? '}'

global_directive:

'diagnostic' '(' ident_pattern_token ',' diagnostic_rule_name ',' ? ')' ';'

| 'enable' ident_pattern_token ( ',' ident_pattern_token )* ',' ? ';'

| 'requires' ident_pattern_token ( ',' ident_pattern_token )* ',' ? ';'

global_value_decl:

attribute * 'override' optionally_typed_ident ( '=' expression )?

| 'const' optionally_typed_ident '=' expression

ident:

ident_pattern_token

int_literal:

decimal_int_literal

| hex_int_literal

interpolate_attr:

'@' 'interpolate' '(' ident_pattern_token ',' ? ')'

| '@' 'interpolate' '(' ident_pattern_token ',' ident_pattern_token ',' ? ')'

invariant_attr:

'@' 'invariant'

lhs_expression:

core_lhs_expression component_or_swizzle_specifier ?

| '&' lhs_expression

| '*' lhs_expression

literal:

bool_literal

| float_literal

| int_literal

member_ident: ident_pattern_token
multiplicative_operator:

'%'

| '*'

| '/'

must_use_attr:

'@' 'must_use'

optionally_typed_ident:

ident ( ':' type_specifier )?

param:

attribute * ident ':' type_specifier

primary_expression:

ident template_elaborated_ident.post.ident

| ident template_elaborated_ident.post.ident argument_expression_list

| literal

| '(' expression ')'

relational_expression.post.unary_expression:

shift_expression.post.unary_expression

| shift_expression.post.unary_expression greater_than unary_expression shift_expression.post.unary_expression

| shift_expression.post.unary_expression greater_than_equal unary_expression shift_expression.post.unary_expression

| shift_expression.post.unary_expression less_than unary_expression shift_expression.post.unary_expression

| shift_expression.post.unary_expression less_than_equal unary_expression shift_expression.post.unary_expression

| shift_expression.post.unary_expression '!=' unary_expression shift_expression.post.unary_expression

| shift_expression.post.unary_expression '==' unary_expression shift_expression.post.unary_expression

shift_expression.post.unary_expression:

( multiplicative_operator unary_expression )* ( additive_operator unary_expression ( multiplicative_operator unary_expression )* )*

| shift_left unary_expression

| shift_right unary_expression

statement:

attribute * 'for' '(' for_init ? ';' expression ? ';' for_update ? ')' compound_statement

| attribute * 'if' expression compound_statement ( 'else' 'if' expression compound_statement )* ( 'else' compound_statement )?

| attribute * 'loop' attribute * '{' statement * ( 'continuing' attribute * '{' statement * ( 'break' 'if' expression ';' )? '}' )? '}'

| attribute * 'switch' expression attribute * '{' switch_clause * '}'

| attribute * 'while' expression compound_statement

| compound_statement

| ident template_elaborated_ident.post.ident argument_expression_list ';'

| variable_or_value_statement ';'

| variable_updating_statement ';'

| assert_statement ';'

| break_statement ';'

| continue_statement ';'

| ';'

| 'discard' ';'

| 'return' expression ? ';'

switch_clause:

'case' case_selector ( ',' case_selector )* ',' ? ':' ? compound_statement

| 'default' ':' ? compound_statement

swizzle_name:

/[rgba]/

| /[rgba][rgba]/

| /[rgba][rgba][rgba]/

| /[rgba][rgba][rgba][rgba]/

| /[xyzw]/

| /[xyzw][xyzw]/

| /[xyzw][xyzw][xyzw]/

| /[xyzw][xyzw][xyzw][xyzw]/

template_arg_expression: expression
template_elaborated_ident.post.ident:

( _template_args_start template_arg_expression ( ',' expression )* ',' ? _template_args_end )?

translation_unit:

global_directive * ( global_decl | global_assert | ';' ) *

translation_unit/0.1/0/0.0:

global_assert

| global_decl

| ';'

type_specifier:

ident ( _template_args_start template_arg_expression ( ',' expression )* ',' ? _template_args_end )?

unary_expression:

primary_expression component_or_swizzle_specifier ?

| '!' unary_expression

| '&' unary_expression

| '*' unary_expression

| '-' unary_expression

| '~' unary_expression

variable_decl:

'var' ( _template_args_start expression ( ',' expression )* ',' ? _template_args_end )? optionally_typed_ident

variable_or_value_statement:

variable_decl

| variable_decl '=' expression

| 'const' optionally_typed_ident '=' expression

| 'let' optionally_typed_ident '=' expression

variable_updating_statement:

lhs_expression ( '=' | compound_assignment_operator ) expression

| lhs_expression '++'

| lhs_expression '--'

| '_' '=' expression

vertex_attr:

'@' 'vertex'

workgroup_size_attr:

'@' 'workgroup_size' '(' expression ',' ? ')'

| '@' 'workgroup_size' '(' expression ',' expression ',' ? ')'

| '@' 'workgroup_size' '(' expression ',' expression ',' expression ',' ? ')'

付録 A: text/wgsl メディアタイプ

Internet Assigned Numbers Authority(IANA)は、[IANA-MEDIA-TYPES] にメディアタイプのレジストリを維持しています。

以下は WGSL モジュール用の text/wgsl メディアタイプの定義です。 これは IANA に登録されており、 https://www.iana.org/assignments/media-types/text/wgsl に掲載されています。

型名

text

サブタイプ名

wgsl

必須パラメーター

N/A

任意パラメーター

なし

エンコーディング上の考慮事項

binary

WGSL は UTF-8 エンコーディングを使用する Unicode テキストであり、バイトオーダーマーク(BOM)はありません。 § 3 テキスト構造を参照してください。

セキュリティ上の考慮事項:

WebGPU Shading Language(WGSL)は、WebGPU API のコンテキストで実行される GPU コード用のプログラミング言語です。セキュリティ上の 考慮事項については、[WebGPU] 2.1 節「セキュリティ上の考慮事項」を参照してください。 プライバシー上の考慮事項については、[WebGPU] 2.2 節「プライバシー上の 考慮事項」を参照してください。

相互運用性上の考慮事項:

WebGPU の実装は異なる機能を持つ場合があり、 これらの違いは WGSL プログラムで利用できる機能に影響する可能性があります。 [WebGPU] 3.6 節「任意機能」、 および § 4.1.2 言語拡張を参照してください。

実装は、この 登録が WGSL の後続版にも適用されるかのように動作することが期待され、その公開された 仕様参照はそれに応じて随時更新される場合があります。 この期待はメディアタイプ登録としては珍しいものですが、 広く普及している業界慣行と一致しています。

公開仕様:

WebGPU Shading Language

このメディアタイプを使用するアプリケーション:

WebGPU の実装。これにはウェブブラウザーが含まれることが期待されます。

フラグメント識別子に関する考慮事項

なし

追加情報:

マジックナンバー: なし

ファイル拡張子: .wgsl

Macintosh ファイルタイプコード: TEXT

詳細情報の連絡先担当者およびメールアドレス:

David Neto, dneto@google.com、または WGSL に記載されている編集者。

想定用途

COMMON

著者

W3C。WGSL に記載されている編集者を参照してください。

変更管理者

W3C

規範的参考文献

[WebGPU] W3C, "WebGPU” W3C Working Draft, January 2023. https://w3.org/TR/webgpu

Webgpu Shading Language W3C, "WebGPU Shading Language" W3C Working Draft, January 2023. https://w3.org/TR/WGSL

適合性

文書の 規約

適合性要件は、 説明的な表明と RFC 2119 の用語を組み合わせて表現されます。 この文書の規範的な部分におけるキーワード “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, および “OPTIONAL” は、RFC 2119 で説明されているとおりに 解釈されなければなりません。 ただし、読みやすさのため、 この仕様ではこれらの語がすべて大文字で表記されるとは限りません。

この仕様のすべての文章は規範的です。ただし、 非規範的であることが明示された節、例、および注記は除きます。 [RFC2119]

この仕様の例は “for example” という語で導入されるか、 規範的な本文とは区別して class="example" が指定されます。 次のようになります:

これは参考情報としての例の一例です。

参考情報としての注記は “Note” という語で始まり、 規範的な本文とは区別して class="note" が指定されます。 次のようになります:

注: これは参考情報としての注記です。

適合する アルゴリズム

アルゴリズムの一部として命令形で記述された要件 (“先頭の空白文字をすべて取り除く” または “false を返してこれらの手順を中止する” など)は、 そのアルゴリズムを導入する際に使用されたキーワード (“must”, “should”, “may” など)の意味で 解釈されなければなりません。

アルゴリズムまたは具体的な手順として記述された適合性要件は、 最終的な結果が等価である限り、 任意の方法で実装できます。 特に、この仕様で定義されるアルゴリズムは 理解しやすいことを意図しており、 高性能であることを意図していません。 実装者には最適化することが推奨されます。

索引

この仕様で定義される 用語

参照によって定義される 用語

参考文献

規範的参考文献

[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS の値と単位 モジュール レベル 4. 2024年3月12日. WD. URL: https://www.w3.org/TR/css-values-4/
[DeRemer1969]
LR(k) 言語のための実用的な トランスレーター. 1969年10月24日. URL: http://publications.csail.mit.edu/lcs/pubs/pdf/MIT-LCS-TR-065.pdf
[ECMASCRIPT]
ECMAScript 言語仕様. URL: https://tc39.es/ecma262/multipage/
[IEEE-754]
IEEE 浮動小数点 演算規格. 2008年8月29日. URL: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933
[Muller2005]
ulp(x) の定義について. 2005年2月. URL: https://inria.hal.science/inria-00070503
[RFC2119]
S. Bradner. RFC で要求レベルを示すために 使用するキーワード. 1997年3月. 現行のベストプラクティス. URL: https://datatracker.ietf.org/doc/html/rfc2119
[UAX14]
Robin Leroy. Unicode 改行 アルゴリズム. 2025年9月5日. Unicode 標準附属書 #14. URL: https://www.unicode.org/reports/tr14/tr14-55.html
[UAX31]
Mark Davis; Robin Leroy. Unicode 識別子と構文. 2025年8月20日. Unicode 標準附属書 #31. URL: https://www.unicode.org/reports/tr31/tr31-43.html
[UnicodeVersion14]
Unicode 標準 バージョン 14.0.0. URL: http://www.unicode.org/versions/Unicode14.0.0/
[VanWyk2007]
Eric R. Van Wyk; August C. Schwerdfeger. 拡張可能な言語の構文解析のための コンテキスト認識スキャン. 2007年. URL: https://dl.acm.org/doi/10.1145/1289971.1289983
[VulkanMemoryModel]
Jeff Bolz; et al. Vulkan メモリーモデル. URL: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#memory-model
[WebGPU]
Kai Ninomiya; Brandon Jones; Myles C. Maxfield. WebGPU. ワーキングドラフト. URL: https://w3.org/TR/webgpu

非規範的参考文献

[CHARMOD-NORM]
Addison Phillips; et al. World Wide Web の文字モデル: 文字列マッチング. 2026年7月16日. FPWD. URL: https://www.w3.org/TR/charmod-norm/
[IANA-MEDIA-TYPES]
メディアタイプ. URL: https://www.iana.org/assignments/media-types/
[Jeannerod2013]
Claude-Pierre Jeannerod; Nicolas Louvet; Jean-Michel Muller. 2x2 行列式を正確に計算するための Kahan アルゴリズムのさらなる 解析. URL: https://www.ams.org/journals/mcom/2013-82-284/S0025-5718-2013-02679-8/S0025-5718-2013-02679-8.pdf
[WASM-CORE-2]
Andreas Rossberg. WebAssembly コア 仕様. 2026年8月12日. CRD. URL: https://www.w3.org/TR/wasm-core-2/