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

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



"it is guaranteed that the state changes made by context A will be observable by context B when context B binds object O." is regarding the *state* of objects. Objects are composed of state and data. Texture filter settings are state, texture texel data is data. Binding only guarantees that state will be consistent.

----- Original Message -----
From: "John Bauman" <jbauman@chromium.org>
To: "Jeff Gilbert" <jgilbert@mozilla.com>
Cc: "Gregg Tavares (社用)" <gman@google.com>, "Ben Vanik" <benvanik@google.com>, "public webgl" <public_webgl@khronos.org>
Sent: Thursday, July 19, 2012 11:51:44 AM
Subject: Re: [Public WebGL] Issues with sharing resources across contexts

For reference, the egl specification has "For other surfaces, eglBindTexImage waits for all effects from previously issued client API commands drawing to the surface to complete before defining the texture image, as though glFinish were called on the last context to which that surface were bound," which is somewhat parallel to this interpretation. 


The ES 2.0.24 spec also includes the phrase "it is guaranteed that the state changes made by context A will be observable by context B when context B binds object O." I don't know whether they intended the rewrite of that section to change its behavior. 


Either way, I guess the only way to know for sure is to ask the people who wrote the spec. 


On Thu, Jul 19, 2012 at 11:34 AM, Jeff Gilbert < jgilbert@mozilla.com > wrote: 


Possibly. It's not very clear, but I think it does not actually make that guarantee. 

Definition 3: 
An object T which is directly attached to the current context may be reattached 
by re-binding T at the same bind point. An object T which is indirectly 
attached to the current context may be re-attached by re-attaching the 
container object C to which T is attached. 
Corollary: re-binding C to the current context re-attaches C and its hierarchy 
of contained objects. 

Rule 4: 

If the contents of an object T are changed in a context other than the current 
context, T must be attached or re-attached to at least one binding point in the 
current context in order to guarantee that the new contents of T are visible in the 
current context. 


Given rule 2 explicitly says that we need to Finish (or similar) before rebinding to propagate the content, and given definition 3 (and corollary), it would seem that the summaries of the rules are: 

Rule 1: Context-local changes of objects are in-order. 
Rule 2a: Context-local changes of containers are in-order. 
Rule 2b: Propagation of changes to a container's attachments requires completion per C.2.1 prior to (re)binding C. 
Rule 3: If you don't rebind, changes might never propagate. 
Rule 4: Rebinding T in one place acts as rebinding all bindings of T in that context. 

It seems possible (though I would guess unlikely) that Rule 4 could additionally guarantee the following, though: 
GLContexts A and B 
Texture T 
On A, CopyTexImage(T) 
On B, BindTexture(T), sample from T. 

By rule 2('2b') the following is *not* guaranteed: 
GLContexts A and B 
Texture T 
Framebuffer C 
On A, FramebufferTexture(C,T), render into C 
On B, BindTexture(T), sample from T. 

However, even with rule 2, the alternate reading of rule 4 would allow: 
GLContexts A and B 
Texture T 
Framebuffer C 
On A, FramebufferTexture(C,T), render into C, CopyTexImage(T) from C 
On B, BindTexture(T), sample from T. 

To me, this makes it even less likely that rule 4 would add any guarantee of completion. 

FWIW, this section is basically unchanged between GL and GLES. 


-Jeff 

----- Original Message ----- 

From: "John Bauman" < jbauman@chromium.org > 
To: "Jeff Gilbert" < jgilbert@mozilla.com > 


Cc: "Gregg Tavares (社用)" < gman@google.com >, "Ben Vanik" < benvanik@google.com >, "public webgl" < public_webgl@khronos.org > 
Sent: Thursday, July 19, 2012 10:52:56 AM 
Subject: Re: [Public WebGL] Issues with sharing resources across contexts 

Doesn't rule 4, which requires "If the contents of an object T are changed in a context other than the current context, T must be attached or re-attached to at least one binding point in the current context in order to guarantee that the new contents of T are visible in the current context" imply that it will still work if you rebind? Rule 2 only applies to containers, such as FBOs, which means that you probably can work around it in most cases. 


On Thu, Jul 19, 2012 at 10:03 AM, Jeff Gilbert < jgilbert@mozilla.com > wrote: 



For GLES2, the relevant bits: 

C.2.1: Determining Completion of Changes to an object 
The contents of an object T are considered to have been changed once a command 
such as described in section C.2 has completed. Completion of a command may 
be determined by calling Finish. 

[...] 

C.2.3: Rules 
[...] 
Rule 2 While a container object C is bound, any changes made to the contents of 
C’s attachments in the current context are guaranteed to be seen. To guarantee 
seeing changes made in another context to objects attached to C, such changes 
must be completed in that other context (see section C.2.1) prior to C being bound. 
Changes made in another context but not determined to have completed as described 
in section C.2.1, or after C is bound in the current context, are not guaranteed 
to be seen. 


Flush only guarantees that commands issued will complete in a finite time. It makes no guarantees about the order of rendering between multiple contexts. I would love to be wrong, but the guarantees of Flush are basically non-existent. 

