Loading hitch when loading large assets at runtime?

Example above will load a large texture (5.5 MB) from the Babylonjs texture library after a second. If you move the camera during the first second you can see when it hits the big hitch and freezes up for a period. In Chrome at least you may also see it complain in the console about a violation on the load handler.

This pause does not appear to be an issue with the actual network speed, since in Chrome we can throttle ourselves and the hitch is about the same duration each time. It instead seems to be CPU based and related to resolving the asset into the final scene upon completion of the download, which happens asynchronously in the background.

To the point: is it possible to mitigate this? Is there an alternate way to load an asset (a texture in my case) such that the entire process to get it into the scene is done asynchronously and doesn’t cause one large frame drop? In our own app we are trying to load lower quality textures first to get users into the app quicker, and then drop in the higher fidelity textures at runtime whenever they happen to finish downloading.

Thanks for any help.

You can load the texture async but it will not help. The hitch is caused by a WebGL call (to my best knowledge) which can’t be avoided. You can create your textures on startup however.

You can see here that you can move the camera without stuttering while the texture is downloading but the movement skips when the texture is created in the WebGL context.


I see. In the same playground, if we load in the 4.7 MB “./textures/specmap.png” instead, it seems to still be visible though a lot less problematic. Would the file format + file size be the deciding factors in how well WebGL handles the creation of the texture?

1 Like

JPG and PNG textures are transferred to the GPU in an uncompressed data format. Maybe the JPG decompression takes more time so the PNG seems to be faster. You might want to consider a compressed texture format which results in smaller data size (fewer data to upload to the GPU so faster) and are optimized for faster sampling on the GPU.



Just out of curiosity, what are your numbers?

similar for me, 67ms and 222ms. Could it be a power of 2 thing and not compression format?


I don’t know but I’ll give it a try now. :wink:

EDIT: as far as I know WebGL2 doesn’t care about the ^2 thing though

EDIT2: Yep!

While OpenGL 2.0 and later for the desktop offer full support for non-power-of-two (NPOT) textures


i just googled about it

found this thing

uploaded here as 2048x2048, to match the other
.textures/GatonaParkWalkway1_Panorama_4Kx2K.jpg at main · jeremy-coleman/textures · GitHub

oh shit, on first load i got a major stutter like the op using the non-power of 2 image.


the 12000 ms vs 220 ms is me just running it again, completely random.

the resized version runs at 35ms, but its a smaller file now also.

my changes

the original was 3840x1920 and I rescaled it using that online photo editor to 2048x2048 (the copy i uploaded to github) . This reduced the load time from 220 to 30

this article says square images load faster too. so maybe a double win
.Make better textures, optimising, 'power of two' and correct sizes : KatsBits TUTORIAL



Here are my numbers. Not a big difference though :slight_smile: I mean 8192 vs 8191


Can you try it please?

I couldn’t go below 100 ms with this example. My Omniverse has failed lol !
i9 5Ghz/RTX 3080Ti, wtf… What are your specs? You don’t need to specify the PSU I know you don’t even have one :stuck_out_tongue:

5950x / 3080ti

1 Like

Intel has failed :smiley:

Actually all my numbers from your PG are higher by ~30-40%…

Hey guys!

i9 5Ghz CPU for sale LOL

1 Like

some highlights:

by far power of 2 is faster

png vs jpg is unclear, but likely not as significant as other factors.

Comparing the 5mb 2048x4096 rectangle vs 2048x2048 square, the square loaded 18ms faster with the same data size at 68ms vs the rectangle 86ms. This supports the articles claim that squares are faster.

data size reduction to speed is logarithmic
16mb reduction to 5mb yields reduction from 135ms to 85ms. roughly 2:1 for this case.
5mb reduction to 1mb yields reduction from 65ms to 35ms. roughly 2.5:1 for this case.

1 Like

It seems to be very HW dependent because on my PC:
8192px 750ms
8191px 800ms
so I can say there is no difference for me. I did one more test with the JPG and:

but also, those textures are huge. we’re definitely limited by chrome. chrome has to check the other frames first so it can be sure we dont miss any ads. also some jitter helps prevent leet hacks, so its not all terrible

    //const res = await fetch("https://playgrounds.babylonjs.xyz/textures/aerial_rocks_02_diff_8192x8192.jpg") // ~750 ms //700-1700
    //const res = await fetch("https://playgrounds.babylonjs.xyz/textures/aerial_rocks_02_diff_8192x8192.png") // ~800 ms //1200
    //const res = await fetch("https://playgrounds.babylonjs.xyz/textures/aerial_rocks_02_diff_8191x8191.jpg") // ~ 800 ms //580
     const res = await fetch("https://playgrounds.babylonjs.xyz/textures/aerial_rocks_02_diff_8191x8191.png") // ~1500 ms //1200

for those huge textures, it’d be worth putting in a worker. can’t really do that so easily in a playground. doable though. we could actually just put an iframe in the playground and wrap all the js code into a base64 and put it as the src, then use esm imports and module workers.

this slide from the latest khronos youtube video shows how to do it in webgpu

the main power being that createImageBitMap is available in workers


:white_flag: I give up ROFL

EDIT: Actually I can’t make good jokes in English and maybe sometimes my reactions doesn’t reflect what I really want to say :smiley: but I definitely like these little jokes LOL

Yes, its fun to poke the bear sometimes :cowboy_hat_face:

1 Like