This document describes my understanding of the Cycles renderer source code. Cycles is a unidirectional path tracer provided with Blender for production rendering. As a production renderer, its code favors performance and simplicity over generality. It can run on CPU or GPU, and the same kernel code can be compiled with a CPU compiler (gcc, msbuild) or a GPU compiler (cuda, OpenCL). To do that, the code tries to remain simple (mostly C code) but exploit macros to specialize some parts of the code.
In this document I focus on the CPU rendering. I compiled blender in "full" mode, meaning Cuda kernels are not compiled. One reason for that is Cuda kernel compilation seems quite expensive so if I want to change the code and quickly iterate, it might be hard. I may do another analysis for GPU part later but I doubt it would be very interesting since it is the same code.
By running blender in render mode with cycles, I can break into the function CPUDevice::thread_render, which seems to be the function run by each thread in order to aquire tiles and render them with path tracing.
The actual call stack is:
- CPUDevice::thread_run which take a DeviceTask instance as parameter. This task is typed either RENDER, FILM_CONVERT and SHADER. For now I'm only interested in the RENDER case, which call thread_render
- CPUDevice::thread_render which is the rendering function
This call stack is triggered in TaskScheduler::thread_run, which seems to be a utility class for task scheduling.
The task has been added from the Session class, in the render() method. render() is called in Session::run_cpu(), which seems after that to wait for the rendering to finish and print progress.
In Visual Studio, the code is divided into multiple projects:
- cycle_util : utility code, not related to rendering, contrains things such as util_xml.h, util_task.h, util_time.h, etc.
- cycle_subd : subdivision code, wrap opensubdiv
- cycle_render : library for the renderer, contains things on top of path tracing, represents a rendering session with the Session class. It seems to be the thing to interract with if we want to make a standalone app using cycles ?
- bf_intern_cycles : bf stands for "blender foundation". It seems to be the library that interract with blender. The concept of session and synchronisation seems also present here. I see some files "blender_*.cpp"
- cycles_graph : obviously a DAG, we seen a node class, XML representation. Maybe it is used to represent shading graphs in cycles.
- cycles_bvh : bounding volume hierarchy for ray tracing. There is a bvh_embree.h file so I think some code has been taken directly from embree.
- cycles_device : cycles seems to abstract the thing is is running on (cpu, gpu, etc) as a Device instance, which make sense. Implementations of such device seems to be in this project.
- cycles_kernel : seems to be the big part, the actual path tracing code. Kernels seem to be simple functions that can be compiled on multiple devices and called from Device instance methods.
- kernel/cycles_kernel_osl : optionally cycles can use OSL for shading graph evaluation, the code for the glue seems here
- kernel/cycles_osl_shaders : well, OSL shaders.