DirectX11(DX11) は DirectX9(DX9) に対応したハードでも一応動かすことが出来ます。このとき、DX9 にのみ対応ハードで動かす場合、DX11 の機能は当然使えません。シェーダーに関しても同様で、頂点シェーダー、ピクセルシェーダーのみを使用することになります。
fxcや関連するドキュメントをみると、そういった DX9 ハード用のシェーダープロファイルとして、次のものを使用するようになっています。
- vs_4_0_level_9_0
- vs_4_0_level_9_1
- vs_4_0_level_9_3
- ps_4_0_level_9_1
- ps_4_0_level_9_3
確かに、DirectX11 の仕様を守って新規にシェーダーファイルを作って行く場合には何の問題も無いのですが、昔からのコードを現世代で動くようにと作業している場合、これだけの指定では足りないのです。
例えば、以下のようなシェーダーファイルのコードがあったとして、これを上記のプロファイルに従い、 vs_4_0_level_9_3 でコンパイルしたとします。
struct VSINPUT { float4 vPos : POSITION; float4 vColor : COLOR; float3 vUV0 : TEXCOORD0; }; struct VSOUTPUT { float4 vPos : POSITION; float4 vColor : COLOR; float3 vUV0 : TEXCOORD0; }; uniform float4x4 mWVP; VSOUTPUT main( VSINPUT In ) { VSOUTPUT Out = (VSOUTPUT)0; Out.vPos = mul( In.vPos, mWVP ); Out.vColor = In.vColor; Out.vUV0 = In.vUV0; return Out; }
これをコンパイルすると次のようにエラーが表示されます。
fxc /T vs_4_0_level_9_3 vs.hlsl
error X4541: vertex shader must minimally write all four components of SV_Position |
これをエラー無く、かつ、シェーダーコードを修正することなくシェーダーコンパイルを成功させるためには、/Gec オプションを指定します。
fxc /T vs_4_0_level_9_3 /Gec vs.hlsl |
これで vs_4_0 系のタイプでシェーダーをコンパイルすることが出来、DirectX11 のプログラム上で使用することが可能になります。
内部的には、出力セマンティクスのPOSITION を SV_POSITION として勝手に扱ってくれるようです。コマンドラインでコンパイルした結果を見るとそんな感じに見えます。
なお、D3DX11ShaderCompileFromFile で、この “Gec” オプションに相当するものは、 D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY となるようです。
感想
意外と DirectX11 で古いシェーダーコードをそのまま使うという話はないのかな?と思いました。
調べてみても情報はほとんど出てきませんでした。
確かにDirectX11 は初心者にはちょっと手間な部分も多いですし、ある程度までなら DirectX9 を使ってしまった方が楽で、やりたいことを実現できますし。
それでもどこかで、同じように悩んだ人に、この記事が役立ってくれるといいなと思います。