CreateInputLayoutで入力レイアウト(ID3D11InputLayout)を作成する際、頂点シェーダが要求する入力パラメータが不足しているとエラーコード(E_INVALIDARG)を返します。ただ作成が失敗するだけならいいのですが、エラーログが出力されてしまうため、シェーダを解析して入力パラメータの不足を調べるようにします。
ID3D11ShaderReflection
このインターフェイスでシェーダの入出力パラメータ、定数バッファの変数名などの情報が取得できます。作成にはD3DReflect関数を使用します。頂点シェーダ以外のシェーダも可能です。
リンクエラー
コンパイル&リンクするとIID_ID3D11ShaderReflectionが見つからないというリンクエラーが発生するため、dxguid.libをリンカー入力に追加します。
入力レイアウトのチェック
// 入力レイアウトチェック
// 頂点シェーダが要求している入力パラメータが定義されているか
// shader_code,code_size シェーダをコンパイルしたバイトコード
bool CheckInputLayout(const void* shader_code, size_t code_size,
const D3D11_INPUT_ELEMENT_DESC* layout, size_t layout_num)
{
ID3D11ShaderReflection* vs_ref;
HRESULT hr = D3DReflect( shader_code,code_size,
IID_ID3D11ShaderReflection, (void**)&vs_ref);
// dxguid.libのリンクが必要
if( FAILED( hr ) )return false;
// シェーダ情報取得
D3D11_SHADER_DESC shd_desc;
hr = vs_ref->GetDesc(&shd_desc);
if( FAILED( hr ) ){
vs_ref->Release();
return false;
}
for(UINT ip=0;ip<shd_desc.InputParameters;++ip){
D3D11_SIGNATURE_PARAMETER_DESC desc;
hr = vs_ref->GetInputParameterDesc(ip, &desc);
if( FAILED( hr ) ){
vs_ref->Release();
return false;
}
//入力レイアウトに必要なセマンティク名がなければ利用不可
UINT il=0;
for(il=0;il<layout_num;++il){
if( strcmp(layout[il].SemanticName, desc.SemanticName) == 0){
break;
}
}
if( il==layout_num){
vs_ref->Release();
return false;//見つからない
}
}
return true;
}