Rendering gets stuck when loading a new tile from a local file

Hi,

I'm willing to implement the full-resolution Blue Marble Imagery (https://visibleearth.nasa.gov/view.php?id=74167).

I have generated a local tileset which I call with

var viewer = new Cesium.Viewer('cesiumContainer', {
    imageryProvider : Cesium.createTileMapServiceImageryProvider({
        url : Cesium.buildModuleUrl('Assets/Textures/BlueMarble'),
    tileWidth: 2700,
    tileHeight: 2700
    }),
}

There are 3 levels, each tile is 2700 x 2700 px in jpg.

Each time a new tile is loading, the rendering stops until it is fully loaded, that's about 800 ms. I believe there is no such limitation when using WMS tiles (a refinement does not block rendering).

Is there any way to avoid that and to keep rendering while a new tile coming from a local file is loading?

Thank you.

Dorian
Cesium 1.50 with Chrome 69

Hey Dorian,

When you say rendering stops, do you mean the render loop blocks (so you can’t move/interact with the viewer)? Or does the imagery flicker/disappear during that time? Either way, I think it isn’t expected behavior and something we might want to look at it.

My first guess is it might be that the tiles are too big. Can you try tiling it to tiles that are smaller? You could also try uploading your imagery to ion (https://cesium.com/ion/) and use its tiling just to compare performance. Let me know what you find out.

Hi,

Thanks for following up. I’m in the case where the render loop stops so that I can’t interact with the viewer. For sure, the tiles are quite big (2700 x 2700 px). Instead of reducing there size, I’d like to understand why this occurs, in order to achieve more robustness.

I tried to upload my imagery files on Ion, but as they are not natively georeferenced (8 JPG files), they don’t seem to be compatible with Ion.

I uploaded my assets here (https://we.tl/t-8fIYJLWdhN), can you try on your side to see what’s happening?

Thanks for your help,

Dorian

Thanks for providing your tiles Dorian. I ran it locally in Sandcastle with this code:

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

imageryProvider : Cesium.createTileMapServiceImageryProvider({

    url : Cesium.buildModuleUrl('/Apps/SampleData/BlueMarble')

}),

baseLayerPicker : false,

geocoder : false

});

setTimeout(function(){

viewer.camera.flyTo({

    destination : Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0)

});

}, 6000);

viewer.extend(Cesium.viewerCesiumInspectorMixin);

``

It was easier to see the hiccup when the camera flies through. Were you doing something like that when you ran into this? It feels a lot less shorter than 800 ms but that could just be my machine.

The last line there also turns on the Cesium inspector, which lets you visualize which tiles are loaded (click “Terrain” and then “Show tile coordinates”) which might help.

I’m not sure at a glance what’s causing this. If you put a break point on ImageryProvider.js’s load image function with Chrome’s debugger:

And you can follow it see that it should all be asynchronous. The Resource.js’s fetchImage function might also be another good place to look.

If you find out any more please continue to update this thread. I hope this helps a bit.

Hi,

I’ve been profiling exactly what’s causing the hiccup, and the picture below tells that each time a new tile (2700 x 2700 px, 1 to 5 MB each) is loaded, the painting subroutine takes 40 to 100 ms of CPU and blocks the render loop.

I have checked that this calculation time is independant from the size of the image file (by reducing the JPEG quality), it is mainly related to the number of pixels of the image.

One solution would definitely be to load smaller tiles. But that shows that the process of tile loading is not fully asynchronous as it should be, right?

Any idea where to dig deeper?

Thank you,

Dorian.

Thanks for the detailed profiling report Dorian! This sounds like the browser itself is the bottleneck here. I found this Chrome issue about the speed of texImage2D:

https://bugs.chromium.org/p/chromium/issues/detail?id=180119

I think what’s happening is, WebGL calls execute in the same thread as JavaScript, so I think that’s why an expensive WebGL call freezes the context. So every time a new tile comes in, it’s drawing it to the screen that takes so long. Even if it’s just for loading, I think sometimes Cesium has to do extra steps, so for example here a texture has to be converted into a power of two texture so that’s an extra draw call:

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/Model.js#L2232

This is from the model class but I believe terrain/imagery work similarly.

A few months ago Chrome announced support for OffscreenCanvas as a way to render things off the main thread:

I’m not aware of any web libraries that use this yet though.