Move cluster operation?

Hello,

I’m now extending my demo program for CLAS/Cluster GAS in my wrapper library so that it can reuse CLASes built in the last frame if they are still drawn instead of rebuilding them.

However, when building Cluster BLASes based on copied CLAS set, the program showed an error:
[CLUSTER_OP_SOURCE_MOVED] Illegal cluster copy encountered in cluster-operation argument. Cluster may only be copied or moved using the move cluster-operation

Is there any API to move clusters in batch in OptiX?
It looks that DXR 2.0 has D3D12_RTAS_OPERATION_TYPE_MOVE_CLUSTER_OBJECTS.

Thanks,

Hi @shocker.0x15!

This is an interesting question. We don’t have the move operation support in OptiX at the moment. But the speed of rebuilding your CLASes should be not too far away from copying them. Are you seeing unexpected perf issues when rebuilding the CLASes?

–
David.

Not really.

I just want to implement somewhat similar to CLAS management in Zorah demo.

Ah, I see! I’m glad you’re trying it. The validation error you’re getting is mainly intended for DX. We will investigate whether OptiX can relax this, or needs to provide CLAS move or relocate support. In the mean time, the only workaround I can recommend is to rebuild the CLASes. I’d be interested to hear whether you see a difference between your CLAS copy timings vs rebuild timings in your app. If it will help your perf, we’ll try to prioritize this.

–
David.

I have really roughly measured performance of the program using NSIGHT systems.
CLAS build vs CLAS copy (including preparative work like scan on output sizes to obtain destination addresses)

Build only (Prefer Fast Build): 200 us
Build only (Prefer Fast Trace): 850 us
Copy only (2nd frame): 220 us
RTX 5070 Ti

With CLAS copy, the program immediately crashes at Cluster BLAS build, so I cannot run the complete program. I disabled Cluster BLAS build, IAS build, renderer, so I cannot observe the view and the second frame determines full CLAS copy because of no camera move.

With camera move, the timing would be something between two timings above (+ some overhead).
CLAS copies does not justify when using Prefer Fast Build but it looks much beneficial when using Prefer Fast Trace.

I’ll appreciate if the next minor version of OptiX supports the relocation or even some near future driver just disables this unnecessary? validation.

Thanks!

Thank you for the timings! I’ve filed this and I think we have time to get it in, so unless something goes wrong, we intend to support CLAS relocate in the upcoming OptiX 9.2.

I think we want a mechanism like D3D12_RTAS_OPERATION_ADDRESS_RESOLUTION_FLAGS in DXR 2.0 as well.
With CLAS reuse/compaction from the previous frame (and putting newly built CLAS set after those reused CLAS set), we need to dynamically set the CLAS mem pool address for CLAS set build for the current frame.
DXR seems to have a mechanism that makes everything one more indirect.

With OptiX terminology

  • outputBuffer, tempBuffer, outputHandlesBuffer and outputSizesBuffer in OptixClusterAccelBuildModeDescImplicitDest are basically something like void*, void*, uintptr_t* and uint32_t* respectively (some with strides), but can be void**, void**, uintptr_t** and uint32_t** respectively.
  • OptixClusterAccelBuildModeDescExplicitDest and OptixClusterAccelBuildModeDescGetSize should be similar.
  • argsArray and argsCount for optixClusterAccelBuild() are basically something like OptixClusterAccelBuildInputTrianglesArgs* and uint32_t* but can be OptixClusterAccelBuildInputTrianglesArgs** and uint32_t**.

It would be really good if we can have the parity with DXR 2.0.

Thanks,

Hi there. I think the address resolution flags are a separate request from MOVE, which is fine, but I want to understand what you’re doing a little better.

When doing a CLAS build, you can pass outputHandlesBuffer yourself containing explicit output device addresses, and OptiX will write each CLAS to that location. It’s OPTIX_CLUSTER_ACCEL_BUILD_MODE_EXPLICIT_DESTINATIONS in the API.

That buffer of handles is itself in device memory, not host. This would seem to allow you to write the dynamic “handles” (really just addresses here) from the previous kernel without a readback. You could also split up the allocations if that helps at all - the dynamic addresses can point to separate allocations.

This is not quite as easy as the dynamic addressing in DXR, which would allow you to write a single dynamic address instead of one per cluster. But not that much harder.

Yet another idea: even with an implicit build into a single starting address, if you compact toward the end rather than the beginning, then you can always pass 0 as the new address. Or you could possibly leave a safe amount of extra space after your compaction zone, and write new clusters after it - that way you don’t need the exact address, at the cost of some extra padding in the buffer.

Anyway, we’re not necessarily opposed to parity with DX; they have moved pretty fast in this area. But I want to see if we can find you a workaround in the current API.

Hello,

As you described, I can actually do similar thing by setting output addresses AS by AS, but this is a bit trouble and needs explicit mode.
Global offsetting by D3D12_RTAS_OPERATION_ADDRESS_RESOLUTION_FLAGSand implicit mode looks more natural here to me.

I have another question in CLAS sizes.
Is there a guarantee that CLAS sizes are multiples of its alignment?
If not, scan operation directly on output CLAS sizes produces misaligned offsets used for CLAS destination address calculation.
Again, DXR 2.0 looks to guarantee this.

Thanks,