C-WebGL: GPUバックエンドの計画
色々考えたけど、とりあえず:
- 制作したWebGL1のステートトラッカー と OpenGL ES2のGPUバックエンドを組み合わせて、今迄のアプリケーションが動作することを確認
- GPUバックエンドをVulkanのものに載せ替えてVulkan移植完了
の2段構えでやっていくことにした。
ステートトラッカー は、例えば glLineWidth
のようなAPIが呼ばれたときに 内部のステートを更新する 。アプリケーションが供給する描画コマンドのパラメタをトラックするのでステートトラッカーと呼んでいる。
GPUバックエンド は、 glDrawElements
のような実際の描画コマンドが呼出されたときに動作し、ステートトラッカーが集めたパラメータと一緒に実際の描画をGPU側に要求する。
現状では glDrawElements は実装していない (空関数のままにしている)。このように空になっている関数を列挙して、GPUバックエンドが実装しなければならないインターフェースを設計していく。
GPUバックエンドが必須なコマンド
現状のトラッカーの実装を眺めてみると、割と頑張ればトラッカーで完結できるものがまだまだ残っているようなので、それらをトラッカーに実装していく必要がありそうだ。
というわけで、まず、GPUバックエンドが必須なコマンドを分離してしまうことにした。
(sX はGLES2規格書の章番号。6章だけ長いので分割している。)
描画系
一般的な意味での描画コマンド。ちょっと難しいのはrenderbuffer/framebufferの扱いで、ユーザが要求した形式のrenderbufferが使えるかどうかは、一旦attachしてみて checkFramebufferStatus で確認するというのが通常の使いみちになっているため、 本来、トラッカーでは完結できない 。一方、設定の度にドライバからトラッカーを呼出してステータスを更新する(= checkFramebufferStatus で返すべき結果もトラッカー側でトラッキングする)という実装も考えられるが、Framebufferについては都度ドライバ側を呼び出すことにした。
- s2:
- cwgl_drawArrays
- cwgl_drawElements
- s4:
- cwgl_clear
- cwgl_readPixels ★ メモリ転送を伴う
- cwgl_renderbufferStorage ★本来はメモリ確保を伴う
- cwgl_checkFramebufferStatus
- s5:
- cwgl_finish
- cwgl_flush
転送系
GPU側のメモリとの転送を伴うAPI群。描画系との境界は非常に曖昧と言える。。
- s2:
- cwgl_bufferData
- cwgl_bufferSubData
- s3:
- cwgl_generateMipmap
- cwgl_texImage2D
- cwgl_copyTexImage2D
- cwgl_texSubImage2D
- cwgl_copyTexSubImage2D
- cwgl_compressedTexImage2D
- cwgl_compressedTexSubImage2D
シェーダー系
Framebufferとは対照的に、 getProgramInfoLog
はトラッカー側に結果をキャッシュさせることにした。大したサイズではないし。。このためココにはリストされない。
- s2:
- cwgl_compileShader
- cwgl_linkProgram
- cwgl_validateProgram
シェーダー関連
これらは描画を行わないが、シェーダコンパイラとの協調が必要なのでGPUバックエンドとしての設計が必要になる:
-
s2:
- cwgl_getActiveAttrib
- cwgl_getAttribLocation
- cwgl_bindAttribLocation
- cwgl_getUniformLocation
- cwgl_getActiveUniform
- cwgl_uniform〜
-
s6shader:
- cwgl_getUniform〜
バックエンドとの協調が必要になるもの
いくつかのget系APIは、ユーザからセットした値ではなく、バックエンド側のデータを必要とするものがある。 例えばベンダ名等 (EDIT: やっぱり可能な限りステートにデータを突っ込む方針に変えた)。たぶんステートトラッカーのオブジェクトをGPUバックエンドから直接書き換える方式にするのが良いんじゃないかと思う。例えば、 getProgramInfoLog
のログデータは、 linkProgram
の際に常にステートトラッカーに書き出す というルールにすれば、GPUバックエンドは getProgramInfoLog
をハンドルする必要はなくなる。
- s6shader:
- cwgl_getShaderParameter_i1
- cwgl_getProgramParameter_i1
- cwgl_getProgramInfoLog
- cwgl_getShaderInfoLog
本来ステートトラッカーで完結できるが現状未実装のもの
いくつか特に理由なく実装をサボっているものがある。
シェーダー関連
WebGL1および2では、フラグメントシェーダ + 頂点シェーダ の組合せを越えるものは存在しないので、getAttachedShaders
はもうちょっとシンプルなAPIに変更できる。
-
s2:
- cwgl_shaderSource
-
s6obj:
- cwgl_getShaderSource
- cwgl_getAttachedShaders
is〜 系API
WebGLにおける is〜 系APIはinvalidatedされているかどうかを判別することも要求している。WebGLの invalidated flag はcontext lostの際にセットされる。C-WebGLには今のところcontext lostの概念は存在しないので、 is〜 系APIは常にtrueを返却するしかない。
ややこしいのは、ShaderやProgramにはDelete APIや DELETE_STATUS
enumが存在するものの、これらが実行されてもuseProgramされている最中はisProgramやisShaderはtrueを返却する必要がある点。
更に、本来のGLES2のisTextureは "bindされるまではtextureでないのでfalse" というルールだが、WebGLのisTextureはcreateTextureで生成された瞬間からtrueとなるので挙動が絶妙に異なる(はず)。
-
s6shader:
- cwgl_isShader
- cwgl_isProgram
-
s6obj:
- cwgl_isTexture
- cwgl_isBuffer
- cwgl_isFramebuffer
- cwgl_isRenderbuffer