急に来たのでびっくりしたよ。GDCで出る可能性をすっかり忘れていた。
まだちゃんと見てないけど。
OpenGL4.0は基本的にはDirect3D11クラスの機能を詰め込んだ様子。Direct3D11は詳しくないんだけど、テッセレータとかそのまま追加されちゃった。そのままかよ…。
OpenGL3.3は名前通り3.x系の拡張。ちょこちょこと機能追加されてるが、インターフェース変更ででかいのがSampler Objectの追加か。
今までのOpenGLではテクスチャの中身とサンプラが一緒になってた。フィルタやリピート処理、ミップマップなんかの設定をテクスチャオブジェクトに行うようになってて不可分だった。
でも一つテクスチャを別設定で読み込みたい時にテクスチャ2枚作らなきゃいけないのは無駄だよね困るよね。ということで設定を別に分けられるようにしたわけだ。これで1つのテクスチャを別設定で同時に読み込むことができる。
そのうち分けたいよーみたいな話だったから遠い将来そうなるのかと思ってたけど意外に早かったな。
あと3.3からGLSLのバージョンもOpenGLに合わせられた。GLSLは1.5の次が3.3。その次が4.0になりました。わかりづらかったもんね。
個々の中身はあとでちゃんと見てできれば書きたい。沢山あるから飽きて書かないかもだけど。
NVIDIAが4.0対応ベータドライバとか出してないかなーと見に行ったが無かった。よく考えたらNVIDIAはまだDirect3D11対応のGPU出してなかったよ。
いや、やっぱり4.0早すぎじゃね?まだ対応できそうなGPUはAMDしか出してないし、EXT拡張どころかAMD拡張すら出してないのに標準化なんて。3.0の時にDirect3D10の機能がねー!って散々言われたからなのかな。
今後は単なるDirect3Dのクロスプラットフォーム版みたいになっちゃうのかな…。
MacRuby 0.5が出たけど入れただけで全く動かしていない今日このごろいかがお過ごしでしょうか。
MacRubyで拡張ライブラリとかどうなってんだと思ってまず気になるGC部分を見てみたんですよ。
どうもGCはauto_zoneっつーライブラリに丸投げのようだ。聞いたことない物なので調べてみたらApple製のGCライブラリ。っつーかObjective-C2.0のGCライブラリだった。
これはスレッドを登録しておけばスタックとかレジスタを勝手に走査してくれるし、並列でごみ回収してくれたり世代別GCだったりとなかなか高機能な感じのライブラリ。
でまあMacRubyがObj-Cのオブジェクトを使ってる関係もありそれをそのまま使っている感じ。
さて、拡張ライブラリを作るとしたらどうなるのか。
実際試したわけではないんで本当にできるかどうかは知らんが、とりあえずGC周りで気をつけるところを上げよう。
メモリ確保はちゃんとxmalloc、xfreeを使う。xmallocではGC対象のメモリ領域を確保してくる。つかxfreeいらなくねぇか?
Data_Wrap_Structなどで指定したmarkやfreeのコールバックは呼び出されない。これは注意。markはまあ勝手にマークしてくれるのでいらない。freeも勝手にfreeするからいらんだろということですね。デストラクタが呼ばれないのかー。
freeが呼ばれないけどどうしても後処理したい場合は、ファイナライザを使うかfinalizeメソッドを実装すればそいつを呼んでくれるっぽい。finalizeメソッドを呼んでくれるのはObjective-Cの仕様ですね。
ライトバリア対応が必要。世代別GCなんでWriteBarrierが必要です。世代別だけじゃなくて並列GCだからってのもあるんかね。とにかくライトバリアってなんじゃらほいという話なんですが、俺もろくに分かってないので適当に書いちゃうと、オブジェクトの中身が変更された時に俺変更されたよ!って言うのが必要なようです。
GC関係の話なので変更されたら常に通知する必要は無くて、オブジェクトが別のGC対象メモリ領域を参照したときに教えてあげればいいだけです。やったー!めんどいぞ!
たぶん俺の下手な説明では分からんと思うのでコードで示すと、
struct NanikaData { VALUE nanika_array; };
こんな構造体がありました。nanika_arrayにメソッドの引数で渡ってきた配列を保持しときたい。
NanikaData* data; Data_Get_Struct(NanikaData, self, data); data->nanika_array = arg_array;
こんな感じ。arg_arrayはRubyの配列オブジェクトですが当然GC対象。dataがGC対象のarg_arrayを参照してるんでMacRubyではこのことを通知してあげないと大変なことになる。
NanikaData* data; Data_Get_Struct(NanikaData, self, data); GC_WB(&data->nanika_arrya, arg_array);
上の代入文をGC_WBに書き換えただけ。これでWriteBarrier対応で安心。簡単だね!
簡単なんだけど問題はこれを見落しなく全部やらんといかんのだよ! markは必要無いけどmarkよりめんどくないかこれ?
Obj-Cだとライトバリアの処理はフィールドにオブジェクトつっこんだりした時に勝手にやってくれるみたいだけど、残念ながら素のCでは手動だよ。
メソッド定義の関数に引数が一個余計についてくる…?これはまだちゃんと確認してないんだけど、普段メソッド定義する関数は
VALUE foo(VALUE self, VALUE arg1, VALUE arg2, ...)
みたいな感じですが、selfのあとくらいにセレクタがつくみたい。
VALUE foo(VALUE self, SEL sel, VALUE arg1, VALUE arg2, ...)
まあObj-Cだしね。
とりあえずソースをさっと見て分かったのはこのくらい。マルチスレッドの場合どうすんのかって話はたぶん何もしてくれない。並列に呼んだらそのまま並列で呼ばれるでしょう。気をつけて。
しかしMacRuby良く出来てんね。GCとかはObj-Cにぶん投げ、RubyのRubyらしい所は元のCRubyのソースにぶん投げ、並列実行とかできないVMはLLVMにぶん投げ、上手く組み合わせて出来てる。いや、ぶん投げっつってもそう簡単に組み合わさる物じゃないんですごいんだけどさ。なんつーかMacOSXらしいね。