From 474d91973994dffdf9ecd8d82c229c8c2ec54c12 Mon Sep 17 00:00:00 2001 From: Stefan Werner Date: Tue, 27 Oct 2026 11:24:36 +0100 Subject: [PATCH] Fix SYCL instID[0] corruption when RTC_MAX_INSTANCE_LEVEL_COUNT > 1 embree_instanced_geometry_sycl.exe produced wrong (uncolored) output compared to the CPU reference tutorial whenever RTC_MAX_INSTANCE_LEVEL_COUNT was built as 2 (it matched when built as 1). Root cause: instance_id_stack::copy_UU() in kernels/common/instance_stack.h filled the instID array using two separate loops with a runtime-variable split point (depth = context->instStackSize): for (l = 0; l < depth; ++l) tgt[l] = src[l]; for (l = depth; l < MAX; ++l) tgt[l] = RTC_INVALID_GEOMETRY_ID; On the Intel GPU SYCL/DPC++ toolchain used for the HW raytracing backend, this two-loop pattern gets miscompiled when depth is a runtime value: the copied value and the invalidation marker end up swapped between tgt[0] and tgt[1]. This was confirmed via device-side printf tracing, showing the valid instance id landing in instID[1] instead of instID[0], so ray.instID[0] (the field tutorials/apps actually read) was always RTC_INVALID_GEOMETRY_ID. This only affects RTC_MAX_INSTANCE_LEVEL_COUNT > 1, because the ==1 case uses a trivial single assignment (tgt[0] = src[0]) with no loop. Fix: replace the two loops with a single fused loop using a per-element ternary, which avoids the problematic codegen pattern: for (l = 0; l < MAX; ++l) tgt[l] = (l < depth) ? src[l] : RTC_INVALID_GEOMETRY_ID; Verified on real Intel Arc B580 hardware: embree_instanced_geometry_sycl.exe built with RTC_MAX_INSTANCE_LEVEL_COUNT=2 now produces pixel-identical output (0 differing pixels) to embree_instanced_geometry.exe (CPU reference), matching the already-correct RTC_MAX_INSTANCE_LEVEL_COUNT=1 build. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- kernels/common/instance_stack.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/kernels/common/instance_stack.h b/kernels/common/instance_stack.h index f4cf821c05..3545950eac 100644 --- a/kernels/common/instance_stack.h +++ b/kernels/common/instance_stack.h @@ -160,12 +160,15 @@ RTC_FORCEINLINE void copy_UU(const RTCRayQueryContext* context, const unsigned* #else unsigned int depth = context->instStackSize; - - for (unsigned l = 0; l < depth; ++l) - tgt[l] = src[l]; - - for (unsigned l = depth; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) - tgt[l] = RTC_INVALID_GEOMETRY_ID; + + /* NOTE: Splitting this into two separate loops (one copying the first + * `depth` elements, one filling the remainder with + * RTC_INVALID_GEOMETRY_ID) has been observed to get miscompiled by some + * SYCL/GPU compilers when `depth` is a runtime value, silently reversing + * which elements get the copied value and which get invalidated. Using a + * single fused loop with a per-element select avoids triggering this. */ + for (unsigned l = 0; l < RTC_MAX_INSTANCE_LEVEL_COUNT; ++l) + tgt[l] = (l < depth) ? src[l] : RTC_INVALID_GEOMETRY_ID; #endif }