How to run Electron JS in Software Rendering Headless

Mohamed Mansour
2 min readOct 24, 2017

--

As some of you know, I am working at Microsoft in AI and Research. In my previous project, we wanted a way to take realistic screenshots of 3D glTF 2.0 models in scale in the cloud in a headless way.

What I propose here is a pretty cool hack, that works today in our production for testing. I thought it would be nice to share the technique I used here with Electron to help others who require server side webgl canvas screenshot capturing on the cloud.

The requirements

  • Must use the exact same renderer we use on the web, to stay consistent in the way it looks on everyone's browser.
  • Must be fast, since we are converting half a million of glTF 2.0 models that we need to test. And we are placing it our real-time processing pipeline.
  • Must be cost efficient. GPU compute is expensive, CPU compute is significantly cheaper (10x cheaper)
  • Must run on the Cloud, Azure Functions, Web App, or Virtual Machines.

What was tried

Most of you will quickly point out to use Selenium. Yes, that is great for integration and functional testing, but unfortunately it is slow. Running single page test would take around a minute. And it requires a full scale Virtual Machine to launch a browser, it is definitely not headless.

Many of you might say what is wrong with PhantomJS? PhantomJS does not allow you to test WebGL

How about the new Chromium Headless initiative by Google? It is currently not supported, but it would be very easy to do so, perhaps in the future we can switch to it.

Finally, we looked into Electron JS, since it uses Node and Chromium.

How it works

The problem with Electron, is that it uses opengl libraries which require a GPU. When I used to be a committer at Google Chrome, I learned that Google acquired a company, SwiftShader long time ago to supply Chrome with Software Rendering.

SwiftShader is a high-performance CPU-based implementation of the OpenGL ES and Direct3D 9 graphics APIs12. Its goal is to provide hardware independence for advanced 3D graphics.

Download or build the library from https://github.com/google/swiftshader. The prebuilt libraries are found in https://goo.gl/5MOcdb.

And just replace the ANGLE implementation with SwiftShader by overwriting (yes this way) libegl.dll and libglesv2.dll. You could write a post install git script hook:

“postinstall”: “xcopy /y ..\\lib\\* node_modules\\electron\\dist\\”

Now to force Electron in software mode in the cloud, Chrome blacklisted GPUs from running. You cannot run it on Azure, AWS, Google Cloud. so you need to disable that by doing the following:

const { app } = require(‘electron’)
app.commandLine.appendSwitch(‘ — ignore-gpu-blacklist’)

To not render the Electron window, you just hide it when constructing it:

new BrowserWindow({ width: 1280, height: 800, show: false })

That is the hack!

Conclusion

If you want 3D CPU WebGL software rendering, this hack works great. Make sure you enforce WebGL1 as well.

Hopefully this hack would help others.

--

--

Mohamed Mansour

I’m a hacker, gamer, health nut, adventurer, and guy who loves art. Currently a Software Engineer working at Microsoft