We have also had issues with this in the past. Incomplete rendering is not visible on all demos, but certain ones (WebGL pasta is great for this) can demonstrate incomplete rendering when using Flush to try to resolve before compositing. 


-Jeff 


----- Original Message ----- 


From: "Gregg Tavares (社用)" < gman@google.com > 
To: "Jeff Gilbert" < jgilbert@mozilla.com > 
Cc: "Ben Vanik" < benvanik@google.com >, "public webgl" < public_webgl@khronos.org > 
Sent: Thursday, July 19, 2012 9:20:27 AM 
Subject: Re: [Public WebGL] Issues with sharing resources across contexts 

According to the spec Flush in 1 context + bind in another guarantees the results are seen. No Finish is required 



On Thu, Jul 19, 2012 at 8:57 AM, Jeff Gilbert < jgilbert@mozilla.com > wrote: 


Flush does *not* guarantee that changes to data in one context are seen in other contexts. It needs a Finish or using some variant of sync objects to guarantee this. 

-Jeff 



----- Original Message ----- 
From: "Ben Vanik" < benvanik@google.com > 
To: "Gregg Tavares (社用)" < gman@google.com > 
Cc: "public webgl" < public_webgl@khronos.org > 
Sent: Monday, July 16, 2012 5:36:02 PM 
Subject: Re: [Public WebGL] Issues with sharing resources across contexts 

In previous systems I've worked with I've used implicit flushes when swapping contexts and it made life much easier. Every call in the graphics layer basically had this: 
void MyGraphicsAPI::SomeCall() { 
MakeCurrent(); 
... 
}; 
void MyGraphicsAPI::MakeCurrent() { 
if (threadCurrentContext != this) { 
Flush(); 
} 
// ... set global threadCurrentContext, etc 
}; 


Using some macro-fu it was made to be a single variable lookup and branch that predicted well per call, and in the common case of single-context apps had little impact on performance. In apps with multiple contexts it made life much easier when dealing with the sometimes long and hairy code sequences that touched both (rare, but often unavoidable). Had the flush not been implicit it would have required a significant amount of bookkeeping logic that every piece of code that touched a context would have to interact with - yuck. It also meant that code could be moved between apps that used single contexts and multiple contexts without having to change, or the app could even decide at runtime with no ill effect. Explicit flushes would have made that a nightmare. 


The one downside of the implicit flushes is that it's easy to start flushing all over the place without knowing about it. A simple counter of flushes/frame was enough to help warn that they were happening though, as the target was usually <5 and if you mess things up you would see dozens. It's also often much trickier to find missing explicit flushes that cause subtle and sometimes very hard to identify behavioral differences. Just look at the number of WebGL pages out there today that emit warnings and imagine what it'd be like with this x_x 



On Mon, Jul 16, 2012 at 5:18 PM, Gregg Tavares (社用) < gman@google.com > wrote: 


So ........... I've been playing around with sharing resources across WebGL contexts and I'm running into issues and looking for solutions. 


The biggest issue is that GL is command buffer driven and so calling some GL function doesn't mean it's actually been executed. You have to call glFlush. This raises lots of issues of where a program might work on some browser / driver / platform combo but not others if the users forgets to call flush. 


For example, assume I have 2 contexts sharing resources. gl1, and gl2 




var vs = gl1.createShader(gl1.VERTEX_SHADER); 
var fs = gl1.createShader(gl1.FRAGMENT_SHADER); 
//... 
// assume shaders are validly compiled 
// ... 
var p = gl1.createProgram(); 
gl1.attachShader(p, vs); 
gl1.attachShader(p, fs); 
gl2.linkProgram(p); 


I attached on gl1 but linked on gl2. There's is no guarantee in GL that that link will succeed because the 2 attach commands may have only been queued and not excuted in which case the linkProgram call will fail with "missing shaders". The correct code is 



var p = gl1.createProgram(); 
gl1.attachShader(p, vs); 
gl1.attachShader(p, fs); 
gl1.flush(); // <--- important 
gl2.linkProgram(p); 


That seems unacceptable. 


2 Approaches off the of my head 


1) Try to make it just work without the flush 


One solution might be for the implementation to track which context last had a call. Any call to a different context causes an automatic implicit flush 


2) Try to make it fail when not done correctly 


This solution would be to try to track of an object is "dirty" (state has been changed) and no flush has been issued since then for that object. When an object is used, if it's dirty then either a flush is issued (which is solution #1) or a error is generated. ("called function on dirty object, did you forget to call flush?") 


Neither solution seems ideal. Worse, whatever solution is chosen also has issues if we ever get WebGL in Workers. 


A 3rd solution is just to leave it with the flush required and forgetting means you get random success / failure. No such a great prospect. :-( 


Thoughts? 
























----------------------------------------------------------- 
You are currently subscribed to public_webgl@khronos.org . 
To unsubscribe, send an email to majordomo@khronos.org with 
the following command in the body of your email: 
unsubscribe public_webgl 
----------------------------------------------------------- 




-----------------------------------------------------------
You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email:
unsubscribe public_webgl
-----------------------------------------------------------