C-WebGL: GLES2エミュレーションの実装(シェーダ関連)

シェーダー関連は割とややこしいトピックが多い。
- ActiveUniform/Attribのクエリ -- WebGL ではDOMStringを返却してくる関係で変換が必要。
- UniformLocationの変換 -- WebGLではUniformLocationはオブジェクトなので何らかの方法でキャッシュしてインデックスに変換する必要がある。WebGL2ではGLSL内でlocationを宣言できるので更にややこしい。
- AttribArrayの指定のトラッキング -- 描画時にclient side arrayになってないかチェックして、そうなっていた場合は手動でGPUにアップロードし、bindしてから描画する。
Emscriptenは、Uniform関連のクエリは完全に自前実装している。C-WebGLもそうすべきなんだけど面倒なので一旦適当に実装して様子見。。早すぎる最適化はどうのこうの。

glGetActiveAttrib
と glGetActiveUniform
length
パラメタは NULL
でも良い。
If the
length
of the returned string is not required, a value of NULL can be passed in the length argument.
というか length
が返却するのは実際に書いた長さなのか。。
GLsizei
が符号付なのは世間的にどうなんだ。。?

Uniform
一度コンテキスト側に覚えさせたUniformLocationの解放はコンテキスト側で勝手にやる方針にした。
吉と出るか凶と出るか。。いやダメだなコレ。。LinkProgramが成功する度にキャッシュ消さないとダメじゃん。。あと、関数は失敗を許容されていて、失敗した場合は -1
を返却する。
LinkProgram
時にステートをクリアする
めんどいので glLinkProgram
が発行されたら常にキャッシュ消すことにした。
ちなみにこの挙動はWebGL固有で、本来のOpenGL ESでは実際にprogramが有効化されるまでは直前の挙動をキープするように要求されている。まぁ実際のプログラムでこれに依存しているケースはバグの可能性が高いから良いんじゃないかということで。。
エラー返却
こっちは簡単。

Arrayは面倒。。
Emscriptenでも話題に挙がってるけど:
glDrawElements
によってclient側のどのメモリにアクセスされるかを検出するのが割と難しい。まぁこのケースは殆ど無いから実装をサボっても良いんじゃないだろうか。。
サボりたいのは:
-
glDrawElements
にclient side arrayがあるケース。Bufferのコピーを持つか、描画の度にELEMENT_ARRAY_BUFFER
になっているバッファをダウンロードしてきて(※ 本来のWebGLではできない)最大のindexを導出し、それを元にGPUに転送すべきデータを求める必要がある。 - 異なる
stride
の複数のattributeを単一のbufferに纏められるケース -
ELEMENT_ARRAY_BUFFER
とARRAY_BUFFER
に同じbuffer objectを使うケース( https://github.com/emscripten-core/emscripten/issues/4033 )
仮にこれで動かないアプリがあれば、32頂点以下ならハンドルするみたいな例外を設けるのが簡単だと思う。

Uniform上の配列のlocationは連続しているとは限らない
とりあえず起票
でもそうなってないGLES2実装って記憶に無いんだよなぁ。。