Skip to content

omm-allocaterayquery2-non-const-flags

Status: shipped (Phase 3) — see CHANGELOG.

(via ADR 0010)

What it detects

An AllocateRayQuery2(...) call (the DXR 1.2 form that takes both static and dynamic ray flags) whose first argument — the constant ray-flag bundle — is not a compile-time constant. Constant-folding through the AST identifies whether the argument resolves to a literal; the rule fires when it does not.

Why it matters on a GPU

AllocateRayQuery2(constFlags, dynFlags) is the DXR 1.2 split-flag intrinsic that lets the developer pass some ray flags as compile-time constants (which the compiler can pattern-match into specialised RayQuery template instantiations) and others as runtime values (which stay generic). The split exists so the compiler can specialise expensive ray-flag combinations — RAY_FLAG_FORCE_OPAQUE, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, the OMM flags — at compile time, while leaving cheap conditional flags (RAY_FLAG_SKIP_TRIANGLES based on a per-thread mask) for runtime.

The first argument must be a compile-time constant: the entire point of the split is that the compiler templates the RayQuery on its bits. DXC enforces this hard: a non-constant first argument is a compile error. The lint catches the more interesting cases that DXC may struggle with — for instance, an argument that comes from a static const global whose value is computed by an inline function, or an argument that is folded behind a #define whose macro expansion the AST shows but DXC's frontend treats opaquely.

The fix is to make the argument literal: either inline the value or move the runtime portion to the second dynFlags argument. The diagnostic names the call site and points at the spec.

Examples

Bad

hlsl
// First argument is computed at runtime — error.
RaytracingAccelerationStructure g_BVH : register(t0);
cbuffer Cfg : register(b0) { uint g_RuntimeFlags; }

[numthreads(8, 8, 1)]
void main(uint3 tid : SV_DispatchThreadID) {
    RayQuery q = AllocateRayQuery2(g_RuntimeFlags,                 // ERROR
                                    RAY_FLAG_NONE);
    q.TraceRayInline(g_BVH, 0, 0xFF, MakeRay(tid));
}

Good

hlsl
// Constant first argument; runtime bits go to the second argument.
RaytracingAccelerationStructure g_BVH : register(t0);
cbuffer Cfg : register(b0) { uint g_RuntimeFlags; }

[numthreads(8, 8, 1)]
void main(uint3 tid : SV_DispatchThreadID) {
    RayQuery q = AllocateRayQuery2(
        RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_CULL_NON_OPAQUE,
        g_RuntimeFlags);
    q.TraceRayInline(g_BVH, 0, 0xFF, MakeRay(tid));
}

Options

none

Fix availability

none — Splitting the argument requires authorial intent (which bits are static vs. dynamic).

See also


Edit this page

© 2026 NelCit, CC-BY-4.0.

© 2026 NelCit — Apache-2.0 (code), CC-BY-4.0 (docs).