shlajin Posted November 1, 2018 Share Posted November 1, 2018 Hey there! I'm developing an electron app, which will load shit tons of SVG files and play them as animations. The process of decoding SVG -> PIXI.Texture is pretty fast, however, with 1000 SVGs it takes some time to process... which makes sense. What I'd like to do is to keep the decoding outside of main thread, so user can interact with the system while images are loaded. Since I'm using electron my first attempt was to spawn/fork a sub process and it failed dramatically, because only JSON-encoded data can be exchanged between them. Bummer. Another option is to use electron's protocol to communicate between browser windows (IPC), which doesn't work too, since for some reason IPC can exchange even binary data, but when it comes to built-in stuff like `new Image` it fails to do so. While, theoretically, I could encode images in something else and transfer them I understand that most likely I'll lose more on added overhead... and well, I'm trying to decode less on main thread, not add something more to do so. By searching through this forum I found few threads which discuss possibility of using service workers and, specifically, `createImageBitmap`. Since I'm using electron I can use both, and, luckily, it even supports SVG decoding! A very nice example: https://svg-zoom-demo.glitch.me/ However... I'm not quite sure what am I doing. In my perfect world, I'd use a "loading stub" as a texture for AnimatedSprite, and then, after my promise resolves, swap textures by simply changing them `animatedSprite.textures = newTextures`. How deep can I go there? Is it possible to prepare Pixi's `Texture` to do that off the main thread? Or if I rasterize SVGs with `createImageBitmap` (and scale it accordingly altogether) I will have a huge boost already? But if I do so, will it result in X2 VRAM usage (rasterized image + a new one created by PIXI)? The latter question may sound silly, but I'm concerned about VRAM since I load a lot of images into VRAM and have no ability to check its usage... Maybe somebody has some thoughts? Help is highly appreciated! Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 1, 2018 Share Posted November 1, 2018 The idea is to create a resource that upload asynchronously and has custom uploading logic. https://github.com/pixijs/pixi.js/wiki/v4-Gotchas#createimagebitmap There's pixi-heaven texture loading, there's no example for SVG, only big atlas thing, but I hope that you are good enough to change it to easy svg loading: https://github.com/gameofbombs/pixi-heaven/blob/master/src/hacks/BaseTexture.ts https://github.com/gameofbombs/pixi-heaven/blob/master/src/hacks/AtlasManager.ts https://github.com/gameofbombs/pixi-heaven/blob/master/src/superAtlas/SuperAtlas.ts#L215 It overrides pixi TextureManager updateTexture() method. Same technology (texture resources) exists in PIXI-V5, but i dont recommend to use that branch yet. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 1, 2018 Share Posted November 1, 2018 Yes, its still will use 2x memory like for all pixi apps, and maybe 3x somewhere. I didnt work on SVG specifically, but I loaded SWF files with this tech and put all vector shapes in atlases like in Mozilla Shumway project. That pixi fork will be released in christmas (probably in russian christmas) Quote Link to comment Share on other sites More sharing options...
Exca Posted November 2, 2018 Share Posted November 2, 2018 If you have already working subprocess that does the thing, why not pass the output as base64 data inside a json if json is the only available transfer method? That way you could just create the basetexture with image that has src as something like "data:image/png;base64, datahere". Quote Link to comment Share on other sites More sharing options...
shlajin Posted November 2, 2018 Author Share Posted November 2, 2018 1 hour ago, Exca said: f you have already working subprocess that does the thing, why not pass the output as base64 data inside a json if json is the only available transfer method? That way you could just create the basetexture with image that has src as something like "data:image/png;base64, datahere". Resource loading happens asynchronously anyway, and since I have SVG I already use `data:xml/svg ...` as `image.src`, so I don't think I can win anything here... 14 hours ago, ivan.popelyshev said: There's pixi-heaven texture loading, there's no example for SVG, only big atlas thing, but I hope that you are good enough to change it to easy svg loading: I've read through the SuperAtlas code and frankly, I don't understand how that can help ? either I don't get something, or I'm bad at explaining my problem... by any chance, is there any SuperAtlas usage example with regular JPG/PNG? I don't think it matters what type of image format is used, the non-blocking way of preparing images do... Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 2, 2018 Share Posted November 2, 2018 The idea is to customize your uploading process, like here: https://github.com/pixijs/pixi.js/blob/next/packages/core/src/textures/resources/ImageResource.js#L156 However its pixi-v5, and you cant use it because there are bugs in new renderer. pixi-heaven has the same architecture and SuperAtlas is example of usage. I'm sorry that I do not have other examples for v4. Here is snippet from another project: https://pastebin.com/LAKjnJdL , different classes, same architecture, I'm changing the way my texture loads. If you don't understand that way, try hacking pixi TextureManager manually and then you'll get it. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 2, 2018 Share Posted November 2, 2018 You asked the good question: how deep it can possibly go. I show you bleeding edge :) Try porting https://github.com/pixijs/pixi.js/blob/next/packages/core/src/textures/resources/ImageResource.js on top of https://github.com/gameofbombs/pixi-heaven/blob/master/src/base/atlas/TextureResource.ts , using superatlas as an example of interface usage. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 2, 2018 Share Posted November 2, 2018 More info: https://github.com/pixijs/pixi.js/issues?utf8=✓&q=is%3Aissue+createImageBitmap Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted November 2, 2018 Share Posted November 2, 2018 Also, if you didnt look at "gotchas" link i sent, it has that dirty snippet for SVG: https://gist.github.com/anonymous/d01963a44c523dc04b21bfd7037081b6 ^^^ Its possible that solves your problem completely Quote Link to comment Share on other sites More sharing options...
shlajin Posted November 5, 2018 Author Share Posted November 5, 2018 Yeah, I did look at it, but it feels like it may bring just some of the work behind the main thread, hence the original question. Thank you for your help – frankly, at this point I don't have stuff setup yet, so I can't test. My idea was to start the "right way" from the scratch, but apparently there's no single silver bullet here. So, I'll continue with "silly" and straightforward way for now and then try to tune that with `createImageBitmap` and report back with results in case anyone else is wondering or encounter the same issue ... and, well, maybe continue discussion if results would not be as good as I aim them to be. Thanks again! Quote Link to comment Share on other sites More sharing options...
shlajin Posted November 12, 2018 Author Share Posted November 12, 2018 So, I played a bit and got to this point (it'll take a bit to load images): https://codepen.io/shlajin-the-encoder/pen/aQBvjo I'm not sure why, but in my chrome browser's `createImageBitmap` behaves way better than inside an electron app – I can tell the difference in browser, but I cannot inside electron. Maybe it's something to do with chromium versions – chrome is 70, while latest electron has somewhat like 68/69 (it's in beta and different pieces give different info...) Nonetheless, even in chrome I still feel a noticeable lag which I'm trying to tackle. Is it any close to the bleeding edge or I can do something else to fix it? ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
xerver Posted November 12, 2018 Share Posted November 12, 2018 I would build the images on a separate thread and write them to disk, then the main thread loads them from disk. That way next time you launch you don't need to convert them again, just load the already converted files from disk. If possible, you can even do this at build time and ship the images in the built format. Quote Link to comment Share on other sites More sharing options...
shlajin Posted November 12, 2018 Author Share Posted November 12, 2018 > If possible, you can even do this at build time and ship the images in the built format. Unfortunately, it's not possible since I'm going to re-size images a lot (from large ones to small ones) and I need to have them as crispy as I possibly can, so vector -> raster is a way to go. > I would build the images on a separate thread and write them to disk, then the main thread loads them from disk. This sounds like a great idea to me, thanks! But at which point will it gain performance? In which format should I save them – png or there's some more "raw" format I can go with? Quote Link to comment Share on other sites More sharing options...
xerver Posted November 12, 2018 Share Posted November 12, 2018 You can store them as an uncompressed bitmap, but PNG is completely fine. The decode time from PNG -> bitmap is usually OK. If you want to avoid that time you can store them as dds or something similar to get some compression, but skip the decoding step that the browser would have to perform. The performance benefit you get is just being able to skip your rasterization step. I bet that PNG -> bitmap by the browser is much faster than your SVG -> bitmap raster. Quote Link to comment Share on other sites More sharing options...
shlajin Posted November 12, 2018 Author Share Posted November 12, 2018 So, save files to .dds in the other friend and pick them via main thread... am I right that I'll still have to load them via `new Image().src="my_file.dds"` or is there any other method for this? Also, would highly appreciate if you could suggest some library to process svg -> dds Quote Link to comment Share on other sites More sharing options...
xerver Posted November 12, 2018 Share Posted November 12, 2018 Yeah the other process would write the files and the main process will pick them up. Pixi doesn't natively support dds, you will need to use a plugin (like pixi-compressed-textures). I have no recommendations for DDS serializers in JS, or rasterizers. Quote Link to comment Share on other sites More sharing options...
shlajin Posted November 12, 2018 Author Share Posted November 12, 2018 Got it, thanks once again! xerver 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.