WebGPU シェーディング言語

W3C 勧告候補草案

この文書の詳細
このバージョン:
https://www.w3.org/TR/2026/CRD-WGSL-20260825/
最新の公開バージョン:
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
参加:
課題を報告未解決の 課題
テストスイート:
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 シェーディング言語(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つ以上の呼び出しに分割されます。 各呼び出しは、わずかに異なる条件下でエントリーポイントを実行します。 シェーダーステージ内の呼び出しは、特定の変数へのアクセスを共有します。

ただし、呼び出しは、同等の呼び出しから区別するための識別値を提供する組み込み入力を含む、 異なるシェーダーステージ入力の集合に作用します。 各呼び出しは、プライベートおよび関数アドレス空間内の 変数という形式で、独立した固有のメモリ空間を持ちます。

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

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

動作 要件は、WGSL プログラムを処理または実行するときに実装が 行うアクションです。プログラマーとの契約における 実装の義務を記述します。 この仕様では、これらの義務が明白でない可能性がある場合に、それらを明示的に記述します。

1.2. 構文表記

次の構文表記は、WGSL の構文文法の規約を記述します。

1.3. 数学用語と表記

角度:

双曲角は、 従来の意味での角度ではなく、単位を持たない面積です。 具体的には、次のとおりです。

このとき、面積 a は、xa の双曲線余弦となり、 ya の双曲線正弦となるような双曲角です。

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

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

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

区間は、 下限と上限を持つ連続した数の集合です。 文脈に応じて、整数、浮動小数点数、実数、または拡張実数の集合となります。

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

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

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

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

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

転置は、 cr 行の行列 A の行を AT の列としてコピーすることによって形成される、rc 行の行列 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 エラー 導関数を計算する組み込み関数呼び出し 箇所の位置。 すなわち、次のいずれかの呼び出し位置です。 組み込み関数の呼び出しが導関数を計算するものの、一様性解析では、 その呼び出しが一様な制御フロー内で行われることを証明できない場合。

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

subgroup_uniformity エラー サブグループまたはクアッドの 組み込み関数の呼び出し 箇所の位置。 サブグループまたはクアッドの組み込み関数が呼び出されるものの、一様性解析では、 その呼び出しが一様な制御フロー内で行われることを証明できない場合。 さらに、次のパラメーター値が一様であることを一様性解析で証明できない場合。

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

単一の診断名トークンからなる認識されないトリガー規則を使用すると、 ユーザーエージェントは警告を発するべきです。

実装は、ここで規定されていないトリガー規則をサポートできます。 ただし、その規則は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およびループ本体。
loopwhile、またはforループのループ本体の開始中括弧('{')の直前。 そのループ本体
先頭となるcontinuing_compound_statementそのcontinuing_compound_statement

注: 次のものも複合文です。 関数本体case節単独のdefault 節whileおよびforループの本体、 ならびにif_clauseelse_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文について、case値の数を合計します。 これにはdefault 節が含まれます。 1023
単一のシェーダーから静的にアクセスされる、 privateアドレス空間でインスタンス化された すべての変数バイトサイズの最大合計 8192
単一の関数内で宣言され、 functionアドレス空間で インスタンス化されたすべての変数バイトサイズの最大合計 8192
単一のシェーダーから静的にアクセスされる、 workgroupアドレス空間で インスタンス化されたすべての変数バイトサイズの最大合計

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

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

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

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

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

3. テキスト構造

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

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

WGSL モジュールのテキストは、一連の Unicode コードポイントからなり、次のものを形成する連続した空でない集合にまとめられます。

プログラムテキストには、ヌルコードポイント(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 標準附属書#31Unicode バージョン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 モジュールに現れる識別子をすべて、 その識別子の同形表記の1つに置き換えると意味が変わる場合、ユーザーエージェントは開発者に見える 警告を発するべきです。 (同形文字とは、読者には別のコードポイント列と同じに見える可能性があるコードポイント列です。 同形文字を検出するための対応付けの例としては、 前の段落で述べた変換、対応付け、および照合アルゴリズムがあります。ある識別子について、部分列をその同形文字に 繰り返し置き換えることで一方のコードポイント列をもう一方へ変換できる場合、その2つのコードポイント列は同形表記です。)

3.8. 文脈依存名

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

3.8.1. 属性名

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

attributeの名前は、 次のとおりです。

3.8.2. 組み込み値名

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

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

builtin_value_name :

ident_pattern_token

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

3.8.3. 診断規則名

診断 名トークンとは、診断のトリガー規則の名前で使用されるトークンです。

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

diagnostic_name_token :

ident_pattern_token

事前定義された診断規則の名前は、次のとおりです。

3.8.4. 診断重要度制御名

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

severity_control_name :

ident_pattern_token

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

3.8.5. 拡張名

有効な有効化拡張の 名前は§ 4.1.1 拡張の有効化に列挙されていますが、一般には 識別子と同じ形式を持ちます。

enable_extension_name :

ident_pattern_token

有効化拡張の 名前は、次のとおりです。

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

language_extension_name :

ident_pattern_token

言語 拡張の名前は、次のとおりです。

3.8.6. 補間型名

補間型名トークンとは、 interpolate_type_nameに対する補間型の名前で使用されるトークンです。

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

補間 型の名前は、次のとおりです。

3.8.7. 補間サンプリング名

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

§ 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. 深度モード名

深度モード 名トークンは、トークンであり、 frag_depth組み込み値で、fragment_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を、次のものを含むレコード型とします。

出力: DiscoveredTemplateListsTemplateListレコードのリスト。

手順:

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

注: 一部の数値リテラルは、たとえば1.0fのように 文字で終わるため、アルゴリズムはリテラルを明示的に読み飛ばします。 終端のfident_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種類があります。

4.1.1. 有効化拡張

有効化拡張は、 次の条件を満たす場合にのみ機能を利用できる拡張です。

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

enable指令は、 1つ以上の有効化拡張のサポートを有効にする指令です。 実装が列挙されたすべての有効化拡張をサポートしていない場合、シェーダー作成 エラーになります。

enable_directive :

'enable' enable_extension_list ';'

enable_extension_list :

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

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

有効な有効化拡張を次の表に示します。

有効化拡張
WGSL 有効化拡張 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が自動的に有効になります
例:仮想的な有効化拡張の使用
// 任意精度浮動小数点型のための仮想的な拡張を有効にする。
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指令は、 プログラムが1つ以上の言語拡張を使用することを文書化する指令です。 実装が公開する機能は変更しません。 実装が必須拡張のいずれかをサポートしていない場合、シェーダー作成 エラーになります。

WGSL モジュールは、移植できない可能性、および移植性に対して意図する最低基準を示すため、 requires指令を使用できます

注: WebGPU 実装外部のツールは、 プログラムが使用するすべての言語拡張が、プログラム内のrequires指令によって網羅されているかを検査できます。

requires_directive :

'requires' language_extension_list ';'

language_extension_list :

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

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

言語拡張
WGSL 言語拡張 説明
readonly_and_readwrite_storage_textures readおよび read_writeアクセスモードストレージテクスチャで使用できるようにします。 さらに、textureBarrier組み込み関数を追加します。
packed_4x8_integer_dot_product 8ビット整数の4成分ベクトルをパックした32ビット整数スカラーを、 dot4U8Packedおよび dot4I8Packed組み込み関数による内積命令の入力として使用できるようにします。 さらに、8ビット整数のパックされた4成分ベクトルを使用するパックおよびアンパック命令を、 pack4xI8pack4xU8pack4xI8Clamppack4xU8Clampunpack4xI8、およびunpack4xU8 組み込み関数によって追加します。
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 サブグループおよび クアッド組み込み関数に対する一様な制御フローに、 同じサブグループ内のすべての呼び出しからなる サブグループという追加のスコープを加えます。

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

texture_and_sampler_let let宣言実効値型を、 テクスチャ型またはサンプラー型にできるようにします。
texture_formats_tier1 次の追加のテクセル 形式をサポートします。 rgba16unormrgba16snormrg8unormrg8snormrg8uintrg8sintrg16unormrg16snormrg16uintrg16sintrg16floatr8unormr8snormr8uintr8sintr16unormr16snormr16uintr16sintr16floatrgb10a2unormrgb10a2uintrg11b10ufloat
linear_indexing global_invocation_indexおよび workgroup_index組み込み値をサポートします。
immediate_address_space immediateアドレス空間を有効にし、 var<immediate>を使用して変数を宣言し、WebGPU API を介してコマンドエンコーダーから直接渡される、 頻繁に更新される少量のデータにバインドできるようにします。
fragment_depth frag-depth組み込み値に対して、 モードlessおよびgreaterを持つ 新しいdepth_mode組み込みパラメーターを導入します。 これらは、フラグメントシェーダーが、既存の深度より小さい(または大きい)ことが 保証される深度値だけを書き込むと宣言するときに使用されます。
buffer_view バッファ型および buffer_view組み込み関数を使用できるようにします。

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

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

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

たとえば、変数vが4要素のベクトルである場合、 v.xz = vec2(1,2);は、1回の読み取りと1回の 書き込みを行いながら、v.x = 1; v.z = 2;と記述する簡略形式です。

pointer_composite_access もサポートされている場合、 これはポインターでも機能します。pが3要素以上のベクトルへのポインターである場合、 p.xz = vec2(1,2);(*p).x = 1; (*p).z = 2;の簡略形式です。

注: その時点で一般的にサポートされている 言語拡張のすべての機能を具体化する言語拡張を、WGSL が時間の経過とともに定義していくことを意図しています。 requires指令では、これらは一般的な機能をすべて列挙するための 簡略形式として機能します。 これらは段階的に増大する機能の集合を表しており、ある種の言語バージョンと考えることができます。

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 文法規則の1つとして構文解析される ソーステキストの区間です。 式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は、 boolvec2<bool>vec3<bool>、またはvec4<bool>という4つの型のいずれかを表せます。 Tvec3<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は、定数式を、GPU で使用できる対応する型付き数値へ変換するときです。 第2は、メモリへの参照からロードが行われ、そのメモリに格納された値が得られるときです。

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

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

ある型から別の型への ConversionRank
Src Dest ConversionRank(Src,Dest) 説明
T T 0 恒等変換。変換は行われません。
ref<AS,T,AM>
アドレス空間 AS について、 アクセスモード AMread または 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>
ここで N1N2 はどちらも定数式であり、Dest は Src の引数に対応する仮パラメーターの型です
N2 < N1 の場合は 1、
それ以外は無限大
固定サイズバッファのポインター引数を、より小さいサイズの ポインターパラメーターへ変換します。1
ptr<AS, buffer<N>, AM>
ここで Src は関数呼び出しの引数の型です
ptr<AS, buffer, AM>
ここで Dest は Src の引数に対応する仮パラメーターの型です
1 固定サイズバッファのポインター引数を実行時サイズバッファのポインターパラメーターへ変換します。1
S T
上記のケースが適用されない場合
無限大 その他の型の間には自動変換がありません。
  1. これらの変換には、unrestricted_pointer_parameters および buffer_view 言語機能が必要です。

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

T の値 e具象化 された値とは、TT の具象化へ写像する実行可能な変換を e に適用して得られる値です。

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

6.1.3. オーバーロード解決

複数の型規則が構文句に適用される場合、 どれを有効にするか決定するために、同順位を解消する手続きが使用されます。 この手続きはオーバーロード解決と呼ばれ、 型検査によって部分式の静的型がすでに正常に検出されていることを前提とします。

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

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

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

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

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

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

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

  3. 候補をランク付けします:2つのオーバーロード候補 C1C2 が与えられたとき、次の場合に C1C2 より優先されます

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

      • すなわち、C1P に適用するために必要な各式変換が、 C2P に適用するために必要な対応する式変換と同等以上に優先されます。

    • 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 から構築可能型への最も優先される自動変換は
//   変換ランク 2 の AbstractInt から i32 への変換である。そのため '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

// 接尾辞のない整数リテラルは、必要な場合に浮動小数点へ変換できる:
//   変換ランク 5 で AbstractInt を f32 へ自動変換する。
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);

// 次の例はすべて f32 に昇格し、初期値は 10f となる。
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 から構築可能型への最も優先される自動変換は
// 変換ランク 2 の AbstractInt から i32 への変換である。そのため '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 型は、 truefalse の値を含みます。

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

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-754binary32(単精度)形式による 32ビット浮動小数点値の集合です。 詳細については、§ 15.7 浮動小数点評価を参照してください。

f16 型は、 IEEE-754binary16(半精度)形式による 16ビット浮動小数点値の集合です。プログラムに enable f16; ディレクティブが含まれ、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. スカラー型

スカラー型は、boolAbstractIntAbstractFloati32u32f32、および f16 です。

数値スカラー型は、 AbstractIntAbstractFloati32u32f32、および f16 です。

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

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

6.2.6. ベクトル型

ベクトルは、2個、3個、または4個の スカラー成分をまとめた列です。

説明
vecN<T> TN 個の成分からなるベクトル。 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> TCR 行の行列。ここで、CR はどちらも {2, 3, 4} のいずれかであり、Tf32f16、または 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 のアトミック。Tu32 または i32 のいずれかでなければなりません

式を評価した結果がアトミック型になってはなりません

アトミック型は、workgroup アドレス空間内の変数、または read_write アクセスモードを持つストレージ バッファ変数によってのみインスタンス化できます。 この型に対する演算のメモリスコープは、それがインスタンス化されるアドレス空間によって決まります。 workgroup アドレス空間内のアトミック型は、 Workgroupメモリスコープを持ちます。一方、 storage アドレス空間内のものは、QueueFamily のメモリスコープを持ちます。

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

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

6.2.9. 配列型

配列は、 インデックスでアクセス可能な要素値の列です。

説明
array<E,N> E の要素を N 個持つ固定サイズ 配列
N は配列の要素数と呼ばれます。
array<E> E の要素からなる実行時サイズ配列。 これは特定の文脈でのみ使用できます。

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

式を評価した結果が実行時サイズ配列型になってはなりません

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

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

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

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

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

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

注: 要素型は単純型でなければなりません。

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 アドレス空間内のメモリビューだけです。 これには、ワークグループ変数の格納型が含まれます。 § 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>;

// オーバーライド可能な要素数はワークグループ変数に対してのみ
// 有効であるため、無効な例。
// 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つの構造体型が同じであるための必要十分条件は、それらが同じ名前を持つことです。

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

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

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

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

構造体のメンバー型と配列の要素型に対する制限から得られる帰結には、次のものがあります:

例:構造体
// 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

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

属性 builtinlocationblend_srcinterpolate、 および invariantIO 属性です。 構造体 S のメンバーに付けられたIO 属性は、 Sエントリーポイント仮パラメーターまたは戻り値の型として使用される場合にのみ効果を持ちます。 § 13.3.1 ステージ間の入力および出力インターフェイスを参照してください。

属性 align および sizeレイアウト属性であり、 構造体型を使用してuniform バッファまたはストレージバッファを定義する場合に必要となることがあります。 § 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 について、NestDepth(T) と記述する T入れ子の深さは、次のとおりです:

6.2.12. 構築可能型

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

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

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

注: アトミック型と実行時サイズ配列型は構築可能ではありません。 アトミック型および実行時サイズ配列を含む複合型も構築可能ではありません。

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

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

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

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

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

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

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

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

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

注: 要素数が定数式ではないオーバーライド式である固定サイズ配列の有効な用途は、 workgroup アドレス空間内の メモリビューだけです。 これには、ワークグループ変数の格納型が含まれます。

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

注: 固定フットプリント型には、 実行時サイズ配列、 実行時サイズバッファ、および実行時サイズ配列を含むすべての構造体が含まれません。

6.3. バッファ型

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

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

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

説明
buffer<N> N バイトのストレージを持つ固定サイズ バッファ
Nオーバーライド式なければなりません
buffer 実行時サイズバッファ

を評価した結果が バッファ型になってはなりません

固定サイズバッファは、storageuniform、および workgroup アドレス空間内の変数によってのみインスタンス化できます。 storage および uniform アドレス空間では、サイズは定数式なければなりません。 実行時サイズバッファは、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 バッファ変数およびストレージバッファ変数の格納型は、 ホスト共有可能でなければなりません

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

注: ステージ間の入力および出力の型に対する制限は、 § 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 に対応し、 その逆も成り立ちます。 ここで、pr は同じメモリビューを記述します。

6.5.4. スウィズルビュー型

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

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

スウィズルビューは、 組 (p,IndexList) です。ここで:

アルゴリズム: SwizzleViewRead

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

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

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

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

手順:

  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 内のすべてのインデックスは、互いに異なっていなければなりません。 この要件は KN を含意します。

変数:

手順:

  1. 慣例により、IndexList = « Idx0, ..., IdxK−1 » とします

  2. 変数 newold_contents で初期化します。

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

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

  4. newp が参照するメモリへ書き込みます。

注: すべての Idxi が異なることを要求することで、 ステップ3が new の各成分を最大1回だけ更新することが保証されます。

注: ステップ2と3は、次の宣言的な規則で置き換えることができます:

型 vecN<S> のベクトル new を形成します。 new の成分 i は、次のとおりです:

  • 0...K−1 内のいずれかの j について i = Idxj である場合、 update の成分 j

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

スウィズルビューはスウィズルビュー型を持ちます:

制約 説明
S具象スカラー型、
NK は、 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回だけ行われる。
  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);

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

  // スウィズルビューへインデックスを付けると、ベクトルの成分の1つへの参照が得られる。
  // これは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);

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

  // スウィズルビューへインデックスを付けると、ベクトルの成分の1つへの参照が得られる。
  // これは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' のメモリへ格納されている値、
          すなわち 0 に対応する i32 値へ評価される。
        - 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. テクスチャ型およびサンプラー型

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

