Recently I got access to a GPU that supports accelerated raytracing and the temptation to tinker with DXR is too strong. This means that I will steer away from compute shader raytracing for the foreseeable future. It is a good opportunity though to do a quick retrospective of the past few years of experimenting with “software” raytracing.
It all started about 4 years ago, when DXR was released and the first GPUs that supported it came out. My lowly Intel HD4000 laptop didn’t support DXR of course but not wanting to miss out on all the fun I decided to implement my own raytracing solution based on compute shaders. I was quite ambitious at the time, choosing to implement both raytraced shadows and reflections, which was a huge learning step having to manage not just BVH creation/traversal and collisions but material sampling, hit point lighting and closest hits as well. I also got a first feel of the impact of ray divergence.
The first attempt at raytracing was decent but quite naive. For example I stopped the BVH build at model level, which meant that I had to iterate over each meshes triangles, in a loop, to determine ray-triangle collisions. That sort of worked for the simple spheres and cubes I was using but would never scale. In my second attempt I improved BVH generation to include all triangles which improved the time to find ray collisions a lot. I also started exploring better BVH generation techniques like Surface Area Heuristic which accelerated traversal massively (left is number of steps to find a collision without SAH, right with SAH).
BVH traversal is memory intensive operation as well which highlighted how important it is to choose the best buffer type for the target platform (for eg Intel GPUs seem to prefer ByteAddressBuffers).
This work coincided with an invitation from Wolfgang Engel to write a hybrid raytraced shadows sample for The Forge, so my experiments end up there, running on DX12, Vulkan and iOS, which was great.
Another technique that was gradually gaining traction was mixing screen space with raytracing techniques and for my next experiment I focused on hybrid raytraced reflections. The idea behind this is to raymarch screen space reflections as normal but for those rays that fail to find a collision in screenspace let raytracing pick them up and find the geometry collisions.

This experiment also gave me the opportunity to directly compare SSR and raytraced reflections and highlight their differences, especially in terms of specular lighting of the hitpoints (left SSR, right raytraced)
At some point I came across Intel’s Embree library and realised that I can use it to generate the BVH trees that I use for raytracing in my toy engine. I made some comparisons in terms of memory and traversal costs, there where mixed results depending on the scene (“reference” was my BVH generation code).

Embree offers options to balance generation time and BVH traversal time which is very useful in cases you generate BVHs in the runtime. It was an overall better option and I am using this to generate my BVH trees since.
Up to that point, I was using a single BVH to bake the whole scene in. This in general produces a higher quality tree but it can be wasteful when trying to trace local rays (imagine local light shadow