シェーダーリフレクション [DirectX10]

シェーダーの中身がどのようなものが詰まっているかを取得するための方法です。
なかなか情報がなくて大変でした。
やりたいこととしては、シェーダーのバイナリファイルから
どのような変数およびデータ型がどの位置に存在するのかと知る方法となります。D3DX9には存在していたID3DXConstantTableのようなものを
D3D10ではどうやるかという感じになるでしょうか。

■サンプルソース

[cpp]
FILE* fp = 0;
fp = fopen( “vs10.bin”, “rb” );
fseek( fp, 0, SEEK_END );
DWORD nLength = ftell( fp );
rewind( fp );
BYTE* pBytecode = new BYTE[ nLength ];
fread( pBytecode, 1, nLength, fp );
fclose( fp ); fp = 0;

ID3D10ShaderReflection* pReflectorVS = 0;
D3D10ReflectShader( pBytecode, nLength, &pReflectorVS );
D3D10_SHADER_DESC descVS;
pReflectorVS->GetDesc( &descVS );
for( UINT i = 0; i < descVS.ConstantBuffers; ++i ) { ID3D10ShaderReflectionConstantBuffer* pReflectCB = pReflectorVS->GetConstantBufferByIndex(i);
D3D10_SHADER_BUFFER_DESC descShaderCB;
pReflectCB->GetDesc( &descShaderCB );
OutputDebugStringA( descShaderCB.Name );
OutputDebugStringA( “\n” );
for( UINT j = 0; j < descShaderCB.Variables; ++j ) { ID3D10ShaderReflectionVariable* pReflectVar = pReflectCB->GetVariableByIndex(j);
D3D10_SHADER_VARIABLE_DESC descVariable;
pReflectVar->GetDesc( &descVariable );
char buf[ 1024 ] = 0;
sprintf_s( buf, ” %s[%-2d, %d]\n”, descVariable.Name, descVariable.StartOffset, descVariable.Size, descVariable ); OutputDebugStringA( buf );
}
}
delete[] pBytecode;
[/cpp]

各種リフレクションのインターフェースを取得して、中身を調査します。

■実行結果

$Globals
g_MaterialAmbientColor[0 , 16]
g_MaterialDiffuseColor[16, 16]
g_nNumLights[32, 4]
g_LightDir[48, 44]
g_LightDiffuse[96, 48]
g_LightAmbient[144, 16]
g_fTime[160, 4]
g_mWorld[176, 64]
g_mWorldViewProjection[240, 64]
$Params
nNumLights[0 , 4]
bTexture[4 , 4]
bAnimate[8 , 4]

この結果は、BasicHLSL10のシェーダーコードを元にしています。
どうやら、グローバルにおいた無名の定数バッファは$Globalsという名前で配置されるようです。

また、関数の引数で uniform と宣言したものについては、
$Paramsという名前の定数バッファとして処理されるようです。

さらに、Descでの値は$Globalsの値を考慮していないっぽいです。

■まとめ

いろいろと注意点はありますが、これでコンパイル済みシェーダーファイルを利用する目処が立ちそうです。
また、このリフレクションはCore APIに搭載されているため、
別途のd3dx10_**.dllに依存しないのもいい点だと思います。

DirectX プログラミング
すらりんをフォローする
すらりん日記

コメント

タイトルとURLをコピーしました