I've been upgrading my PC this week in the Scirra office. Now I'm on Windows 8 with a new nVidia GeForce GTX 660 graphics card. I actually bought it based on some reports from the forum of some unusually high performance results with our WebGL performance test with top-end nVidia cards. So once everything was all set up, I ran the performance test once more.
The result blew my mind. I am not sure if something has gone wrong, or if the test is somehow incorrect. But with this setup and running in Chrome 25, Construct 2's WebGL renderer is faster than our previous native C++ DirectX 9 based engine - the one we developed for Construct Classic.
The WebGL test can reach 141,911 sprites on-screen. The Construct Classic test reaches 109,280. The WebGL result is almost 30% faster than native.
Try it for yourself: here's the WebGL performance test, and the same in native from Construct Classic (warning: EXE). My full setup is: Windows 8 RTM (64 bit), Intel Core i5-2500 @ 3.3GHz (quad core), 8 GB RAM, nVidia GeForce GTX 660 (driver v306.97). However, note I could not reproduce similar results on Windows 7 with a different AMD Radeon card (which I haven't tried on Windows 8 yet). Firefox 19 also came in slower than native, and of course IE doesn't support WebGL at all. So it seems likely many of you reading this will not be able to reproduce the same results; you will likely see WebGL coming in a few times less than the native test. But with the right setup, it seems possible that WebGL can overtake the native.
There's also the test with WebGL disabled, so it always renders with the Canvas 2D renderer. Chrome 25 scores 3821 on this one for me, making the WebGL result a whole 37 times faster in the same browser. Now I'm really glad we wrote a WebGL renderer!
How come the result is suddenly so much better? Unfortunately I don't know enough about the technical details to say for sure. I have a theory: it may be to do with moving WebGL's security checks in to hardware. The WebGL specification mandates that browsers must check all buffers are used correctly, and not accessed beyond the end or before the start. With the long buffers used for rendering large numbers of sprites, it could be a CPU-draining job to keep checking through the buffers to ensure they are used safely. However, some GPU manufacturers may now be able to do these checks on the GPU hardware, which frees the CPU from this security check entirely. Perhaps this is only enabled if your specific OS, driver and hardware setup allows it, otherwise the CPU check is still done. This could explain the vastly improved result on some systems. On the other hand, this is pretty much a guess and it may be something else entirely. I'd love it if any graphics engineers can explain this - email me at ashleytub@scirra.com or post a comment below and I'd be happy to do a followup blog post explaining further!
There is another important aspect of the result: our WebGL renderer is designed to be more efficient than our old C++ DirectX 9 engine from Construct Classic. When working in C++, it's easy to be lazier - C++ is super fast, so any code you write will be fast, right? When porting our engine to Javascript, we knew it was a few times slower than C++ in most benchmarks. This made us pay much closer attention to performance, as well as taking a smarter overall strategy. Classic's native engine computes the positions of vertices (the object corners) when rendering every single sprite. With Construct 2 we realised these positions are already calculated and cached for use in the collisions engine. This prevents Construct 2 from having to do any vertex calculations at all - they are simply copied out from what the collision engine calculated. So the Javascript engine has less work to do. We thought this might help slightly close the gap between Javascript and C++; perhaps it has a lot bigger effect than we thought!
So, as always, performance is complicated. Javascript is not faster than C++ - this is not what we have proved. Our Javascript engine does less, which helps explain how with just the right circumstances it can edge ahead of a less efficiently written C++ engine. If the C++ engine was written to do the same work as the Javascript one, it would likely be significantly faster again. However since we no longer officially maintain Classic this is unlikely. There's still an interesting lesson here: using a "fast" language like C++ does not guarantee better performance than a "slow" language like Javascript. A smart approach to the problem can make up the difference. This also suggests there may be other native engines out there which could be beaten by a more cleverly written Javascript/WebGL renderer, because the native programmers were lazier! This also bodes well for the future of HTML5 games on mobile, which may be able to actually reach the same benchmark results as native engines (or more!).
I really hope this is not some technical fault or bug that I'm misinterpreting, and if so I will be quite embarrassed about spouting such a load of rubbish. On the other hand, if this is a real result, it's a pretty fascinating one. Most of the time you hear people wondering exactly how much slower an app will be once ported to HTML5 from native. How often do you hear that it ended up faster?