変数構文 (DirectX HLSL)
HLSL 変数を宣言するには、次の構文規則を使用します。
[Storage_Class] [Type_Modifier] Type Name[Index] [: Semantic] [Annotations] [= Initial_Value] [: Packoffset] [: Register]; |
---|
パラメーター
Storage_Class
コンパイラに変数のスコープと有効期間に関するヒントを提供する記憶域クラス修飾子 (省略可能)。修飾子は任意の順序で指定できます。値 説明 extern シェーダーへの外部入力として、グローバル変数をマークします。これは、すべてのグローバル変数の既定値です。static と組み合わせて使用することはできません。 nointerpolation ピクセル シェーダーに渡す前に、頂点シェーダーの出力を補間しません。 precise 安全ではない最適化をコンパイラで実行しないようにすることで、変数の結果を変化させるすべての結果に影響を与えます。たとえば、パフォーマンスの向上を目的として、いくつかの最適化を実行するために、定数とストリームの入力から得られる浮動小数点変数については、NaN と INF の結果の可能性をコンパイラで無視します。precise キーワードを使用すると、変数の結果に影響するすべての計算でこれらの最適化が実行されなくなります。 shared エフェクト間で共有する変数をマークします。コンパイラへのヒントとなります。 groupshared コンピュート シェーダーのスレッド グループ共有メモリー用として変数をマークします。groupshared ストレージ クラスを指定したすべての変数の最大合計サイズは、D3D10 で 16 KB、D3D11 で 32 KB です。「例」を参照してください。 static ローカル変数をマークすることで、そのローカル変数が一度だけ初期化されて、関数の呼び出し間で保持されるようにします。この宣言で初期化子を指定しなかった場合、値は 0 に設定されます。グローバル変数が static でマークされると、アプリケーション側から見えなくなります。 uniform シェーダーの実行中常に定数であるデータ (頂点シェーダー内のマテリアルの色など) を持つ変数をマークします。グローバル変数は既定で uniform 宣言されているものと見なされます。 volatile 頻繁に変わる変数をマークします。コンパイラへのヒントとなります。この記憶域クラスは、ローカル変数にのみ適用できます。 Type_Modifier
変数型の修飾子 (省略可能)。値 説明 const シェーダーが変更できない変数をマークします。したがって、変数宣言で初期化される必要があります。グローバル変数は、既定では const と見なされます (この既定の動作を無効にするには、コンパイラに /Gec フラグを指定します)。 row_major 4 成分を単一の行に格納する変数をマークします。これにより、4 成分を単一の定数レジスタ内に格納することができます。 column_major 4 成分を単一の列に格納する変数をマークします。これにより、行列式を最適化することができます。 Type
データ型 (DirectX HLSL) に記載されている HLSL データ型 のいずれか。Name[Index]
シェーダー変数を一意に識別する ASCII 文字列。任意で配列を定義するには、配列サイズの index (≥ 1 の正の整数) を指定します。Semantic
パラメーターの使用方法に関する情報 (省略可能)。コンパイラがシェーダー入力および出力をリンクするために使用します。頂点シェーダーおよびピクセル シェーダーにはいくつかの定義済みセマンティクスが用意されています。コンパイラは、セマンティクスがグローバル変数またはシェーダーに渡されるパラメーターで宣言されていない限り、セマンティクスを無視します。Annotation(s)
グローバル変数に付加される文字列形式のメタデータ (省略可能)。アノテーションは、エフェクト フレームワークによって使用され、HLSL によって無視されます。構文の詳細については、アノテーションの構文を参照してください。Initial_Value
初期値 (省略可能)。値の数は、Type 内の成分の数と一致する必要があります。extern でマークされた各グローバル変数は、リテラル値で初期化される必要があります。また、static でマークされた各変数は、定数で初期化される必要があります。static や extern を指定していないグローバル変数は、シェーダーにコンパイルされず、最適化できません。このタイプのグローバル変数を初期化するには、反射を使用してその値を取得し、取得した値を定数バッファーを使用してシェーダーに設定します。
Packoffset
シェーダー定数を手動でパックするためのオプションのキーワードです。「packoffset (DirectX HLSL)」を参照してください。Register
シェーダー変数を特定のレジスタに割り当てるためのオプションのキーワードです。「register (DirectX HLSL)」を参照してください。
例
次に、シェーダー変数宣言のいくつかの例を示します。
float fVar;
float4 color; float fVar = 3.1f; int iVar[3]; int iVar[3] = {1,2,3}; uniform float4 position : SV_POSITION; const float4 lightDirection = {0,0,1};
グループ共有
Direct3D 10 では、groupshared に書き込む際にスレッドが同期しないので、各スレッドでの書き込みは配列内の単一の位置に制限されます。SV_GroupIndex システム値を使用して、書き込み時にこの配列のインデックスを指定することで、2 つのスレッドの競合を防止できます。読み取りの場合は、すべてのスレッドから配列全体にアクセスできます。
struct GSData { float4 Color; float Factor; } groupshared GSData data[5*5*1]; [numthreads(5,5,1)] void main( uint index : SV_GroupIndex ) { data[index].Color = (float4)0; data[index].Factor = 2.0f; GroupMemoryBarrierWithGroupSync(); ... }
パッキング
レジスタの境界を越えることのない十分な大きさのベクトルおよびスカラーのサブコンポーネントをパックします。たとえば、下記はすべて有効です。
cbuffer MyBuffer { float4 Element1 : packoffset(c0); float1 Element2 : packoffset(c1); float1 Element3 : packoffset(c1.y); }
異なるパッキングの型を混在させることはできません。
register キーワードと同様に、packoffset も特定のターゲットを指定できます。サブコンポーネントのパッキングは、packoffset キーワードを使用してのみ実行できます。register キーワードは使用できません。cbuffer 宣言内で、register キーワードはプラットフォーム間の互換性に対するものであると見なされるため、Direct3D 10 ターゲットに対しては無視されます。
パックされた要素は重複可能です。このため、コンパイラがエラーや警告を発行することはありません。次の例では、Element2 と Element3 は Element1.x および Element1.y と重複します。
cbuffer MyBuffer { float4 Element1 : packoffset(c0); float1 Element2 : packoffset(c0); float1 Element3 : packoffset(c0.y); }
packoffset を使用するサンプルについては、「HLSLWithoutFX10 サンプル」を参照してください。