DXIL Debugger Use DXIL Signature for the Inputs

Use the DXIL Signature input register and element linkage to extract the correct data from the initial values
This commit is contained in:
Jake Turner
2024-10-31 18:26:14 +00:00
parent b9372b403f
commit 281c34c922
3 changed files with 79 additions and 47 deletions
+33 -10
View File
@@ -3078,6 +3078,8 @@ struct PSInitialData
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
DXILDebug::ThreadState &activeState = debugger->GetActiveLane();
rdcarray<ShaderVariable> &ins = activeState.m_Input.members;
const rdcarray<DXIL::EntryPointInterface::Signature> &dxilInputs =
debugger->GetDXILEntryPointInputs();
// Fetch constant buffer data from root signature
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.graphics, refl,
@@ -3086,15 +3088,35 @@ struct PSInitialData
// TODO SAMPLE EVALUTE MASK
// globalState.sampleEvalRegisterMask = sampleEvalRegisterMask;
// The initial values are packed into register and elements
// DXIL Inputs are not packed and contain the register and element linkage
rdcarray<DXILDebug::PSInputData> psInputDatas;
for(int i = 0; i < initialValues.count(); i++)
{
PSInputElement &elem = initialValues[i];
if(elem.reg >= 0)
psInputDatas.emplace_back(i, elem.numwords, elem.sysattribute, elem.included, data);
PSInputElement &inputElement = initialValues[i];
int packedRegister = inputElement.reg;
if(packedRegister >= 0)
{
int dxilInputIdx = -1;
int packedElement = inputElement.elem;
// Find the DXIL Input index and element from that matches the register and element
for(int j = 0; j < dxilInputs.count(); ++j)
{
const DXIL::EntryPointInterface::Signature &dxilParam = dxilInputs[j];
if((dxilParam.startRow == (int32_t)packedRegister) && (dxilParam.startCol == packedElement))
{
dxilInputIdx = j;
break;
}
}
RDCASSERT(dxilInputIdx >= 0);
if(elem.included)
data += elem.numwords;
psInputDatas.emplace_back(dxilInputIdx, inputElement.numwords, inputElement.sysattribute,
inputElement.included, data);
}
if(inputElement.included)
data += inputElement.numwords;
}
{
@@ -3110,26 +3132,27 @@ struct PSInitialData
int32_t *rawout = NULL;
ShaderVariable &invar = ins[psInput.input];
int outElement = 0;
if(psInput.sysattribute == ShaderBuiltin::PrimitiveIndex)
{
invar.value.u32v[0] = pHit->primitive;
invar.value.u32v[outElement] = pHit->primitive;
}
else if(psInput.sysattribute == ShaderBuiltin::MSAASampleIndex)
{
invar.value.u32v[0] = pHit->sample;
invar.value.u32v[outElement] = pHit->sample;
}
else if(psInput.sysattribute == ShaderBuiltin::MSAACoverage)
{
invar.value.u32v[0] = pHit->coverage;
invar.value.u32v[outElement] = pHit->coverage;
}
else if(psInput.sysattribute == ShaderBuiltin::IsFrontFace)
{
invar.value.u32v[0] = pHit->isFrontFace ? ~0U : 0;
invar.value.u32v[outElement] = pHit->isFrontFace ? ~0U : 0;
}
else
{
rawout = &invar.value.s32v[0];
rawout = &invar.value.s32v[outElement];
memcpy(rawout, psInput.data, psInput.numwords * 4);
}
}
+41 -37
View File
@@ -5710,11 +5710,23 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
ParseDebugData();
// Add inputs to the shader trace
const rdcarray<SigParameter> &inParams = dxbcContainer->GetReflection()->InputSig;
// Use the DXIL reflection data to map the input signature to input variables
const EntryPointInterface *entryPointIf = NULL;
for(size_t e = 0; e < m_Program->m_EntryPointInterfaces.size(); ++e)
{
if(entryFunction == m_Program->m_EntryPointInterfaces[e].name)
{
entryPointIf = &m_Program->m_EntryPointInterfaces[e];
break;
}
}
RDCASSERT(entryPointIf);
m_EntryPointInterface = entryPointIf;
const rdcarray<EntryPointInterface::Signature> &inputs = m_EntryPointInterface->inputs;
// TODO: compute this from DXIL
// TODO: compute coverage from DXIL
const bool inputCoverage = false;
const uint32_t countInParams = (uint32_t)inParams.size();
const uint32_t countInParams = (uint32_t)inputs.size();
if(countInParams || inputCoverage)
{
@@ -5726,46 +5738,42 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
inStruct.type = VarType::Struct;
inStruct.members.resize(countInParams + (inputCoverage ? 1 : 0));
for(uint32_t sigIdx = 0; sigIdx < countInParams; sigIdx++)
const rdcarray<SigParameter> &dxbcInParams = dxbcContainer->GetReflection()->InputSig;
for(uint32_t i = 0; i < countInParams; ++i)
{
const SigParameter &sig = inParams[sigIdx];
const EntryPointInterface::Signature &sig = inputs[i];
ShaderVariable v;
v.name = sig.semanticIdxName;
v.rows = 1;
v.columns = (uint8_t)sig.compCount;
v.type = sig.varType;
ShaderVariable &v = inStruct.members[i];
ShaderVariable &dst = inStruct.members[sigIdx];
// if the variable hasn't been initialised, just assign. If it has, we're in a situation
// where two input parameters are assigned to the same variable overlapping, so just update
// the number of columns to the max of both. The source mapping (either from debug info or
// our own below) will handle distinguishing better.
if(dst.name.empty())
dst = v;
// Get the name from the DXBC reflection
SigParameter sigParam;
if(FindSigParameter(dxbcInParams, sig, sigParam))
{
v.name = sigParam.semanticIdxName;
}
else
dst.columns = RDCMAX(dst.columns, v.columns);
{
v.name = sig.name;
}
v.rows = (uint8_t)sig.rows;
v.columns = (uint8_t)sig.cols;
v.type = VarTypeForComponentType(sig.type);
SourceVariableMapping inputMapping;
inputMapping.name = v.name;
inputMapping.type = v.type;
inputMapping.rows = 1;
inputMapping.columns = sig.compCount;
inputMapping.signatureIndex = sigIdx;
inputMapping.variables.reserve(sig.compCount);
for(uint32_t c = 0; c < 4; c++)
inputMapping.rows = sig.rows;
inputMapping.columns = sig.cols;
inputMapping.variables.reserve(sig.cols);
inputMapping.signatureIndex = sig.startRow;
for(uint32_t c = 0; c < sig.cols; ++c)
{
if(sig.regChannelMask & (1 << c))
{
DebugVariableReference ref;
ref.type = DebugVariableType::Input;
ref.name = inStruct.name + "." + v.name;
ref.component = c;
inputMapping.variables.push_back(ref);
}
DebugVariableReference ref;
ref.type = DebugVariableType::Input;
ref.name = inStruct.name + "." + v.name;
ref.component = c;
inputMapping.variables.push_back(ref);
}
// ret->sourceVars.push_back(inputMapping);
// Put the coverage mask at the end
if(inputCoverage)
@@ -5830,10 +5838,6 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
ShaderVariable &dst = outStruct.members[sigIdx];
// if the variable hasn't been initialised, just assign. If it has, we're in a situation where
// two input parameters are assigned to the same variable overlapping, so just update the
// number of columns to the max of both. The source mapping (either from debug info or our own
// below) will handle distinguishing better.
if(dst.name.empty())
dst = v;
else
@@ -424,6 +424,10 @@ public:
const DXBC::DXBCContainer *const GetDXBCContainer() { return m_DXBC; }
uint32_t GetEventId() { return m_EventId; }
const FunctionInfo *GetFunctionInfo(const DXIL::Function *function) const;
const rdcarray<DXIL::EntryPointInterface::Signature> &GetDXILEntryPointInputs(void) const
{
return m_EntryPointInterface->inputs;
}
private:
void CalcActiveMask(rdcarray<bool> &activeMask);
@@ -456,6 +460,7 @@ private:
const DXBC::DXBCContainer *m_DXBC = NULL;
const DXIL::Program *m_Program = NULL;
const DXIL::Function *m_EntryPointFunction = NULL;
const DXIL::EntryPointInterface *m_EntryPointInterface = NULL;
ShaderStage m_Stage;
uint32_t m_EventId = 0;