テクスチャは、 レンダリングに役立つ特殊な操作をサポートするテクセルの集合である。 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 つのチャネル、すなわち rgba があり、 通常は赤、緑、青、およびアルファの各チャネルという概念に対応する。

チャネル 形式

チャネル内のビット数、およびそれらのビットの解釈方法。

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. サンプリングテクスチャ型

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

テクセル形式は、 テクスチャ変数にバインドされたGPUTextureformat 属性である。 WebGPU は、テクスチャ、バインドグループレイアウトのsampleType、 およびテクスチャ変数のサンプリング型の間の 互換性を検証する

テクスチャはサンプリング型によってパラメーター化され、 f32i32、または 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 以上のサンプル数を持つ。 名前に反して、サンプラーとともに使用することはできない。 サンプルインデックスを無視した場合、実質的には 論理テクセル アドレスごとに複数のテクセル分の データを格納する。

テクセル形式は、 テクスチャ変数にバインドされたGPUTextureformat 属性である。 WebGPU は、テクスチャ、バインドグループレイアウトのsampleType、 およびテクスチャ変数のサンプリング型の間の 互換性を検証する

texture_multisampled_2dサンプリング型によってパラメーター化され、 f32i32、または 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 は、frexpmodf、および 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. 変数宣言および値宣言

変数宣言および 宣言は、 データ値に名前を与える。

値宣言は 値の名前を作成し、その値は宣言された後は不変となる。 値宣言には constoverridelet、および 仮引数宣言の 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>
不変 モジュール 具象ホスト共有可能禁止 はい。
ストレージ バッファ
var<storage, read_write>5,6 可変 モジュール 具象ホスト共有可能禁止 はい。
ストレージ バッファ
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 キーワードの後に テンプレートリストとして記述される:

privatestorageuniformworkgroup、およびhandleアドレス空間の変数は、 モジュールスコープでのみ宣言しなければならない。 一方、functionアドレス空間の変数は、 関数スコープでのみ宣言しなければならない。 handle および function を除くすべてのアドレス空間では、アドレス空間を指定しなければならない。 handle アドレス空間を指定してはならない。 function アドレス空間の指定は省略可能である。

アクセスモードには 常にデフォルト値があり、storageアドレス空間の変数を除き、 WGSL ソースで指定してはならない§ 14.3 アドレス空間を参照のこと。

uniformアドレス空間の変数は、uniform バッファ変数である。 その格納型は、 ホスト共有可能構築可能型または 固定サイズバッファ 型でなければならず、 アドレス空間のレイアウト制約を満たさなければならない。

storageアドレス空間の変数は、ストレージバッファ変数である。 その格納型ホスト共有可能型でなければならず、 アドレス空間のレイアウト制約を満たさなければならない。 変数はreadまたはread_write アクセスモードで宣言できる。デフォルトは read である。

immediateアドレス空間の変数は、イミディエイトデータ変数である。 その格納型は、 配列および配列メンバーを含む構造体を除く、ホスト共有可能構築可能型でなければならない。 各エントリーポイント静的にアクセスする イミディエイトデータ変数は、最大 1 つでなければならない。 immediate 変数の値は、WebGPU API のコマンドエンコーダーによって記録される setImmediatesコマンドを介して設定され、 シェーダーの実行中は一定のままである。 変数のサイズは、パイプラインレイアウトのimmediateSize設定によって制限される。

AccessibleSlotsには、 構造体メンバー間および構造体の末尾にあるパディングバイトが含まれない。 シェーダーでイミディエイトデータ変数へアクセスする前に WebGPU API を介して初期化する必要があるのは、 アクセス可能なスロットだけである。

テクスチャリソースは、 実効値型テクスチャ型である変数である。 これはモジュールスコープで宣言される。 これは、テクスチャ内にある基礎となる テクセルのグリッドへアクセスするために使用される 不透明なハンドルを保持する。 ハンドル自体はhandleアドレス空間にあり、常に読み取り専用である。 多くの場合、基礎となるテクセルは読み取り専用であり、テクスチャ変数は不変であるという。 書き込み専用ストレージテクスチャおよび読み書き可能なストレージ テクスチャでは、基礎となるテクセルは可変であり、慣例により テクスチャ変数も可変であるという。

サンプラーリソースは、 実効値型サンプラー型である変数である。 これはモジュールスコープで宣言され、 handleアドレス空間に存在し、 不変である。

§ 13.3.2 リソースインターフェイスで説明するように、uniform バッファ、 ストレージバッファ、テクスチャ、およびサンプラーは、 シェーダーのリソースインターフェイスを形成する。

変数の生存期間とは、 シェーダーの実行中にメモリ位置が変数と関連付けられている期間である。 モジュールスコープ 変数の生存期間は、シェーダーステージの実行全体である。 privateおよびfunctionアドレス空間の変数には、 呼び出しごとに独立したものが存在する。 関数スコープ変数は 動的コンテキストである。 関数スコープ変数の生存期間は、そのスコープによって決まる:

2 つのリソース変数は、 重複するメモリ位置を持つことがあるが、 それらの変数のいずれかが可変である場合は動的エラーとなる。 生存期間が重複するその他の変数は、重複するメモリ位置を持たない。 変数の生存期間が終了すると、そのメモリを別の変数に使用できる。

注: WGSL は、変数の内容が その変数の生存期間中にのみ観測できることを保証する。

privatefunction、 または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 バッファ

// 読み書き用のストレージバッファ
@group(0) @binding(0)
var<storage,read_write> pbuf: array<vec2<f32>>;

// テクスチャおよびサンプラーは、常に "handle" 空間にある。
@group(0) @binding(1)
var filter_params: sampler;
例: バッファのアクセスモード
// ストレージバッファ
@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 がゼロ以外の値へオーバーライドされる場合、エラーは発生しない。
// * 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 抽象浮動小数点リテラル値。
ei 接尾辞を持つ整数リテラル e: i32 32 ビット符号付き整数リテラル値。
eu 接尾辞を持つ整数リテラル e: u32 32 ビット符号なし整数リテラル値。
ef 接尾辞を持つ浮動小数点リテラル e: f32 32 ビット浮動小数点リテラル値。
eh 接尾辞を持つ浮動小数点リテラル 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の第 1 成分を選択する

これは 1 文字のスウィズルである。

e: vecN<T>
e.y: T
e.g: T
eの第 2 成分を選択する

これは 1 文字のスウィズルである。

e: vecN<T>
Nは 3 または 4
e.z: T
e.b: T
eの第 3 成分を選択する

これは 1 文字のスウィズルである。

e: vec4<T> e.w: T
e.a: T
eの第 4 成分を選択する

これは 1 文字のスウィズルである。

e: vecN<T>
i: i32 または u32
T具象
e[i]: T ベクトルの第 i 成分を選択する
最初の成分はインデックス i=0 にある。

iが範囲 [0,N-1] の外側にある場合:

e: vecN<T>
i: i32 または u32
T抽象
iconst 式
e[i]: T ベクトルの第 i 成分を選択する
最初の成分はインデックス i=0 にある。

iが範囲 [0,N-1] の外側にある場合、 シェーダー作成エラーとなる。

注: 抽象ベクトル値 eに、const 式ではない式を使用してインデックス付けする場合、 インデックスを適用する前にベクトルが具象化される。

8.5.1.2. ベクトルの複数成分の選択

この節の式は、内側の式に複数文字のスウィズルを適用する:

注: swizzle_assignment言語拡張がサポートされていない 場合、複数文字のスウィズル代入の左辺に置くことはできない。 代入の左辺は参照型でなければならないが、 この拡張がない場合、複数文字のスウィズル式は常にベクトル型の値を生成するためである。

ベクトルの分解:複数成分の選択
前提条件 結論 説明
e: vecN<T>
Iは文字 xyz、または w
Jは文字 xyz、または w
e.IJ: vec2<T>
第 1 成分が e.I、第 2 成分が e.Jである 2 成分ベクトルを計算する。
文字 z は、Nが 3 または 4 の場合にのみ有効である。
文字 w は、Nが 4 の場合にのみ有効である。
e: vecN<T>
Iは文字 rgb、または a
Jは文字 rgb、または a
e.IJ: vec2<T>
第 1 成分が e.I、第 2 成分が e.Jである 2 成分ベクトルを計算する。
文字 b は、Nが 3 または 4 の場合にのみ有効である。
文字 a は、Nが 4 の場合にのみ有効である。
e: vecN<T>
Iは文字 xyz、または w
Jは文字 xyz、または w
Kは文字 xyz、または 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は文字 rgb、または a
Jは文字 rgb、または a
Kは文字 rgb、または 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は文字 xyz、または w
Jは文字 xyz、または w
Kは文字 xyz、または w
Lは文字 xyz、または 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は文字 rgb、または a
Jは文字 rgb、または a
Kは文字 rgb、または a
Lは文字 rgb、または 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は文字 xyz、または w
Jは文字 xyz、または w
AMread または read_write

pr.IJ: vec2<T>
eを、評価時に pr が参照するメモリ位置に格納されている ベクトルとして、e.IJを計算する。

文字 z は、Nが 3 または 4 の場合にのみ有効である。
文字 w は、Nが 4 の場合にのみ有効である。

swizzle_assignmentはサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
Iは文字 rgb、または a
Jは文字 rgb、または a
AMread または read_write

pr.IJ: vec2<T>
eを、評価時に pr が参照するメモリ位置に格納されている ベクトルとして、e.IJを計算する。

文字 b は、Nが 3 または 4 の場合にのみ有効である。
文字 a は、Nが 4 の場合にのみ有効である。

swizzle_assignmentはサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
Iは文字 xyz、または w
Jは文字 xyz、または w
Kは文字 xyz、または w
AMread または read_write

pr.IJK: vec3<T>
eを、評価時に pr が参照するメモリ位置に格納されているベクトルとして、 e.IJKを計算する。

文字 z は、Nが 3 または 4 の場合にのみ有効である。
文字 w は、Nが 4 の場合にのみ有効である。

swizzle_assignmentはサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
Iは文字 rgb、または a
Jは文字 rgb、または a
Kは文字 rgb、または a
AMread または read_write

pr.IJK: vec3<T>
eを、評価時に pr が参照するメモリ位置に格納されているベクトルとして、 e.IJKを計算する。

文字 b は、Nが 3 または 4 の場合にのみ有効である。
文字 a は、Nが 4 の場合にのみ有効である。

swizzle_assignmentはサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
Iは文字 xyz、または w
Jは文字 xyz、または w
Kは文字 xyz、または w
Lは文字 xyz、または w
AMread または read_write

pr.IJKL: vec4<T>
eを、評価時に pr が参照するメモリ位置に格納されているベクトルとして、 e.IJKLを計算する。

文字 z は、Nが 3 または 4 の場合にのみ有効である。
文字 w は、Nが 4 の場合にのみ有効である。

swizzle_assignmentはサポートされていない

pr: ref<AS,vecN<T,AM>> または ptr<AS,vecN<T,AM>>
Iは文字 rgb、または a
Jは文字 rgb、または a
Kは文字 rgb、または a
Lは文字 rgb、または a
AMread または read_write

pr.IJKL: vec4<T>
eを、評価時に pr が参照するメモリ位置に格納されているベクトルとして、 e.IJKLを計算する。

文字 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 が参照する ベクトルの第 1 成分への参照を計算する。
結果の参照の起点変数は、 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抽象
iconst 式
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抽象
iconst 式
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 を次のように定義する:

次の場合、スウィズルZK 個のインデックス « Idx0, ..., IdxK−1 » を表すという:

注: たとえば、スウィズル wzyx は 4 つのインデックス «3, 2, 1, 0» を表し、スウィズル rb は 2 つのインデックス «0, 2» を表す。 スウィズル rgbzrgba の文字と xyzwの文字を混在させているため、いかなるインデックス列も表さない。

参照からスウィズルビューを形成する
前提条件 結論 説明
swizzle_assignmentがサポートされている

r: ref<AS,T,read_write>
Tは vecN<S>
スウィズル名 ZK 個のインデックス 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>
スウィズル名 ZK 個のインデックス 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>
スウィズル名 ZKZ 個のインデックス IZ = « IZ [0], ..., IZ [KZ −1] » を表す
KZは {2,3,4} に含まれる
sv.Z : swizzle< AS,S,N,KZ > svスウィズルビューp, Iin)とする。 定義により、列 IinKin 個の項目を持つ。

Ioutを次の列とする:
« Iin [IZ [0]], ..., Iin [IZ [KZ -1]] »。

式の結果は、スウィズルビューp, Iout)となる。

IZ内の各インデックスは、 Kinより小さくなければならない

sv無効なスウィズルビューである場合、結果は無効なスウィズルビューとなる。

8.7. 論理式

単項論理演算
前提条件 結論 説明
e: T
Tは bool または vecN<bool>
!e: T 論理否定。 efalse の場合、結果は true となり、 etrue の場合、結果は false となる。 Tがベクトルの場合は成分ごと
二項論理式
前提条件 結論 説明
e1: bool
e2: bool
e1 || e2: bool 短絡「または」。e1または e2 のいずれかが true の場合、trueを生成する。 e1が false の場合にのみ e2 を評価する。
e1: bool
e2: bool
e1 && e2: bool 短絡「かつ」。e1e2 の両方が true の場合、trueを生成する。 e1が true の場合にのみ e2 を評価する。
e1: T
e2: T
Tは bool または vecN<bool>
e1 | e2: T 論理「または」。Tがベクトルの場合は成分ごとe1e2 の両方を評価する。
e1: T
e2: T
Tは bool または vecN<bool>
e1 & e2: T 論理「かつ」。Tがベクトルの場合は成分ごとe1e2 の両方を評価する。

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 回ずつ評価し、次のように評価される:

