Hacker News new | ask | show | jobs
by lispit 3884 days ago
Original game:

An entire game, written mostly in C for a (comparatively) extremely primitive CPU with a similarly primitive compiler. Performs all rendering in software, with tightly optimized x86 assembly targeted towards said extremely out of date architecture, and was the absolute bleeding edge of what was possible when it was released. On top of that, DOS was the target, which meant that a fair part of the codebase is dedicated to what programmers today would think of as an operating system, from device drivers to interrupt handlers to memory managers.

This:

A level renderer with none of the game logic, written in a higher level language that, nonetheless, has access to a much, much more sophisticated compiler and target hardware than the original game had, that offloads most of the rendering to the GPU anyway, whose author was never once required to think about optimizing anything because any computer made in the last decade could render such scenes in its sleep a thousand times over without so much as a snore.

I'm not at all trying to poo-poo the author here, but there is no meaningful comparison you can draw from this.

3 comments

I'm the author, no poo-poo-ing taken. You're completely right. The rendering code is shamelessly unoptimized indeed: doing frustum culling naively actually slows down the code because of the extra draw calls. I could probably get a boost in frame rate--by for instance memcpy-ing chunks into a dynamic buffer and keeping the single draw calls---although it already runs at 300 FPS on the integrated intel card of my laptop. So I'd rather add more features, testing and documentation than worry about perf just yet.
Thank you for not taking it that way. From-scratch recreations of games and renderers are always cool, and you're absolutely right to not obsess over the performance of a Doom level renderer in 2015. I just wanted to make it clear that this is not the right candidate for a "C vs. Rust" benchmark.
Not to mention that it's a completely different rendering algorithm that produces different scenes: this is a "true 3D" geometry converter, while the original Carmack code was a "2.5D" rasteriser. That's why original Doom couldn't look up or down and has only one "vanishing point", whereas you can clearly see non-parallel vertical features in the modern screenshots.

Edit: the original renderer is actually very readable, https://github.com/id-Software/DOOM/blob/77735c3ff0772609e9c...

I don't see a great scope for auto-vectorisation etc there. You could write a new 2.5D renderer which assumed its availability, but that would be not quite directly comparable.

Do you think it would be possible to write the original game in mostly safe Rust with no performance hit?
No perceptible performance hit on a modern machine? Absolutely. I'm sure you can run 100 copies of Doom simultaneously in Javascript or whatever.

No perceptible performance hit on a 486? Somehow, I don't think that the 486 is an especially important target for the LLVM or Rust developers (though such chips are used in embedded applications to this day).

But the real reason that the comparison makes no sense is that the bulk of the processing time (but not the bulk of the code, mind you) is spent in those tightly optimized assembly loops. Either you keep it as such and it's not really much of a battle between C and Rust any more, or you rewrite the critical sections in Rust and you'd lose as hard or more as if you wrote them in C.

Weirdly the i586 is the problematic one. 3, 4, 6, 7, and 8 all apparently work fine.

https://users.rust-lang.org/t/i586-support-illegal-hardware-...

That bug just looks like a glitch with ISA support in the generated code. It's trivially fixable I'm sure, and not really relevant to the subject of optimized assembly.
There would most definitely be a performance hit, but you would notice.
Even if the new code made itself amenable to those nice vector units in modern CPUs?