頂点シェーダと頂点宣言の分離

頂点シェーダと頂点宣言の分離

Microsoft® DirectX® 9.0 では、シェーダ作成 (CreateVertexShader) 時には頂点シェーダと頂点宣言をバインドしなくなった。シェーダの評価は 2 つの部分に分かれた。最初の部分をシェーダ作成時に実行し、残りの部分を描画 (DrawPrimitive) 時に実行する。

  • DirectX 8.x 頂点宣言の DirectX 9.0 頂点宣言へのマッピング
  • FVF コードの DirectX 9.0 頂点宣言へのマッピング
  • DirectX 9.0 頂点宣言の DirectX 8.x 頂点宣言へのマッピング
  • DirectX 9.0 頂点宣言の FVF コードへのマッピング

頂点シェーダと頂点宣言はオブジェクトによって表現する。DirectX 8.x ドライバを使ってこれを行う場合は、いくらかのキャッシングが行われる。ランタイムは "描画時" に、現在の宣言とシェーダをカプセル化した結合シェーダ オブジェクトが存在するかどうかを確認する。存在する場合は、それをドライバに送り、存在しない場合は、そのシェーダ宣言を組み合わせた新しいオブジェクトを作成する。さらに、アプリケーション プログラミング インターフェイス (API) の可用性の問題を解決するために、SetVertexDeclaration 呼び出しに相当する個別の SetFVF 呼び出しを行う。これは便利な関数である。この呼び出しを行うと、現在設定されている宣言は無効になり、新しい宣言が有効になる。DirectX 8.0 以前のドライバ (ストリーム数が 0) では、宣言 を柔軟な頂点フォーマット (FVF) に変換できないために SetVertexDeclaration が失敗する場合がある。

  • SetVertexDeclaration 呼び出しと SetVertexShader 呼び出しはステートブロックによって記録される。宣言またはシェーダを設定または取得すると、そのオブジェクトの参照カウントが増える。
  • FVF コードは、固定機能頂点パイプラインとプログラマブル頂点パイプラインの両方で共通に使える。FVF は、テーブルを使って、頂点シェーダ宣言に変換される。頂点シェーダ機能の DCL コマンドは、このことを踏まえて作成する必要がある。
  • ソフトウェア頂点処理は、テセレーションに加えて DirectX 9.0 レベルの機能もサポートしている。そのため、ソフトウェア頂点処理による描画時には、より多くの宣言がサポートされる。
  • プログラマブル頂点パイプラインの場合: Microsoft Direct3D® は描画時に、現在の頂点宣言と現在の頂点シェーダ機能の中に同じ "使用方法 - 使用方法インデックス" の組み合わせを探す。この組み合わせが見つかった場合、シェーダ機能の DCL のレジスタが頂点要素の宣言として使われる。
  • XYZRHW タイプの位置座標を持つ FVF をプログラマブル頂点パイプラインと共に使った場合、頂点は「トランスフォーム済み ライティング済み」として処理され、頂点シェーダ機能は適用されない。
  • 現在の頂点宣言内の頂点要素が持つ使用法が現在の頂点シェーダ内にないと、その頂点要素は無視される。

DirectX 8.x ドライバ (ストリーム数は 0 ではないが、ストリーム オフセットをサポートしていない) で使えるのは宣言のサブセットである。DirectX 8.x 形式の宣言に変換可能なものだけを作成できる。したがって、指定された宣言を変換できないと、CreateVertexDeclaration 呼び出しは失敗する場合がある。ミックス モードの場合、DrawXXX を実行するとこの失敗が起きる。このシェーダがハードウェア頂点処理で使われているのか、ソフトウェア頂点処理で使われているかがわかるのはこのときだけである。この変換についてまとめた表を示す。

DirectX 8.0 以前のドライバ (ストリーム数が 0) で使えるのは、decl のさらに小さなサブセットである。適切な FVF に変換できる宣言だけが使える。この変換ができないと、CreateVertexDeclaration は失敗する場合がある。ミックス モードの場合、DrawXXX を実行するとこの失敗が起きる。このシェーダがハードウェア頂点処理で使われているのか、ソフトウェア頂点処理で使われているかがわかるのはこのときだけである。この変換についてまとめた表を示す。使用できるのはストリーム 0 だけである (MaxStreams 能力から明らか)。

