Delete/Remove GeometryAcceleration, best way to go about it

I went through the manual and samples but couldn’t find anything.

I need to be able to delete and replace some of the geometry.
What would be the best/correct way to go about this? My main concern is not having to rebuild all of the GeometryAcc in the scene. (The scenes are in the range of 10s of millions of triangles. I need to replace maybe a few hundred k max)

I keep a list of TraversbleHandles, so I know which one to remove, just don’t know where to go from here.

You are using OptiX 7, correct? Is the geometry you need to swap in / swap out changing often?

Since you mention a list of multiple traversables, I assume you are using (at least) a two level BVH structure, where the top level is instances? In that case, you can remove from and add instances to your IAS, and the only BVH that needs to be rebuilt is your top level IAS. This is typically fast enough for real time applications, and only depends on the number of instances, not on the number of triangles.

If you’re only swapping a few static layers of geometry in and out, and you want to avoid rebuilding any BVH, then have a look at the visibility mask feature. With OptiX visibility masks you can use up to 8 bits to identify up to 8 separate ‘layers’ in your scene that you can toggle per-frame or even per-ray. This is the fastest way to turn on a off different sets of geometry, but is limited to 8 layers and may not be helpful if you need to dynamically update your layers.

If neither of these solutions seems to apply in your case, let us know why and we can discuss some other alternatives.


David.

Also there actually is a chapter about that topic inside the OptiX 7 Programming Guide.
https://raytracing-docs.nvidia.com/optix7/guide/index.html#acceleration_structures#dynamic-updates

Have a look over these OptiX forum topics dealing with updates.

@dhart Sorry, yes. Optix 7.2. And yes, instances at the top and then the geometry.

That’s where I am stuck… How do I do that? I am sure now that there is something obvious I am missing.

As for performance… rebuilding all the geometry takes about 10 seconds, which is too long for that use case. I’d really like to push that whole operation (remove old geometry, add new one, rebuild as) under half a second or so.

As for masks, I might them another use case later on. But with this I have the problem that there may be lots of updates over time and the GPU would just accumulate a lot of deprecated objects.(and we’re already fighting over VRAM)

@droettger The way I understand that chapter, the update abilities are limited and I can only really change vertices and bounding boxes, which doesn’t really help me. (or I least I haven’t figure out how it would)

There are only a few simple rules.

  • Change the topology in a GAS? => Rebuild that GAS and refit all IAS above it. (*)
  • Keep the topology intact but move vertex positions in a GAS? => Rebuild or refit the GAS and refit all IAS above it .(*)
    Refit of the GAS is faster, but the GAS quality degrades when the model changes much spatially.
    Then rebuild from time to time instead of refit.
  • Changing the number of instances in an IAS? => Rebuild the IAS and refit all IAS above it (if you’re using more than a two-level hierarchy) (*)
    For that you need to track all active OptixInstances at all times and just rebuild the IAS with them if there is any change.

(*) No need to refit the IAS when you know that the AABB over the children has not changed.

Ok, so there is no way to delete/destroy a particular GAS? I saw destroy functions for almost everything else.

And yes, no matter what I have to rebuild the IAS.

If the GAS you want to remove from a scene is below an OptixInstance, you would remove the OptixInstance from the IAS and rebuild the IAS. Depending on how you structured your shader binding table, that might also need changes.

The GAS or IAS is a mere CUdeviceptr and a traversable handle.
Destryoing an AS means freeing that CUdeviceptr and never touching that orphaned traversable handle again.

Yes, but building an IAS is fast. It’s just one AABB per instance (without motion blur). GAS builds are the expensive ones.

Ok, so there is some sort of GC at work here the figures out that those vertices aren’t needed anymore?

remove the OptixInstance from the IAS and rebuild the IAS.

Sorry to come back to that… this means I rebuild that IAS from scratch, right? I tried it via cudaFree, but that expects a devicePtr, where as accelBuild “return” a TraversableHandle. I found the function to get a handle from a ptr, but not the other way around.

Ok, so there is some sort of GC at work here the figures out that those vertices aren’t needed anymore?

No, all memory handling is your responsibility.
If you hook out an instance from the top-level IAS, the GAS child of that can simply not be reached during traversal anymore (unless it’s still used by another instance). But the GAS memory allocation and traversable handle of that still exist. See below.

this means I rebuild that IAS from scratch, right?

Yes, call optixAccelBuild with all active OptixInstance as build input.

optixAccelBuild fills the CUdeviceptr you provided for the AS and returns the traversable handle of that AS.

That are the two arguments d_outputbuffer and outputHandle in the above API reference link.
These two belong together as long as you use that traversable handle!

You free the d_outputBuffer when you do not need the AS anymore, because that is what you allocated for the AS data.
You must not use that traversable handle anymore after freeing that AS buffer.
No need to “free” that traversable handle, it’s just a 64-bit value which is useless without the CUdeviceptr containing the AS data.

Phew, ok. Thanks, both of you… again :) It finally clicked.

For a code example, my intro_motion_blur example does IAS updates (refit) when calculating new motion transforms per frame.
This is the initial build of the root IAS:
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/intro_motion_blur/src/Application.cpp#L1801
This is the IAS update when changing any of the motion transforms:
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/intro_motion_blur/src/Application.cpp#L2473

You caught me :)

We don’t need motion blur, so I didn’t look too deep into that one. Thanks for pointing it out

I’d really like to push that whole operation (remove old geometry, add new one, rebuild as) under half a second or so.

I recently did something similar while trying to render fluid dynamics … where the fluid mesh had to be updated with new geometry every frame or so. My RTX 2070 Super was rendering around 500/600 fps while replacing meshes with around 80-100k triangles. I rebuild the GAS and IAS every tick but as you can see there aren’t millions of other triangles in the scene.:)

2 Likes

Looks really cool! And yes, it’s going much better than I thought