This project is a real-time Mandelbrot Set renderer built with C++17 and raylib 5.5, exploring the impact of several optimization strategies on fractal rendering performance.
The renderer visualizes the Mandelbrot Set using multiple algorithmic approaches: from a simple, naive escape-time algorithm to AVX/AVX2-optimized versions running across multiple threads and a thread pool.
By leveraging raylib, the user can interactively explore the fractal space with smooth zooming, panning, and algorithm switching; all rendered in real time.
- Interactive controls (via raylib)
- Mouse wheel: Zoom in/out
- Hold Left Mouse Button + Move: Pan view
- Right Mouse Button: Reset to original view
- + / -: Increase or decrease maximum number of iterations
- 1: Select escape-time algorithm
- 2: Select AVX/AVX2 implementation
- 3: Select AVX/AVX2 + Threads implementation
- 4: Select AVX/AVX2 + ThreadPool implementation
- Fixed window size (1280x720) is used to keep rendering performance consistent and predictable and to apply some precomputation.
The project explores and compares the following implementations
- Escape-Time Algorithm: Straightforward pixel-by-pixel computation.
- AVX/AVX2 Intrinsics: Vectorized computations for parallel pixel evaluation using SIMD instructions.
- AVX/AVX2 + Threads: Workload distributed among multiple threads (36 in total)
- AVX/AVX2 + Thread Pool: Tasks dispatched to a persistent thread pool to avoid repeated thread creation/destruction overhead.
While each optimization step brought measurable speedups over the naive approach, the performance difference between the threaded and thread pool implementations was negligible.
Possible explanations include:
- Improved cache locality: Each thread processes a contiguous pixel region reducing cache misses.
- Thread count overhead balance: With 36 threads, the creation/destruction cost in method 3 may be effectively masked by the workload size.
In fact, later testing revealed that pushing the number of threads to the number of rows in the screen buffer (720) resulted in a substantial improvement of the threadpool implementation performance over the other methods.
Originally, this project computed the colorouing of the Mandelbrot set in the implementation code. As time passed I have moved this responsibility to the GPU by providing shaders that can be found... wait for it... in the shaders folder.
So far three shaders are provided:
grayscale.fscontaining the original palette used during developmenteriksonn.fscontaining the palette used by OneLoneCoder in its youtube videowikipedia.fscontaining the reversed engineered palette used in the Wikipedia article about the Manderlbrot set.
- C++17 or newer
- raylib 5.5 (graphics and input handling)
- A CPU supporting AVX/AVX2 instructions for SIMD acceleration
$ git clone https://github.com/marcope-98/fractal-rendering.git
$ cd fractal-rendering
$ mkdir build && cd build
$ cmake ..
$ make -j4
$ ./fractal_rendering <path-to-shader.fs>