spammer爆発しろ!!!!
OpenGLでアセンブリシェーダ書くのに、さすがに手でアセンブリ書くのはないからglslで書いてcgcでarbvp1とかにコンパイルしてたんですよ。Feb 2010のやつ。最新。
そしたらなんかやけになげぇアセンブリ吐きやがる。レジスタも8個とか使ってるし。
ModelViewProjection行列とWorld行列をgl_Vertexにかけてgl_Positionにつっこむのと、sinとcosでテクスチャ座標を回転させてgl_TexCoord[0]に入れてるだけなんだけど、47命令で8一時レジスタとかになってしまった。おお?
どうもsinとcosを計算してるのが長いらしい。つかsinとcosって命令ないのかよ。と思ったらARB_vertex_programには無いようだ。ARB_fragment_programにはあって頂点シェーダではNV_gpu_program4を待たないといけない。なのでgp4vpプロファイル向けにコンパイルしたら結構短くなった。
それでも長いんだが…。こいつが問題っぽいな。
gl_Positon = gl_ModelViewProjectionMatrix * world_matrix * gl_Vertex;
world_matrixはmat4のuniform変数ね。
ここで律儀にgl_ModelViewProjectionMatrixとworld_matrixをかけてからgl_Vertexにかけに行ってるようだ。 gl_ModelViewProjectionMatrixとworld_matrixはここでしか使ってないしそんな必要ないんだけどなぁ。
gl_Positon = gl_ModelViewProjectionMatrix * (world_matrix * gl_Vertex);
こうしたら超短くなった。上のコードでは25命令だったのが9命令に。えー、頂点は行列の左から掛けろってことですかねぇ。
sinとcosはarbvp1では使えないのでcpu側でcosだけ計算してやって1.0-cos^2でsinは計算するようにしたら同じ長さで済んだ。
合計で20命令3一時レジスタに。半分より小さくなりましたよ!レジスタはまだ1個無駄に使ってるように見えるけど、まあべつに最適化がしたかったわけではないのでこれ以上は気にしない。
うーん、思ったよりcgcって頭悪いのか?sin、cos命令が無いとかは仕方ないけど、掛ける順番で命令数もレジスタ数も大幅に変わるのはこわいなぁ。cgcだけの話ならべつにいいんだけど、これとだいたい同じコンパイラが普通にドライバ内部でも使われてるはずだから、速度を気にする場合はコンパイラを過信するわけにはいかんわな。
あとNVIDIAはcgcでだいたいどんなコード吐いてくれるかわかるけど、AMDはどうすればいいんだろう。なんかのツールで見れるんだっけかな。