Jump to content

Bad iOS cache managment for cubeTexture loading


Vousk-prod.
 Share

Recommended Posts

Hey everyone !

The brand new iOS 10 update fracking sucks to load BJS cube textures.

I've already had noticed this problem several month ago (on iOS 9) but it happened only very occasionnaly (and pretty randomly). But now, since iOS 10, I don't know what Apple has changed but the bug is happening at least 9 times out of 10, in every mobile browser on iOS.

What the bug is exactly ? When a cube texture is loaded, the cascadeLoad call in Engine.createCubeTexture bugs in the callback for-loop :

for (var index = 0; index < faces.length; index++) {
   _this._workingContext.drawImage(imgs[index], 0, 0, imgs[index].width, imgs[index].height, 0, 0, width, height);
   gl.texImage2D(faces[index], 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, _this._workingCanvas);
}

The code stops in one of the loops claiming that imgs[index] is undefined. The faulty loop iteration number is randomly changing, sometimes the third, sometimes the fourth, sometimes another one... it probably depends how quick the cube images files are loaded.

The bug happens retroactively from BJS 2.5 to (at least) BJS 2.1.

And now, the cherry on the cake: the bug never occur if the browser is in private browsing mode. As if the caching process of the images is responsible of a kind of loading delay or something like that...

Link to comment
Share on other sites

Nope, I absolutly don't know. Unfortunatly I don't fully understand the blob and indexedDB process (that was @davrous work, isn't it ?). It may be related to caching stuff.

Strangely the problem doesn't occur with other textures loadings. Is your image loading mechanism different for cube textures ? It's as if the for loop for the 6 images can run before the 6 blob images are fully loaded in memory. Maybe the iOS caching system takes too much time and the cascadeLoad is called without some enough robust "images are really ready" test. I very often noticed that cube texture loading is particularly time consuming in the whole network calls.

Link to comment
Share on other sites

Ah ah :D of course, but only very provisional...

The 3d data and textures caching system is one of the major feature of BJS. When dealing with Web and 3D, the data are so heavy that indexedDB is a powerful friend, and native BJS compliance with that is just true power compared to other libs (like for instance one.js, two.js, or any other :P). It's probably easy to detect iOS and disable cache for those devices, but in real life I'm not sure this is a good policy (even if I don't really like iOS devices, I must admit it's a big part of global mobile fleet...)

 

Link to comment
Share on other sites

Erm it doesn't work... :blink:

If I turn engine caching off before creating the new CubeTexture and then turn it on again after, the bug still appear. It only disappear if I turn caching off when I create the engine. Are you sure the enableOfflineSupport  flag is not checked only once at the begining ?

Link to comment
Share on other sites

The problem is that when accessing the imgs array, imgs._internalCount is 6, but the real imgs length is only 3 (for instance).

If we look at the partialLoad method (called by the cascadeLoad used in cube texture creation), everything looks fine and logical :

var partialLoad = function (url, index, loadedImages, scene, onfinish) {
        var img;
        var onload = function () {
            loadedImages[index] = img;
            loadedImages._internalCount++;
            scene._removePendingData(img);
            if (loadedImages._internalCount === 6) {
                onfinish(loadedImages);
            }
        };
        var onerror = function () {
            scene._removePendingData(img);
        };
        img = BABYLON.Tools.LoadImage(url, onload, onerror, scene.database);
        scene._addPendingData(img);
    };

So the problem certainly comes from something processed differently in iOS in the Tools.LoadImage function, and most probably related to blob creation. I don't understand all the process in there but maybe the onload callback is called for an image before the blob is really accessible (in iOS) , or something like that...

FYI I didn't see any engine.enableOfflineSupport reference in the whole cube texture creation process, it's only checked sooner, when creating the database object used in LoadImage, that's why I can't call it around my cube texture creations.

 

Link to comment
Share on other sites

Also strange, for what I understand, engine.enableOfflineSupport seems to be only used for mesh loading (and mesh's related textures), but not used at all for cube textures dynamically created later (but I can be wrong in my source code interpretation). So the fact I deactivate offlineSupport solves the blob loading image process is just a (benefic) side effect...

Link to comment
Share on other sites

Hi! Thanks for the report. iOS/Safari Mobile is well known for shipping crap on the IndexedDB implementation... :-(

 If I understand correctly, this means that any scene using offline & containing a cube texture would fails on iOS 10?

This is weird as we're using it on our Sponza demo: http://www.babylonjs.com/demos/sponza and it works well on my iPhone 6s / iOS 10.

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...