注: 結果がゼロでない場合、その符号は 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>
行列の加算:結果は成分ごとに計算される。 結果の列 ie1[i] + e2[i] となる
e1 - e2: matCxR<T> 行列の減算:結果は成分ごとに計算される。 結果の列 ie1[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>
線形代数における行列と列ベクトルの積: 結果の成分 idot(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
TS または vecN<S>
T がベクトルの場合、TB は vecN<bool>、
それ以外の場合、TB は bool
e1 == e2: TB 等価。T がベクトルの場合、成分ごと
e1: T
e2: T
S は AbstractInt、AbstractFloat、bool、i32、u32、f32、または f16
TS または 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
TS または vecN<S>
TS の場合、TS は u32。それ以外の場合、TS は vecN<u32>
e1 << e2: T 左シフト(シフトされる値は具象):

e1 を左にシフトし、最下位位置にゼロビットを挿入し、 最上位ビットを破棄する。

シフトするビット数は、e2 の値を e1 のビット幅で剰余を取った値である。
e2e1 のビット幅以上の場合、次のようになる:

e1e2 の両方がシェーダー実行開始前に 判明している場合、結果はオーバーフローしてはならない:

T がベクトルの場合、成分ごと

e1: T
e2: TS
T は AbstractInt または vecN<AbstractInt>
T が AbstractInt の場合、TS は u32。それ以外の場合、TS は vecN<u32>
e1 << e2: T 左シフト(シフトされる値は抽象):

e1 を左にシフトし、最下位位置にゼロビットを挿入し、 最上位ビットを破棄する。

シフトするビット数は e2 の値である。

e1 の最上位 e2+1 ビットは、同じ ビット値でなければならない。 そうでなければオーバーフローが発生する。

注: この条件は、破棄されるすべての ビットが元の値の符号ビットと同じであり、 かつ最終的な値の符号ビットとも同じでなければならないことを意味する。

T がベクトルの場合、成分ごと

e1: T
e2: TS
S は i32 または u32
TS または vecN<S>
TS の場合、TS は u32。それ以外の場合、TS は vecN<u32>
e1 >> e2: T 右シフト(シフトされる値は具象)。

e1 を右にシフトし、最下位ビットを破棄する。

S が符号なし型の場合、最上位位置にゼロビットを挿入する。

S が符号付き型の場合:

  • e1 が負の場合、挿入される各ビットは 1 となり、そのため結果も 負になる。

  • それ以外の場合、挿入される各ビットは 0 となる。

シフトするビット数は、e2 の値を e1 のビット幅で 剰余を取った値である。

e2e1 のビット幅以上の場合、次のようになる:

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無効なメモリ参照の場合、結果の ポインターも無効なメモリ参照となる。

AShandle アドレス空間の場合、 シェーダー作成エラーとなる。

rベクトル成分への参照の場合、 シェーダー作成エラーとなる。

8.15. 間接参照式

間接参照演算子は、 ポインターを対応する参照へ変換する。

ポインターからの参照の取得
前提条件 結論 説明
p: ptr<AS,T,AM> *p: ref<AS,T,AM> 結果は、ポインター値 p と同じメモリビューに対応する 参照値となる。

p無効なメモリ参照の場合、結果の 参照も無効なメモリ参照となる。

8.16. 値宣言に対する識別子式

constoverride、または 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 個以上の文からなる列である。 宣言がそれらの文のいずれかである場合、 その識別子は、 次の文の先頭から複文の末尾まで スコープ内となる。

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は書き込み可能なアドレス空間
アクセスモード AMwriteまたは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 の第 1 成分へ 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 節のいずれか、または 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'トークンは、 1 つのcase_selectorリスト内に複数回現れては ならない

型規則の前提条件: 1 つの switch 文について、セレクター式とすべての case セレクター式は、 同じ具象整数スカラー型で なければならない

case_selectors内の式は、 const 式なければならない

同じ switch 文内の異なる 2 つの case セレクター式が、 同じ値を持ってはならない

セレクター値がcase_selectorリスト内の式の値と等しい場合、 制御はそのcase 節の本体へ移る。 セレクター値がいずれの case セレクター値とも等しくない場合、 制御はdefault 節の本体へ移る。

制御が節の本体の末尾へ到達すると、switch 文の直後にある最初の文へ移る。

節の本体内にある文の 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 {       // case セレクターでは const 式を使用できる
    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 つが宣言である場合、 その宣言は、複文内の宣言についての通常の スコープおよび 生存期間の規則に従う。 つまり、ループ本体は文の列であり、そのいずれかが宣言である場合、 その宣言のスコープは、列内の次の文の先頭からループ本体の末尾まで広がる。 宣言は到達するたびに実行されるため、新しい反復ごとに 変数またはの新しいインスタンスが作成され、 再初期化される。

注: 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文は次の形式のループへ脱糖される:

{
initializer ;
loop {
if !(condition) { break; }
body
continuing { update_part }
}
}
条件式が存在しない場合、for文は次の形式のループへ脱糖される:
{
initializer ;
loop {
body
continuing { update_part }
}
}

さらに:

for ループのinitializerは、ループの実行前に 1 回実行される。 initializer に宣言が現れる場合、その 識別子は、 bodyの末尾までスコープ内となる。 body内の宣言とは異なり、その宣言は反復ごとに再初期化されない。

conditionbodyupdate_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
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文で 使用される宣言を飛び越えて制御を移すことになる位置に配置しては ならない

注: continuecontinuing文内で使用できるのは、 そのcontinuing文内に入れ子になった別のループ内で 制御フローを移すために使用する場合のみである。 つまり、現在実行中のcontinuing文の先頭へ制御を移すために continueを使用することはできない。

例: 宣言を迂回する無効な 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は、 loopfor、または 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
B1B2
loop {s1 continuing {s2}} s1: B1
s2: B2
B1 = {Return}
{Continue, Return} のいずれもB2に含まれない
{Return}
s1: B1
s2: B2
B1 ≠ {Return}
{Continue, Return} のいずれもB2に含まれない
Break は (B1B2) に含まれない
(B1B2)∖{Continue, Next}
s1: B1
s2: B2
B1 ≠ {Return}
{Continue, Return} のいずれもB2に含まれない
Break は (B1B2) に含まれる
(B1B2 ∪ {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}
    }
  }            // switch が Break を Next で置き換えるため、動作は {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 は無効
同じ例でcontinuebreakに置き換えた場合も、 同じ理由で無効となる。

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 関数を宣言する。
// これには i と b という 2 つの仮パラメーターがある。
// 戻り値の型は 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);  // 無効。1 つ以上が書き込まれる場合、
               // 同じルート識別子を持つ 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

属性の説明で明示的に許可されている場合を除き、 1 つのオブジェクトまたは型に同じ属性を複数回指定しては ならない

12.1. align

align_attr :

'@' 'align' '(' expression ',' ? ')'

align属性
説明 メモリ内における構造体メンバーの配置を制約する。

構造体型のメンバーにのみ適用 しなければならない

この属性は、包含する構造体型の値がメモリ内にどのように現れ得るかに影響する。 つまり、構造体自体とその構成メンバーが現れ得るバイトアドレスを制約する。

align(n)が、 型Tを持つSのメンバーへ適用され、 Sがアドレス空間ASにある変数の 格納型となることができ、 ASuniformでない場合、 nは次を満たさ なければならない:
ある正の整数kについて、 n = k × RequiredAlignOf(T,AS)。

アラインメントとサイズの規則は相互再帰的である。 ただし、上記の制約は入れ子になった型に必要なアラインメントに依存し、 型の入れ子の深さには上限があるため、 適切に定義されている。

uniformまたは storageバッファーへ バインドされたメモリの開始アドレスのアラインメントが、 属性で指定された値より低い場合、結果のアラインメントは両者の最小値となる。 実装は、変数のベースアドレスを基準としてのみ属性を満たす。

§ 14.4 メモリレイアウトを参照。

パラメーター i32または u32解決される const 式なければならない
正でなければならない
2 の累乗でなければならない

12.2. binding

binding_attr :

'@' 'binding' '(' expression ',' ? ')'

binding属性
説明 バインドグループ内における リソースのバインディング番号を指定する。 § 13.3.2 リソースインターフェースを参照。

リソース変数にのみ適用 しなければならない

パラメーター i32または u32解決される const 式なければならない
非負でなければならない

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 診断を参照。

1 つの構文形式に複数のdiagnostic属性を指定できるが、 それぞれ異なるトリガー規則を指定 しなければならない

パラメーター 最初のパラメーターはseverity_control_nameである。

2 番目のパラメーターは、トリガー規則を指定する diagnostic_rule_nameトークンである。

12.7. group

group_attr :

'@' 'group' '(' expression ',' ? ')'

group属性
説明 リソースのバインディンググループを指定する。 § 13.3.2 リソースインターフェースを参照。

リソース変数にのみ適用 しなければならない

パラメーター i32または u32解決される const 式なければならない
非負でなければならない

12.8. id

id_attr :

'@' 'id' '(' expression ',' ? ')'

id属性
説明 パイプラインでオーバーライド可能な定数の 代替名として数値識別子を指定する。

スカラー型の override 宣言にのみ適用 しなければならない

パラメーター i32または u32解決される const 式なければならない
非負でなければならない

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 式なければならない
非負でなければならない

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より小さい場合、 パイプライン作成エラーとなる。

値がsubgroupMinSizesubgroupMaxSizeの間であっても、 レジスター圧力または特定のハードウェア制限により、 パイプライン作成時に未分類エラーが発生することがある。

12.15. workgroup_size

workgroup_size_attr :

'@' 'workgroup_size' '(' expression ',' ? ')'

| '@' 'workgroup_size' '(' expression ',' expression ',' ? ')'

| '@' 'workgroup_size' '(' expression ',' expression ',' expression ',' ? ')'

workgroup_size 属性
説明 コンピュートシェーダーのワークグループグリッドの x、y、z 次元を指定する。

第1パラメーターは x 次元を指定する。 第2パラメーターが指定されている場合は y 次元を指定し、それ以外の場合は 1 とみなされる。 第3パラメーターが指定されている場合は z 次元を指定し、それ以外の場合は 1 とみなされる。

必ずコンピュートシェーダーのエントリーポイント関数にのみ適用しなければならない。 その他のオブジェクトには適用してはならない

パラメーター 1個、2個、または3個のパラメーターを取る。

各パラメーターは必ずconst 式またはoverride 式でなければならない。 すべてのパラメーターは必ず同じ型、すなわち i32 または u32 のいずれかでなければならない。

指定されたパラメーターのいずれかが、非正の値に評価される const 式である場合、 シェーダー作成エラーとなる。

指定されたパラメーターのいずれかが非正の値に評価される場合、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つの組み込み入力を持ってはならない

ステージ S に対する、名前 X、型 TX の組み込み入力には、 シェーダーステージ Sエントリーポイント仮パラメーターを介して、 以下の2つの方法のいずれかでアクセスする。

  1. パラメーターが属性 builtin(X) を持ち、 型 TX である。

  2. パラメーターが構造体型を持ち、その構造体メンバーの1つが属性 builtin(X) を持ち、型 TX である。

逆に、エントリーポイントのパラメーターまたはパラメーターのメンバーがbuiltin 属性を持つ場合、 対応する組み込み値は、そのエントリーポイントのシェーダーステージに対する入力でなければならない

組み込み出力 値は、パイプライン内の後続の処理ステップへ制御情報を伝えるためにシェーダーによって使用される。 エントリーポイントは、同じ組み込み値名を持つ2つの組み込み出力を持ってはならない

ステージ S に対する、名前 Y、型 TY の組み込み出力は、 シェーダーステージ Sエントリーポイント戻り値を介して、以下の2つの方法のいずれかで設定される。

  1. エントリーポイントの戻り値の型が属性 builtin(Y) を持ち、型 TY である。

  2. エントリーポイントの戻り 値の型が構造体型を持ち、その構造体メンバーの1つが属性 builtin(Y) を持ち、型 TY である。

逆に、エントリーポイントの戻り値の型または戻り値の型のメンバーがbuiltin 属性を持つ場合、 対応する組み込み値は、そのエントリーポイントのシェーダーステージに対する出力でなければならない

注: position 組み込み値は、 頂点シェーダーの出力であると同時に、フラグメントシェーダーへの入力でもある。

組み込み入力値と組み込み出力値を総称して組み込み値という。

次の表は、利用可能な組み込み値をまとめたものである。 それぞれは、組み込み値に対する組み込み値名トークンである。 それぞれの詳細は後続の節で説明する。

組み込み入力値および出力値
名前 ステージ 方向 拡張
vertex_index 頂点 入力 u32
instance_index 頂点 入力 u32
clip_distances 頂点 出力 array<f32, N>(N8clip_distances
position 頂点 出力 vec4<f32>
フラグメント 入力 vec4<f32>
front_facing フラグメント 入力 bool
frag_depth フラグメント 出力 f32
primitive_index フラグメント 入力 u32 primitive_index
sample_index フラグメント 入力 u32
sample_mask フラグメント 入力 u32
フラグメント 出力 u32
local_invocation_id コンピュート 入力 vec3<u32>
local_invocation_index コンピュート 入力 u32
global_invocation_id コンピュート 入力 vec3<u32>
global_invocation_index コンピュート 入力 u32 linear_indexing
workgroup_id コンピュート 入力 vec3<u32>
workgroup_index コンピュート 入力 u32 linear_indexing
num_workgroups コンピュート 入力 vec3<u32>
subgroup_invocation_id コンピュート 入力 u32 subgroups
フラグメント
subgroup_size コンピュート 入力 u32 subgroups
フラグメント
subgroup_id コンピュート 入力 u32 subgroups および subgroup_id
num_subgroups コンピュート 入力 u32 subgroups および 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
ステージ 頂点
array<f32, N>
方向 出力
説明 配列内の各値は、ユーザー定義のクリップ平面までの距離を表す。クリップ距離 0 は頂点が平面上にあることを意味し、正の距離は頂点がクリップ 半空間の内側にあることを意味し、負の距離は頂点がクリップ半空間の外側にあることを意味する。 clip_distances の配列サイズは必ず8 でなければならない。 WebGPU § 23.2.4 プリミティブのクリッピングを参照。
13.3.1.1.2. frag_depth
名前 frag_depth
ステージ フラグメント
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
ステージ フラグメント
bool
方向 入力
説明 現在のフラグメントが前面プリミティブ上にある場合は true。 それ以外の場合は false。
13.3.1.1.4. global_invocation_id
名前 global_invocation_id
ステージ コンピュート
vec3<u32>
方向 入力
説明 現在の呼び出しのグローバル呼び出し ID、すなわちコンピュートシェーダーグリッド内の位置。 global_invocation_id の値は、 workgroup_id * workgroup_size + local_invocation_id に等しい。
13.3.1.1.5. global_invocation_index
名前 global_invocation_index
ステージ コンピュート
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
ステージ 頂点
u32
方向 入力
説明 現在の API レベルの描画コマンド内における、現在の頂点のインスタンスインデックス。

最初のインスタンスは、直接または間接のいずれで指定されたかにかかわらず、 描画の firstInstance 引数と等しいインデックスを持つ。 描画内の追加の各インスタンスについて、インデックスは1ずつ増加する。

13.3.1.1.7. local_invocation_id
名前 local_invocation_id
ステージ コンピュート
vec3<u32>
方向 入力
説明 現在の呼び出しのローカル呼び出し ID、すなわちワークグループ グリッド内の位置。
13.3.1.1.8. local_invocation_index
名前 local_invocation_index
ステージ コンピュート
u32
方向 入力
説明 現在の呼び出しのローカル呼び出しインデックス。 これはワークグループグリッド内における呼び出しの位置を線形化したインデックスである。
13.3.1.1.9. num_workgroups
名前 num_workgroups
ステージ コンピュート
vec3<u32>
方向 入力
説明 API によってディスパッチされた コンピュートシェーダーのディスパッチサイズ vec3<u32>(group_count_x, group_count_y, group_count_z)
13.3.1.1.10. position
名前 position
ステージ 頂点
vec4<f32>
方向 出力
説明 クリップ空間座標における現在の頂点のクリップ位置

出力値 (x,y,z,w) は、WebGPU の正規化デバイス座標における (x/w, y/w, z/w) に写像される

WebGPU § 3.3 座標系およびWebGPU § 23.2.4 プリミティブのクリッピングを参照。

w 座標がゼロの場合、動的エラーが発生する。

名前 position
ステージ フラグメント
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
ステージ フラグメント
u32
方向 入力
説明 現在の描画操作の開始以降に現在のインスタンスについて処理されたプリミティブ数に基づく、 プリミティブ単位のインデックス。0 から始まり、点、線、または三角形プリミティブが 処理されるたびに1ずつ増加する。描画されるインスタンスごとに 0 にリセットされる。 プリミティブ再開値によってストリッププリミティブを 再開しても、プリミティブインデックスには影響しない。このインデックスは、 プリミティブのすべてのフラグメントにわたって一様である。
13.3.1.1.12. sample_index
名前 sample_index
ステージ フラグメント
u32
方向 入力
説明 現在のフラグメントのラスタライズ点に対するサンプルインデックス。 値は 0 以上 sampleCount-1 以下である。ここで sampleCount は、 GPU レンダーパイプラインに指定されたサンプルの count である。 この属性が適用され、フラグメントシェーダーの効果がsample_index の値に基づいて変化する場合、 フラグメントシェーダーはサンプルごとに1回呼び出される。

WebGPU § 10.3 GPURenderPipelineを参照。

13.3.1.1.13. sample_mask
名前 sample_mask
ステージ フラグメント
u32
方向 入力
説明 現在のフラグメントに対するサンプルカバレッジのビットマスク。

ビットは半開区間 [0, sampleCount) 内のサンプルインデックスによって索引付けされる。 ここで sampleCount は、GPU レンダーパイプラインに指定されたサンプルの count である。

サンプルがレンダリング中のプリミティブに覆われている場合に限り、 ビットは 1 に設定される。 インデックスが sampleCount 以上のビットは常にゼロに設定される。

ビットマスクには、次の2つの値の可能性がある。

  • ビットマスクは、フラグメントによって覆われているすべてのサンプルについて 1 のビットが設定されている。 この場合、ビットマスクはフラグメントの RasterizationPointcoverageMask に等しい。

  • ビットマスクでは、現在のフラグメントシェーダー呼び出しによって処理される サンプルに対応する1つのビットだけが 1 に設定されている。 すなわち、sample_index 組み込み入力を使用したかのように、 ビットマスクは (1 << sample_index) となる。

注: sampleCount = 1 の場合、これら2つの場合は同一である。

注: sampleCount > 1 の場合、これは既知の移植性上の危険要因である。 完全なカバレッジマスクを生成するデバイスもあれば、単一ビットのマスクを生成するデバイスもある。

WebGPU § 23.2.10 サンプル単位シェーディングおよびWebGPU § 23.2.11 サンプルマスキングを参照。

名前 sample_mask
ステージ フラグメント
u32
方向 出力
説明 現在のフラグメントに対するサンプルカバレッジマスクの制御。 この変数へ最後に書き込まれた値がシェーダー出力マスクとなる。 書き込まれた値のゼロのビットにより、カラーアタッチメント内の対応するサンプルが破棄される。

WebGPU § 23.2.11 サンプルマスキングを参照。

13.3.1.1.14. vertex_index
名前 vertex_index
ステージ 頂点
u32
方向 入力
説明 描画のインスタンス化に依存しない、現在の API レベルの描画コマンド内における 現在の頂点のインデックス。

インデックスなし描画の場合、最初の頂点は、直接または間接のいずれで指定されたかにかかわらず、 描画の firstVertex 引数と等しいインデックスを持つ。 描画インスタンス内の追加の各頂点について、インデックスは1ずつ増加する。

インデックス付き描画の場合、インデックスは、その頂点に対するインデックスバッファーの エントリーに、直接または間接のいずれで指定されたかにかかわらず、 描画の baseVertex 引数を加えた値に等しい。

13.3.1.1.15. workgroup_id
名前 workgroup_id
ステージ コンピュート
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
ステージ コンピュート
u32
方向 入力
説明 現在の呼び出しのワークグループインデックス、すなわち全体のコンピュートシェーダーグリッド内における ワークグループの線形位置。

同じワークグループ内のすべての呼び出しは、同じワークグループインデックスを持つ。

注: ディスパッチされるワークグループ数によって この値が u32 型の範囲を超える場合、ディスパッチは失敗する。
  • dispatchWorkgroups の場合、GPUComputePassEncoder は無効化される。

  • dispatchWorkgroupsIndirect の場合、ディスパッチは実行されない。

13.3.1.1.17. subgroup_invocation_id
名前 subgroup_invocation_id
ステージ コンピュートまたはフラグメント
u32
方向 入力
説明 現在の呼び出しのサブグループ呼び出し ID

ID は [0, subgroup_size - 1] の範囲内にある。

コンピュートシェーダーでは、ID はゼロから始まり、 欠番なく連続する。すなわち、コンピュートシェーダーが実行を開始すると、 各サブグループ内では次のようになる。

  • 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
ステージ コンピュートまたはフラグメント
u32
方向 入力
説明 現在の呼び出しが属するサブグループのサブグループサイズ

subgroup_size 属性を持つコンピュートシェーダーでは、 この値は指定された属性値に等しい。

13.3.1.1.19. subgroup_id
名前 subgroup_id
ステージ コンピュート
u32
方向 入力
説明 ワークグループ内における、 現在の呼び出しが属するサブグループサブグループ ID

ID は [0, num_subgroups - 1] の範囲内にある。

13.3.1.1.20. num_subgroups
名前 num_subgroups
ステージ コンピュート
u32
方向 入力
説明 現在の呼び出しが属するワークグループ内のサブグループ数。
13.3.1.2. ユーザー定義の入力と出力

ユーザー定義データは、パイプラインの開始位置へ入力として渡したり、 パイプラインのステージ間で渡したり、パイプラインの末尾から出力したりできる。

ユーザー定義 入力データおよび ユーザー定義 出力データは、次の条件を満たさなければならない

コンピュートシェーダーは、 ユーザー定義の入力または出力を持ってはならない

13.3.1.3. 入出力ロケーション

各入出力ロケーションは、最大16バイトのサイズの値を格納できる。 型のバイトサイズは、§ 14.4.1 整列とサイズSizeOf 列を使用して定義される。 たとえば、浮動小数点値の4成分ベクトルは、単一のロケーションを占有する。

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

補間はサンプルごとに実行される。 この属性が適用されると、フラグメントシェーダーはサンプルごとに1回呼び出される。

first

値はプリミティブの最初の頂点によって提供される。

either

値はプリミティブの最初の頂点または最後の頂点によって提供される。 値が最初の頂点と最後の頂点のどちらから取得されるかは、実装に依存する。

スカラーまたはベクトルの浮動小数点型のユーザー定義 IO については、次のとおりである。

スカラーまたはベクトルの整数型であるユーザー定義の頂点出力およびフラグメント入力には、 常に補間型 flat指定しなければならない

ステージ間インターフェース検証は、 レンダーパイプライン内で、ユーザー定義の各フラグメント入力の補間特性が、同じ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 のバインディング型
ユニフォームバッファー buffer GPUBufferBindingType "uniform"
read_write アクセスのストレージバッファー "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. バッファーバインディングによる実行時サイズ配列の要素数の決定

ストレージバッファー変数が実行時サイズ配列を含む場合、その配列の要素数は、 対応する 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 {                          //             整列(16) サイズ(32)
  position : vec3f,                          // オフセット(0)   整列(16) サイズ(12)
  // -- 暗黙的なメンバー整列のパディング -- // オフセット(12)            サイズ(4)
  color : vec3f,                             // オフセット(16)  整列(16) サイズ(12)
  // -- 暗黙的な構造体サイズのパディング --      // オフセット(28)            サイズ(4)
}

struct LightStorage {                        //             整列(16)
  pointCount : u32,                          // オフセット(0)   整列(4)  サイズ(4)
  // -- 暗黙的なメンバー整列のパディング -- // オフセット(4)             サイズ(12)
  point : array<PointLight>,                 // オフセット(16)  整列(16) 要素サイズ(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. メモリアクセスモード

メモリアクセスとは、 メモリロケーションに作用する操作である。

単一の操作は、読み取り、書き込み、または読み書きの両方を行うことができる。

特定のメモリロケーションは、メモリのアクセスモードとして表される、特定の種類のアクセスだけを サポートすることがある。

アクセスモード
アクセスモード サポートされるアクセス
read 読み取りアクセスをサポートするが、書き込みはサポートしない。
write 書き込みアクセスをサポートするが、読み取りはサポートしない。
read_write 読み取りアクセスと書き込みアクセスの両方をサポートする。

WGSL は、列挙子 readwrite、および read_write事前宣言する。

14.3. アドレス空間

メモリロケーションは、アドレス空間に分割される。 各アドレス空間には、可変性、可視性、格納できる値、およびそこで変数を使用する方法を 決定する固有の特性がある。 詳細については、§ 7 変数および値の宣言を参照。

特定のメモリビューのアクセスモードは、 多くの場合コンテキストによって決定される。

storage アドレス空間は、 readread_write の両方のアクセスモードをサポートする。 その他の各アドレス空間は、1つのアクセスモードだけをサポートする。 各アドレス空間の既定のアクセスモードを次の表に示す。

アドレス空間
アドレス空間 呼び出し間の共有 既定のアクセスモード 注記
function 同じ呼び出し内のみ read_write
private 同じ呼び出し内のみ read_write
workgroup 同じコンピュートシェーダーワークグループ内の呼び出し read_write 最外側の配列の要素数には、パイプラインからオーバーライド可能な定数を指定できる。
uniform 同じシェーダーステージ内の呼び出し read ユニフォームバッファー変数用
storage 同じシェーダーステージ内の呼び出し read ストレージバッファー変数用
immediate 同じシェーダーステージ内の呼び出し read 即時データ変数用。
エントリーポイント静的にアクセスできる即時変数は最大1つである。
handle 同じシェーダーステージ内の呼び出し read サンプラー変数およびテクスチャ変数用。

WGSL は、handle アドレス空間を除く各アドレス空間について、 列挙子事前宣言する。

workgroup アドレス空間内の変数には、 コンピュートシェーダーステージ内でのみ静的にアクセスしなければならない。

storage アドレス空間内の変数ストレージバッファー)に頂点シェーダーステージから静的にアクセスできるのは、 アクセスモードがread の場合だけである。 格納型が、 write またはread_writeアクセスモードを持つストレージテクスチャである変数には、頂点シェーダーステージから静的にアクセスできない。 WebGPU の createBindGroupLayout() を参照。

注: 各アドレス空間のパフォーマンス特性は異なる場合がある。

WGSL ソース内で変数宣言またはポインター型を記述する場合、次のようになる。

14.4. メモリレイアウト

WGSL における型のレイアウトは、アドレス空間に依存しない。 ただし厳密にいえば、そのレイアウトを観測できるのはホスト共有可能な バッファーだけである。 ユニフォームバッファー変数とストレージバッファー変数は、メモリ内でバイト列として 構成された大容量データを共有するために使用される。 バッファーは、CPU と GPU の間、パイプライン内の異なるシェーダーステージ間、 または異なるパイプライン間で共有される。

バッファーデータは再フォーマットまたは変換されることなく共有されるため、 バッファーの生成側と消費側がメモリレイアウトについて合意していない場合、動的エラーとなる。 メモリレイアウトとは、バッファー内のバイトを型付き WGSL 値としてどのように構成するかの記述である。 これらのバイトは、共通の基準ロケーションに対する値のメモリロケーションである。

バッファー変数の格納型は、以下で説明する完全に展開されたメモリレイアウトを持つ、 ホスト共有可能な型でなければならない

各バッファー変数は、uniform またはstorage のいずれかのアドレス空間で宣言しなければならない

型のメモリレイアウトが重要となるのは、次のものを含む式を評価する場合だけである。

8ビットのバイトは、ホスト共有可能なメモリの最も基本的な単位である。 この節で定義する用語は、8ビットバイトの個数を表す。

次の表記を使用する。ここで、 Tホスト共有可能または固定フットプリントの型、 S はホスト共有可能または固定フットプリントの構造体型、 A はホスト共有可能または固定フットプリントの配列、あるいは実行時サイズ配列である。

14.4.1. 整列とサイズ

ホスト共有可能または固定フットプリントのデータ型 T はサイズを持つ。 バッファー型を除き、 ホスト共有可能または固定フットプリントの各型は整列を持つ。

型の整列は、その型の値をメモリ内のどこに配置できるかについての制約であり、 整数として表される。 型の整列は、その型の値の開始メモリロケーションの バイトアドレスを余りなく割り切らなければならない。 整列により、値へアクセスするためのより効率的なハードウェア命令を使用でき、 または特定のアドレス空間における、より厳しいハードウェア要件を満たすことができる。 (アドレス空間のレイアウト制約を参照)。

注: 構成上、各整列値は常に2の累乗である。

型または構造体メンバーのバイトサイズとは、その型または構造体メンバーの値を格納するために、 ホスト共有可能なメモリ内に予約される連続したバイト数である。 サイズには、型の末尾にあるアドレス指定不可能なパディングが含まれることがある。 したがって、値のロードおよびストアがアクセスするメモリロケーションの数は、 その値のサイズより少ない場合がある。

ホスト共有可能型および固定フットプリント型の整列とサイズは、 次の表で再帰的に定義される。

ホスト共有可能型および固定フットプリント型の整列とサイズ
ホスト共有可能または固定フットプリントの型 T AlignOf(T) SizeOf(T)
bool
を参照。
4 4
i32u32、またはf32 4 4
f16 2 2
atomic<T> 4 4
vec2<T>。 Tbooli32u32、またはf32 8 8
vec2<f16> 4 4
vec3<T>。Tbooli32u32、 またはf32 16 12
vec3<f16> 8 6
vec4<T>。Tbooli32u32、 または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
メンバー M1...MN を持つstruct S 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 は、潜在的なデータ競合を生じさせずに単一バイトの書き込みを実装することができない。 bool 値が4バイト整列で4バイトを占有すると規定することにより、 実装はデータ競合を生じさせずに、メモリ内で隣接するブール値をサポートできる。

14.4.2. 構造体メンバーのレイアウト

構造体の内部レイアウトは、 そのメンバーのサイズと整列から算出される。 既定では、メンバーの整列要件を満たしながら、メンバーは重複することなく順番に密に配置される。

この既定の内部レイアウトは、次のレイアウト属性を使用して上書きできる。

構造体型 Si 番目のメンバーはサイズと整列を持ち、それぞれ SizeOfMember(S, i) および AlignOfMember(S, i) と表記する。 メンバーのサイズと整列は、§ 14.4.4 値の内部レイアウトで 説明するように、構造体の先頭から各メンバーまでのバイトオフセットを算出するために使用される。

Si 番目のメンバーが属性 size(k) を持つ場合、SizeOfMember(S, i) は k である。 それ以外の場合、メンバーの型を T とすると、 SizeOf(T) である。
Si 番目のメンバーが属性 align(k) を持つ場合、AlignOfMember(S, i) は k である。 それ以外の場合、メンバーの型を T とすると、 AlignOf(T) である。

構造体メンバーに size 属性が適用されている場合、その値は メンバーの型のサイズ以上でなければならない

SizeOfMember(S, i) ≥ SizeOf(T)
ここで T は、Si 番目のメンバーの型である。

最初の構造体メンバーは、構造体の先頭からのバイトオフセットが常にゼロである。

OffsetOfMember(S, 1) = 0

後続の各メンバーは、そのメンバー型の整列を満たし、かつ直前のメンバーとの重複を避ける 最小のオフセットに配置される。 各メンバーインデックス i > 1 について、次のようになる。

OffsetOfMember(S, i) = roundUp(AlignOfMember(S, i ), OffsetOfMember(S, i-1) + SizeOfMember(S, i-1))
例: 暗黙的なメンバーのサイズと整列を使用する構造体のレイアウト
struct A {                                     //             整列(8)  サイズ(24)
    u: f32,                                    // オフセット(0)   整列(4)  サイズ(4)
    v: f32,                                    // オフセット(4)   整列(4)  サイズ(4)
    w: vec2<f32>,                              // オフセット(8)   整列(8)  サイズ(8)
    x: f32                                     // オフセット(16)  整列(4)  サイズ(4)
    // -- 暗黙的な構造体サイズのパディング --      // オフセット(20)            サイズ(4)
}

struct B {                                     //             整列(16) サイズ(160)
    a: vec2<f32>,                              // オフセット(0)   整列(8)  サイズ(8)
    // -- 暗黙的なメンバー整列のパディング -- // オフセット(8)             サイズ(8)
    b: vec3<f32>,                              // オフセット(16)  整列(16) サイズ(12)
    c: f32,                                    // オフセット(28)  整列(4)  サイズ(4)
    d: f32,                                    // オフセット(32)  整列(4)  サイズ(4)
    // -- 暗黙的なメンバー整列のパディング -- // オフセット(36)            サイズ(4)
    e: A,                                      // オフセット(40)  整列(8)  サイズ(24)
    f: vec3<f32>,                              // オフセット(64)  整列(16) サイズ(12)
    // -- 暗黙的なメンバー整列のパディング -- // オフセット(76)            サイズ(4)
    g: array<A, 3>,    // 要素ストライド 24       オフセット(80)  整列(8)  サイズ(72)
    h: i32                                     // オフセット(152) 整列(4)  サイズ(4)
    // -- 暗黙的な構造体サイズのパディング --      // オフセット(156)           サイズ(4)
}

@group(0) @binding(0)
var<storage,read_write> storage_buffer: B;
例: 明示的なメンバーのサイズと整列を持つ構造体のレイアウト
struct A {                                     //             整列(8)  サイズ(32)
    u: f32,                                    // オフセット(0)   整列(4)  サイズ(4)
    v: f32,                                    // オフセット(4)   整列(4)  サイズ(4)
    w: vec2<f32>,                              // オフセット(8)   整列(8)  サイズ(8)
    @size(16) x: f32                           // オフセット(16)  整列(4)  サイズ(16)
}

struct B {                                     //             整列(16) サイズ(208)
    a: vec2<f32>,                              // オフセット(0)   整列(8)  サイズ(8)
    // -- 暗黙的なメンバー整列のパディング -- // オフセット(8)             サイズ(8)
    b: vec3<f32>,                              // オフセット(16)  整列(16) サイズ(12)
    c: f32,                                    // オフセット(28)  整列(4)  サイズ(4)
    d: f32,                                    // オフセット(32)  整列(4)  サイズ(4)
    // -- 暗黙的なメンバー整列のパディング -- // オフセット(36)            サイズ(12)
    @align(16) e: A,                           // オフセット(48)  整列(16) サイズ(32)
    f: vec3<f32>,                              // オフセット(80)  整列(16) サイズ(12)
    // -- 暗黙的なメンバー整列のパディング -- // オフセット(92)            サイズ(4)
    g: array<A, 3>,    // 要素ストライド 32       オフセット(96)  整列(8)  サイズ(96)
    h: i32                                     // オフセット(192) 整列(4)  サイズ(4)
    // -- 暗黙的な構造体サイズのパディング --      // オフセット(196)           サイズ(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 = ストライド * 要素数 = 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 = ストライド * 要素数 = 16 * 8
var bigger_stride: array<vec3<f32>, 8>;
例: 実行時サイズ配列のレイアウト例
// 次の配列:
//   - 整列は 4 = AlignOf(f32)
//   - 要素ストライドは 4 = roundUp(AlignOf(f32),SizeOf(f32)) = 4
// B が描画またはディスパッチコマンドのバインディングに対する
// 有効バッファーバインディングサイズである場合、要素数は次のとおり:
//   N_runtime = floor(B / 要素ストライド) = 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 / 要素ストライド) = floor(B / 16)
var<storage> directions: array<vec3<f32>>;

14.4.4. 値の内部レイアウト

この節では、値全体の配置が仮定されている場合に、ホスト共有可能な値の内部が、 バッファーのバイトロケーションにどのように配置されるかを説明する。 これらのレイアウトは値の型、および構造体メンバー上のalign 属性とsize 属性に依存する。 これらの規則は、以下で説明する非不透明型に適用される。 buffer 型の値には内部構造がなく、 これらの規則による制約を受けない。

値が配置されるバッファーのバイトオフセットは、型の整列要件を満たさなければならない。 型 T の値がバッファーオフセット k に配置される場合、 ある非負整数 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-754binary32 形式で表現される。 これは1個の符号ビット、8個の指数ビット、および23個の仮数ビットを持つ。 V がホスト共有バッファーのバイトオフセット k に配置される場合、 次のようになる。

f16 の値 V は、 IEEE-754binary16 形式で表現される。 これは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 アドレス空間と同じ制約がある。

変数から直接または間接的に参照されるすべての構造体型および配列型は、 その変数のアドレス空間の制約に従わなければならない。 アドレス空間の制約への違反は、シェーダー作成エラーとなる。

この節では、アドレス空間 C で使用される場合における、 ホスト共有可能または固定フットプリントの型 S の値に対する バイトオフセットの整列要件を、 RequiredAlignOf(S, C) と定義する。

アドレス空間 C におけるホスト共有可能型または固定フットプリント型の整列要件
ホスト共有可能または固定フットプリントの型 SSC 内に現れ得るものと仮定する RequiredAlignOf(S, C)。
uniform_buffer_standard_layout がサポートされているか、 Cuniform ではない場合
RequiredAlignOf(S, C)。
uniform_buffer_standard_layout がサポートされておらずCuniform である場合
booli32u32f32、 または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)
Cuniform である場合、 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 は非負整数であり、構造体 Si 番目のメンバーは 型 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 アドレス空間は次を要求する。

注: 次の例は、ユニフォームバッファーのレイアウト要件を満たすために、 構造体メンバー上で 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> // ストライド 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> // ストライド 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 メモリモデルにおける メモリ書き込み操作と同等である。

呼び出しが次のいずれかを実行すると、読み取りアクセスが発生する。

呼び出しが次のいずれかを実行すると、書き込みアクセスが発生する。

アトミックな読み取り・変更・書き込み組み込み関数は、 読み取りアクセス書き込みアクセスの両方である 単一のメモリ操作を実行する。

読み取りアクセスと書き込みアクセスは、これ以外の状況では発生しない。 読み取りアクセスと書き込みアクセスを総称して、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. メモリモデル参照

モジュールスコープの各リソース変数は、固有のgroupbinding の組に対するメモリモデル参照を形成する。 その他の各変数(すなわち、functionprivate、およびworkgroup アドレス空間内の変数)は、 その変数の生存期間にわたる固有のメモリモデル参照を形成する。

14.5.3. スコープ付き操作

呼び出しがスコープ付き操作を実行すると、1つまたは2つの呼び出し集合に影響する。 これらの集合はメモリスコープと実行スコープである。 メモリスコープは、その操作が影響する メモリ内容の更新を認識する呼び出しの集合を指定する。 同期組み込み関数の場合、これは、 その関数よりプログラム順序上前にある影響対象のすべてのメモリ操作が、 その関数よりプログラム順序上後にある影響対象の操作から可視となることも意味する。 実行スコープは、操作に参加できる呼び出しの集合を指定する (§ 15.6 集合操作を参照)。

アトミック組み込み関数は、 メモリスコープが次のようになるアトミック操作へ対応付けられる。

同期組み込み関数は、実行およびメモリのスコープWorkgroup である制御バリアへ対応付けられる。

暗黙的および明示的な微分は、暗黙的なクアッド実行スコープを持つ。

注: 生成されたシェーダーで Vulkan メモリモデルが有効になっていない場合、 QueueFamily の代わりに Device スコープを使用するべきである。

14.5.4. メモリセマンティクス

すべてのアトミック組み込み関数は、 Relaxedメモリセマンティクスを使用するため、 ストレージクラスのセマンティクスを使用しない。

注: WGSL におけるアドレス空間は、SPIR-V におけるストレージクラスと同等である。

workgroupBarrierAcquireReleaseメモリセマンティクスWorkgroupMemory セマンティクスを使用する。 storageBarrierAcquireReleaseメモリセマンティクスUniformMemory セマンティクスを使用する。 textureBarrierAcquireReleaseメモリセマンティクスImageMemory セマンティクスを使用する。

注: workgroupBarrierstorageBarrier を組み合わせたものは、 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 上で同時に実行される異なる呼び出し間の協調が必要である。 すべての呼び出しがその操作を同時に、すなわち一様な制御フロー内で実行すると、 操作は正しく移植可能な形で実行される。

逆に、呼び出しの真部分集合が操作を実行する場合、すなわち非一様な制御フロー内では、 不正確または移植不可能な動作が発生する。 非形式的にいえば、非一様な制御依存関係の結果として、一部の呼び出しは集合操作へ到達するが、 ほかの呼び出しは到達しないか、同時には到達しない。 非一様な制御依存関係は、非一様な値に動作が依存する 制御フロー文から生じる。

たとえば、異なる呼び出しが ifbreak-ifwhile、またはfor の条件について異なる値を算出する場合、 switch のセレクターについて異なる値を算出する場合、 または短絡評価二項演算子(&& または ||)の 左オペランドについて異なる値を算出する場合、非一様な制御依存関係が生じる。

これらの非一様な値は、多くの場合、一様であることが静的に証明されていない 特定の発生源までたどることができる。 これらの発生源には次が含まれるが、これらに限定されない。

正しく移植可能な動作を保証するため、WGSL 実装は静的な一様性解析実行し、 各集合操作が一様な制御フロー内で実行されることの証明を試みる。 後続の小節でこの解析を説明する。

特定の集合操作一様な制御フロー内で 実行されることを一様性解析が証明できない場合、 一様性失敗発生する

15.2.1. 用語と概念

次の定義は参考情報にすぎず、次の小節の解析が何を算出しているかについての 直感を与えることを目的としている。 実際にこれらの概念、およびプログラムが有効となる場合や一様性規則に違反する場合を 定義するものは解析である。

特定の呼び出しグループについて、次のようになる。

15.2.2. 一様性解析の概要

残りの小節では、集合操作一様な制御フロー内でのみ実行されることを検証する 静的解析を規定する。 subgroup_uniformity 機能が サポートされている場合、複数の一様性スコープが存在する。 この解析はスコープごとに1回実行される。

注: 解析はスコープごとに1回実行されるものとして説明されているが、 実装は各スコープを含む単一の解析を実行してもよい。 ワークグループ一様性スコープと描画一様性スコープは、 異なるシェーダーステージに作用し、シェーダーステージ内の最大の一様性スコープを表すため、 実質的に同等である。

解析では、動的エラーが発生しないものと仮定する。 動的エラーを持つシェーダーステージは、 一様性解析の結果にかかわらず、すでに移植不可能である。

注:この解析には、次の望ましい特性がある。

各関数は、次の2点を保証することを試みながら解析される。

これら2つの検査のいずれかが失敗した場合、一様性失敗が発生する。

この処理の一部として、解析はその関数に関するメタデータを算出し、 続いてその呼び出し元を解析するために役立てる。 これは、最初に呼び出しグラフを構築し、葉から上に向かって、 すなわち標準ライブラリー外の関数を呼び出さない関数からエントリーポイントに向かって、 関数を解析しなければならないことを意味する。 これにより、ある関数を解析するときには、そのすべての呼び出し先のメタデータが すでに算出されている。 この言語では再帰が禁止されているため、循環に陥る危険性はない。

注: 同じことを別の言い方で表すと、「(間接的な場合を含め)呼び出し先である」という 半順序によって関数をトポロジカルソートし、その順序で解析するということである。

さらに、各関数呼び出しについて、解析は、その呼び出しが一様な制御フロー内にあることを 証明できない場合に発生する発生規則の集合があれば、それを算出して伝播する。 これを呼び出しの潜在的発生集合という。 この集合の要素は、次の可能性から選ばれる。

15.2.3. 関数の一様性要件の解析

各関数は2段階で解析される。

第1段階では、後続の小節の規則に基づいて、途中で有向グラフを構築しながら 関数の構文を走査する。 第2段階では、そのグラフを探索し、この関数を呼び出す際の制約を算出し、 場合によっては一様性失敗を発生させる。

注:4つの特別なノード、 RequiredToBeUniform.errorRequiredToBeUniform.warningRequiredToBeUniform.info、およびMayBeNonUniformを除き、 各ノードは、次のいずれかの文の真偽値を表すものとして理解できる。

エッジは、その起点ノードに対応する文から終点ノードに対応する文への含意として理解できる。

たとえば、一様性要件の1つとして、workgroupBarrier 組み込み関数は、 一様な制御フロー内でのみ呼び出されなければならない。 これを表すため、RequiredToBeUniform.error から、 workgroupBarrier呼び出し場所に対応するノードへの エッジを追加する。 これを理解する1つの方法は、RequiredToBeUniform.error が命題 True に対応するため、 RequiredToBeUniform.error -> X は、 X が true であるということと同じだと考えることである。

逆に、あるものの一様性を保証できないこと (たとえばスレッド ID を保持する変数)を表すためには、対応するノードからMayBeNonUniform へのエッジを追加する。 これを理解する1つの方法は、MayBeNonUniform が命題 False に対応するため、 X -> MayBeNonUniform は、 X が false であるということと同じだと考えることである。

この解釈から、RequiredToBeUniform.error から到達可能な すべてのノードは、プログラムが有効となるために一様であることを要求されるものに対応し、 MayBeNonUniform へ到達可能なすべてのノードは、 一様性を保証できないものに対応することが導かれる。 したがって、RequiredToBeUniform.error からMayBeNonUniform への経路が存在する場合、 一様性違反があり、一様性失敗が発生する。

ノード RequiredToBeUniform.warning およびRequiredToBeUniform.info も同様に使用されるが、 代わりに警告または情報診断を発生させる場合を決定するために役立つ。

§ 2.3 診断で説明したように、より高い重大度の診断も 生成されている場合、より低い重大度の診断は破棄されることがある。

各関数について、2つのタグが算出される。

関数の各仮パラメーターについて、1つまたは2つのタグが算出される。

呼び出し場所タグの値
呼び出し場所タグ 説明
CallSiteRequiredToBeUniform.S,
ここで S は重大度のerrorwarning、またはinfo のいずれかである。
この関数は一様な制御フローからのみ呼び出さなければならない。 それ以外の場合、重大度 S の診断が発生する。

潜在的発生集合に関連付けられる。

CallSiteNoRestriction この関数は非一様な制御フローから呼び出すことができる。
関数タグの値
関数タグ 説明
ReturnValueMayBeNonUniform 関数の戻り値は非一様である可能性がある。
NoRestriction この関数は非一様性を導入しない。
パラメータータグの値
パラメータータグ 説明
ParameterRequiredToBeUniform.S,
ここで S は重大度のerrorwarning、またはinfo のいずれかである。
パラメーターは一様な値でなければならない。 パラメーター型がポインターである場合、その内容は必ずしも一様である必要はないが、 メモリビューは一様でなければならない。 それ以外の場合、重大度 S の診断が発生する。

潜在的発生集合に関連付けられる。

ParameterContentsRequiredToBeUniform.S,
ここで S は重大度のerrorwarning、または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 にこの変数を使用する
  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 つ持つ配列型である場合に発生し得る。

単一のメンバーを持つ構造体型と、その型を格納する変数を考える:

struct S { member: i32; }
fn foo () {
   var v: S;
}

この場合、v は完全参照であり、v.member は部分参照である。 それらのメモリビューは同じメモリ位置を包含するが、v の格納型は S であり、 v.s の格納型は i32 である。

単一の要素を持つ配列でも同様の状況が発生する:

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
ここで Nexts1 の振る舞いに含まれる。

注: s1 は多くの場合、 セミコロンで終わる。

Vin(s2) Vout(s1)
if e s1 else s2
ここで Nexts1s2 の両方の振る舞いに含まれる
Vin(next) Vout(s1), Vout(s2)
if e s1 else s2
ここで Nexts1 の振る舞いには含まれるが、s2 には含まれない
Vin(next) Vout(s1)
if e s1 else s2
ここで Nexts2 の振る舞いには含まれるが、s1 には含まれない
Vin(next) Vout(s2)
loop { s1 continuing { s2 } } Vin(s1) Vout(prev),
s1 の振る舞いが {Next,Continue} と交差する場合は Vout(s2)
loop { s1 continuing { s2 } } Vin(s2) Nexts1 の振る舞いに含まれる場合は Vout(s1),
振る舞いが {Continue} であり、制御を s2 に移す s1 内の すべての si について Vout(si)
loop { s1 continuing { s2 } } Vin(next) Breaks1 の振る舞いに含まれる場合は 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 の静的解析は、if 文、switch 文、およびloop 文の 振る舞いが {Next} である場合、それらの文の終端で 一様な制御フローに戻るものと保守的に仮定する。 これは前述の表において、結果の制御フローノードを入力制御フローノードと同じにすることでモデル化される。

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}
非読み取り専用のアクセスモードを持つ storageworkgroup、 またはprivate アドレス空間にあるポインター型形式パラメーター解決される識別子であり、 その識別子がメモリビューMVEルート識別子として現れ、 型検査中に MVE に対してロード規則が呼び出される場合 MayBeNonUniform
非読み取り専用のアクセスモードを持つ storageworkgroup、 またはprivate アドレス空間にあるポインター型形式パラメーター解決される識別子であり、 その識別子がスウィズルビュー式 SVEルート識別子として現れ、 型検査中に SVE に対してスウィズルビューのロード規則が呼び出される場合
非読み取り専用のアクセスモードを持つ storageworkgroup、 またはprivate アドレス空間にあるポインター型形式パラメーター解決される識別子であり、 その識別子がメモリビューMVEルート識別子として現れ、 型検査中に MVE に対してロード規則が呼び出されない場合 CF
非読み取り専用のアクセスモードを持つ storageworkgroup、 または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 文の条件が一様な値であった場合 (たとえば、各呼び出しがユニフォームバッファから同じ値を読み取る場合)も、 プログラムは妥当だった。

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とは、 その呼び出しに対応するワークグループグリッドの点の座標三つ組 (i,j,k) である。

呼び出しがローカル呼び出し IDを持つ場合、 そのローカル呼び出しインデックスは次のとおりである:

i + (j × workgroup_size_x) + (k × workgroup_size_x × workgroup_size_y)

ワークグループが W 個の呼び出しを持つ場合、 そのワークグループの各呼び出し I は、0 ≤ L(I) < W を満たす一意のローカル呼び出しインデックス L(I) を持ち、 その範囲全体が包含されることに注意。

コンピュートシェーダーの実行は、WebGPU 実装がキューからディスパッチコマンドを取り出し、 GPU 上で指定された処理を開始すると始まる。 ディスパッチコマンドは、次に説明するように、実行するワークグループ数を示す整数三つ組 (group_count_x, group_count_y, group_count_z) であるディスパッチサイズを指定する。

特定のディスパッチに対するコンピュートシェーダーグリッドとは、 次を満たす整数座標 (CSi,CSj,CSk) の点の集合である:

ここで workgroup_size_xworkgroup_size_y、および workgroup_size_z は、前述したコンピュートシェーダーのエントリーポイントに対する値である。

コンピュートシェーダーのディスパッチが実行する処理は、 コンピュートシェーダーグリッド内の各点について、エントリーポイントの呼び出しを ちょうど 1 つ実行することである。

呼び出しのグローバル呼び出し IDとは、 その呼び出しに対応するコンピュートシェーダーグリッドの点の座標三つ組である。

呼び出しはワークグループに編成されるため、各呼び出しのグローバル呼び出し ID (CSi, CSj, CSk) は、ワークグループ IDで識別される 1 つのワークグループに対応する:

( ⌊ CSi ÷ workgroup_size_x ⌋, ⌊ CSj ÷ workgroup_size_y ⌋, ⌊ CSk ÷ workgroup_size_z ⌋)

また、次のローカル呼び出し IDで識別される、 そのワークグループ内の 1 つの呼び出しにも対応する:

( 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. サブグループ

サブグループとは、 コンピュートまたはフラグメントシェーダーステージのエントリーポイントを並行して実行し、 データを効率的に共有して結果を集合的に計算できる呼び出しの集合である。 コンピュートシェーダーまたはフラグメントシェーダー内の各呼び出しは、 ちょうど 1 つのサブグループに属する。 コンピュートシェーダーでは、各サブグループは特定のワークグループの部分集合である。 フラグメントシェーダーでは、サブグループに複数の描画コマンドからの呼び出しが含まれる場合がある。 各クアッドは 1 つのサブグループ内に包含される。

サブグループサイズとは、 サブグループ内の呼び出しの最大数である。 シェーダー内では、subgroup_size 組み込み値を介してこの値へアクセスできる。 サブグループサイズはディスパッチコマンド内、 したがってワークグループ内では一様な値であるが、 描画コマンド内では一様な値でない場合がある。 すべてのサブグループサイズは [4, 128] の範囲内の 2 の累乗であり、 特定のデバイス向けにコンパイルされたシェーダーの値は、 WebGPU § 4.3 GPUAdapter の [subgroupMinSize, subgroupMaxSize] の範囲内になる。 実際のサイズは、シェーダー、デバイスのプロパティ、およびデバイスコンパイラーに依存する。 各デバイスは、使用可能なサブグループサイズの範囲の部分集合 (単一の値である場合もある)をサポートする。 デバイスコンパイラーは、さまざまなヒューリスティックを使用して、 サポートされているサイズから 1 つを選択する。 各サブグループに含まれる呼び出しは、報告されたサブグループサイズより少ない場合がある (たとえば、起動された呼び出しがサブグループサイズより少ない場合)。

呼び出しのサブグループ呼び出し IDとは、 サブグループ内の一意な ID である。 この ID にはsubgroup_invocation_id 組み込み値を介してアクセスでき、その範囲は [0, subgroup_size - 1] である。

subgroup_id 機能がサポートされている場合、 コンピュートシェーダー内のサブグループ IDとは、 ワークグループ内のサブグループに対する一意な ID である。 この ID にはsubgroup_id 組み込み値を介してアクセスでき、 その範囲は [0, num_subgroups - 1] である。

サブグループの値(すなわち、subgroup_invocation_id および subgroup_id)とlocal_invocation_index の間には、 定義された関係は存在しない。 移植性のないコードを避けるため、シェーダー作者はこれら 2 つの値の間に 特定の対応関係があると仮定するべきではない。

同じサブグループ内の呼び出しが異なる制御フロー経路を実行するとき、 サブグループの実行が分岐したという。 これは非一様な制御フローの特殊な場合である。 分岐はサブグループ演算の意味論に影響する。 サブグループ演算を並行して実行するサブグループ内の呼び出しは、 その演算についてアクティブである。 サブグループ内のその他の呼び出しは、その演算について非アクティブである。 サブグループサイズがサブグループ内の呼び出し数を超える場合、 追加の仮想的な呼び出しは非アクティブであるとみなされる。 ヘルパー呼び出しは、 演算でアクティブまたは非アクティブになる場合がある。 すなわち、一部のデバイスではヘルパー呼び出しがサブグループ演算に参加することがあるが、 他のデバイスでは参加しないことがある。

注: 非一様な制御フロー内で動作する際、 基礎となるデバイス間には相当な移植性の違いがあり、 デバイスコンパイラーはそのようなコードを積極的に最適化することが多い。 その結果、サブグループに含まれるアクティブな呼び出しの集合が、 シェーダー作者の予想と異なる場合がある。

15.6. 集合演算

15.6.1. バリア

バリアは、プログラム内のメモリ操作の順序を定める同期組み込み関数である。 制御バリアは、同じワークグループ内のすべての呼び出しにより、 並行して実行されたかのように実行される。 したがって、制御バリアはコンピュートシェーダー内の一様な制御フロー内でのみ 実行されなければならない

15.6.2. 微分

偏微分とは、軸に沿った値の変化率である。 同じクアッド内の フラグメントシェーダー呼び出しは、近似的な偏微分を計算するために協調する。

微分を計算する組み込み関数は次のとおりである:

フラグメント座標の偏微分は、次の組み込み関数の処理の一部として暗黙的に計算される:

これらについて、微分はサンプリングするテクセルのミップレベルを決定するために役立ち、 textureSampleCompare の場合は、サンプリングして参照値と比較するために役立つ。

呼び出しによって指定された値の偏微分は、 § 17.6 微分組み込み関数で説明される 組み込み関数によって計算される:

隣接する呼び出しが協調して微分を計算するため、これらの関数は フラグメントシェーダー内の一様な制御フロー内でのみ呼び出すべきである。 これらの関数の呼び出しごとに、一様性解析が その呼び出しが一様な制御フロー内で発生することを証明できない場合、 derivative_uniformity 診断が発生する。

これらの関数のいずれかが非一様な制御フロー内で呼び出された場合、 結果は不定値となる。

注: 微分は暗黙的な種類のクアッド演算である。 その使用に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、二進浮動小数点型の値のビット表現。

出力: FBits が表す浮動小数点値。

手順:

浮動小数点演算の定義域とは、その演算が適切に定義される拡張実数入力の集合である。

丸めは、拡張実数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=1.0 かつ y=1.17e-38 (最小の正の正規単精度浮動小数点数)である x - y である。 これらの数の指数は 126 単位離れている。IEEE-754binary64(倍精度)形式は仮数部に 52 ビットしかないため、 減算を行うと y のすべての有効ビットが失われる。 丸めモードによっては、この場合や y が小さいもののゼロではない他の多くの場合に、 WGSL 式 x - yx と同じ値を生成することがある。 [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) ij である場合の (x[i] * y[j] - x[j] * y[i]) から継承
degrees(x) x * 57.295779513082322865 から継承
determinant(m:mat2x2<T>)
determinant(m:mat3x3<T>)
determinant(m:mat4x4<T>)
無限 ULP。
注:WebGPU 実装は、実用上有用な行列式関数を提供するべきである。

理想的な数学では、行列式は加算、減算、および乗算演算によって計算される。

しかし、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) 正しく丸められる

xy の両方が非正規である場合、 結果はいずれかの入力になる場合がある。

min(x, y) 正しく丸められる。

xy の両方が非正規である場合、 結果はいずれかの入力になる場合がある。

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-754binary64 型と同一であると仮定する。

binary64 形式の仮数部は f32 型の仮数部より 29 ビット長いため、 f32 値の 1 ULP は、 IEEE-754 binary64 値の 1 ULP より 229 倍大きい。

たとえば、演算の真の結果値が 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 つである。

注: 例:

数値スカラーから浮動小数点への変換 アルゴリズムは次のとおりである:

アルゴリズム: 浮動小数点への数値スカラー変換

入力:

出力: XOutX を型 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 は、すべての事前宣言済み型およびすべての構築可能構造体型に対して、 値コンストラクターを提供する。 そのようなコンストラクター組み込み関数の表記は、その型またはその型の型エイリアスと同じである。 そのような組み込み関数が使用されるすべての箇所で、識別子はその型または型エイリアスのスコープ内になければならず、 その識別子は別の宣言に解決されてならない

注: frexpmodf、および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 値を構築する。

Tbool である場合、これは恒等演算である。
それ以外の場合、これはブール型への型強制である。 eゼロ値 (浮動小数点型では -0.0 も含む)である場合、結果は false、 それ以外の場合は true である。

17.1.2.3. f16
オーバーロード
@const @must_use fn f16(e : T) -> f16
パラメーター化 Tスカラー型である
説明 f16 値を構築する。

Tf16 である場合、これは恒等演算である。
Tf16 以外の数値スカラーである場合、 ef16 に変換される (無効な変換を含む)。
Tbool である場合、 etrue なら結果は 1.0h、 それ以外の場合は 0.0h である。

17.1.2.4. f32
オーバーロード
@const @must_use fn f32(e : T) -> f32
パラメーター化 T具象スカラー型である
説明 f32 値を構築する。

Tf32 である場合、これは恒等演算である。
Tf32 以外の数値スカラーである場合、 ef32 に変換される (無効な変換を含む)。
Tbool である場合、 etrue なら結果は 1.0f、 それ以外の場合は 0.0f である。

17.1.2.5. i32
オーバーロード
@const @must_use fn i32(e : T) -> i32
パラメーター化 Tスカラー型である
説明 i32 値を構築する。

Ti32 である場合、これは恒等演算である。
Tu32 である場合、これはビットの再解釈である (すなわち、結果は e と同じビットパターンを持つi32 内の一意の値である)。
T浮動小数点型である場合、 e はゼロ方向へ丸められi32変換される
Tbool である場合、 etrue なら結果は 1i、 それ以外の場合は 0i である。
TAbstractInt である場合、 ei32 で表現できるならこれは恒等演算であり、 それ以外の場合はシェーダー作成エラーを生成する。

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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 2x2 列優先行列のコンストラクター。

TS と一致しない場合、 変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 2x3 列優先行列のコンストラクター。

TS と一致しない場合、 変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 2x4 列優先行列のコンストラクター。

TS と一致しない場合、 変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 3x2 列優先行列のコンストラクター。

TS と一致しない場合、変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 3x3 列優先行列のコンストラクター。

TS と一致しない場合、変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 3x4 列優先行列のコンストラクター。

TS と一致しない場合、変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 4x2 列優先行列のコンストラクター。

TS と一致しない場合、変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 4x3 列優先行列のコンストラクター。

TS と一致しない場合、変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 Tf16 またはf32
SAbstractFloatf16、またはf32
説明 4x4 列優先行列のコンストラクター。

TS と一致しない場合、変換が行われる。

オーバーロード
@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>
パラメーター化 TAbstractFloatf16、または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>
パラメーター化 TAbstractFloatf16、または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 値を構築する。

Tu32 である場合、これは 恒等演算である。
Ti32 である場合、これは ビットの再解釈である(すなわち、結果は u32 内で e と同じビットパターンを持つ一意の値である)。
T浮動小数点型である場合、 e について変換を行ってu32 とし、ゼロ方向への丸めを行う。
Tboolである場合、 etrue なら結果は 1u、それ以外なら 0u である。
TAbstractInt であり、 eu32 で表現できる場合は恒等演算であり、それ以外の場合はシェーダー作成 エラーを生成する。

注: 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スカラー
説明 2 成分のベクトルを、両方の成分を e として構築する。
オーバーロード
@const @must_use fn vec2<T>(e : vec2<S>) -> vec2<T>
@const @must_use fn vec2(e : vec2<S>) -> vec2<S>
パラメーター化 T具象スカラー
Sスカラー
説明 成分ごとに 2 成分のベクトルを、e.xe.yを成分として構築する。

TS と一致しない場合は変換が使用され、成分は 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スカラー
説明 成分ごとに 2 成分のベクトルを、e1e2を成分として構築する。
オーバーロード
@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スカラー
説明 3 成分のベクトルを、すべての成分を e として構築する。
オーバーロード
@const @must_use fn vec3<T>(e : vec3<S>) -> vec3<T>
@const @must_use fn vec3(e : vec3<S>) -> vec3<S>
パラメーター化 T具象スカラー
Sスカラー
説明 成分ごとに 3 成分のベクトルを、e.xe.y、および e.zを成分として構築する。

TS と一致しない場合は変換が使用され、成分は 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スカラー
説明 成分ごとに 3 成分のベクトルを、e1e2、および e3 を成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 3 成分のベクトルを、v1.xv1.y、および e1を成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 3 成分のベクトルを、e1v1.x、および v1.yを成分として構築する。
オーバーロード
@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スカラー
説明 4 成分のベクトルを、すべての成分を e として構築する。
オーバーロード
@const @must_use fn vec4<T>(e : vec4<S>) -> vec4<T>
@const @must_use fn vec4(e : vec4<S>) -> vec4<S>
パラメーター化 T具象スカラー
Sスカラー
説明 成分ごとに 4 成分のベクトルを、e.xe.ye.z、 および e.wを成分として構築する。

TS と一致しない場合は変換が使用され、成分は 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スカラー
説明 成分ごとに 4 成分のベクトルを、e1e2e3、および e4を成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 4 成分のベクトルを、e1v1.xv1.y、 および e2を成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 4 成分のベクトルを、e1e2v1.x、 および v1.yを成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 4 成分のベクトルを、v1.xv1.yv2.x、および v2.yを成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 4 成分のベクトルを、v1.xv1.ye1、 および e2を成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 4 成分のベクトルを、v1.xv1.yv1.z、および e1を成分として構築する。
オーバーロード
@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スカラー
説明 成分ごとに 4 成分のベクトルを、e1v1.xv1.y、 および v1.zを成分として構築する。
オーバーロード
@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
TS ではなく、i32、u32、または f32 である
説明 ビットを T として再解釈する。
結果は、e のビットを T 値として再解釈したものである。
オーバーロード
@const @must_use fn bitcast<vecN<T>>(e : vecN<S>) -> vecN<T>
パラメーター化 S はi32、u32、または f32
TS ではなく、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>
パラメーター化
説明 eu32 として表現できる場合は恒等演算となり、 それ以外の場合はシェーダー作成エラーを生成する。 すなわち、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実行時サイズ配列の要素型である。
ASstorageuniform、 またはworkgroupのいずれかである。
アクセスモード AMread またはread_writeであり、 必ず AS に対して有効でなければならない。

注: AS は、uniform またはworkgroupに限られる。これは、p が 次のいずれかの組み込み関数の結果から派生している場合に限られる: bufferView または bufferArrayView

説明 NRuntime、すなわち 実行時サイズ配列の要素数を返す。

§ 13.3.4 バッファー バインディングによる実行時サイズ配列の要素数の決定を参照。

pbufferView または 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>
説明 逆余弦(cos-1)について、 e の主値をラジアン単位で返す。
すなわち、0 ≤ x ≤ π かつ cos(x) = e となる x を近似する。

成分ごとに処理される(T がベクトルの場合)。

スカラーの定義域 区間 [−1, 1]

17.5.3. acosh

オーバーロード
@const @must_use fn acosh(x: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 逆双曲余弦(cosh-1)について、x に対する値を双曲角 として返す。
すなわち、0 ≤ a ≤ +∞ かつ cosh(a) = x となる a を近似する。

成分ごとに処理される(T がベクトルの場合)。

スカラーの定義域 区間 [1, +∞]

17.5.4. asin

オーバーロード
@const @must_use fn asin(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 逆正弦(sin-1)について、 e の主値をラジアン単位で返す。
すなわち、-π/2 ≤ x ≤ π/2 かつ sin(x) = e となる x を近似する。

成分ごとに処理される(T がベクトルの場合)。

スカラーの定義域 区間 [−1, 1]

17.5.5. asinh

オーバーロード
@const @must_use fn asinh(y: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 逆双曲正弦(sinh-1)について、y に対する値を双曲角 として返す。
すなわち、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>
説明 逆正接(tan-1)について、 e の主値をラジアン単位で返す。
すなわち、− π/2 ≤ x ≤ π/2 かつ tan(x) = e となる x を近似する。

成分ごとに処理される(T がベクトルの場合)。

17.5.7. atanh

オーバーロード
@const @must_use fn atanh(t: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 逆双曲正接(tanh-1)について、t に対する値を双曲角 として返す。
すなわち、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 となる、区間 [-π, π] 内の角度をラジアン単位で返す。

結果によって選択される象限は、yx の符号に依存する。 例えば、この関数は次のように実装できる:

  • 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)、または elowhigh の 3 値の中央値となる。

成分ごとに処理される(T がベクトルの場合)。

lowhigh より大きい場合:

17.5.11. cos

オーバーロード
@const @must_use fn cos(e: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e の余弦を返す。e の単位はラジアンである。 成分ごとに処理される(T がベクトルの場合)。
スカラーの定義域 区間 (−∞, +∞)

17.5.12. cosh

オーバーロード
@const @must_use fn cosh(a: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 a の双曲余弦を返す。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
説明 e1e2 の外積を返す。
定義域 可能な実装によって与えられる線形項から導出される:
  • 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>
説明 e1e2 の距離を返す(例えば、 length(e1 - e2))。

定義域は、減算 e1e2 が有効なすべてのベクトル (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
説明 e1e2 の内積を返す。
定義域 e1[i] × e2[i] の総和の線形項から導出される

17.5.21. dot4U8Packed

オーバーロード
@const @must_use fn dot4U8Packed(e1: u32,
                                 e2: u32) -> u32
説明 e1e2 は、4 個の 8 ビット符号なし整数成分を持つ ベクトルとして解釈される。 これら 2 つのベクトルの符号なし整数内積を返す。

17.5.22. dot4I8Packed

オーバーロード
@const @must_use fn dot4I8Packed(e1: u32,
                                 e2: u32) -> i32
説明 e1e2 は、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 がスカラー型の場合:

  • wT のビット幅
  • o = min(offset, w)
  • c = min(count, w - o)
  • c が 0 の場合、結果は 0 となる。
  • それ以外の場合、結果のビット 0..c - 1e のビット o..o + c - 1 からコピーされる。 結果のその他のビットは、結果のビット c - 1 と同じになる。
成分ごとに処理される(T がベクトルの場合)。

count + offsetw より大きい場合:

17.5.26. extractBits(符号なし)

オーバーロード
@const @must_use fn extractBits(e: T,
                                offset: u32,
                                count: u32) -> T
パラメーター化 T は u32 または vecN<u32>
説明 整数からビットを符号拡張なしで読み取る。

T がスカラー型の場合:

  • wT のビット幅
  • o = min(offset, w)
  • c = min(count, w - o)
  • c が 0 の場合、結果は 0 となる。
  • それ以外の場合、結果のビット 0..c - 1e のビット o..o + c - 1 からコピーされる。 結果のその他のビットは 0 となる。
成分ごとに処理される(T がベクトルの場合)。

count + offsetw より大きい場合:

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 の符号ビットと異なる 最上位ビットの位置。

成分ごとに処理される(T がベクトルの場合)。

注: 符号付き整数は 2 の補数表現を使用するため、 符号ビットは最上位ビット位置に現れる。

17.5.29. firstLeadingBit(符号なし)

オーバーロード
@const @must_use fn firstLeadingBit(e: T) -> T
パラメーター化 T は u32 または vecN<u32>
説明 スカラー T の場合、結果は次のとおり:
  • e が 0 の場合は 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 が 0 の場合は 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-754fusedMultiplyAdd 演算は、範囲と精度が無制限であるかのように中間結果を計算し、最終結果だけを出力先の型の値へ丸める。 ただし、fma に関する§ 15.7.4 浮動小数点の精度の規則では、 対象型への通常の乗算に続いて通常の加算を行う実装が許可される。 この場合、中間結果の値はオーバーフローしたり精度を失ったりする 可能性があり、演算全体はまったく「融合」されない。

定義域 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 が 0 の場合、小数部は 0 となる。

  • e が 0 ではない正規数の場合、e = fraction * 2exponent であり、 小数部は [0.5, 1.0) または (-1.0, -0.5] の範囲に含まれる。

  • それ以外の場合、e非正規化数、NaN、または無限大である。結果の 小数部と指数部は不定値となる。

__frexp_result_f32 組み込み構造体を返す。定義は次のとおり:

struct __frexp_result_f32 {
  fract : f32, // fraction part
  exp : i32    // exponent part
}

注: frexp という名前は 「fraction and exponent」と覚えられる。

例: frexp の使用
// Infers result type
let fraction_and_exponent = frexp(1.5);
// Sets fraction_only to 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 が 0 の場合、小数部は 0 となる。

  • e が 0 ではない正規数の場合、e = fraction * 2exponent であり、 小数部は [0.5, 1.0) または (-1.0, -0.5] の範囲に含まれる。

  • それ以外の場合、e非正規化数、NaN、または無限大である。結果の 小数部と指数部は不定値となる。

__frexp_result_f16 組み込み構造体を返す。次のように定義されたものとして扱う:

struct __frexp_result_f16 {
  fract : f16, // fraction part
  exp : i32    // exponent part
}

注: frexp という名前は 「fraction and exponent」と覚えられる。

注: 値を型 __frexp_result_f16 で明示的に宣言することはできないが、 値の型として推論されることはある。

オーバーロード
@const @must_use fn frexp(e: T) -> __frexp_result_abstract
パラメーター化 T は AbstractFloat
説明 e を小数部と指数部に分割する。
  • e が 0 の場合、小数部は 0 となる。

  • e が 0 ではない正規数の場合、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, // fraction part
  exp : AbstractInt      // exponent part
}

注: frexp という名前は 「fraction and exponent」と覚えられる。

例: 抽象 frexp の使用
// Infers result type
const fraction_and_exponent = frexp(1.5);
// Sets fraction_only to 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 が 0 の場合、小数部は 0 となる。

  • ei が 0 ではない正規数の場合、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>, // fraction part
  exp : vecN<i32>    // exponent part
}

注: 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 が 0 の場合、小数部は 0 となる。

  • ei が 0 ではない正規数の場合、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>, // fraction part
  exp : vecN<i32>    // exponent part
}

注: 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 が 0 の場合、小数部は 0 となる。

  • ei が 0 ではない正規数の場合、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>, // fraction part
  exp : vecN<AbstractInt>      // exponent part
}

注: 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 がスカラー型の場合:

  • wT のビット幅
  • o = min(offset, w)
  • c = min(count, w - o)
  • c が 0 の場合、結果は e となる。
  • それ以外の場合、 結果のビット o..o + c - 1newbits のビット 0..c - 1 からコピーされる。 結果のその他のビットは e からコピーされる。
成分ごとに処理される(T がベクトルの場合)。

count + offsetw より大きい場合:

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>
I がベクトルであるのは、T がベクトルである場合に限る
T抽象になれるのは、I抽象である場合に限り、その逆も同様である

注: いずれかのパラメーターが具象である場合、もう一方のパラメーターには 自動変換が適用され、 該当する場合は具象型となり、結果も 具象型となる。

説明 e1 * 2e2 を返す。ただし:

ここで、bias は浮動小数点形式の指数バイアスである:

  • f16 では 15

  • f32 では 127

  • AbstractFloat が IEEE-754binary64 である場合、AbstractFloat では 1023

x が 0 またはその型の有限の正規値である場合:

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>
説明 e1e2 より小さい場合は e2、それ以外の場合は e1 を返す。 成分ごとに処理される(T がベクトルの場合)。

e1e2 が浮動小数点値の場合:

  • e1e2 の両方が非正規化数の場合、 結果はいずれの値にもなり得る。

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>
説明 e2e1 より小さい場合は e2、それ以外の場合は e1 を返す。 成分ごとに処理される(T がベクトルの場合)。

e1e2 が浮動小数点値の場合:

  • e1e2 の両方が非正規化数の場合、 結果はいずれの値にもなり得る。

17.5.43. mix

オーバーロード
@const @must_use fn mix(e1: T,
                        e2: T,
                        e3: T) -> T
パラメーター化 S は AbstractFloat、f32、または f16
T は S または vecN<S>
説明 e1e2 の線形混合(例えば、 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>
説明 e1e2 を成分ごとに線形混合し、 各成分にスカラー混合係数 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, // fractional part
  whole : f32  // whole part
}
例: modf の使用
// Infers result type
let fract_and_whole = modf(1.5);
// Sets fract_only to 0.5
let fract_only = modf(1.5).fract;
// Sets whole_only to 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, // fractional part
  whole : f16  // whole part
}

注: 値を型 __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, // fractional part
  whole : AbstractFloat  // whole part
}
例: 抽象 modf の使用
// Infers result type
const fract_and_whole = modf(1.5);
// Sets fract_only to 0.5
const fract_only = modf(1.5).fract;
// Sets whole_only to 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>, // fractional part
  whole : vecN<f32>  // whole part
}

注: 値を型 __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>, // fractional part
  whole : vecN<f16>  // whole part
}

