cuBQL backend - #14
Conversation
|
The latest set of changes have made a start on cleaning up the protyped codex code - namely by removing the duplicated plucker intersection functions for cuBQL. Now we directly use the existing plucker intersection code that the other two ray tracers make use of. Tests are still passing so this looks to be a good change which cuts out around 15 lines of prototype code 🥳 There is an inherent problem with the way I am currently linking libomptarget in this branch. Every test links libxdg.so and libxdg.so is built with the OpenMP target flags so even a test which has nothing to do with cuBQL or any openmp offloading regions gets hit with a fixed initialisation time cost. This pushes up the total time of completing the tests but does not change or affect the results of any. Of course the only tests which actually need the libomptarget offload setup are the ones which make use of the |
|
Some notes on BVH traversal from Ingo:
|
6b1f729 to
68c51ae
Compare
Handling senseSense is an important part of XDG's traversal algorithm allowing traversal to be topology aware. We do so by adjusting normals of primitives on the fly based on a ray's inherent orientation it is launched with along with the volume it is being queried against. XDG has two distinct types that can refer to a volume:
Currently XDG doesn't expose TreeIDs to the public API. Rather the public API for any query expects to be given a MeshID corresponding to a volume and internally maps to the underlying TreeID for that volume. This works great with Embree but for the GPU ray tracers it leads to some potentially unnecessary obfuscation. In the intersection shader we need to flip a normal based on the sense relative to the volume being queried against. But this means we also need to still pass the volume MeshID of the volume a ray is being queried against to determine the sense at intersection time. Primitive normal handling has now been moved directly into the primitive intersection lambda, along with sense handling for normal flipping. |
|
A new omp_device probe has been added to mirror the same logic for GPRT. This means that tests gracefully skip when no GPU device is detected for both omp (cuBQL) and vulkan (GPRT), though this change won't actually be noticeable in CI since we dont have gpu runners and trying to compile an omp_target_offload based code on a system with no offload support seems quite difficult. |
|
Working towards realising a two-level traversal scheme. I have a decent idea of what this should look like in my head and am slowly chipping away at this. Right now the code is looking more overly complicated to achieve the same structure we already had before of looping over all surfaces. I am introducing some new types:
Some consideration with the current structure I am implementing which follows more directly what DPRT does: Once I have Will need to be careful to remember Ingo's suggestions:
|
|
We are now constructing a two-level traversal scheme and successfully ray tracing against it :) Things are messy and extremely explicit everywhere... but it works as expected with all tests passing including a ray tracer cross test with 1000 queries with cuBQL agreeing with embree. I am slightly concerned about performance but we can tackle that later I suppose. I opted to go for a structure with three types (like DPRT) with some simplifications since we don't need certain features:
Each owner has a nested DD type, following the DPRT/cuBQL “device data” pattern. The host-side structs own memory and lifetime; the DD structs are compact, device-copyable views used inside OpenMP target traversal.
I think this has been a really interesting problem to solve and has shown that the added verbosity of working directly with the underlying BVH builder and query engine instead of the front facing ray tracer has allowed for a much much more tailor made solution for XDG. Instead of having to constantly fit XDG around the ray tracer (like embree or especially gprt), I have significantly more control over how I want to define parts of the ray tracer around XDG. |
|
Implemented I have also done a little bit of refactoring adding in a new |
…witch to cuda path
…t changes from main
…hway a little slow
…ndling is performed at intersection time Also had to change the create_global_*_trees stubs for cuBQL to return a warning rather than fatal_error Cross check verified to produce consistent results across all three ray tracers
…he vk_device probe
- New structs - Corrected lambdas - New mappings
… per topological surface
…cts for the intersection routine used with the cubql backend
…lume into its own function I am essentially trying to make this look more like our embree interface
- Volume to query against carried on ray - Lookup table for volume mesh id to BVH uploaded to device
- intersect_surface_tree() intersects a single ray with BVH - Can be used from within different intersection algorithms, i.e scalar and batch (when implemented)
- Expects populated device pointer of d_rays and populates d_hits
Internal PR for me to track progress on this since it'll be quite an in depth piece of work.
cuBQL is the BVH construction and traversal engine that DPRT is built around. it's designed to be highly flexible and seems to better suit our needs in XDG than DPRT does. Most importantly it has a working OpenMP target offloading backend.
I have made a start on the cuBQL backend here. The nature of the library being quite low level means it requires a little bit more plumbing to get the same functionality working as the Embree and GPRT back ends. Nevertheless, in my prototyping here I think it is definitely doable.
Progress so far
Whats next?