Jump to content

Upload images to GPU in a web worker


royibernthal
 Share

Recommended Posts

uploading is actually two parts:

1) decypher PNG ro RGBA

2) upload to GPU

second task is effectively async, but first one is pain. And pixi-v5 will use new html5 feature called "window.createImageBitmap" that is available in some of browsers.

You can google it yourself and use it for all the images you loaded, just swap "baseTexture.source" to the ImageBitmap of that source asynchronously.

Link to comment
Share on other sites

window.createImageBitmap looks great but it's still widely unsupported so it can't be used in production.

 

Is it possible to simply create a web worker and use prepare from within it or doesn't it work like that?

 

If not:

1) Assuming this could work for client-side as well I guess this lib could be helpful? https://github.com/niegowski/node-pngjs

2) How? Is there any lib that simplifies  the process, or perhaps some functionality that PIXI exposes?

Link to comment
Share on other sites

Unfortunately, the only thing that can be passed to a web worker is ... wait for it... IMAGEBITMAP.

No, browser pnglib is much faster than js, and createImageBitmap has exactly that purpose - call browser pnglib in async mode. I treid webworkers with CRN format, which is better for png for such purposes, and it was horrible.

Link to comment
Share on other sites

Well since you can't have a WebGL context in a WebWorker at all, there is no way to upload from the webworker. Firefox has offscreen webgl support, but no one else AFAIK (source: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/transferControlToOffscreen).

That being said, some browsers do support a way to do the expensive part of uploading, the decoding, in a webworker. The support for doing this is much higher than having a WebGL context in a worker (source: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap).

Your options are:

  • Use a non-existant API to upload from a worker
  • Use a not widely supported API to do decoding in a worker
  • Use the prepare plugin on a loading screen so when it freezes, it is OK.

I'd go with option 3, until we build support for worker decoding in v5. At that point we would be doing feature detection and using this feature if we can, and not using it if we can't.

Link to comment
Share on other sites

  • 4 months later...
On 6/29/2017 at 12:03 PM, ivan.popelyshev said:

You can google it yourself and use it for all the images you loaded, just swap "baseTexture.source" to the ImageBitmap of that source asynchronously.

I don't understand. If you're changing baseTexture.source, wouldn't the image have already been loaded using the normal pipeline?

All I want is a fromImage() that detects window.createImageBitmap and uses that instead, but I can't seem to make it work.

Can you provide an example?

 

Link to comment
Share on other sites

oh, that thing..

We are going to add it to v5. https://github.com/pixijs/pixi.js/blob/next/src/core/textures/resources/ImageResource.js#L49

You can either dig into pixi sources and hack `fromImage` that it uses createImageBitmap, then pass it as `source` to baseTexture, either wait for next release of pixi-v5 month or two.

Link to comment
Share on other sites

4 hours ago, ivan.popelyshev said:

Either you can show me your code and i'll try to fix it :)

https://gist.github.com/anonymous/c4cd1e33446036d263ccf80cfc43f7b3

Also tried setting source / scope to imageBitmap inside the promise.

Textures load fine, however everything is the same as before (huge stutters in fps when loading). Which leads me to believe thats it's not really doing anything. I'm definitely missing something here.

Link to comment
Share on other sites

1 hour ago, ivan.popelyshev said:

You call sourceLoaded before you set that source, I believe line 55 doesnt need to be called in case of createImageBitmap, at all. Move it to 69.

I did but it still needs hasLoaded to true and its dimensions calculated. BaseTexture.update() needs a change as well.

So I ended up with this ugly, ugly hack https://gist.github.com/anonymous/d01963a44c523dc04b21bfd7037081b6

Main thread hang when loading is reduced from 900-1000 ms to 500-600 ms.

Kinda anticlimactic I guess. I thought ImageBitmap would completely eliminate it :P

 

Link to comment
Share on other sites

> BaseTexture.update() needs a change as well.

Something like that , yes. When I experimented with createImageBitmap i changed whole BaseTexture.

You have to make sure that https://github.com/pixijs/pixi.js/blob/dev/src/core/renderers/webgl/TextureManager.js#L129 gets called when source is ImageBitmap. If its not , then you missed somethign.

Link to comment
Share on other sites

11 minutes ago, ivan.popelyshev said:

You have to make sure that https://github.com/pixijs/pixi.js/blob/dev/src/core/renderers/webgl/TextureManager.js#L129 gets called when source is ImageBitmap. If its not , then you missed somethign.

I can confirm that when using my code, an ImageBitmap is passed to glTexture.upload(). Without my code I'm getting an <img> dom element. Is that correct?

If this is indeed a 2x improvement in time spent loading (minus the network) then it should be backported to v4 - by someone who knows what they're doing, not me :D. It's only a few lines of code.

Thanks for all the help ivan.popelyshev !

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...