頂点要素の順番は FVF コードの順番と同じでなければならない。D3DDECLUSAGE_POSITION および D3DDECLUSAGE_NORMAL の使用方法インデックスは 0 でなければならない。デバイスの頂点処理モードをミックス モードに切り替える場合、入力頂点 (およびインデックス) ストリーム、頂点宣言、頂点機能をすべてリセットする必要はない。NULL は、SetVertexDeclaration に対する無効な入力である。ソフトウェア頂点処理を使っている場合、プログラマブルな頂点パイプラインのシェーダ コードで指定したすべての使用方法が、描画時にバインドした宣言 (または FVF) の中に存在しなければならない。

次のルールを採用している宣言は、固定機能パイプラインでレンダリングできる (テセレーションは不要と想定)。

  • D3DDECLMETHOD_DEFAULT のみを使う。
  • 頂点要素間に隙間がない (DirectX 8.x 宣言では、SKIP は使えない)。
  • 使用法 POSITION を指定する。
  • 使用法 POSITION に対して D3DDECLTYPE_FLOAT3 データ タイプを指定する。
  • 次の表に記述されていない頂点要素は、DirectX 8.0 以前のすべてのドライバで有効な FVF に変換することはできない。したがって、それらのドライバで固定機能頂点処理と共には使えない。

DirectX 8.x 頂点宣言の DirectX 9.0 頂点宣言へのマッピング

DirectX 8.x DirectX 9.0 使用法 DirectX 9.0 使用法インデックス
D3DVSDE_POSITION D3DDECLUSAGE_POSITION 0
D3DVSDE_POSITION2 D3DDECLUSAGE_POSITION 1
D3DVSDE_NORMAL D3DDECLUSAGE_NORMAL 0
D3DVSDE_NORMAL2 D3DDECLUSAGE_NORMAL 1
D3DVSDE_BLENDWEIGHT D3DDECLUSAGE_BLENDWEIGHT 0
D3DVSDE_BLENDINDICES D3DDECLUSAGE_BLENDINDICES 0
D3DVSDE_PSIZE D3DDECLUSAGE_PSIZE 0
D3DVSDE_DIFFUSE D3DDECLUSAGE_COLOR 0
D3DVSDE_SPECULAR D3DDECLUSAGE_COLOR 1
D3DVSDE_TEXCOORDn D3DDECLUSAGE_TEXCOORD n

FVF コードの DirectX 9.0 頂点宣言へのマッピング

FVF データ タイプ 使用法 使用法インデックス
D3DFVF_XYZ D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_POSITION 0
D3DFVF_XYZRHW D3DDECLTYPE_FLOAT4 D3DDECLUSAGE_POSITIONT 0
D3DFVF_XYZW D3DDECLTYPE_FLOAT4 D3DDECLUSAGE_POSITIONT 0
D3DFVF_XYZB5 および D3DFVF_LASTBETA_UBYTE4 D3DVSDT_FLOAT3、D3DVSDT_FLOAT4、D3DVSDT_UBYTE4 D3DDECLUSAGE_POSITION、D3DDECLUSAGE_BLENDWEIGHT、D3DDECLUSAGE_BLENDINDICES 0
D3DFVF_XYZB5 D3DDECLTYPE_FLOAT3、D3DDECLTYPE_FLOAT4、D3DDECLTYPE_FLOAT1 D3DDECLUSAGE_POSITION、D3DDECLUSAGE_BLENDWEIGHT、D3DDECLUSAGE_BLENDINDICES 0
D3DFVF_XYZBn (n=1..4) D3DDECLTYPE_FLOAT3、D3DDECLTYPE_FLOATn D3DDECLUSAGE_POSITION、D3DDECLUSAGE_BLENDWEIGHT 0
D3DFVF_XYZBn (n=1..4) および D3DFVF_LASTBETA_UBYTE4 D3DDECLTYPE_FLOAT3、D3DDECLTYPE_FLOAT(n-1)、D3DDECLTYPE_UBYTE4 D3DDECLUSAGE_POSITION、D3DDECLUSAGE_BLENDWEIGHT、D3DDECLUSAGE_BLENDINDICES 0
D3DFVF_NORMAL D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_NORMAL 0
D3DFVF_PSIZE D3DDECLTYPE_FLOAT1 D3DDECLUSAGE_PSIZE 0
D3DFVF_DIFFUSE D3DDECLTYPE_D3DCOLOR D3DDECLUSAGE_COLOR 0
D3DFVF_SPECULAR D3DDECLTYPE_D3DCOLOR D3DDECLUSAGE_COLOR 1
D3DFVF_TEXCOORDSIZEm(n) D3DDECLTYPE_FLOATm D3DDECLUSAGE_TEXCOORD n

