ArchimedLight currently works around a RayCore/Metal correctness issue by building the mutable RayCore TLAS on KernelAbstractions.CPU() and then adapting the resulting tlas.static_tlas arrays to the requested backend.
See my comment on RayCore here: JuliaGeometry/Raycore.jl#19 (comment)
Current behavior:
tlas_build_backend =
config.backend isa KernelAbstractions.CPU ? config.backend : KernelAbstractions.CPU()
tlas = Raycore.TLAS(tlas_build_backend)
# push geometry / instances
Raycore.sync!(tlas)
kernel_tlas = Adapt.adapt(config.backend, tlas.static_tlas)
This gives correct Metal traversal results, but it means the GPU backends don't build the TLAS directly on GPU...
Once RayCore supports or fixes direct Metal TLAS construction (or Simon help me correct my mistakes 🙂), we should re-enable TLAS construction directly on the GPU:
tlas = Raycore.TLAS(config.backend)
Then we should validate the computation by passing the same validate=true checks than RayCore CPU (i.e. KernelAbstraction CPU) without silently falling back to the RasterCPUBackend. If this works, we could even remove this option of validation.
Details
This is a summary from Codex:
Direct Metal TLAS construction produces different raw hit stacks from the CPU RayCore reference on realistic scenes. The mismatch appeared before ArchimedLight reductions:
CPU-built static_tlas adapted to Metal gave exact raw-stack parity.
Metal-built TLAS produced missing/different hits.
Increasing max_hits_per_pixel did not resolve the mismatch.
No hit-buffer overflow was reported.
Raycore.all_hits! raw-hit mode, requested by passing a negative duplicate epsilon, still showed mismatches.
Instance-index and metadata decoding looked correct when using the CPU-built static_tlas.
This points to TLAS/BLAS construction or synchronization on Metal rather than ArchimedLight reduction logic.
Acceptance criteria
Add an option or restore default behavior so non-CPU RayCore backends can build the TLAS directly on config.backend.
Keep a CPU-built TLAS fallback/workaround available if needed for compatibility while RayCore support stabilizes.
Validate direct GPU TLAS construction against the existing raw-stack comparison tests:simple plant,
bundled coffee scene,
reduced agrivoltaics scene when available.
Direct GPU TLAS construction should pass the same validate=true RayCore CPU-reference checks without silently falling back to RasterCPUBackend.
Update GPU backend docs to explain the TLAS build mode and any remaining backend limitations.
Relevant code
Primary location:
src/interception.jl
_raycore_scene_data(...)
Current workaround:
tlas_build_backend =
config.backend isa KernelAbstractions.CPU ? config.backend : KernelAbstractions.CPU()
Target, once safe:
tlas_build_backend = config.backend
ArchimedLight currently works around a RayCore/Metal correctness issue by building the mutable RayCore TLAS on
KernelAbstractions.CPU()and then adapting the resultingtlas.static_tlasarrays to the requested backend.See my comment on RayCore here: JuliaGeometry/Raycore.jl#19 (comment)
Current behavior:
This gives correct Metal traversal results, but it means the GPU backends don't build the TLAS directly on GPU...
Once RayCore supports or fixes direct Metal TLAS construction (or Simon help me correct my mistakes 🙂), we should re-enable TLAS construction directly on the GPU:
Then we should validate the computation by passing the same
validate=truechecks than RayCore CPU (i.e. KernelAbstraction CPU) without silently falling back to the RasterCPUBackend. If this works, we could even remove this option of validation.Details
This is a summary from Codex:
Direct Metal TLAS construction produces different raw hit stacks from the CPU RayCore reference on realistic scenes. The mismatch appeared before ArchimedLight reductions:
CPU-built static_tlas adapted to Metal gave exact raw-stack parity.
Metal-built TLAS produced missing/different hits.
Increasing max_hits_per_pixel did not resolve the mismatch.
No hit-buffer overflow was reported.
Raycore.all_hits! raw-hit mode, requested by passing a negative duplicate epsilon, still showed mismatches.
Instance-index and metadata decoding looked correct when using the CPU-built static_tlas.
This points to TLAS/BLAS construction or synchronization on Metal rather than ArchimedLight reduction logic.
Acceptance criteria
Add an option or restore default behavior so non-CPU RayCore backends can build the TLAS directly on config.backend.
Keep a CPU-built TLAS fallback/workaround available if needed for compatibility while RayCore support stabilizes.
Validate direct GPU TLAS construction against the existing raw-stack comparison tests:simple plant,
bundled coffee scene,
reduced agrivoltaics scene when available.
Direct GPU TLAS construction should pass the same validate=true RayCore CPU-reference checks without silently falling back to RasterCPUBackend.
Update GPU backend docs to explain the TLAS build mode and any remaining backend limitations.
Relevant code
Primary location:
src/interception.jl
_raycore_scene_data(...)
Current workaround:
tlas_build_backend =
config.backend isa KernelAbstractions.CPU ? config.backend : KernelAbstractions.CPU()
Target, once safe:
tlas_build_backend = config.backend