// rayQuery picking smoke test (WebGPU/DOM software ray-query path).
//
// Shoots a single, fully-determined ray at a known TLAS instance through
// the injected `rayQuery*` shim and records the committed hit into a
// storage buffer the host reads back. The whole point is to exercise
// `_rqTraverseTlas`'s TLAS descent for a realistic (< 8193) instance
// count — the regime where a hardcoded 16384-leaf start makes every node
// look internal and the pick always misses (issue #25).
//
// rayQuery=true ⇒ @group(1) is the reserved RT heap (do NOT declare it).
// User bindings live at @group(2)+; the optional push uniform at @group(0).

struct PushData {
    origin: vec3<f32>,
    _p0:    f32,
    dir:    vec3<f32>,
    _p1:    f32,
};
@group(0) @binding(0) var<uniform> push : PushData;

struct PickResult {
    hit:                 u32,   // 1 = committed triangle hit, 0 = miss
    instanceCustomIndex: u32,
    primitiveIndex:      u32,
    tHit:                f32,
};
@group(2) @binding(0) var<storage, read_write> result : PickResult;

@compute @workgroup_size(1)
fn main() {
    var rq: RayQuery;
    rayQueryInitialize(&rq, 0u, RT_FLAG_OPAQUE, 0xFFu,
                       push.origin, 0.001, push.dir, 10000.0);
    // Software shim resolves the whole traversal in one proceed call.
    while (rayQueryProceed(&rq)) {}

    if (rayQueryGetCommittedIntersectionType(&rq) != RT_INTERSECTION_NONE) {
        result.hit                 = 1u;
        result.instanceCustomIndex = rayQueryGetCommittedInstanceCustomIndex(&rq);
        result.primitiveIndex      = rayQueryGetCommittedPrimitiveIndex(&rq);
        result.tHit                = rayQueryGetCommittedT(&rq);
    } else {
        result.hit                 = 0u;
        result.instanceCustomIndex = 0xFFFFFFFFu;
        result.primitiveIndex      = 0xFFFFFFFFu;
        result.tHit                = -1.0;
    }
}
