Add DXIL Debugger Support for workgroup query functions

HLSL
WaveGetLaneCount()
WaveIsFirstLane()

DXIL
DXOp::WaveGetLaneCount
DXOp::WaveIsFirstLane
This commit is contained in:
Jake Turner
2025-04-06 12:39:11 +01:00
parent 5e6cfd73a0
commit e9f5c93062
3 changed files with 36 additions and 18 deletions
+31 -16
View File
@@ -1704,6 +1704,23 @@ bool ThreadState::JumpToBlock(const Block *target, bool divergencePoint)
return true;
}
void ThreadState::GetSubgroupActiveLanes(const rdcarray<bool> &activeMask,
const rdcarray<ThreadState> &workgroup,
rdcarray<uint32_t> &activeLanes) const
{
const uint32_t firstLaneInSub = m_WorkgroupIndex - m_SubgroupIdx;
for(uint32_t lane = firstLaneInSub; lane < firstLaneInSub + m_GlobalState.subgroupSize; lane++)
{
// wave operations exclude helpers
if(activeMask[lane])
{
if(!m_GlobalState.waveOpsIncludeHelpers && workgroup[lane - firstLaneInSub].m_Helper)
continue;
activeLanes.push_back(lane - firstLaneInSub);
}
}
}
bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
const rdcarray<ThreadState> &workgroup,
const rdcarray<bool> &activeMask)
@@ -3647,12 +3664,24 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
break;
}
// Wave/Subgroup Operations
case DXOp::WaveGetLaneCount:
{
result.value.u32v[0] = m_GlobalState.subgroupSize;
break;
}
case DXOp::WaveGetLaneIndex:
{
// SV_PrimitiveID
result.value.u32v[0] = m_SubgroupIdx;
break;
}
case DXOp::WaveIsFirstLane:
{
// determine active lane indices in our subgroup
rdcarray<uint32_t> activeLanes;
GetSubgroupActiveLanes(activeMask, workgroup, activeLanes);
result.value.u32v[0] = (m_WorkgroupIndex == activeLanes[0]) ? 1 : 0;
break;
}
case DXOp::WaveActiveOp:
{
// WaveActiveOp(value,op,sop)
@@ -3666,19 +3695,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
// determine active lane indices in our subgroup
rdcarray<uint32_t> activeLanes;
const uint32_t firstLaneInSub = m_WorkgroupIndex - m_SubgroupIdx;
for(uint32_t lane = firstLaneInSub; lane < firstLaneInSub + m_GlobalState.subgroupSize;
lane++)
{
// wave operations exclude helpers
if(activeMask[lane])
{
if(!m_GlobalState.waveOpsIncludeHelpers && workgroup[lane - firstLaneInSub].m_Helper)
continue;
activeLanes.push_back(lane - firstLaneInSub);
}
}
GetSubgroupActiveLanes(activeMask, workgroup, activeLanes);
ShaderVariable accum;
RDCASSERT(GetShaderVariable(inst.args[1], opCode, dxOpCode, accum));
@@ -4023,8 +4040,6 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
case DXOp::EmitThenCutStream:
// Wave/Subgroup Operations
case DXOp::WaveIsFirstLane:
case DXOp::WaveGetLaneCount:
case DXOp::WaveAnyTrue:
case DXOp::WaveAllTrue:
case DXOp::WaveActiveAllEqual:
@@ -302,6 +302,9 @@ struct ThreadState
bool IsVariableAssigned(const Id id) const;
ShaderVariable GetBuiltin(ShaderBuiltin builtin);
void GetSubgroupActiveLanes(const rdcarray<bool> &activeMask,
const rdcarray<ThreadState> &workgroup,
rdcarray<uint32_t> &activeLanes) const;
struct AnnotationProperties
{
@@ -1870,7 +1870,9 @@ rdcstr Program::GetDebugStatus()
"Only supported when debugging pixel shaders dx.op call `%s` %s",
callFunc->name.c_str(), ToStr(dxOpCode).c_str());
continue;
case DXOp::WaveGetLaneCount:
case DXOp::WaveGetLaneIndex:
case DXOp::WaveIsFirstLane:
case DXOp::WaveActiveOp:
if(!D3D_Hack_EnableGroups())
return StringFormat::Fmt("Unsupported dx.op call `%s` %s", callFunc->name.c_str(),
@@ -1896,8 +1898,6 @@ rdcstr Program::GetDebugStatus()
case DXOp::StorePatchConstant:
case DXOp::OutputControlPointID:
case DXOp::CycleCounterLegacy:
case DXOp::WaveIsFirstLane:
case DXOp::WaveGetLaneCount:
case DXOp::WaveAnyTrue:
case DXOp::WaveAllTrue:
case DXOp::WaveActiveAllEqual: