syghの新フラグメント置き場

プログラミングTipsやコード断片の保管場所です。お絵描きもときどき載せます。

Effects10, Effects11の実行時コンパイル

(これは2013-05-11に書いた故OCNブログの記事を移植したものです)

以前書いた、「Effects11 for Windowsストア アプリ」の記事とは趣旨が逆行する話ですが、一応参考程度に書き残しておきます。デスクトップ アプリでは実行時コンパイルを使うこともできますが、いろいろ問題点(特にランタイム再配布に関するもの)があるので、極力実行時コンパイルは避けて、エフェクトやシェーダーのコンパイルには fxc.exe を使ってオフラインで行なうようにしておいたほうがいいです。

今回のサンプルは単純なコンソール アプリです。下記の環境で検証しています。
D3DEffectLoadTest.zip

昔(2010年頃)、Effects10を使っていたコードをEffects11に移行したときにハマったことがあったのですが、D3D10&D3DX10&Effects10と、D3D11&D3DX11&Effects11には細かい違いが結構あります。単純な置き換えでは済まない部分もあるし、紛らわしい部分もかなりあります。

Effects10 Effects11
対応するDirect3D API Direct3D 10.x Direct3D 11.x
使用可能なプロファイル名 fx_4_0, fx_4_1 fx_5_0
使用可能なテクニック technique10 technique10, technique11
外部ソースファイルからの直接生成 D3DX10CreateEffectFromFile() N/A
メモリ上ソースファイルからの直接生成 D3DX10CreateEffectFromMemory() N/A
ソースファイルのコンパイル D3DX10CompileFromFile() D3DX11CompileFromFile()
コンパイル済みバイトコードからの生成 D3D10CreateEffectFromMemory() D3DX11CreateEffectFromMemory()

特にまぎらわしいのが、下記2つです。

  • D3DX10CreateEffectFromMemory()
  • D3DX11CreateEffectFromMemory()

名前は似てますが、前者はメモリ上ソースファイルからのエフェクト生成、後者はメモリ上バイトコードからの生成であり、機能が全然違うので注意が必要です。

前者はFromSourceFileOnMemory()、後者はFromBytecodeOnMemory()にして欲しかった……

エフェクトのプロファイル名というのは、エフェクト ファイルをコンパイルするときに必要となるバージョンのようなもので、各シェーダーステージのプロファイル(vs_4_0やgs_5_0など)とは意味が異なります。fx_5_0を使っていても、vs_4_0_level_9_1などのダウンレベル プロファイルもきちんと使えます。

なお、D3DXはWindows SDK 8.0以降では廃止されていて、D3DCompilerランタイムもろともWindowsストア アプリ開発で使用できない(DLLをリンクするとストア アプリが起動できなくなる*1)ので、今後はできるかぎり使用を避けたほうが良いのですが、ディレクトリの優先順位を

Windows SDK 8.x>旧DirectX SDK June 2010

のように設定することで、Visual C++ 2012/2013コンパイラでもD3DXライブラリを補助的に使うことはできます。要するに、D3D9/D3D10.x/D3D11.xコア ライブラリはWindows SDK 8.xのものを使用して、D3DX9/D3DX10/D3DX11ライブラリは旧DXSDKのものを使うというわけです。これにより、デスクトップ アプリではD3D 11.1&D2D 1.1とD3DX11、もしくはD3D 11.2&D2D 1.2とD3DX11を共存させることも一応できます。

D3DX MathからDirectXMathへの移行は(演算子オーバーロードがなくなっていることを除いて)比較的簡単だと思います。DirectXTKのSimpleMathライブラリを使うとさらに簡単になるでしょう。D3DX TextureからDirectXTexへの移行も、互換機能がだいたい用意されているようなので、注意深く実装すれば大丈夫でしょう。しかし、D3DX Mesh/Sprite/EffectsなどからDirectXTKへの移行はかなり大変な作業になることが予想されます。代替機能がないものも多数あります。また、DirectXTKはD3D11専用で、D3D9/D3D10からは使用できません。実際にDirectXTex/DirectXTKへ移行するか、それともそれらに頼らずD3DXを自前のライブラリで置き換えるか、それを決めるまでの暫定的対処としてしばらくD3DXライブラリを使い続けるという手もあります。

ちなみにSMAAのソースに付属するDirect3D 10サンプルコードではEffects10を使っているのですが、FXLVM(Effects Language Virtual Machine?)が1か所だけ使用されています。Effects11はFXLVMをサポートしないので、移植しようとするとき変更が必要になります。

*1:D3DCompilerランタイムに関してはWindows 8.1ストア アプリにおいて制限付きながら利用できるようになりました。