phoboslab / Ejecta

A Fast, Open Source JavaScript, Canvas & Audio Implementation for iOS
2.81k stars 322 forks source link

Updating WebGL texture performance #360

Open weepy opened 10 years ago

weepy commented 10 years ago

I'm finding that on the device, updating a [large] WebGL texture can cause the UI to block for about a second. It's about a millisecond on my Macbook/Chrome. Does it make sense for such a large discrepancy ?

FYI I'm calling PIXI.updateWebGLTexture.

phoboslab commented 10 years ago

In Ejecta, all images (JPG, PNG) and all Canvases are internally represented as RGBA with premultiplied alpha. If you hand over a 2D Canvas as a texture to WebGL, Ejecta may have to un-premultiply this Canvas. This is done on the CPU and probably quite slow for large textures (source).

Try to enable WebGL's UNPACK_PREMULTIPLY_ALPHA_WEBGL mode and see if it makes a difference.

weepy commented 10 years ago

Ah that makes a lot of sense. I'll give that a go. Is that flag just unlocking a faster way of doing the same?

phoboslab commented 10 years ago

That flag instructs WebGL to load textures as RGBA with premultiplied alpha - which happens to be Ejecta's internal format for Images and Canvas2D, so there's no conversion needed when handing these over to WebGL.

Uploading a Canvas2D as a texture in WebGL still causes Ejecta to get the Canvas' pixel data (using glReadPixels()) and creating a new texture with it, which is expensive.

We can't just share the Canvas2D FBO with WebGL, as the Canvas2D may be re-used for something else. Maybe there's a smarter way to handle this, but it's complicated enough as it is.

I would advise you to use Canvas2D for 2D stuff.

weepy commented 10 years ago

Hey thanks for the in depth explanation. I'll give the flag a go to see how it goes, but I think you're right that Canvas 2D is probably the best way to go. I was mostly seduced by the pixel shading filters that you can do with WebGL, but I can do without these for now.

Canvas2D also affords some nice optimisations by only updating stuff that changes which is useful for me.

On Sat, Mar 15, 2014 at 8:26 PM, Dominic Szablewski < notifications@github.com> wrote:

That flag instructs WebGL to load textures as RGBA with premultiplied alpha - which happens to be Ejecta's internal format for Images and Canvas2D, so there's no conversion needed when handing these over to WebGL.

Uploading a Canvas2D as a texture in WebGL still causes Ejecta to get the Canvas' pixel data (using glReadPixels()) and creating a new texture with it, which is expensive.

We can't just share the Canvas2D FBO with WebGL, as the Canvas2D may be re-used for something else. Maybe there's a smarter way to handle this, but it's complicated enough as it is.

I would advise you to use Canvas2D for 2D stuff.

Reply to this email directly or view it on GitHubhttps://github.com/phoboslab/Ejecta/issues/360#issuecomment-37737020 .

phoboslab commented 10 years ago

I just realized that we could use glCopyTexImage2D to copy the canvas into a new texture for WebGL if there's no further processing needed. This should be faster than getting pixel data using glReadPixels and re-uploading it. I'll try that sometime.

weepy commented 10 years ago

I had a look - it seems that PIXI is already using that mode :

PIXI.createWebGLTexture = function(texture, gl)  {
   ...
   gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
   ....
}
weepy commented 10 years ago

We're finding that like for like WebGL is much faster than Canvas for our purposed, except for the canvas => texture conversion. I wanted to try out glCopyTexImage2D - wondering if this is something I can try easily (or not?)

Thanks

On Sun, Mar 16, 2014 at 3:45 PM, Dominic Szablewski < notifications@github.com> wrote:

I just realized that we could use glCopyTexImage2D to copy the canvas into a new texture for WebGL if there's no further processing needed. This should be faster than getting pixel data using glReadPixels and re-uploading it. I'll try that sometime.

Reply to this email directly or view it on GitHubhttps://github.com/phoboslab/Ejecta/issues/360#issuecomment-37760449 .