Control Flow, Attributes & Functions
These are *hints*; DXC (LLVM) often makes its own decisions, but [unroll] and [loop] are generally honored.
11.1 Statements
if (x > 0) { ... } else if (x < 0) { ... } else { ... }
for (int i = 0; i < 8; ++i) { if (i == 3) continue; if (i == 6) break; }
while (n > 1) { n >>= 1; }
do { k++; } while (k < 4);
switch (mode)
{
case 0: color = float3(1, 0, 0); break;
case 1: color = float3(0, 1, 0); break;
default: color = 0; break;
}
clip(alpha - 0.5); // PS: discard pixel if any component < 0
if (alpha < 0.5) discard; // PS: explicit discard11.2 Flow-control attributes
[unroll] / [unroll(n)] fully unroll (or by factor n); requires a compile-time trip count for full unroll keep as a real loop (no unrolling) reduce compile time; less optimization (FXC) allow loop condition that depends on a UAV read (FXC) emit a real (dynamic) branch evaluate both sides and select (no branch) [forcecase], [call] jump table / subroutine (FXC)
These are *hints*; DXC (LLVM) often makes its own decisions, but [unroll] and [loop] are generally honored.
[unroll]
for (int i = 0; i < 9; ++i) sum += tex.Sample(s, uv + offsets[i]) * weights[i];
[branch]
if (shadowEnabled) // uniform across the draw: a cheap, coherent branch
lit *= ComputeShadow(posLS);
[flatten]
if (x > 0.5) y = a; else y = b; // tiny bodies: select is cheaper than a branch11.3 Divergence
Branches are free when all lanes in a wave take the same path (uniform/coherent). When lanes diverge, the wave executes both paths with masking. Gradient operations (Sample, ddx) inside divergent flow are undefined in pixel shaders — use SampleLevel/SampleGrad there, or compute derivatives before the branch.
11.4 Functions
Out parameters are copy-out, not references. inout copies in then out (no aliasing). HLSL 2021 adds member functions in structs and templates (Chapter 35).
// Parameters: in (default, by value), out (write-only), inout (copy in/out)
void ComputeLight(in float3 N, in float3 L, out float diffuse, inout float3 accum)
{
diffuse = saturate(dot(N, L));
accum += diffuse;
}
// Overloading by parameter types
float Square(float x) { return x * x; }
float3 Square(float3 x) { return x * x; }
// Default parameter values
float4 Tint(float4 c, float amount = 0.5) { return lerp(c, float4(1, 0.8, 0.6, 1), amount); }
// 'inline' is implied — all functions are inlined; recursion is not allowed