Tuesday, May 31, 2011

Followup to Doom on the Web

The Doom on the Web demo has been viewed over 35,000 times so far. Based on the responses, I'd like to clarify some things that I should have mentioned before (sorry for not doing so).

First off, I should have linked to the details page more clearly. It explains a bit about the demo, where it is currently known to work, etc.

Now, to the main issue: This demo is not a good benchmark of anything. The goal here was not to run a version of Doom with good performance, but to run DOOM itself, the original, with as few changes as possible, on the web. I made no effort to optimize the code, which was written and heavily optimized for a completely different architecture (it uses fixed-point arithmetic! :) I wasn't sure if it would be playable at all.

That is, the point of the demo is, "Doom can be run, with hardly any modifications, on the web." Showing that sounded like a cool thing to do, so I spent several evenings and a weekend or two on it.

As for frame rates, Doom caps them at 35 - you won't see it get any better than that, simply because of how the main loop works (and as mentioned before, I didn't try to improve it). It will also max out your CPU, even if it doesn't need to, for the same reasons. It might be possible to optimize this with some modifications to the Doom source code, but I didn't look into that. So, if you are seeing 35fps and 100% CPU, that doesn't mean your machine is actually working hard to generate it.

For example, I get close to 35fps on a slow 1.2GHz laptop. A modern machine would probably be able to get over 100fps with a proper main loop. And again, even this is not a fair measure of how fast Doom could be, if it were actually optimized for JavaScript. So please don't run this demo, be disappointed by the speed, and say "JavaScript is too slow, we need Flash/NaCl/Java/native apps" etc. The demo can't be used to conclude anything like that. Valid benchmarks (which this demo is not) show that JavaScript is quite fast, and getting faster more quickly than any other language - something that shouldn't be surprising, given that it probably has the most developer effort put into it, these days.

I hope the above explains what frame rates in the demo actually mean (that is, almost nothing). Now, aside from that, some people said the demo was very slow for them. I suspect that depends on the browser, as both Firefox and Safari play it very speedily even on older machines (as I mentioned earlier, my old laptop at 1.2GHz runs it well on FF7). On the other hand, Opera runs it slowly, while Chrome is unplayable (I reported the issue to them, and am doing my best to help figure it out). So, performance depends on the browser. That's disappointing, clearly, but that is another point of this demo - to push the limits, and hopefully to motivate JavaScript engine devs to fix whatever bugs are in the way, and be even faster and more awesome.

P.S. I apologize for the quality of sound in the demo. I never used any audio generating API before, and I still don't know what the numbers I am passing from Doom to the Audio Data API actually mean ;) I basically just hacked together something quickly, got it to the point it is in the demo, and stopped there. Someone that knows this stuff could probably make it sound right.

Monday, May 30, 2011

ammo.js: Bullet on the Web

We already had a demo of the Bullet physics engine in JavaScript a while ago. People asked for an easier way to use it, so I set up ammo.js, a separate project to port Bullet to the web.

The starting point is Bullet compiled to JavaScript using Emscripten, and the main challenge is to make a friendly API for JavaScript applications to use. See Issue #1 in that github repo, we are currently looking for ideas and help in doing this. Discussion also takes place on Emscripten's IRC channel (#emscripten on irc.mozilla.org).

Emscripten 1.2, Doom on the Web

Emscripten, the LLVM to JavaScript compiler, is now at version 1.2. The main updates in this release were to enable this demo of Doom on the Web - a playable version of the classic game Doom, compiled from C to JavaScript and rendering using Canvas.

The demo is known to work on Firefox and Safari. It works, but slowly, on Opera. I can't get it to run properly in Chrome due to a problem with V8. I have no idea if it runs on IE9, since I don't have a Windows machine, but since IE9 has a fast JS engine and supports canvas, it should (please let me know if you try it there). Edit: Here's a screencast of the demo running on Firefox Nightly if you can't run it yourself.

Highlights of Emscripten 1.2:
  • Many improvements to Emscripten's implementation of the SDL API in JavaScript, including support for color palettes (Doom uses a 256-color palette), input events (we translate normal web keyboard events into their SDL forms), and audio (for now, just using the Mozilla Audio Data API - it's the most straightforward API at this point. Patches are welcome for other ones).
  • Many improvements to the CHECK_* and CORRECT_* options, which are very important for generating optimized code using Emscripten. In particular, there is a new AUTO_OPTIMIZE option which will output a summary of which checks ran how any times, and how many of those checks failed, giving you a picture of which lines are important to be optimized, and which can be.
  • Some additional experimental work is ongoing about supporting OpenGL in WebGL. I don't know either OpenGL or WebGL very well, I'm learning as I go, and I'm not sure how feasible this project is. If you can help here, please do!
  • Various bug fixes. Thanks to all the people that submitted bug reports. In addition compiling Doom uncovered a few small bugs, for example we were not doing bit shifts on 64-bit integers properly.

Sunday, May 1, 2011

Emscripten 1.1!

Emscripten is an LLVM to JavaScript compiler, allowing you to run code written in C or C++ on the web. I released version 1.1 today, with the following updates:
  • A much improved Bullet demo - check it out! This version is much faster. The main differences are use of memory compression (see below), LLVM optimizations, and CubicVR.js for rendering.
  • QUANTUM_SIZE == 1, a.k.a memory compression. This is an advanced, and somewhat risky, optimization technique. I see speedups of around 25%, but take note, this must be used carefully. See the docs.
  • Dead function elimination tool: A Python script that scrubs an .ll file to remove unneeded functions. This is useful to reduce the size of the generated code and speed up compilation. Note though that if you want to compile a library, then this tool will remove functions that you probably want left in - it removes everything that cannot be reached by main(). The test runner now uses this by default.
  • Various performance improvements and bug fixes.