[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Issues with sharing resources across contexts

On Aug 24, 2012, at 1:52 PM, Gregg Tavares (社用) wrote:

On Fri, Aug 24, 2012 at 10:30 AM, Florian Bösch <pyalot@gmail.com> wrote:
On Fri, Aug 24, 2012 at 7:04 PM, Gregg Tavares (社用) <gman@google.com> wrote:
Vladimir above mentioned the case of rendering to a canvas from a worker. I think we should look at their proposal once they make it public. But that specific use case is orthogonal to the issues of shared resources among multiple canvases and shared resources with workers.

So, back to the shared resources issues. Others have suggested passing the objects. So,

   texture: someTexture,

would pass ownership of the WebGLTexture referenced by 'someTexture' to the worker. At that point using 'someTexture' in the main page would start generating INVALID_OPERATION just like a WebGLTexture created in another context does now.

That sounds simpler. Basically you dont' have to designate which objects are shared. You can just only use them in one thread (main or worker) at a time.
I think the "shared resources between canvasii" idea is superfluos. The only reason you want a second canvas is in order to display something. If you just want to display something, you can take all the complexity entirely out of that so you don't have to mangle it together with cross thread/process sharing and just do that, display something. We already know how to make off-screen rendering with FBOs. The compositor already uses textures to composit the page, and texturing is used in the compositor to avoid readbacks for hardware accelerated canvasii. In order to render a second view of our data we'd just like to be able to bind a "surface", emit our drawing commands and then be done. The canvas (singular, bound to a single context) is so far the only "front" buffer we have. But given that it's all texturing underneath, there isn't a logical reason why such an exceedingly simple idea as using as many "front" surfaces as you want bound to an FBO should be in any way be impacted by complex things like resource sharing.

That's a really good idea!

if you could call

   gl.bindFramebuffer(gl.FRAMEBUFFER, someCanvas);

or similar that would mean sharing resources on the main page is not needed.

You'd still arguably need a way to mark a canvas as using WebGL although maybe it could happen automagically on bind. 

Would this work

var canvas1 = document.createElement("canvas");
var canvas2 = document.createElement("canvas");
var gl1 = canvas1.getContext("webgl");
var gl2 = canvas2.getContext("webgl");

//now both canvases are webgl canvases

// swap them just for fun
gl1.bindFramebuffer(gl.FRAMEBUFFER, canvas2);
gl2.bindFramebuffer(gl.FRAMEBUFFER, canvas1);

It seems like a little bit of a waste to have to create the second context just so the canvas is a WebGL canvas

Also, ti seems like overloading the meaning of bindFramebuffer might not be the best method since there all various operations you can do to currently bound framebuffer. So maybe it should be something like




and then like normal, calling 


renders to the current backbuffer/canvas with all the limits that normally entails (can't call framebufferRenderbuffer or framebufrferTexture2D on it)

gl.bindCanvas(canvas) seems the clear winner to me. 

Concretely speaking, though, in that case what would have created the first webgl context? Would the first webgl context come from some specific canvas, and then it could be bound to other canvases? Out of an aesthetic preference for symmetry (why is context creation coming from one canvas element and not the other?), I think it would be more elegant to allow WebGL context creation to happen outside any canvases, and that the current

var canvas1 = document.createElement("canvas");
var canvas2 = document.createElement("canvas");
var gl = canvas1.getContext("webgl") ;
gl.bindCanvas(canvas2); // this line feels arbitrarily asymmetric to me
would then become synonymous with
var canvas1 = document.createElement("canvas");
var gl = document.createWebGLContext(); // or something like that
var canvas2 = document.createElement("canvas");

Without this, I think people will end up creating hidden canvas elements just so they get a WebGL context. If you don't know exactly when a canvas will be created, you will need to check whether a context exists. This is really minor, but it would be nice to get right.

I also like how this ends up feeling similar to your earlier proposal with share groups, but now the "share groups" happen automatically simply by using the methods from that context:

var gl1 = document.createWebGLContext(); // everything called in gl1 is shared.
var gl2 = document.createWebGLContext(); // everything called in gl2 is shared.

 gl1.bindCanvas(canvas1); // draw on canvas1 using resources from gl1,
 gl2.bindCanvas(canvas1); // draw on canvas1 using resources from gl2,
 gl1.bindCanvas(canvas2); // draw on canvas2 using resources from gl1,
 gl2.bindCanvas(canvas2); // draw on canvas2 using resources from gl2, etc.

The API is really clear, and things like accidentally binding textures from one share group in another context will signal an error exactly how it happens currently.