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

Re: [Public WebGL] Caching shader compile assembly

On Wed, May 2, 2012 at 3:41 PM, Glenn Maynard <glenn@zewt.org> wrote:
On Wed, May 2, 2012 at 5:08 PM, Florian Bösch <pyalot@gmail.com> wrote:
On Thu, May 3, 2012 at 12:01 AM, Patrick Baggett <baggett.patrick@gmail.com> wrote:
Just by the way OpenGL works on the desktop, I'm thinking the answer is going to be "not without a lot of effort". If the browser vendors used "GL_ARB_get_program_binary" and kept a separate "compiled program cache", I think it is possible.

 But the thing we haven't solved with this caching is the first-load experience :/

It would be a big improvement to be able to compile shaders asynchronously, so browser tabs don't freeze up and you can keep smoothly rendering any loading animations, etc.  Like other things this is probably not possible for pure GLES-based implementations, but it's almost certainly possible for D3D-backed ones, and it probably is for OpenGL (non-ES) ones (where if I remember correctly you can compile in a new context in another thread, then use resource sharing extensions to move the compiled shader across).

Technically speaking compilation is asynchronous now (compileShader can return immediately), but there's no way to tell if the compilation is finished; all you can do is call finish() or getLastError(), which block.  One possible API would be a call which causes an event to be dispatched when the render queue is empty; you'd call it, then return to the browser, and the event would be dispatched once it's possible to call getLastError without blocking.  On implementations that can't do this (GLES, probably), they'd just send the message immediately when you return to the browser.

(I'm just brainstorming; if anyone thinks this is interesting enough to discuss further, please bump replies to a new thread.)

So just FYI, you can already _effectively_ do this on Chrome.  Call

vs = gl.createShader(gl.VERTEX_SHADER);
fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vs, vsrc);
gl.shaderSource(fs, vsrc);
p = gl.createProgram();
gl.attachShader(p, vs);
gl.attachShader(p, fs);
setTimeout(checkResults, 1000);

function checkResults() {
  if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {

You can't know how long to set the timeout but you can make the entire thing effectively async. Certainly a async API might be nice in the future. I'm just pointing out what's available now. Note: You probably need Chrome 20 to get the full effect.

On Wed, May 2, 2012 at 5:16 PM, Brandon Jones <tojiro@gmail.com> wrote:
It's worth noting that a great many desktop games will run through an "Optimizing shaders" step on first run or possibly during install. In that sense, the first-run experience for a WebGL app vs. a Desktop app wouldn't be that different.

Trying to cache compiled shaders server side strikes me as a bad idea anyway. You're denying the driver an opportunity to make the best choices for that particular hardware.

It's not, since it's caching it for the user's particular configuration; the browser can always discard it.

I'm not saying it's wrong to do it client-side, just that "server-side"--more likely something like IndexedDB, which is technically client-side--doesn't make this worse.

Glenn Maynard