日別アーカイブ: 2007年9月28日

Direct3D 10 HLSL の関数型マクロ定義

SDK マニュアルを見ていて HLSL Grammar の Operators に
‘##’ や ‘#@’ という演算子を発見しました。
これは本来 #define マクロの引数に適用される演算子です。

これまで Effect fx/HLSL のプリプロセッサは非常に制限された
ものだと思っていました。例えば

・#define も基本的に定数や #if 用。
・引数を伴う関数型のマクロ定義は出来ない。

などなど。
もしやと思って実際に試してみたら、なんと関数型の引数を持ったマクロも
普通に定義して使うことが出来ました。

例えば上記演算子を使ってみるとこんな感じです。

#define	VARNAME(_n,_m)     _n##_m
#define	SEMANTIC_TEX(_id)  TEXCOORD##_id

float VARNAME(light,ambient)= 1.0f;

void VS_Main( uint vid : SV_VertexID,
			out float4 opos : SV_POSITION,
			out float2 ouv : SEMANTIC_TEX(0) )
{
  :

この場合 VARNAME(light,ambient) は「lightambient」と
連結された変数名になるし、SEMANTIC_TEX(0) は TEXCOORD0 に
置き換わります。

#@ は文字定数 ‘~’ への変換に相当します。例として次のように
記述してみます。

#define LCHAR(_n)	#@_n
int id= LCHAR(Z);

LCHAR(Z) は ‘Z’ に置き換わりました。つまり

int id= 'Z';

と等価です。

引数の文字列定数化を行う、単一の ‘#’ 演算子はありませんでした。

使えないと思っていたのでかなり驚きました。思い込んでいただけで
しょうか。
SDK Sample fx から “define” を検索しても、やはり引数を持った
関数型の define は全く使われていないようです。

試しに DirectX SDK 2006 October の fxc.exe (DX9向け) で実行したら
エラーになりました。
同じ 2006 October の fxc10.exe ではコンパイルが通ります。
D3D10 で HLSL 用プリプロセッサの機能拡張が行われたことは間違い
なさそうです。

Preprocessor は HLSL コンパイラ DLL 呼び出しとは別なので、/LD
オプションは使えませんでした。
D3D10 core API 側の Preprocessor が呼ばれると拡張タイプになり、
D3DX9 側の Preprocessor だと従来どおりの簡易型になるのではない
かと考えられます。

結論
・Direct3D10 の HLSL/Effect(fx) では、従来使えなかった関数型の
 マクロ定義が使える
・さらにマクロ引数の演算子 ## と #@ も使える