DirectX 9.0 頂点宣言の DirectX 8.x 頂点宣言へのマッピング

使用法 使用法インデックス DirectX decl
D3DDECLUSAGE_POSITION 0 D3DVSDE_POSITION
D3DDECLUSAGE_POSITION 1 D3DVSDE_POSITION2
D3DDECLUSAGE_BLENDWEIGHT 0 D3DVSDE_BLENDWEIGHT
D3DDECLUSAGE_BLENDINDICES 0 D3DVSDE_BLENDINDICES
D3DDECLUSAGE_NORMAL 0 D3DVSDE_NORMAL
D3DDECLUSAGE_NORMAL 1 D3DVSDE_NORMAL2
D3DDECLUSAGE_PSIZE 0 D3DVSDE_PSIZE
D3DDECLUSAGE_COLOR 0 D3DVSDE_DIFFUSE
D3DDECLUSAGE_COLOR 1 D3DVSDE_SPECULAR
D3DDECLUSAGE_TEXCOORD n D3DVSDE_TEXTUREn, n <= 7

DirectX 9.0 頂点宣言の FVF コードへのマッピング

DirectX 8.0 およびそれ以降のドライバでは、宣言に正常に変換でき、したがって固定機能頂点処理で使えるタイプが他にもある。

  • DirectX 8.x ドライバを使う場合、頂点宣言は次のルールに従って DirectX 8.x 宣言に変換される。この他の使用法の組み合わせでは、Direct3D は失敗する。
  • D3DVSD_STREAM の新しいストリームごとに、トークンが挿入される。
  • 複数の頂点要素が 1 つのストリーム内の同じオフセットを共有したり、オーバーラップすることはできない。
  • データ タイプは D3DDECLTYPE_SHORT4 以下でなければならない。
  • D3DDECLMETHOD_DEFAULT メソッドを使った頂点要素ごとに、D3DVSD_REG トークンが挿入される。
  • 使用法と使用法インデックスは、次の表を使ってレジスタ値に変換される。DrawRectPatch (RT パッチ) を使っている場合、テセレータからの出力は上記のルールに従っていなければならない。
データ タイプ 使用法 使用法インデックス FVF
D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_POSITION 0 D3DFVF_XYZ
D3DDECLTYPE_FLOATn D3DDECLUSAGE_BLENDWEIGHT 0 D3DFVF_XYZBn
D3DDECLTYPE_UBYTE4 D3DDECLUSAGE_BLENDINDICES 0 D3DFVF_XYZB (nWeights+1)
D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_NORMAL 0 D3DFVF_NORMAL
D3DDECLTYPE_FLOAT1 D3DDECLUSAGE_PSIZE 0 D3DFVF_PSIZE
D3DDECLTYPE_D3DCOLOR D3DDECLUSAGE_COLOR 0 D3DFVF_DIFFUSE
D3DDECLTYPE_D3DCOLOR D3DDECLUSAGE_COLOR 1 D3DFVF_SPECULAR
D3DDECLTYPE_FLOATm D3DDECLUSAGE_TEXCOORD n D3DFVF_TEXCOORDSIZEm(n)
D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_POSITION 1 不適用
D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_NORMAL 1 不適用