Read My Chapter in Ray Tracing Gems II!

comparison of computing irradiance from a directional light with L1 SH and L2 SH projections

Ray Tracing Gems II was released a few weeks ago, and like the first one it’s free to download as a PDF from the publisher’s website. There are 50 articles in this thing written by over 80 authors, so I think it’s safe to say that this book is absolutely jam-packed with useful knowledge and techniques related to ray tracing.

Yours truly contributed a chapter called “Using Bindless Resources With DirectX Raytracing”, which as you’d expect is all about using bindless techniques in the context of DXR. I had already written a simple open source path tracer in DXR which uses bindless for all SRVs, so it seemed like a natural fit for me to write full article that dives into all of the details required to make that happen. I also wasn’t aware of a comprehensive article or tutorial explaining the ins and outs of bindless in D3D12, and I thought my article could help fill that niche. Hopefully I was successful! If you do end up reading it, feel free to let me know if you have any thoughts or have any lingering questions that I can help clear up.

I also wanted to use this blog post as an opportunity to emphasize a few things in an informal way, just in case they don’t fully come through in the article:

  • Bindless is great, it really is! There are downsides of course (mostly on the tooling and debugging side of things), but I firmly believe the pros outweigh the cons. I don’t really see any future for the older binding models.
  • It’s hard to oversell how bad of an experience it is dealing with multiple root signatures and descriptor tables/ranges compared to bindless. Once you go bindless a lot of that complexity just disappears, which could end up being a good thing for people that are new to D3D12/Vulkan or graphics programming in general.
  • On a related note: just don’t bother with local root signatures in DXR, at least for binding descriptor tables. Ray tracing is inherently global, and it makes so much sense to have global access to all of your resources/descriptors.
  • In the article I mention how the indirection offered by using descriptor indices can let you do some really cool things. Basically as long as you keep your descriptor index persistent, you’re free to update the descriptor located at the index without having to also go and update whatever data structures have that index in it. Got a ring buffer system where you swap to a different buffer when the contents are updated by the CPU? Just update the descriptor when you do that and everything keeps working great! Same goes for updating textures due to streaming in new mips, or swapping between aliased render target textures as part of an adaptive resolution system.
  • Bindless is awesome for CPU performance and really helps unlock the original dream of low CPU overhead that was promised by D3D12 and Vulkan. Once you’ve moved all of your “binding” out of API functions and into your own user-managed memory you can do things much more quickly, and you can really fly through your draw calls. Combine that with multithreaded command buffer recoding and you can do a ton of draws and dispatches with very low latency.

Finally, I want to finish with a note addressing Shader Model 6.6 and the new “dynamic resource binding” feature. When I started working on the article it was March of 2020, since RTG II was originally supposed to be released that year. At the time the idea of a new HLSL feature that makes it simple and trivial to access bindless descriptors was little more than some hopes and dreams in a GitHub issue, and I thought the situation would be the same by the time the release date rolled around. I did not expect the book release to be pushed back, I really did not expect for Shader Model 6.6 to be announced before the year end, and I definitely did not expect for the D3D team to release an awesome new Agility SDK that allowed for SM 6.6 to be deployed to end user machines without waiting for Windows updates. But of course all of those things happened, when meant by the time the chapter came out people were already using dynamic resources in their code. It’s too bad, but it was of course bound to happen eventually. For those not using the latest-and-greatest the article should still help with spelling out the right HLSL and root signature incantations required for pre-SM6.6 bindless, and those that are on the bleeding edge can simply ignore that part and make use of the other content. On the plus side: dynamic resources are really really great. They fix a lot of little rough edges that show up when doing bindless the old way, and take an even further step towards simplifying and reducing the number of root signatures.

Thanks for reading!