注: 値を型 __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>, // fractional part
  whole : vecN<AbstractFloat>  // whole part
}

注: 値を型 __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>
説明 e1e2 乗した値を返す。 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 を、eIEEE-754binary16 値に変換され、その後 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 が整数 kk + 1 のちょうど中間にある場合、 k が偶数なら結果は kk が奇数なら 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 の双曲線正弦を返す。ここで a双曲角である。 純粋な数学関数 (eae−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 の場合、関数は edge0 より小さい x に対して 0 であり、その後 xedge1 に達するまで滑らかに増加し、それ以降は 1 のままとなる。

  • edge0 > edge1 の場合、関数は edge1 より小さい x に対して 1 であり、その後 xedge0 に達するまで滑らかに減少し、それ以降は 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>
説明 edgex の場合は 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 の双曲線正接を返す。ここで a双曲角である。 純粋な数学関数 (eae−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>
説明 切り捨て(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

テクスチャ、またはテクスチャのミップレベルの寸法をテクセル単位で返す。

パラメーター化 オーバーロード
STi32u32、または f32
Fテクセル形式
Aアクセスモード

Ttexture_1d<ST> または texture_storage_1d<F,A>
@must_use fn textureDimensions(t: T) -> u32
STi32u32、または f32

Ttexture_1d<ST>

Li32、または u32

@must_use fn textureDimensions(t: T,
                               level: L) -> u32
STi32u32、または f32
Fテクセル形式
Aアクセスモード

Ttexture_2d<ST>texture_2d_array<ST>texture_cube<ST>texture_cube_array<ST>texture_multisampled_2d<ST>texture_depth_2dtexture_depth_2d_arraytexture_depth_cubetexture_depth_cube_arraytexture_depth_multisampled_2dtexture_storage_2d<F,A>texture_storage_2d_array<F,A>、 または texture_external
@must_use fn textureDimensions(t: T) -> vec2<u32>
STi32u32、または f32

Ttexture_2d<ST>texture_2d_array<ST>texture_cube<ST>texture_cube_array<ST>texture_depth_2dtexture_depth_2d_arraytexture_depth_cube、または texture_depth_cube_array

Li32、または u32

@must_use fn textureDimensions(t: T,
                               level: L) -> vec2<u32>
STi32u32、または f32
Fテクセル形式
Aアクセスモード

Ttexture_3d<ST> または texture_storage_3d<F,A>
@must_use fn textureDimensions(t: T) -> vec3<u32>
STi32u32、または f32

Ttexture_3d<ST>

Li32、または 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 サンプラー記述子で説明されている サンプリング領域を形成する。

パラメーター化 オーバーロード
Ci32、または u32
STi32u32、または f32
@must_use fn textureGather(component: C,
                           t: texture_2d<ST>,
                           s: sampler,
                           coords: vec2<f32>) -> vec4<ST>
Ci32、または u32
STi32u32、または f32
@must_use fn textureGather(component: C,
                           t: texture_2d<ST>,
                           s: sampler,
                           coords: vec2<f32>,
                           offset: vec2<i32>) -> vec4<ST>
Ci32、または u32
Ai32、または u32
STi32u32、または f32
@must_use fn textureGather(component: C,
                           t: texture_2d_array<ST>,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> vec4<ST>
Ci32、または u32
Ai32、または u32
STi32u32、または 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>
Ci32、または u32
STi32u32、または f32
@must_use fn textureGather(component: C,
                           t: texture_cube<ST>,
                           s: sampler,
                           coords: vec3<f32>) -> vec4<ST>
Ci32、または u32
Ai32、または u32
STi32u32、または 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>
Ai32、または u32
@must_use fn textureGather(t: texture_depth_2d_array,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> vec4<f32>
Ai32、または u32
@must_use fn textureGather(t: texture_depth_2d_array,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A,
                           offset: vec2<i32>) -> vec4<f32>
Ai32、または u32
@must_use fn textureGather(t: texture_depth_cube_array,
                           s: sampler,
                           coords: vec3<f32>,
                           array_index: A) -> vec4<f32>

パラメーター:

component 非深度テクスチャにのみ適用される。
選択したテクセルから読み取るチャンネルのインデックス。
指定する場合、component 式は定数式 (例: 1)でなければならない
値は 0 以上 3 以下でなければならない。この範囲外の値は シェーダー作成エラーとなる。
t 読み取り元のサンプル対象または 深度テクスチャ。
s サンプラー型
coords テクスチャ座標。
array_index 0 基点のテクスチャ配列インデックス。
この値は範囲 [0, textureNumLayers(t) - 1]クランプされる
offset テクスチャをサンプリングする前に、正規化されていないテクスチャ座標へ適用される 任意指定のテクセルオフセット。このオフセットは、テクスチャのラップモードを適用する前に適用される。
offset 式は定数式(例: 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 つのテクセルに対して 深度比較を実行し、次のように結果を 1 つのベクトルへ収集する。

パラメーター化 オーバーロード
@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>
Ai32、または u32
@must_use fn textureGatherCompare(t: texture_depth_2d_array,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  array_index: A,
                                  depth_ref: f32) -> vec4<f32>
Ai32、または 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>
Ai32、または 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 式は定数式(例: 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

サンプリングまたはフィルタリングを行わず、テクスチャから単一のテクセルを読み取る。

パラメーター化 オーバーロード
Ci32、または u32
Li32、または u32
STi32u32、または f32
@must_use fn textureLoad(t: texture_1d<ST>,
                         coords: C,
                         level: L) -> vec4<ST>
Ci32、または u32
Li32、または u32
STi32u32、または f32
@must_use fn textureLoad(t: texture_2d<ST>,
                         coords: vec2<C>,
                         level: L) -> vec4<ST>
Ci32、または u32
Ai32、または u32
Li32、または u32
STi32u32、または f32
@must_use fn textureLoad(t: texture_2d_array<ST>,
                        coords: vec2<C>,
                        array_index: A,
                        level: L) -> vec4<ST>
Ci32、または u32
Li32、または u32
STi32u32、または f32
@must_use fn textureLoad(t: texture_3d<ST>,
                         coords: vec3<C>,
                         level: L) -> vec4<ST>
Ci32、または u32
Si32、または u32
STi32u32、または f32
@must_use fn textureLoad(t: texture_multisampled_2d<ST>,
                         coords: vec2<C>,
                         sample_index: S)-> vec4<ST>
Ci32、または u32
Li32、または u32
@must_use fn textureLoad(t: texture_depth_2d,
                         coords: vec2<C>,
                         level: L) -> f32
Ci32、または u32
Ai32、または u32
Li32、または u32
@must_use fn textureLoad(t: texture_depth_2d_array,
                         coords: vec2<C>,
                         array_index: A,
                         level: L) -> f32
Ci32、または u32
Si32、または u32
@must_use fn textureLoad(t: texture_depth_multisampled_2d,
                         coords: vec2<C>,
                         sample_index: S)-> f32
Ci32、または u32
@must_use fn textureLoad(t: texture_external,
                         coords: vec2<C>) -> vec4<f32>
Ci32、または u32
AMread または read_write
CF はストレージテクセル形式 F に依存する。 テクセル形式からチャンネル形式への対応については、 テクセル形式表を参照
@must_use fn textureLoad(t : texture_storage_1d<F, AM>,
                         coords : C) -> vec4<CF>
Ci32、または u32
AMread または read_write
CF はストレージテクセル形式 F に依存する。 テクセル形式からチャンネル形式への対応については、 テクセル形式表を参照
@must_use fn textureLoad(t : texture_storage_2d<F, AM>,
                         coords : vec2<C>) -> vec4<CF>
Ci32、または u32
AMread または read_write
Ai32 または u32
CF はストレージテクセル形式 F に依存する。 テクセル形式からチャンネル形式への対応については、 テクセル形式表を参照
@must_use fn textureLoad(t : texture_storage_2d_array<F, AM>,
                         coords : vec2<C>,
                         array_index : A) -> vec4<CF>
Ci32、または u32
AMread または 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アクセスモード
STi32u32、または f32

Ttexture_2d_array<ST>texture_cube_array<ST>texture_depth_2d_arraytexture_depth_cube_array、 または texture_storage_2d_array<F,A>
@must_use fn textureNumLayers(t: T) -> u32

パラメーター:

t サンプル対象深度、または ストレージテクスチャの配列テクスチャ。

戻り値:

テクスチャがキューブを基にする場合、キューブ配列テクスチャ内のキューブ数を返す。

それ以外の場合、配列テクスチャ内のレイヤー(テクセルの同種グリッド)数を返す。

17.7.6. textureNumLevels

テクスチャのミップレベル数を返す。

パラメーター化 オーバーロード
STi32u32、または f32

Ttexture_1d<ST>texture_2d<ST>texture_2d_array<ST>texture_3d<ST>texture_cube<ST>texture_cube_array<ST>texture_depth_2dtexture_depth_2d_arraytexture_depth_cube、または texture_depth_cube_array
@must_use fn textureNumLevels(t: T) -> u32

パラメーター:

t サンプル対象または 深度テクスチャ。

戻り値:

テクスチャのミップレベル数

17.7.7. textureNumSamples

マルチサンプルテクスチャ内の 1 テクセル当たりのサンプル数を返す。

パラメーター化 オーバーロード
STi32u32、または f32

Ttexture_multisampled_2d<ST> または texture_depth_multisampled_2d
@must_use fn textureNumSamples(t: T) -> u32

パラメーター:

t マルチサンプルテクスチャ

戻り値:

マルチサンプルテクスチャサンプル数

17.7.8. textureSample

テクスチャをサンプリングする。

フラグメント シェーダーステージでのみ使用しなければならない

一様性解析によって、この関数の呼び出しが 一様制御フロー内にあると証明できない場合、 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>
Ai32、または u32
@must_use fn textureSample(t: texture_2d_array<f32>,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> vec4<f32>
Ai32、または u32
@must_use fn textureSample(t: texture_2d_array<f32>,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A,
                           offset: vec2<i32>) -> vec4<f32>
Ttexture_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>
Ai32、または 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
Ai32、または u32
@must_use fn textureSample(t: texture_depth_2d_array,
                           s: sampler,
                           coords: vec2<f32>,
                           array_index: A) -> f32
Ai32、または 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
Ai32、または 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 式は定数式(例: vec2<i32>(1, 2))でなければならない
offset 成分は -8 以上 7 以下で なければならない。 この範囲外の値はシェーダー作成エラーとなる。

戻り値:

サンプリングされた値。

非一様制御フロー内で呼び出された場合、 不定値となる。

17.7.9. textureSampleBias

ミップレベルにバイアスを適用してテクスチャをサンプリングする。

必ずフラグメントシェーダーステージでのみ 使用しなければならない。

一様性解析によって、 この関数の呼び出しが一様制御フロー内にあることを証明できない場合、 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>
Ai32 または u32
@must_use fn textureSampleBias(t: texture_2d_array<f32>,
                               s: sampler,
                               coords: vec2<f32>,
                               array_index: A,
                               bias: f32) -> vec4<f32>
Ai32 または 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>
Ttexture_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>
Ai32 または u32
@must_use fn textureSampleBias(t: texture_cube_array<f32>,
                               s: sampler,
                               coords: vec3<f32>,
                               array_index: A,
                               bias: f32) -> vec4<f32>

パラメーター:

t サンプリングするサンプルドテクスチャ
s sampler 型。
coords サンプリングに使用するテクスチャ座標。
array_index サンプリングする 0 を基準としたテクスチャ配列インデックス。
この値は [0, textureNumLayers(t) - 1] の範囲にクランプされる
bias サンプリング前にミップレベルへ適用するバイアス。
この値は [-16.0, 15.99] の範囲にクランプされる
offset テクスチャのサンプリング前に、正規化されていないテクスチャ座標へ適用する省略可能な テクセルオフセット。このオフセットは、テクスチャのラッピングモードを適用する前に 適用される。
offset 式は、const-expression(例: vec2<i32>(1, 2))でなければならない
offset 成分は -8 以上 7 以下でなければならない。この範囲外の値は シェーダー作成エラーとなる。

戻り値:

サンプリングされた値。

17.7.10. textureSampleCompare

深度テクスチャを サンプリングし、サンプリングされた深度値を参照値と比較する。

必ずフラグメントシェーダーステージでのみ 使用しなければならない。

一様性解析によって、 この関数の呼び出しが一様制御フロー内にあることを証明できない場合、 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
Ai32 または u32
@must_use fn textureSampleCompare(t: texture_depth_2d_array,
                                  s: sampler_comparison,
                                  coords: vec2<f32>,
                                  array_index: A,
                                  depth_ref: f32) -> f32
Ai32 または 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
Ai32 または 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-expression(例: 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
Ai32 または u32
@must_use fn textureSampleCompareLevel(t: texture_depth_2d_array,
                                       s: sampler_comparison,
                                       coords: vec2<f32>,
                                       array_index: A,
                                       depth_ref: f32) -> f32
Ai32 または 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
Ai32 または 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-expression(例: 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>
Ai32 または 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>
Ai32 または 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>
Ttexture_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>
Ai32 または 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 sampler
coords サンプリングに使用するテクスチャ座標。
array_index サンプリングする 0 を基準としたテクスチャ配列インデックス。
この値は [0, textureNumLayers(t) - 1] の範囲にクランプされる
ddx サンプリング位置の計算に使用する x 方向の導関数ベクトル。
ddy サンプリング位置の計算に使用する y 方向の導関数ベクトル。
offset テクスチャのサンプリング前に、正規化されていないテクスチャ座標へ適用する省略可能な テクセルオフセット。このオフセットは、テクスチャのラッピングモードを適用する前に 適用される。
offset 式は、const-expression(例: 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>
Ai32 または u32
@must_use fn textureSampleLevel(t: texture_2d_array<f32>,
                                s: sampler,
                                coords: vec2<f32>,
                                array_index: A,
                                level: f32) -> vec4<f32>
Ai32 または 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>
Ttexture_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>
Ai32 または u32
@must_use fn textureSampleLevel(t: texture_cube_array<f32>,
                                s: sampler,
                                coords: vec3<f32>,
                                array_index: A,
                                level: f32) -> vec4<f32>
Li32 または u32
@must_use fn textureSampleLevel(t: texture_depth_2d,
                                s: sampler,
                                coords: vec2<f32>,
                                level: L) -> f32
Li32 または u32
@must_use fn textureSampleLevel(t: texture_depth_2d,
                                s: sampler,
                                coords: vec2<f32>,
                                level: L,
                                offset: vec2<i32>) -> f32
Ai32 または u32
Li32 または u32
@must_use fn textureSampleLevel(t: texture_depth_2d_array,
                                s: sampler,
                                coords: vec2<f32>,
                                array_index: A,
                                level: L) -> f32
Ai32 または u32
Li32 または u32
@must_use fn textureSampleLevel(t: texture_depth_2d_array,
                                s: sampler,
                                coords: vec2<f32>,
                                array_index: A,
                                level: L,
                                offset: vec2<i32>) -> f32
Li32 または u32
@must_use fn textureSampleLevel(t: texture_depth_cube,
                                s: sampler,
                                coords: vec3<f32>,
                                level: L) -> f32
Ai32 または u32
Li32 または u32
@must_use fn textureSampleLevel(t: texture_depth_cube_array,
                                s: sampler,
                                coords: vec3<f32>,
                                array_index: A,
                                level: L) -> f32

パラメーター:

t サンプリングするサンプルドテクスチャまたは深度テクスチャ。
s sampler 型。
coords サンプリングに使用するテクスチャ座標。
array_index サンプリングする 0 を基準としたテクスチャ配列インデックス。
この値は [0, textureNumLayers(t) - 1] の範囲にクランプされる
level ミップレベル。レベル 0 にはテクスチャのフルサイズ版が含まれる。 levelf32 である関数では、 テクスチャ形式の機能に 従って形式がフィルタリング可能な場合、小数値によって 2 つのレベル間を補間できる。
offset テクスチャのサンプリング前に、正規化されていないテクスチャ座標へ適用する省略可能な テクセルオフセット。このオフセットは、テクスチャのラッピングモードを適用する前に 適用される。
offset 式は、const-expression(例: vec2<i32>(1, 2))でなければならない
offset 成分は -8 以上 7 以下でなければならない。この範囲外の値は シェーダー作成エラーとなる。

戻り値:

サンプリングされた値。

17.7.14. textureSampleBaseClampToEdge

以下で説明するようにテクスチャ座標を端にクランプし、テクスチャビューをそのベースレベルで サンプリングする。

パラメーター化 オーバーロード
Ttexture_2d<f32> または texture_external
@must_use fn textureSampleBaseClampToEdge(t: T,
                                          s: sampler,
                                          coords: vec2<f32>) -> vec4<f32>

パラメーター:

t サンプリングするサンプルドテクスチャまたは外部テクスチャ。
s sampler 型。
coords サンプリングに使用するテクスチャ座標。

サンプリング前に、指定された座標は次の矩形へクランプされる

[ half_texel, 1 - half_texel ]

ここで、

half_texel = vec2(0.5) / vec2<f32>(textureDimensions(t))

注: 半テクセルの調整により、 サンプラーの アドレッシング モードおよび フィルター モードに関係なく、ラッピングが発生しないことが保証される。 すなわち、端の近くをサンプリングする場合、サンプリングされるテクセルはその端上または その端に隣接するものとなり、反対側の端から選択されることはない。

戻り値:

サンプリングされた値。

17.7.15. textureStore

単一のテクセルをテクスチャへ書き込む。

パラメーター化 オーバーロード
Fテクセル形式
Ci32 または u32
AMwrite または read_write
CF はストレージテクセル形式 F に依存する。 テクセル形式からチャネル形式への対応については、テクセル形式の表を参照
fn textureStore(t: texture_storage_1d<F,AM>,
                coords: C,
                value: vec4<CF>)
Fテクセル形式
Ci32 または u32
AMwrite または read_write
CF はストレージテクセル形式 F に依存する。 テクセル形式からチャネル形式への対応については、テクセル形式の表を参照
fn textureStore(t: texture_storage_2d<F,AM>,
                coords: vec2<C>,
                value: vec4<CF>)
Fテクセル形式
Ci32 または u32
AMwrite または read_write
Ai32 または u32
CF はストレージテクセル形式 F に依存する。 テクセル形式からチャネル形式への対応については、テクセル形式の表を参照
fn textureStore(t: texture_storage_2d_array<F,AM>,
                coords: vec2<C>,
                array_index: A,
                value: vec4<CF>)
Fテクセル形式
Ci32 または u32
AMwrite または 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 メモリ順序付けを 使用する。これは、同期および順序付けの保証が、同じメモリ位置に作用する アトミック操作間にのみ適用されることを意味する。アトミックメモリアクセスと非アトミックメモリアクセスの間、 または異なるメモリ位置に作用するアトミックアクセスの間には、同期や順序付けの保証は適用されない。

アトミック組み込み関数は、頂点シェーダーステージで使用してはならない

すべてのアトミック組み込み関数における atomic_ptr パラメーターのアドレス空間 AS は、storage または workgroup の いずれかでなければならない

Tu32 または 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 を使用した 加算演算をアトミックに実行し、演算前にアトミックオブジェクトに格納されていた元の値を返す。

例: 関数としてのアトミック加算の演算
// All operations are performed atomically
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 を使用した 減算演算をアトミックに実行し、演算前にアトミックオブジェクトに格納されていた元の値を返す。

例: 関数としてのアトミック減算の演算
// All operations are performed atomically
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 を使用した 最大値演算をアトミックに実行し、演算前にアトミックオブジェクトに格納されていた元の値を返す。

例: 関数としてのアトミック最大値演算
// All operations are performed atomically
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 を使用した 最小値演算をアトミックに実行し、演算前にアトミックオブジェクトに格納されていた元の値を返す。

例: 関数としてのアトミック最小値演算
// All operations are performed atomically
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 演算
// All operations are performed atomically
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 演算
// All operations are performed atomically
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 演算
// All operations are performed atomically
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 をアトミックに格納し、 演算前にアトミックオブジェクトに格納されていた元の値を返す。

例: 関数としてのアトミック交換の演算
// All operations are performed atomically
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,   // old value stored in the atomic
  exchanged : bool // true if the exchange was done
}

注: __atomic_compare_exchange_result 型の値を明示的に宣言することはできないが、 値がこの型を推論することはできる。

次の手順をアトミックに実行する。

  1. atomic_ptr が指す元の値をロードする。

  2. 等価演算を使用して、元の値と値 cmp を比較する。

  3. 等価比較の結果が true であった場合にのみ、値 v を格納する。

2 つのメンバーを持つ構造体を返す。第 1 メンバー old_value は演算前の アトミックオブジェクトの元の値であり、第 2 メンバー exchanged は比較が成功したかどうかを示す。

例: 関数としてのアトミック比較交換の演算
// All operations are performed atomically
fn atomicCompareExchangeWeak(atomic_ptr: ptr<AS, atomic<T>, read_write>, cmp : T, v : T) ->
  _atomic_compare_exchange_result<T> {
  let old = *atomic_ptr;
  // This comparison may spuriously fail.
  let comparison = old == cmp;
  if comparison {
    *atomic_ptr = v;
  }
  return _atomic_compare_exchange_result<T>(old, comparison);
}

注: 一部の実装では、等価比較が見かけ上失敗する 場合がある。すなわち、結果ベクトルの第 1 成分が cmp と等しい場合でも、 結果ベクトルの第 2 成分が false になることがある。

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 ビットチャンクに分解し、各チャンクを符号なし正規化 浮動小数点値として再解釈する。
結果の成分 iv ÷ 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 ビットチャンクに分解し、各チャンクを符号なし正規化 浮動小数点値として再解釈する。
結果の成分 iv ÷ 65535 である。ここで v は、 e のビット 16×i から 16×i + 15 までを 符号なし整数として解釈した値である。

17.10.7. unpack2x16float

オーバーロード
@const @must_use fn unpack2x16float(e: u32) -> vec2<f32>
説明 32 ビット値を 2 つの 16 ビットチャンクに分解し、各チャンクを浮動小数点値として 再解釈する。
結果の成分 iv の f32 表現である。ここで v は、e のビット 16×i から 16×i + 15 までを IEEE-754 binary16 値として 解釈したものである。 § 15.7.6 浮動小数点変換を参照。

17.11. 同期組み込み関数

すべての同期関数は、Acquire/Release メモリ順序付けを伴う 制御バリアを実行する。 すなわち、すべての同期関数、ならびに影響を受けるメモリ操作およびアトミック操作は、 同期関数を基準としてプログラム順序で順序付けられる。 さらに、同期関数より前にプログラム順序付けされた、影響を受けるメモリ操作およびアトミック操作は、 同期関数より後にプログラム順序付けされた、影響を受けるメモリ操作またはアトミック操作が ワークグループのメンバーによって実行される前に、ワークグループ内の他のすべてのスレッドから 可視でなければならない。

すべての同期関数は、Workgroup メモリスコープを使用する。
すべての同期関数は、Workgroup 実行スコープを持つ。
すべての同期関数は、コンピュートシェーダーステージでのみ使用しなければならない。 すべての同期関数は、一様制御フロー内でのみ呼び出さなければならない

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 サブグループ操作を参照。

これらの関数の呼び出しには、次が適用される。

注: コンピュートシェーダーステージでは、 一様制御フローのスコープはワークグループである。 フラグメントシェーダーステージでは、 一様制御フローのスコープは描画コマンドである。 これらのスコープはいずれもサブグループより大きい。

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
説明 サブグループ内の すべてのアクティブな呼び出しについて etrue である場合、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
説明 サブグループ内の いずれかのアクティブな呼び出しについて etrue である場合、true を返す。

17.12.5. subgroupBallot

オーバーロード
@must_use fn subgroupBallot(pred : bool) -> vec4<u32>
説明 サブグループ内で predtrue であるアクティブな呼び出しの ビットマスクを返す。

戻り値の 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具象数値スカラーまたは具象数値ベクトル
Iu32 または i32
説明 サブグループ内でサブグループ呼び出し IDid と一致する呼び出しの e の値を、 サブグループ内のすべてのアクティブな呼び出しへ返す。

id は範囲 [0, 128) 内のconst-expressionなければならない

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具象数値スカラーまたは具象数値ベクトル
Iu32 または i32
説明 サブグループ呼び出し IDid と一致する呼び出しの e を返す。

id が範囲 [0, 128) 外である場合:

idアクティブな呼び出しを選択しない場合、 不定値が返される。

17.12.12.1. subgroupShuffleDown
オーバーロード
@must_use fn subgroupShuffleDown(e : T, delta : u32) -> T
前提条件 T具象数値スカラーまたは具象数値ベクトル
説明 現在の呼び出しについて、サブグループ呼び出し IDsubgroup_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具象数値スカラーまたは具象数値ベクトル
説明 現在の呼び出しについて、サブグループ呼び出し IDsubgroup_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具象数値スカラーまたは具象数値ベクトル
説明 現在の呼び出しについて、サブグループ呼び出し IDsubgroup_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 クアッド操作を参照。

これらの関数の呼び出しは、次の条件を満たす:

注: コンピュートシェーダーステージでは、 一様制御フローのスコープは ワークグループである。 フラグメント シェーダーステージでは、一様制御フローのスコープは 描画コマンドである。 これらのスコープはいずれもクアッドより大きい。

17.13.1. quadBroadcast

オーバーロード
@must_use fn quadBroadcast(e : T, id : I) -> T
前提条件 T具象数値スカラーまたは具象数値ベクトル
Iu32またはi32
説明 クアッド内でクアッド呼び出し IDid と一致する呼び出しの 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>
前提条件 ASstorageuniform、または workgroupのいずれかである。
AMAS に対して有効なアクセスモードである。

Tホスト共有可能な型である。
Tアトミック型またはバッファー型であってはならず、 それらを含んでもならない
TASアドレス空間レイアウト制約を満たさ なければならない

Iu32またはi32である。

説明 p の先頭から offset バイト離れた メモリビューを 型 T として再解釈する。 すなわち、p に関連付けられたメモリ位置が範囲 [0, bufferLength(p)) 内にある場合、結果に関連付けられた メモリ位置は、格納型 T を持つ範囲 [offset, bufferLength(p)) 内となる。

Ii32である場合:

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>
前提条件 ASstorageuniform、または workgroupのいずれかである。
AMAS に対して有効なアクセスモードである。

Tホスト共有可能な型である。
Tアトミック型またはバッファー型であってはならず、 それらを含んでもならない
TASアドレス空間レイアウト制約を満たさ なければならない

Iu32またはi32である。

説明 p の先頭から offset バイト離れた メモリビューを 型 T として再解釈する。 すなわち、p に関連付けられたメモリ位置が範囲 [0, bufferLength(p)) 内にある場合、結果に関連付けられた メモリ位置は、格納型 T を持つ範囲 [offset, bufferLength(p)) 内となる。

Ii32である場合:

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>) {
  // Read and write some of the data as vec4u.
  let p1 = bufferView<vec4u>(&in, offsets[0]);
  *bufferView<vec4u>(&out, offsets[1]) = *p1;

  // Read and write some of the other data via a structure.
  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>
前提条件 ASstorageuniform、または workgroupのいずれかである。
AMAS に対して有効なアクセスモードである。

T固定フットプリントを持たない、 ホスト共有可能な型である。
Tアトミック型またはバッファー型であってはならず、 それらを含んでもならない
TASアドレス空間レイアウト制約を満たさ なければならない

OIu32またはi32である。
SIu32またはi32である。

説明 p の先頭から offset バイト離れた位置から size バイト分のメモリビューを、型 T として再解釈する。 すなわち、p に関連付けられたメモリ位置が範囲 [0, bufferLength(p)) 内にある場合、結果に関連付けられた メモリ位置は、格納型 T を持つ範囲 [offset, offset + size) 内となる。

OIi32である場合:

SIi32である場合:

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>
前提条件 ASstorageuniform、または workgroupのいずれかである。
AMAS に対して有効なアクセスモードである。

T固定フットプリントを持たない、 ホスト共有可能な型である。
Tアトミック型またはバッファー型であってはならず、 それらを含んでもならない
TASアドレス空間レイアウト制約を満たさ なければならない

OIu32またはi32である。
SIu32またはi32である。

説明 p の先頭から offset バイト離れた位置から size バイト分のメモリビューを、型 T として再解釈する。 すなわち、p に関連付けられたメモリ位置が範囲 [0, bufferLength(p)) 内にある場合、結果に関連付けられた メモリ位置は、格納型 T を持つ範囲 [offset, offset + size) 内となる。

OIi32である場合:

SIi32である場合:

MinTypeSize(T) > size の場合、 無効なメモリ参照が返される。

offset + size > N の場合、 無効なメモリ参照が返される。

  • offset または size のいずれかがconst 式である場合、 シェーダー作成エラーとなる (パラメーターが const 式でない場合は、そのパラメーターに 0 を使用する)。

  • offset または size のいずれかがoverride 式である場合、 パイプライン作成エラーとなる (パラメーターが override 式でない場合は、そのパラメーターに 0 を使用する)。

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) {
  // Read a strided array from in and copy it unstrided to 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
前提条件 ASstorageuniform、または workgroupのいずれかである。
AMAS に対して有効なアクセスモードである。
説明 手続き間解析中に検出された、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) パーサーに適した形式で規定されている。 実装では、代わりに再帰下降パーサーを使用したい場合がある。

規範的な文法では複数の規則が左再帰になっているため、再帰下降パーサーで直接使用することはできない。 定義される非終端記号が、その生成規則のいずれかの先頭に現れる場合、その文法規則は直接左再帰である。

以下は WGSL の文法であるが、次のように機械的に変換されている:

ただし、これは LL(1) ではない。 一部の非終端記号では、複数の生成規則が共通の先読み集合を持つ。 たとえば、非終端記号 attribute のすべての生成規則は attr トークンで始まる。 より微妙な例は global_decl であり、3 つの生成規則が attribute * 句で始まるが、 その後のトークン fnoverride、および 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

必須パラメーター

該当なし

任意パラメーター

なし

エンコーディングに関する考慮事項

binary

WGSL は、バイトオーダーマーク(BOM)を付けずに UTF-8 エンコーディングを使用する Unicode テキストである。 § 3 テキスト構造を参照。

セキュリティに関する考慮事項:

WebGPU Shading Language(WGSL)は、WebGPU API のコンテキストで実行される GPU コード用の プログラミング言語である。セキュリティに関する考慮事項については、 [WebGPU] の 2.1 節「セキュリティに関する考慮事項」を参照。 プライバシーに関する考慮事項については、[WebGPU] の 2.2 節「プライバシーに関する考慮事項」を参照。

相互運用性に関する考慮事項:

WebGPU の実装は異なる能力を持つ場合があり、その相違は WGSL プログラムが利用できる機能に影響する可能性がある。 [WebGPU] の 3.6 節「任意の能力」、および§ 4.1.2 言語拡張を参照。

実装は、この登録が WGSL の後続版にも適用されるものとして動作すると期待されており、 公開された仕様への参照は、それに応じて随時更新される場合がある。 この期待はメディアタイプの登録としては一般的ではないが、広く普及している業界慣行と一致する。

公開仕様:

WebGPU シェーディング言語

このメディアタイプを使用するアプリケーション:

WebGPU の実装。これにはウェブブラウザーが含まれると予想される。

フラグメント識別子に関する考慮事項

なし

追加情報:

マジックナンバー: なし

ファイル拡張子: .wgsl

Macintosh ファイルタイプコード: TEXT

詳細情報の連絡先担当者およびメールアドレス:

David Neto(dneto@google.com)、または WGSL に記載されている編集者。

想定される用途

COMMON

作成者

W3C。WGSL に記載されている編集者を参照。

変更管理者

W3C

規範的な参考文献

[WebGPU] W3C, "WebGPU” W3C ワーキングドラフト、2023 年 1 月。https://w3.org/TR/webgpu

WebGPU Shading Language、W3C、「WebGPU Shading Language」、W3C ワーキングドラフト、2023 年 1 月。 https://w3.org/TR/WGSL

適合性

文書の規約

適合性要件は、記述的な表明と RFC 2119 の用語を組み合わせて表現される。 この文書の規範的な部分にあるキーワード “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、 “SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”、および “OPTIONAL” は、 RFC 2119 の記述に従って解釈される。 ただし、読みやすさのため、この仕様ではこれらの単語がすべて大文字で表記されるとは限らない。

非規範的であることが明示された節、例、および注を除き、この仕様のすべての文章は規範的である。[RFC2119]

この仕様の例は「たとえば」という語で導入されるか、次のように class="example" によって規範的な文章から区別される:

これは参考例の一例である。

参考注記は「注」という語で始まり、次のように class="note" によって規範的な文章から区別される:

注: これは参考注記である。

適合する アルゴリズム

アルゴリズムの一部として命令形で表現される要件 (「先頭にあるすべての空白文字を除去する」や「false を返し、これらの手順を中止する」など)は、 アルゴリズムの導入時に使用されたキーワード(「must」、「should」、「may」など)の意味で解釈される。

アルゴリズムまたは特定の手順として表現された適合性要件は、最終結果が同等である限り、 どのような方法で実装してもよい。 特に、この仕様で定義されるアルゴリズムは理解しやすいことを目的としており、 高い性能を目的としたものではない。 実装者には最適化が推奨される。

索引

この仕様で定義される 用語

参照先で定義される 用語

参考文献

規範的な参考文献

[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 ほか。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 ほか。World Wide Web の文字モデル: 文字列照合。2026 年 7 月 16 日。最初の公開ワーキングドラフト。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 日。勧告候補草案。URL: https://www.w3.org/TR/wasm-core-2/