はかせのラボ

私の頭の中を書いていく雑記ブログです

プログラミング コンパイル済みシェーダーを使ってみる

あいさつ

どうも、はかせです。
今回はコンパイル済みシェーダーを使えるようにしたのでその話です。

どゆこと?

DirectXを使う関係上シェーダーを使うことは避けられません。
ですが、シェーダーというのは所詮プログラムであってコンパイルして初めて使えます。

今まではデバッグしながらイテレーションを回す関係上
ランタイムでシェーダーをコンパイルして使っていました。

ただリリースすることになったらランタイムで
シェーダーをコンパイルするっていうのは悪手です。

ランタイムでの処理コストもかかりますし、
なによりシェーダーをそのまま生データで配布することになるので
最悪シェーダーを弄られて変なことになるかもしれません。

そのためこういうものはバイナリデータとして実行ファイルの中に埋め込むに限ります。
それをするためにコンパイル済みシェーダーを使えるようにしたわけです。

手順

さて、コンパイル済みシェーダーを使うべきという話をしたところで
実際にやっていきたいと思います。

コンパイル済みシェーダーを使うと言っているだけあって
まずシェーダーをコンパイルする必要があります。

今回シェーダーコンパイルにはfxc.exeを使いました。
確かVisualStudioにしれっとついてたコンパイラだったと思います。
多分CドライブのProgramFiles(x86)のなかのどっかにあります。

こいつを使ってHLSLのシェーダーをコンパイルします。
こいつはコマンドプロンプトから叩いて使います。
まずは基本の構文です。

fxc.exe/T <シェーダーバージョン> /E <エントリポイント> /Fh <出力ファイルパス> <コンパイルするシェーダーのパス>

シェーダーバージョンはvs_5_0みたいなやつです。
エントリポイントはコンパイルするメソッド名です。
出力ファイルパスはコンパイルしたファイルを置くパスを書きます。
コンパイルするシェーダーのパスはそのままです。

実行後出力ファイルパスに、
コンパイルされたシェーダーのヘッダファイルができます。
そのヘッダファイルの中にはg_から始まるBYTE配列が宣言されています。

const BYTE g_PS[] =
{
     68,  88,  66,  67,  17,  37, .....
};

これがコンパイルされたシェーダーです。

あとはこれを

device->CreateVertexShader(&g_VS, sizeof(g_VS), NULL, &info->vertexShader);
device->CreatePixelShader(&g_PS, sizeof(g_PS), NULL, &info->pixelShader);
device->CreateInputLayout(info->shader->InputLayout, info->shader->LayoutNum, g_VS, sizeof(g_VS), &info->inputLayout);

こんな感じであてがってやれば完了です。

あとがき

今回はコンパイル済みシェーダーを使えるようにした話でした。

多分DirectX初心者がまずやってみることだと思うんですが、
私はなんやかんやあってズルズルと後回しになっていました。

これでランタイムのコストがさらに削減されます。
ただリリースビルドの際にわざわざシェーダーも別でコンパイルしなきゃいけないので
少しめんどくさいですね。

それでは今回はこの辺でノシ