WebGL1のAPIレビュー(3周目)
prev: https://zenn.dev/okuoku/scraps/a8ffaa73862409
next: https://zenn.dev/okuoku/scraps/99fa92f6aae12e
CWGL → WebGL wrapperを作る
目的 : WebGLをC言語で実装したライブラリを作る
いきなりGLES2を実装するのは大変なので単なるwrapper、つまりGLES2実装を呼ぶだけのコードを用意する。
これマジで面白くない(直球)... 1日1章目標で1週間ちょっとか。。
単純なwrapではダメなところはWebGL仕様の Differences Between WebGL and OpenGL ES 2.0 に記述がある。この辺はとりあえず無視する。
Wrapの基本方針
CWGL_API cwgl_enum_t
cwgl_getError(cwgl_ctx_t* ctx){
cwgl_enum_t r;
CTX_ENTER(ctx);
r = (cwgl_enum_t)glGetError();
CTX_LEAVE(ctx);
return r;
}
基本的には CTX_ENTER
CTX_LEAVE
で囲んで元のAPIを呼ぶだけ。コレをWebGLの全インターフェースに対して手書きする。。
CWGL_API cwgl_UniformLocation_t*
cwgl_getUniformLocation(cwgl_ctx_t* ctx, cwgl_Program_t* program,
const char* name){
GLint nameu;
GLuint namep;
cwgl_UniformLocation_t* r;
CTX_ENTER(ctx);
namep = CTX_GETNAME(ctx, program);
nameu = glGetUniformLocation(namep, name);
if(nameu == -1){
r = NULL;
}else{
r = CTX_ALLOC(ctx, UniformLocation);
CTX_SETNAME(ctx, r, nameu);
}
CTX_LEAVE(ctx);
return r;
}
OpenGL的なハンドルはwrapする。 CTX_ALLOC
で確保、 CTX_GETNAME
CTX_SETNAME
がgetter/setter。
開発環境
PowerVRのOpenGL ES2エミュレータを使うことにした。APIトレースとかが付いてくるため。
内製のトレーサでも良いんだけどトレーサのデバッグまではやりたくない。。
2章 (一部飛ばした)
GetattribとUniformはちょっと自信無いので飛ばした。Uniform系はAPIを省略しない方が良いかな。。
あと、WebGLではVertexAttribPointerなどホスト側のポインタを取る操作で、ポインタがGPUに渡るものの殆どは実ポインタを取れないのでそのチェックをどこかに追加する必要がある。
実際APIを int32_t
にしちゃってるので必ずキャストされることになる。
glVertexAttribPointer(indx, size, type, normalized,
stride, (void*)(uintptr_t)offset);
明かに実メモリは取れないよね。なので実際にポインタを渡してついうっかり動いてしまうということはそんなに無い(WebAssemblyを通る段階でアドレスはマングルされてしまう -- ということはFFIで混成ポインタを扱う必要がたぶん無いはず。要確認 ★ 。)
3 〜 6章 (いっぱい飛ばした)
... 飽きたんではなく、そもそもJavaScript側からWebGLにセットしたオブジェクトをクエリした場合、 ==
なオブジェクトを返却しないと不味いんではないかという気がしてきたので。。これを実現するためには、JavaScript側からセットしたオブジェクトはJavaScript側で 折り返す 実装にするしかない。つまり、そもそもC APIとして出す必要がない。
そして、常識的なプログラムは、そもそもWebGLに渡した値をクエリして再取得したりしない。どっちにせよ遅い。別にConformantなWebブラウザを作りたいわけではないので、この辺は割り切ってしまうことにした。