日別アーカイブ: 2007年7月21日

Direct3D 10 ShaderReflection を

「Direct3D 10 ShaderReflection を安全に取得する方法」
以前こちらで ID3D10Effect から ID3D10ShaderReflection を取得する方法を
紹介しましたが、このままだと少々問題がありました。
D3D10/DX10 Effect Interface内情報
というのは、以前も書いたように Effect 内で NULL が渡されたシェーダーで
あっても D3D10Effect の API はほとんど有効なまま素通りしてしまうからです。

例えば

ID3D10Effect* iEffect; // Input

ID3D10EffectTechnique* iEffectTechnique= iEffect->GetTechniqueByIndex( 0 );
if( !iEffectTechnique || !iEffectTechnique->IsValid() ){
 return FALSE;
}
ID3D10EffectPass* iEffectPass= iEffectTechnique->GetPassByIndex( 0 );
if( !iEffectPass->IsValid() ){
 return FALSE;
}
D3D10_PASS_SHADER_DESC pass_shader_desc;
if( FAILED( ipass->GetGeometryShaderDesc( &pass_shader_desc ) ) ){
 return FALSE;
}
ID3D10EffectShaderVariable* iShaderVariable= pass_shader_desc.pShaderVariable;
if( !iShaderVariable->IsValid() ){
 return FALSE;
}
D3D10_EFFECT_SHADER_DESC effect_shader_desc;
if( FAILED( shader->GetShaderDesc( pass_shader_desc.ShaderIndex, &effect_shader_desc ) ){
 return FALSE;
}
ID3D10ShaderReflection* iReflection; // Output
if( FAILED( D3D10ReflectShader( esdesc.pBytecode, esdesc.BytecodeLength, &iReflection ) ){
}

と幾重にチェックを入れても引っかからず、最後の D3D10ReflectShader() で
E_INVALIDARG になります。一旦 iShaderVariable->GetGeometryShader() で実際の
シェーダーインターフェース
(ID3D10GeometryShader, ID3D10VertexShader, ID3D10PixelShader)
を取得して、設定されているシェーダーが NULL かどうか判定しても良いのですが、
この場合 Get で AddRef() されるため Release() が必要になってしまいます。

D3D10_EFFECT_SHADER_DESC effect_shader_desc が取れたところで、バイトコード
サイズによって

if( !effect_shader_desc.BytecodeLength ){
 return FALSE;
}

とはじいてあげるのが良さそうです。

またすっかり忘れてましたが、NULL になる可能性があるのは GeometryShader
だけではありませんでした。StreamOutput を使ったときは PixelShader も NULL
設定される可能性があります。