はじめに
皆さんこんにちは。貴方を心の中で見守るもう一人の貴方自身、エマ・デュランダルです(もう挨拶ワケわかんなくなってきたね)。
いやまったく悲報ですよ悲報! 悲しみの報せ以外の何物でもないですよ!
私、不肖ながら自作のWebGLライブラリなんぞを作っておりまして、そこで複数のWebGLコンテキストを作った場合のリソースの扱いをどうしようかと悩んでおりました。
せっかくなら、汎用的な仕様にしたかったのです。
リソース共有ってステキ☆
汎用的な仕様というのは、 『OpenGL系は「〜〜〜Object」と名前の付くリソースは、複数のコンテキスト間で共有できる』 という特性をちゃんと考慮した仕様です。
ええ〜〜〜!? そんなことできるんですか? できるんです。
OpenGLもOpenGL ESもできます。
具体的には、例えば以下のようなリソースが共有できます。
- Program Object
- Frame Buffer Object
- Vertex Buffer Object
- Index Buffer Object
- Texture Object
ということで、「じゃあこれWebGLでも当然できるんじゃね?w」とエマさん思ったわけですよ。
例えば、Canvasを複数ページに配置しておいて、それぞれのCanvasから取得したコンテキスト間で、同じリソースをシェアすればGPUリソースの節約につながるよね! と……。
ここで悲報
で、やってみたらですね。 できないでやんの(爆笑)
WebGL: INVALID_OPERATION: bindBuffer: object not from this context
とかWebGL: INVALID_OPERATION: getUniformLocation: object does not belong to this context
といったエラーの嵐で、全然使えません。
ん? 本当に使えんのか? WebGLはOpenGL ES 2.0をベースにしているんだぞ。おかしくね?
と思って、ググって調べてみましたよ私。
そしたら、以下の感じのページがヒットしましてね。
一応、偉い人たち議論はしてるみたい
早い話が、
「WebGLでの複数コンテキスト間のリソース共有は、標準では非サポート」
なんだけれども、一応「できるようにしたいね」って議論はされていて、実際にWEBGL_shared_resources
という拡張も提案されてます。
なんだけど、調べてみたところ、このWEBGL_shared_resources
に対応しているブラウザが今の所 皆無(爆)
なんなんでしょうね。ANGLEの制約とかあるんでしょうかね。よー事情はわからんけども。
一応、このWEBGL_shared_resources
を(将来サポートしたブラウザで)使うと、コンテキストの初期化時に
var canvas1 = document.createElement("canvas");
var canvas2 = document.createElement("canvas");
var ctx1 = canvas1.getContext("webgl");
var sharedResourcesExtension = ctx1.getExtension("WEBGL_shared_resources");
var ctx2 = canvas2.getContext("webgl", {
shareGroup: sharedResourcesExtension.group
});
ってやると、ctx1で作ったリソースをctx2でも使えるようになるみたいです。
早く実現されるといいなー。
あ、ちなみに。OpenGL / OpenGL ESではすでに複数コンテキスト間のリソースの共有はできますが。
バインド状態などのステートに関しては、それぞれのコンテキスト固有の情報で、それらの状態は共有でないので、そこは留意してください。(WebGLで実現されるようになったとしても、同じようになるはずです)
あーあ、残念だったなー。
謝辞
本記事の執筆にあたって、株式会社トップゲート/山下武志様が書かれた以下の書籍を参考にさせていただきました。お礼申し上げます。