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:
width height #samples
R G B R G B ... f64 triples each sample line 1
R G B R G B ... f64 triples each sample line 2
R G B R G B ... etc
Generating the file is pretty simple, but loading it back again to merge it has been a major source of frustation.
My best effort is here. I welcome suggestions to improve it, notably:
load_file
tries to be a good citizen and return an io::Result<>
. That means it
can use the try!
macro. But there’s a couple of panic!
s in there I’d like to
make into Error
s, but I couldn’t get the syntax right to make them…or else I
need to make the whole routine return something else (then try!
won’t work?).
I’m confused!R G B
) I’ve lost a bunch of flexibility.
I couldn’t see a way to take an iterator<T>
and return (T, T, T)
in threes
in a tuple.unwrap
s() seems a bad smell. All that unwrap().ok().unwrap()
nonsense to
carve off the first line and treat it differently seems really ugly.
Maybe I can use “match” here to make it more elegant.operator +=
for my Vec3d
type.Vec<Vec<X>>
is awkward. Maybe I could do
something smarter?More generally I found the cargo setup to make a package with two binaries
very awkward, painting myself into a corner multiple times before realising if
I just name things “correctly” and get rid of all my crap in Cargo.toml, it
kinda “just works”. Though now I need to run each binary by name in
cargo run --bin path_tracer --release -- my args here
.
Anyway, I’m still liking Rust, but I think I need to get my head around how to use it more effectively. I’ve asked for help from Phil Dawes (author of racer – a Rust code completion tool), who works for the same company as me, so hopefully I’ll be able to post a follow-up with improvements soon!
Matt Godbolt is a C++ developer living in Chicago. Follow him on Mastodon or Bluesky.