Making your WebGL code more flexible

The August update for Internet Explorer 11 includes new capabilities to help web developers detect when their WebGL application might encounter performance problems due to underlying hardware, including support for the failIfMajorPerformanceCaveat flag and WEBGL_debug_renderer_info extension. These can be added to other best practices to make your WebGL code more adaptable to the hardware that it is running on.

WebGL strategies for addressing hardware diversity

Web developers know that the world where we live is a complex one. The diversity of operating systems, hardware and browsers that our code can run on is huge. For example, to have your code work across diverse hardware means creating adaptable layouts or using graceful degradation. For a WebGL developer this means designing your code to run on high-end hardware that can render millions of triangles, or on a low-end device where 1000 triangles is the limit.

To allow your 3D scene to run on a small device, you can use some of these strategies to address this diversity:

  • Remove visual enhancements like shadows or particles
  • Reduce texture resolution
  • Reduce object complexity by using level of details
  • Change the resolution of your canvas and use hardware scaling
  • Reduce shader complexity (fewer lights, etc…)

Here's how I handled these differences in the WorldMonger demo on the www.babylonjs.com site:

Full version of WorldMonger demo

Here's the full version, complete with shadows, reflection, refraction, and post-process effects. The following steps outline how I reduced the complexity to accommodate less powerful devices.

 

Step 1 – The post-process is disabled, particles are disabled, shadows are disabled, and the texture resolution is reduced for reflection and refraction

Step 1 – The post-process is disabled, particles are disabled, shadows are disabled, and the texture resolution is reduced for reflection and refraction

 

Step 2 – The hardware scaling is now 2x, meaning the canvas resolution is the screen resolution / 2

Step 2 – The hardware scaling is now 2x, meaning the canvas resolution is the screen resolution / 2

 

Step 3 – The hardware scaling is now 4x and texture resolution is reduced again for reflection and refraction

Step 3 – The hardware scaling is now 4x and texture resolution is reduced again for reflection and refraction

 

To be able to apply these strategies to reduce scene complexity, you must figure out if the current device is powerful enough or not. To do so, let’s see together different options you have.

Benchmarking

The obvious option is benchmarking. One way is to render some scenes and measure the frames per second on a specific hardware to judge the overall performance. You can get more detail in an article I wrote about how to measure performance:

https://blogs.msdn.com/b/eternalcoding/archive/2013/05/21/benchmarking-a-html5-game-html5-potatoes-gaming-bench.aspx

The main idea in measuring performance is to compute the delta in time between two frames. If the delta time is lower than a given threshold, then you can consider taking actions to reduce your overall rendering complexity.

failIfMajorPerformanceCaveat

Because of the direct access to the GPU allowed by WebGL, browsers must ensure that running your code will not cause a major security issue. For some specific drivers that are not perfectly secure, the browser can prevent hardware acceleration in order to prevent security issues.

To enforce this, IE has a block-list of drivers that are not safe for use with hardware acceleration. On these devices, WebGL will software rendering instead, resulting in a slower but safer experience.

In the August update of Internet Explorer, we support a new flag that you can specify when getting your WebGL context: failIfMajorPerformanceCaveat.

The Khronos specification defines how this attribute works:

Context creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than that of a native application making equivalent OpenGL calls.

When a context is requested on a computer with a block-listed driver, the failIfMajorPerformanceCaveat flag prevents IE from returning a software context, and instead returns no context.

To use it you just have to add it as an option to the getContext function:

 var canvas = document.getElementById('renderCanvas');
 var context = canvas.getContext('webgl', 
    { 
         failIfMajorPerformanceCaveat: true 
    });

Using this attribute, you can know that the current device isn't powerful or secure enough to run hardware accelerated 3D rendering. Then you can decide to use the software renderer, or if you prefer, let the user know their computer or graphics card aren't supported.

Identifying the renderer

Finally, in conjunction with the failIfMajorPerformanceCaveat attribute, IE also now supports the WEBGL_debug_renderer_info extension (Khronos specification).

The WEBGL_debug_renderer_info extension is a tool to get the renderer and vendor strings for the underlying graphics driver:

 var gl = document.createElement('renderCanvas').getContext('experimental-webgl');
 var extension = gl.getExtension('WEBGL_debug_renderer_info');
 if (extension != undefined) {
     var renderer = gl.getParameter(extension.UNMASKED_RENDERER_WEBGL);
     console.log('UNMASKED_RENDERER_WEBGL = ' + renderer);
     var vendor = gl.getParameter(extension.UNMASKED_VENDOR_WEBGL);
     console.log('UNMASKED_VENDOR_WEBGL = ' + vendor);
 }

For instance, here is the result I get on one of my computers:

 UNMASKED_RENDERER_WEBGL = NVIDIA GeForce GTX 750 Series
UNMASKED_VENDOR_WEBGL = Microsoft

You can use this information to gather useful information for debugging; for example, if you detect using benchmarking that your code is running slowly, then you will be able to gather data for reproducing the issue.

But beware: Like user agent sniffing, using this feature to create a GPU “approved list” could result in a lot of other devices not being able to experience the best your app has to offer. Instead, I recommend targeting the broader audience by using it to only block specific devices that you've identified to perform poorly with your app.

Conclusion

Being able to create WebGL experiences that works seamlessly in all kinds of configurations is extremely hard. However, you can use these tools to have more control over the device and give more feedback to your users.

We will be sharing more details about WebGL support in the latest version of IE11 soon. In the meantime, we look forward to your feedback @IEDevChat or on Connect.

— David Catuhe, Principal Program Manager, Internet Explorer