A small unpretentious software rasterizer written in Odin, just for fun.
NOTE: The pipeline only supports 4D floating-point vectors. This includes buffers, varyings, uniforms, and framebuffers.
- SIMD rasterization
- Vertex and fragment shaders
- Shader uniforms
- Dynamic attributes/varyings
- Perspective correct
- Texture sampling
- Depth function
- Blend function
- Depth mask
- Clipping
- Configurable face culling
- MRT
Performance isn't "wow", but for a triangle in a 400×225 box on my Ryzen 3600, here are the 10 second averages:
With shader indirection:
Clear: 101.81 µs (9.8%)
Render: 92.15 µs (8.9%)
Blit: 269.04 µs (26.0%)
Present: 572.09 µs (55.3%)
Without shader indirection:
Clear: 114.07 µs (11.3%)
Render: 58.12 µs (5.7%)
Blit: 269.47 µs (26.6%)
Present: 569.83 µs (56.3%)
Render is the part that rasterizes the triangle (~90k pixels).
- With indirection: ~92 µs
- Without indirection: ~58 µs
Which roughly gives (ballpark, please don’t quote me in court):
- Total cycles: 0.000058s * 3.6GHz ~= 208,800 cycles
- Per SIMD iteration: 208'800 / 11'250 ~= 18.6 cycles
- Per pixel: 18.6 / 8 ~= 2.3 cycles
The most expensive step is Blit, because the rendering is done in an internal framebuffer where each component is stored as vectors of 8 floats (SoA), and then needs to be converted to an RGBA8 buffer.
Compilation flags used:
-o:speed -microarch:native
So these tests are rough and I'm not aiming for maximum performance. This is mainly for fun, and if it allows cool offline renders that's more than enough :D