As I spend more time working with Rust, I find myself hitting more edge cases, and ultimately into learning more about how Rust is implemented.
This weekend I was working on path-tracer, refactoring it to make shapes generic instead of always spheres, and adding explicit light sampling. While doing so I hit some unusual error messages, of the form:
the trait `renderable::Renderable` is not implemented for the type `renderable::Renderable`
With the partial image and seeding support in my Rust path tracer, I was finally able to do what I had hoped…use some idle time on my work computers to render a “proper” number of samples.
Well, there you go then!
Rust made the brave decision to not support exceptions. Instead, a rich set of features are used to build more explicit error handling:
The only thing remotely exception-like is the last-resort “panic” that prints a diagnostic message and exits the current thread.
Last time I looked at Rust’s performance vs C++ for a simple path tracer. Since then I’ve been further hacking on the source to get a little extra functionality, like partial rendering and merging (so I can try out some distributed rendering).
I guess the honeymoon is over. I tried a bit of “simple” file manipulation, and I’m finding all sorts of trickinesses. In this post I am referring to this version of path-tracer on GitHub. I’m sure by the time anyone reads this I’ll have found workarounds, so check the most recent version to see how I’m getting on.
My path tracer can now spit out intermediate partial renders, each containing a set of samples, which are then merged together at the end. Although the image library I’m using for PNG support can probably do something similar, as an experiment I output my own simple text-based format of the form:
In this short post I’m updating with some performance figures. I’m really impressed; the Rust version really is as good as the C++ version! I tested on my home server, a 4-core 2.5GHz X3323, which was otherwise idle.
Due to some stack limitations in Rust, the Rust code bails out after 500 levels of recursion; so I modified smallpt to do the same.
Rust is touted as a systems language in the same vein as C, C++ and to a lesser extent, Google’s Go. It offers both high level abstractions like generic programming and object-orientism while also giving access to lower-level facilities like fine-grained memory allocation control and even inline assembly.
Critically for me, it has a “only pay for what you use” mentality like C++, a well-sized standard library and runtime, and no garbage collection. It’s quite feasible to use Rust to make a “bare metal” system in (for example, Zinc).