17 ms·
Rust-Doom: A Doom renderer in Rust, with no unsafe code
- estefan 11y agoWhat's the status of Rust these days? I can see it's hit 1.x, but in practice is it ready for production use? How comprehensive is the standard library, dependency management, etc.? From a brief glance through the examples it looks pretty functional... is it basically a systems-ish scala?
- nbaksalyar 11y agoIt's pretty stable at this point (1.x means that no backwards compatibility will be lost as in the past), and it's already used in production (e.g. Skylight [0] is written in Rust, as far as I know, and don't forget about Servo). Dependency management with Cargo is hands down one of the best out there, it just works. The standard library continues to expand, but there are also many other external libraries you can find on crates.io. > it looks pretty functional... is it basically a systems-ish scala? I think it's better to compare Rust to ML languages family (OCaml, F#, and so on), as it was clearly influenced by it. It has many features you can find in ML languages - pattern matching, ADTs (algebraic types that are enums in Rust), and many other similarities. Overall, the language feels very robust now, and I enjoy it much - it's a very decent replacement for C++, basically "C/C++ done right". [0] https://www.skylight.io/ https://www.skylight.io/
- estefan 11y agoOh cool, thanks for the summary. Maybe it's time I start to dabble... It'd be good to be able to deploy binaries without VMs/requiring a ton of dependencies to be preinstalled.
- nbaksalyar 11y agoRust doesn't require a VM or any prerequisites installed on a target system. In this regard it's comparable to Go (though I'm not sure that it's viable to statically compile everything into one binary, but technically it should be possible). Anyway, it compiles down to the machine code, so at most you'll need to have a bunch of libraries along with your executable file. Hopefully you'll have a lot of fun with learning! :) Oh, and almost forgot: Rust community is one of the best that I've seen, so feel free to ask any questions on http://users.rust-lang.org http://users.rust-lang.org - I'm sure there's a lot of people who'll be glad to help you.
- steveklabnik 11y agoSmall detail: most Rust programs do need glibc installed. Unless you've built with MUSL specifically.
- kibwen 11y agoTo elaborate, by default Rust programs are entirely statically linked (dynamic linking is available with a compiler flag), though with a single dynamic dependency on libc. This means you can compile ordinary Rust code into a single executable and run that executable on any machine with a compatible version of libc (which is fairly universally available, so not a problem in practice). If you want no dynamic dependencies whatsoever, then Rust supports linking to musl, which is an implementation of libc that's designed for static linking.
- MrBuddyCasino 11y agoIn case your're into Linux systems programming, we had a talk recently that we filmed. Youtube & Github links here: http://www.meetup.com/rust-munich/events/224140986/?comment_table_id=456845889&comment_table_name=event_comment#comments-tab http://www.meetup.com/rust-munich/events/224140986/?comment_...
- lmm 11y agoScala was also heavily ML influenced and is sometimes considered part of that family, so I think it's fair to relate the two.
- kibwen 11y agoRust and Scala may be cousins due to their ML influence, but Rust itself isn't particularly influenced by Scala. In contrast, there are quite a few design decisions in Rust that were lifted directly from OCaml. Calling Rust "C++20 + OCaml" would be a decent categorical starting point. (Caveat: the lead designer of Rust's type system, Niko Matsakis, has done a fair bit of work with Scala, so there may be subtle influences.)
- justthistime_ 11y ago> Rust itself isn't particularly influenced by Scala Agree! Sadly, they didn't use all the lessons Scala could offer them when designing their own language. :-( Painful to watch as they introduce stuff where Scala developers already know that it's completely broken.
- steveklabnik 11y agoWould you mind expanding on what these things are?
- lmm 11y agoThe cascade of efforts at error handling, which I think at one point involved a macro and a magic method name, rather than getting on with higher-kinded types to allow them to do it right. Allowing "return". Mandating braces for functions and control flow constructs. Rust iteration, which is both more limited and less safe (laziness) than the scala/ruby style of passing a closure.
- kibwen 11y ago> The cascade of efforts at error handling You must be referring to ancient Rust with its condition system and such. Modern Rust code just uses Result types. > rather than getting on with higher-kinded types to allow > them to do it right Er, no, you don't need HKTs to "do it right", you'd just need HKTs to do it generically. Rust's error handling works fine for specific types; you can even write macros to emulate do-notation (and people have). > Allowing "return" Welcome to the realities of imperative programming. :) Unlike Scala, Rust does not aspire to functional godhood. > Mandating braces for functions and control flow constructs Scope in Rust is very, very important for expressing when references go out of scope and when resources are freed. Leaving scope implicit would be massively frustrating. > the scala/ruby style of passing a closure Rust had internal iterators for years, and the entire `for` construct was based around them. They were removed because they were found wanting. As I've mentioned in a sibling comment, the lessons that Scala may have learned in its life do not necessarily apply to Rust. They are very, very different languages.
- cballard 11y ago> 1.x means that no backwards compatibility will be lost as in the past Why? They could easily go to 2.x, no?
- ColinDabritz 11y agoI believe this refers to the difference between pre 1.0 churn as the language was being initially designed, and post 1.0 stability. Before, existing code was frequently broken by new changes as the language evolved. Now you should generally expect to see any current code run on any future 1.x versions without issue, and probably in all future versions. If any new language constructs are added in future, they should typically be backwards compatible, only extending the old system, rather than making changes. It's possible at some point they will be compelled to break something to fix a serious flaw or issue. For Rust, I'd have to imagine this would be safety based. As language designers they will try hard not to, and it would be a major version change, such as 2.0. Python has had a lot of challenges with their changes from 2.x to 3.x, even though the language seems clearly improved. Much of the problem is converting popular existing libraries, which rely on a lot of donated time and effort. The Rust community is hoping to keep from being in a similar situation if at all possible. See "What does it mean for Rust to be 1.0" in the release announcement: http://blog.rust-lang.org/2015/05/15/Rust-1.0.html http://blog.rust-lang.org/2015/05/15/Rust-1.0.html Stability Guarantee: http://blog.rust-lang.org/2014/10/30/Stability.html http://blog.rust-lang.org/2014/10/30/Stability.html
- Tyr42 11y agoThough, I want to make clear that it is permissible for some theoretical code to stop compiling when going from 1.4 to 1.5, for example. Check out https://github.com/nikomatsakis/rfcs/blob/projection-and-lifetimes/text/0000-projections-lifetimes-and-wf.md https://github.com/nikomatsakis/rfcs/blob/projection-and-lif..., for an example of this. This is because the compiler wasn't checking some cases strictly enough, and you could "hide" constraints from the compiler, causing them to fail to be enforced. They checked against crates.io when raising this RFC, and found that there were 35 crates (packages) that would be able to keep compiling if this turned into a future-compat warning, to become an error in the release afterwards. The example trait Test { fn test(&self) -> Option<Self>; // ~~~~~~~~~~~~ // Incorrectly permitted before. } Should be trait Test: Sized { fn test(&self) -> Option<Self>; } Because `Option<T>` requires that `T` be `Sized`. Poking around on 1.3, I think that it would be an error to instantiate this trait with a [i8] or something that was not sized anyways, so you're not losing much by needing to declare the trait properly.
- Animats 11y agoNice. Someone previously ported Doom to Rust, but they kept the general form of the C data structures and had to use lots of unsafe code.
- cristicbz 11y agoIt's the same project, I just been keeping it up to date and removed all the unsafe code. It never _needed_ unsafe code, but it was my first Rust project and I didn't know what the hell I was doing---it's now much cleaner, safer and faster than the incarnation you saw last year :)
- krisdol 11y agoThat's awesome! I'm just learning rust and I'm really enjoying it, though it was more challenging getting into the right mindset after working on GCed languages for most of the last 4-5 years. Certainly wrestled with the ownership system for a while but it's all making a lot more sense now, and I'd much rather have the compiler telling me about these problems than incorrectly dereferencing memory in C code. How long have you worked on only this project?
- cristicbz 11y ago> How long have you worked on only this project? It's hard to quantify how much time _this_ project took, since when I started a year ago I knew nothing about Doom or Rust. If I started writing it now from scratch, I could probably hammer it out in a working week. A better programmer could probably do it in a weekend. It's neither very big nor very hard. But that's not how programming works, is it? In fairness, you'd need to count some of the time I spent working on a lot of other random Rust side projects and reading blog posts over the last year, while only spending a couple of hours ever other week or so on rust-doom. > Certainly wrestled with the ownership system for a while I think my background in modern C++ helped me a lot with this, since the "one owner per thing, move semantics" model is how you're supposed to write C++ too. That said, figuring out the cleanest design is not easy and I'm still wrestling with it today. The code was an absolute mess last year and now it's better, but still needs plenty of work: just yesterday I decoupled WAD parsing from the rest of the code properly (https://github.com/cristicbz/rust-doom/pull/53 https://github.com/cristicbz/rust-doom/pull/53). I'm still learning a lot a year after dedicating all my free-time programming to Rust.
- polskibus 11y agoCan anyone tell how performant this code is vs original C code? How much do we lose (if anything) by using Rust in comparison to C?
- filipncs 11y agoNote that this is an openGL renderer, not a software renderer implemented in Rust. Makes it hard to compare.
- mkesper 11y agoThis is not a 1:1 conversion of game mechanics, see goals of the project.
- cristicbz 11y agoI am hoping it will eventually cover game mechanics, see "Goals (subject to change)". Pull requests welcome!
- deleted 11y ago[deleted]
- fsiefken 11y agoIn general Rust is fast but slower then C: "Rust is safe indeed but, unfortunately, far from fast. By the moment of writing this article, it is comparable to Java, Go, and Haskell regarding performance" http://www.viva64.com/en/b/0324/ http://www.viva64.com/en/b/0324/
- pshc 11y agoWow, the article you linked is being defensive about something.
- MichaelGG 11y agoAnd since it was published, Rust is now in second place in that benchmark game graph: http://benchmarksgame.alioth.debian.org/u64q/which-programs-are-fastest.html http://benchmarksgame.alioth.debian.org/u64q/which-programs-...
- callumlocke 11y agoCan someone tell me what it means to have "no unsafe code"? (I'm a JavaScript developer with very little experience of languages like Rust and C++.)
- DasIch 11y agoRust allows you define blocks of unsafe code in which certain checks aren't enforced by the compiler. In these sections you have pretty much as much freedom as you always do in C.
- ekidd 11y agoIn languages like C and C++, you have precise control over memory allocation and pointers. If you want to say, "My data structure should contain exactly these bytes, and be located here", then you can easily do so. This low-level control makes C and C++ very fast. Similarly, the language does very little "behind your back." It's why most kernels, interpreters, web browsers, compilers and AAA games are still written in a low-level language like C or C++. But this control comes at a price: You need to be very careful. You need to manage memory manually, you need to avoid accidentally writing into memory you don't own, and so on. Overlooking small details results in security bugs. Rust attempts to provide the same low-level control as C and C++, but it adds safeguards which keep you from shooting yourself in the foot. In "safe" mode, all of these safeguards are fully engaged. In "unsafe" mode, Rust allows you to do some sketchy things. The idea is to use as much safe code as you can, and only use a tiny amount of unsafe code if you need to do something Rust can't prove to be safe. For example, there's a great series of blog posts about writing a toy OS kernel in Rust: http://blog.phil-opp.com/ http://blog.phil-opp.com/ The author uses some assembly to set things up, and a tiny amount of "unsafe" Rust to directly access VGA memory. But all the higher level code is safe, which rules out a whole class of bugs. Personally, I've spent a lot time using both C++ and functional languages. And for me, Rust hits a sweet spot: I can get down to the metal when I want, and I can build nice abstractions. And I can write almost all my code in "safe" mode, and not worry about dumb pointer bugs. It's an interesting combination and it makes me want to hack on new things. :-)
- moron4hire 11y ago
- kellros 11y agoI have a sinking feeling: https://github.com/cristicbz/rust-doom/blob/master/src/game/camera.rs#L33 https://github.com/cristicbz/rust-doom/blob/master/src/game/...
- cristicbz 11y agoI mean, the camera handling code is just the tip of the iceberg.
- devy 11y agoLOL, nice pun!
- acqq 11y agoCan you please elaborate?
- pauljz 11y agoIt's a joke - the comment references a song [0] from the movie Titanic, which prominently features a sinking ship. [0] https://en.wikipedia.org/wiki/My_Heart_Will_Go_On https://en.wikipedia.org/wiki/My_Heart_Will_Go_On
- ehartsuyker 11y agoIt's a reference to the Celine Dion song from the movie Titanic.
- deevus 11y agoI love stuff like this. I and some other students made a Quake 3 engine in C# using OpenTK (OpenGL 4) in about 6 weeks. None of us had ever done real game development before. It was a great learning experience and overall we're pretty happy with what we accomplished. It's still very preliminary and not optimised, but I might tinker away at it now that my degree is all but done. At this point it can load and render any Q3 (or OpenArena) BSP map, but most all other things are missing. https://github.com/aggregates/tk-quake https://github.com/aggregates/tk-quake
- loaaa 11y agoRust will push C++ becoming much better!
- ChuckMcM 11y agoThis is awesome. Now to go dig up my WAD files. To add to the list of languages where bringing up Doom was helpful in vetting the language, Java. Patrick Naughton built a BSP rendering platform in Oak using the Doom WAD files and found a number of places where the JVM needed tweaks.
- kibwen 11y agoIn related news, note that Rust 1.4 was just released yesterday: http://blog.rust-lang.org/2015/10/29/Rust-1.4.html http://blog.rust-lang.org/2015/10/29/Rust-1.4.html , which I figure is worth mentioning here as the announcement thread didn't get much traction on HN.
- eridius 11y agoDefinitely worth mentioning! I completely missed this release. A bit sad too, since it's the first release (since Rust started listing contributors) that I didn't contribute to :'(
- somesaba 11y agoThis is great. I've wanted to start a project in Rust but I'm hesitant since I haven't found any profiling tools akin to VisualVM. I'd feel a bit blind writing multi-threaded code where I can't see what's going on. What do people use to sanity check this sort of thing?
- steveklabnik 11y agoOne nice aspect is that Rust gives you many kinds of threading errors at compile time, so that helps. :) Any profiling tool that works for C or C++ should work just fine for Rust. For example, people often use perf for performance work.
- cjdrake 11y agoWhat a great project! The author should do a talk about his experiences. I searched for something like this on YouTube, and only found this: https://www.youtube.com/watch?v=0_-TRvbo54Y https://www.youtube.com/watch?v=0_-TRvbo54Y.
- cristicbz 11y agoThanks! Uh, I'm not good at writing/saying things that are not checked by a compiler. But I'll try to write a blogpost about it.
- grimmdude 11y agoI'm going to create a programming language called Mildew. Stay posted.