diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index 65068f28b..49e4e8eaa 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -3078,6 +3078,8 @@ struct PSInitialData DXILDebug::GlobalState &globalState = debugger->GetGlobalState(); DXILDebug::ThreadState &activeState = debugger->GetActiveLane(); rdcarray &ins = activeState.m_Input.members; + const rdcarray &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 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); } } diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.cpp b/renderdoc/driver/shaders/dxil/dxil_debug.cpp index 2d57a834e..f41fb540b 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debug.cpp @@ -5710,11 +5710,23 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain ParseDebugData(); // Add inputs to the shader trace - const rdcarray &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 &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 &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 diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.h b/renderdoc/driver/shaders/dxil/dxil_debug.h index 6eb3031b2..47992bf66 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.h +++ b/renderdoc/driver/shaders/dxil/dxil_debug.h @@ -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 &GetDXILEntryPointInputs(void) const + { + return m_EntryPointInterface->inputs; + } private: void CalcActiveMask(rdcarray &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;