Rendering with Swift


I just finished a blog post about rendering a production scene from Disney, Moana, with my renderer, gonzales, written in Swift. I would appreciate comments and suggestions for improvement.




This is fabulous! Do you have any plans for extracting some of the code used for rendering as separate libraries that could be used in other projects?

Not at the moment but if the need arises I would be glad to re-architect or help extracting.

This is great work!

It'd be really interesting to drill into some of the challenges you had with arrays, especially the issues with subscripts. It may be some of these could provide useful indications of improvements to the optimizer in cases where a human can see opportunities the optimizer is missing. Also any traces showing hotspots in the runtime for things like unspecialized generic code or unnecessary allocation/deallocation.


Gonzales shows 23 protocols, 57 structs, 47 final classes and 2 non-final classes.

if swift had move-only struct, you could replace classes with move-only structs, so performance and memory usage would be better.

Path tracers (as Gonzales) spend 99% of their time walking the bounding hierarchy and intersecting triangles, both of which are read-only data structures at that time. I also fixed many performance and memory related bugs in the past so I doubt you would get far by just changing classes/structs.

You would definitely get more performance by building better bounding hierarchies, optimising the walking of those and taking a hard look at interactive ray tracers like the ones mentioned above.

There are still many optimisations regarding memory usage, bounding hierarchy nodes could be smaller, curves could be regenerated on demand instead of converting to many segments, and I believe there is still plenty of memory that could be freed earlier, like parameters not needed anymore.

As I said, I spent quite some time fixing a lot of bugs like these and decided to release the code after I was able to get it rendered with less than 64GB in a reasonable amount of time (if you agree that 26 hours is reasonable of course).



One thing that keeps showing at the top of a perf run is a subscript.getter in getLocalPoint in Triangle.swift. It returns a Point (three Floats) from an Array and I wondered why that one was not inlined but did not have the time to investigate closer.

It is often the case that a swift_retain or swift_release shows up at the top of a perf run but most of the time it was an indication of a design problem in my code. I will try to do another analysis and report the findings.


you're a legend

You are probably talking about runtime performance but the biggest obstacle I ran across is compile performance of large arrays. These are quite common in rendering for generating low-discrepancy samples:

I filed a few bugs for this, e.g.
An array of 10.000 elements for example needs 16 seconds to compile where in C++ or Python it is 0.04 seconds (400x faster!).

1 Like

@xedin and @hborla may have some thoughts on whether the typechecker improvements happening on main currently might address this.

edit: ah, though looking at it points at an optimizer pass rather than the typechecker.

1 Like

As a follow-up, the raytracing kernel (written in Swift) was used to implement Optix in Software. Or at least a tiny bit of it. I started with Ingo Wald's SIGGRAPH Optix course (from GitHub - ingowald/optix7course) and followed it step by step, just the other way around; instead of using the official Optix SDK I wrote some glue code in C++, made use of the fact that CUDA kernels can be parsed with Clang as pure C, generating a dso on the fly, and let the renderer from (GitHub - gonsolo/gonzales: Rendering Disney's Moana in Swift) do the rest.

The result is a bit hacky but you can have a look at GitHub - gonsolo/optix7course.
There is also a small blog post: Optix in Software – gonsoloblog


Terms of Service

Privacy Policy

Cookie Policy