Search Unity

[Workaround/Hack] Get large WebGL builds working on that damned IE!

Discussion in 'Web' started by dark_end, Jul 22, 2015.

  1. dark_end

    dark_end

    Joined:
    Jun 24, 2015
    Posts:
    5
    IE's lack of Math.fround() makes it necessary to somehow remove the calls from the asm.js code.

    If you build a WebGL from Unity, the generated HTML file will contain a script that downloads the whole asm.js data file via XmlHttpRequest, then runs a regex on that giant blob and comments out all occurences of the Math.fround() call. After thats done, the rewritten Javascript ("almost asm") code gets inserted into the DOM.

    IE - everyones favorite browser - just fails silently on this approach if the file is too large or not enough memory can be reserved for that operation. So the user will be stuck on the loading screen forever.

    If you have this issue and your client demands that the WebGL content has to run in IE, just do the following:
    • Go to the <script> tag at the bottom of the generated HTML file of your webgl build.
    • Add the following line of code at the start of the script tag:
      if(!Math.fround) Math.fround = function(x) { return x; }
    • The whole else branch is now useless and you can remove it
    • Install an i7 CPU and a S***load of RAM into your clients computer without him noticing
    • Enjoy unoptimized, low-fps, almost-browser crashing Unity WebGL experience in the damn IE
    Obviously this is only a quick&dirty fix, but you can use this as an argument to convince your client to abandon Internet Explorer for good. Because it has S***ty performance compared to Firefox.

    Why does it hang after initialization and whenever some heavy geometry calculations are done?
    Because the code is no longer asm.js compliant (i think) and the whole application will work with double precision instead of single precision floats. Also, the need to use a js function call adds a lot of overhead.

    Do not use this for things where your life depends on the single precision results, or basically anything thats too complex.

    Instead of just returning x, you could also return new Float32Array([x])[0] but that will heavily decrease your performance even further (it is very noticeable) due to even more overhead.

    -------------

    Benchmark IE11 - 20 MB main js file, 3 MB .mem file and 20 MB .data file
    - Out-of-the-box workaround for missing Math.fround() ==> Unusable
    - return x ==> ~25 fps on almost empty scene, drops to 10 fps if more objects get added dynamically
    - return new Float32Array([x])[0] ==> ~10fps on almost empty scene, becomes unusable if more gets added


    ------------

    Another solution would be to deploy 2 different releases and use browser detection to load the supported one:
    - The "standards compliant" version you get from building your project.
    - The "quirks mode" version where you manually "optimized out" all Math.fround() calls


    The advantage of this would be that the performance would be a bit better, since no polyfill method overhead.

    The disadvantage would be that you have to deal with 2 different releases, where you have to "optimize out" the code on every build. And ofc. the issue of having to deal with double the amount of files and wasted space on your webserver.
     
    Last edited: Jul 22, 2015
    mgear likes this.
  2. OOLE

    OOLE

    Joined:
    May 13, 2015
    Posts:
    14
    Hi,

    thanks for sharing this workaround! My WebGL application is running in IE11 by using this fix or at least the memory exception is shown less often.

    Can you explain what "optimized out all Math.fround() calls" means? I noticed that there are some more Math.fround() calls in the "main.js" (the 20MB file). But how should i replace them or "optimize out"?

    Can you give me a hint, please?

    Thanks a lot!
     
  3. dark_end

    dark_end

    Joined:
    Jun 24, 2015
    Posts:
    5
    I dont know either why the unity devs are calling it like this. This is what gets logged to the console if you run a normal WebGL build on IE. Basically all you need to do is Find & Replace all "Math.fround(x)" calls with "x" in the .js files, just like that piece of code did you just made obsolete with the polyfill. (Note that "x" could be anything in the generated files)

    But be aware that you should not do this for your production builds that will run fine on other webbrowsers, because you will lose all the performance advantages of asm.js - so you need 2 different deployments (IE-special and non-IE-normal).
     
  4. OOLE

    OOLE

    Joined:
    May 13, 2015
    Posts:
    14
    Thanks for the explanation!

    Because i have to get the WebGL working in IE 11 as good as possible the solution of hosting two different js-files on the server seems to be the best way for me.

    For generating the 'optimzed' file for IE11 i have made a little webapplication (and attached it). So that i can copy the big generated js-file into the folder of this webapplication, call the website and get the new code for IE. Besides of 'optimizing out' the math.fround calls it also removes the "Web Audio API is not supported in this browser"-warning which pops up at the beginning.

    If someone has more ideas how to get WebGL run better in IE or remove more code from the generated js-file i would be very interested.
     

    Attached Files:

    PrisedRabbit likes this.