microsoft / microsoft/DirectXShaderCompiler
dxc moves wave intrisics out of a waterfall loop
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 3.7k
- Forks
- 900
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 44
Description
Description
The output of a wave intrinsic depends on the current state of which threads are active. When a wave intrinsic occurs in a loop it needs to execute in the loop body since the state of active threads changes over time (threads can exit the loop at different times). The shader in this bug shows a case where dxc is incorrectly moving wave intrinsics and their dependent operations out of a loop.
In this shader the InterlockedOr operation is only done once outside the loop, but it should be done inside the loop for each unique value of arrayIndex.
The bug only repros with lifetime markers enabled. If I compile with them off (either by default in the shader model or explicitly with a flag) the code looks correct. My guess is maybe jump-threading is interfering with the dx.break calls working as expected. Note that we also get correct code with partial lifetime markers -opt-enable partial-lifetime-markers .
Steps to Reproduce
// dxc /Tps_6_6 bug.hlsl
RWBuffer<uint> rwOutput : register(u0);
struct PixelInput {
uint m_InstanceID : PARAM0;
};
[earlydepthstencil]
void main(PixelInput input)
{
uint arrayIndex = input.m_InstanceID >> 5;
uint bitIndex = (input.m_InstanceID & 31);
bool isThisLaneNotDone = true;
do {
if (isThisLaneNotDone) {
uint firstLaneArrayIndex = WaveReadLaneFirst(arrayIndex);
if (firstLaneArrayIndex == arrayIndex) {
uint mask = WaveActiveBitOr(1u << bitIndex);
if (WaveIsFirstLane()) {
InterlockedOr(rwOutput[firstLaneArrayIndex], mask);
}
isThisLaneNotDone = false;
}
}
} while (isThisLaneNotDone);
}
Lifetime markers on
dxc /Tps_6_6 bug.hlsl
dxc /Tps_6_5 -enable-lifetime-markers bug.hlsl
Lifetime markers off
dxc /Tps_6_5 bug.hlsl
dxc /Tps_6_6 -disable-lifetime-markers bug.hlsl
Actual Behavior
The CFG with lifetime markers on shows the atomic operation is moved out of the loop.
Environment
- DXC version
dxcompiler.dll: 1.8 - 1.7.0.4383 (ad3958c2d); dxil.dll: 1.6(101.6.2104.33) - Host Operating System
Windows
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by compiling the reproduced bug.hlsl shader with lifetime markers enabled and disabled using the dxc commands in the issue, then compare the generated CFG. Trace the optimization responsible for moving the InterlockedOr out of the loop; done means the operation remains in the loop for each unique arrayIndex and the corrected behavior is verified in the generated CFG.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100