mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-11-02 20:18:36 +00:00
Rework DXIL D3D12APIWrapper helper in preparation for Multithreading
Make it persistent in the lifetime of the DXIL Debugger session Add the wrapper to the DXIL Debugger Make the wrapper replay reset consistent Store initialisation data in the ApiWrapper Pull data from ApiWrapper into Debugger during BeginDebug() Makes DXIL debugger behave more like SPIRV debugger during its initialisation
This commit is contained in:
1 parent
1ea88a43f2
commit
0dba797e30
5 files changed
+900
-726
No files matched your search
@@ -134,7 +134,7 @@ static bool IsShaderParameterVisible(DXBC::ShaderType shaderType,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void FillViewFmtFromResourceFormat(DXGI_FORMAT format, GlobalState::ViewFmt &viewFmt)
|
||||
static void FillViewFmtFromResourceFormat(DXGI_FORMAT format, ViewFmt &viewFmt)
|
||||
{
|
||||
RDCASSERT(format != DXGI_FORMAT_UNKNOWN);
|
||||
ResourceFormat fmt = MakeResourceFormat(format);
|
||||
@@ -190,315 +190,6 @@ static uint32_t GetSRVBufferStrideFromShaderMetadata(const DXIL::EntryPointInter
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FlattenSingleVariable(const rdcstr &cbufferName, uint32_t byteOffset,
|
||||
const rdcstr &basename, const ShaderVariable &v,
|
||||
rdcarray<ShaderVariable> &outvars,
|
||||
rdcarray<SourceVariableMapping> &sourcevars)
|
||||
{
|
||||
size_t outIdx = byteOffset / 16;
|
||||
size_t outComp = (byteOffset % 16) / 4;
|
||||
|
||||
if(v.RowMajor())
|
||||
outvars.resize(RDCMAX(outIdx + v.rows, outvars.size()));
|
||||
else
|
||||
outvars.resize(RDCMAX(outIdx + v.columns, outvars.size()));
|
||||
|
||||
if(outvars[outIdx].columns > 0)
|
||||
{
|
||||
// if we already have a variable in this slot, just copy the data for this variable and add
|
||||
// the source mapping. We should not overlap into the next register as that's not allowed.
|
||||
memcpy(&outvars[outIdx].value.u32v[outComp], &v.value.u32v[0], sizeof(uint32_t) * v.columns);
|
||||
uint32_t oldColumns = outvars[outIdx].columns;
|
||||
uint32_t newColumns = (uint32_t)(outComp + v.columns);
|
||||
uint32_t numColumns = RDCMAX(oldColumns, newColumns);
|
||||
numColumns = RDCMIN(4U, numColumns);
|
||||
outvars[outIdx].columns = (uint8_t)numColumns;
|
||||
|
||||
SourceVariableMapping mapping;
|
||||
mapping.name = basename;
|
||||
mapping.type = v.type;
|
||||
mapping.rows = v.rows;
|
||||
mapping.columns = v.columns;
|
||||
mapping.offset = byteOffset;
|
||||
mapping.variables.resize(v.columns);
|
||||
|
||||
for(int i = 0; i < v.columns; i++)
|
||||
{
|
||||
mapping.variables[i].type = DebugVariableType::Constant;
|
||||
mapping.variables[i].name = StringFormat::Fmt("%s[%u]", cbufferName.c_str(), outIdx);
|
||||
mapping.variables[i].component = uint16_t(outComp + i);
|
||||
}
|
||||
|
||||
sourcevars.push_back(mapping);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t numRegisters = v.RowMajor() ? v.rows : v.columns;
|
||||
for(uint32_t reg = 0; reg < numRegisters; reg++)
|
||||
{
|
||||
outvars[outIdx + reg].rows = 1;
|
||||
outvars[outIdx + reg].type = v.type;
|
||||
outvars[outIdx + reg].columns = v.columns + (uint8_t)outComp;
|
||||
outvars[outIdx + reg].flags = v.flags;
|
||||
}
|
||||
|
||||
if(v.RowMajor())
|
||||
{
|
||||
for(size_t ri = 0; ri < v.rows; ri++)
|
||||
memcpy(&outvars[outIdx + ri].value.u32v[outComp], &v.value.u32v[ri * v.columns],
|
||||
sizeof(uint32_t) * v.columns);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we have a matrix stored in column major order, we need to transpose it back so we can
|
||||
// unroll it into vectors.
|
||||
for(size_t ci = 0; ci < v.columns; ci++)
|
||||
for(size_t ri = 0; ri < v.rows; ri++)
|
||||
outvars[outIdx + ci].value.u32v[ri] = v.value.u32v[ri * v.columns + ci];
|
||||
}
|
||||
|
||||
SourceVariableMapping mapping;
|
||||
mapping.name = basename;
|
||||
mapping.type = v.type;
|
||||
mapping.rows = v.rows;
|
||||
mapping.columns = v.columns;
|
||||
mapping.offset = byteOffset;
|
||||
mapping.variables.resize(v.rows * v.columns);
|
||||
|
||||
RDCASSERT(outComp == 0 || v.rows == 1, outComp, v.rows);
|
||||
|
||||
size_t i = 0;
|
||||
for(uint8_t r = 0; r < v.rows; r++)
|
||||
{
|
||||
for(uint8_t c = 0; c < v.columns; c++)
|
||||
{
|
||||
size_t regIndex = outIdx + (v.RowMajor() ? r : c);
|
||||
size_t compIndex = outComp + (v.RowMajor() ? c : r);
|
||||
|
||||
mapping.variables[i].type = DebugVariableType::Constant;
|
||||
mapping.variables[i].name = StringFormat::Fmt("%s[%zu]", cbufferName.c_str(), regIndex);
|
||||
mapping.variables[i].component = uint16_t(compIndex);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
sourcevars.push_back(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
static void FlattenVariables(const rdcstr &cbufferName, const rdcarray<ShaderConstant> &constants,
|
||||
const rdcarray<ShaderVariable> &invars,
|
||||
rdcarray<ShaderVariable> &outvars, const rdcstr &prefix,
|
||||
uint32_t baseOffset, rdcarray<SourceVariableMapping> &sourceVars)
|
||||
{
|
||||
RDCASSERTEQUAL(constants.size(), invars.size());
|
||||
|
||||
for(size_t i = 0; i < constants.size(); i++)
|
||||
{
|
||||
const ShaderConstant &c = constants[i];
|
||||
const ShaderVariable &v = invars[i];
|
||||
|
||||
uint32_t byteOffset = baseOffset + c.byteOffset;
|
||||
|
||||
rdcstr basename = prefix + rdcstr(v.name);
|
||||
|
||||
if(v.type == VarType::Struct)
|
||||
{
|
||||
// check if this is an array of structs or not
|
||||
if(c.type.elements == 1)
|
||||
{
|
||||
FlattenVariables(cbufferName, c.type.members, v.members, outvars, basename + ".",
|
||||
byteOffset, sourceVars);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int m = 0; m < v.members.count(); m++)
|
||||
{
|
||||
FlattenVariables(cbufferName, c.type.members, v.members[m].members, outvars,
|
||||
StringFormat::Fmt("%s[%zu].", basename.c_str(), m),
|
||||
byteOffset + m * c.type.arrayByteStride, sourceVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(c.type.elements > 1 || (v.rows == 0 && v.columns == 0) || !v.members.empty())
|
||||
{
|
||||
for(int m = 0; m < v.members.count(); m++)
|
||||
{
|
||||
FlattenSingleVariable(cbufferName, byteOffset + m * c.type.arrayByteStride,
|
||||
StringFormat::Fmt("%s[%zu]", basename.c_str(), m), v.members[m],
|
||||
outvars, sourceVars);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FlattenSingleVariable(cbufferName, byteOffset, basename, v, outvars, sourceVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void AddCBufferToGlobalState(const DXIL::Program *program, GlobalState &global,
|
||||
rdcarray<SourceVariableMapping> &sourceVars,
|
||||
const ShaderReflection &refl, const BindingSlot &slot,
|
||||
bytebuf &cbufData)
|
||||
{
|
||||
// Find the identifier
|
||||
size_t numCBs = refl.constantBlocks.size();
|
||||
for(size_t i = 0; i < numCBs; ++i)
|
||||
{
|
||||
const ConstantBlock &cb = refl.constantBlocks[i];
|
||||
if(slot.registerSpace == (uint32_t)cb.fixedBindSetOrSpace &&
|
||||
slot.shaderRegister >= (uint32_t)cb.fixedBindNumber &&
|
||||
slot.shaderRegister < (uint32_t)(cb.fixedBindNumber + cb.bindArraySize))
|
||||
{
|
||||
uint32_t arrayIndex = slot.shaderRegister - cb.fixedBindNumber;
|
||||
|
||||
rdcarray<ShaderVariable> &targetVars =
|
||||
cb.bindArraySize > 1 ? global.constantBlocks[i].members[arrayIndex].members
|
||||
: global.constantBlocks[i].members;
|
||||
RDCASSERTMSG("Reassigning previously filled cbuffer", targetVars.empty());
|
||||
|
||||
ConstantBlockReference constantBlockRef = {i, arrayIndex};
|
||||
global.constantBlocksDatas[constantBlockRef] = cbufData;
|
||||
rdcstr resName = Debugger::GetResourceReferenceName(program, ResourceClass::CBuffer, slot);
|
||||
global.constantBlocks[i].name = resName;
|
||||
|
||||
SourceVariableMapping cbSourceMapping;
|
||||
cbSourceMapping.name = refl.constantBlocks[i].name;
|
||||
cbSourceMapping.variables.push_back(
|
||||
DebugVariableReference(DebugVariableType::Constant, global.constantBlocks[i].name));
|
||||
sourceVars.push_back(cbSourceMapping);
|
||||
|
||||
rdcstr identifierPrefix = global.constantBlocks[i].name;
|
||||
rdcstr variablePrefix = refl.constantBlocks[i].name;
|
||||
if(cb.bindArraySize > 1)
|
||||
{
|
||||
identifierPrefix =
|
||||
StringFormat::Fmt("%s[%u]", global.constantBlocks[i].name.c_str(), arrayIndex);
|
||||
variablePrefix = StringFormat::Fmt("%s[%u]", refl.constantBlocks[i].name.c_str(), arrayIndex);
|
||||
|
||||
// The above sourceVar is for the logical identifier, and FlattenVariables adds the
|
||||
// individual elements of the constant buffer. For CB arrays, add an extra source
|
||||
// var for the CB array index
|
||||
SourceVariableMapping cbArrayMapping;
|
||||
global.constantBlocks[i].members[arrayIndex].name = StringFormat::Fmt("[%u]", arrayIndex);
|
||||
cbArrayMapping.name = variablePrefix;
|
||||
cbArrayMapping.variables.push_back(
|
||||
DebugVariableReference(DebugVariableType::Constant, identifierPrefix));
|
||||
sourceVars.push_back(cbArrayMapping);
|
||||
}
|
||||
const rdcarray<ShaderConstant> &constants =
|
||||
(cb.bindArraySize > 1) ? refl.constantBlocks[i].variables[0].type.members
|
||||
: refl.constantBlocks[i].variables;
|
||||
|
||||
rdcarray<ShaderVariable> vars;
|
||||
StandardFillCBufferVariables(refl.resourceId, constants, vars, cbufData);
|
||||
FlattenVariables(identifierPrefix, constants, vars, targetVars, variablePrefix + ".", 0,
|
||||
sourceVars);
|
||||
for(size_t c = 0; c < targetVars.size(); c++)
|
||||
targetVars[c].name = StringFormat::Fmt("[%u]", (uint32_t)c);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FetchConstantBufferData(WrappedID3D12Device *device, const DXIL::Program *program,
|
||||
const D3D12RenderState::RootSignature &rootsig,
|
||||
const ShaderReflection &refl, GlobalState &global,
|
||||
rdcarray<SourceVariableMapping> &sourceVars)
|
||||
{
|
||||
WrappedID3D12RootSignature *pD3D12RootSig =
|
||||
device->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rootsig.rootsig);
|
||||
const DXBC::ShaderType shaderType = program->GetShaderType();
|
||||
|
||||
size_t numParams = RDCMIN(pD3D12RootSig->sig.Parameters.size(), rootsig.sigelems.size());
|
||||
for(size_t i = 0; i < numParams; i++)
|
||||
{
|
||||
const D3D12RootSignatureParameter &rootSigParam = pD3D12RootSig->sig.Parameters[i];
|
||||
const D3D12RenderState::SignatureElement &element = rootsig.sigelems[i];
|
||||
if(IsShaderParameterVisible(shaderType, rootSigParam.ShaderVisibility))
|
||||
{
|
||||
if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS &&
|
||||
element.type == eRootConst)
|
||||
{
|
||||
BindingSlot slot(rootSigParam.Constants.ShaderRegister, rootSigParam.Constants.RegisterSpace);
|
||||
UINT sizeBytes = sizeof(uint32_t) * RDCMIN(rootSigParam.Constants.Num32BitValues,
|
||||
(UINT)element.constants.size());
|
||||
bytebuf cbufData((const byte *)element.constants.data(), sizeBytes);
|
||||
AddCBufferToGlobalState(program, global, sourceVars, refl, slot, cbufData);
|
||||
}
|
||||
else if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV && element.type == eRootCBV)
|
||||
{
|
||||
BindingSlot slot(rootSigParam.Descriptor.ShaderRegister,
|
||||
rootSigParam.Descriptor.RegisterSpace);
|
||||
ID3D12Resource *cbv = device->GetResourceManager()->GetCurrentAs<ID3D12Resource>(element.id);
|
||||
bytebuf cbufData;
|
||||
device->GetDebugManager()->GetBufferData(cbv, element.offset, 0, cbufData);
|
||||
AddCBufferToGlobalState(program, global, sourceVars, refl, slot, cbufData);
|
||||
}
|
||||
else if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE &&
|
||||
element.type == eRootTable)
|
||||
{
|
||||
UINT prevTableOffset = 0;
|
||||
WrappedID3D12DescriptorHeap *heap =
|
||||
device->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(element.id);
|
||||
|
||||
size_t numRanges = rootSigParam.ranges.size();
|
||||
for(size_t r = 0; r < numRanges; r++)
|
||||
{
|
||||
// For this traversal we only care about CBV descriptor ranges, but we still need to
|
||||
// calculate the table offsets in case a descriptor table has a combination of
|
||||
// different range types
|
||||
const D3D12_DESCRIPTOR_RANGE1 &range = rootSigParam.ranges[r];
|
||||
|
||||
UINT offset = range.OffsetInDescriptorsFromTableStart;
|
||||
if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
|
||||
offset = prevTableOffset;
|
||||
|
||||
D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr;
|
||||
desc += element.offset;
|
||||
desc += offset;
|
||||
|
||||
UINT numDescriptors = range.NumDescriptors;
|
||||
if(numDescriptors == UINT_MAX)
|
||||
{
|
||||
// Find out how many descriptors are left after
|
||||
numDescriptors = heap->GetNumDescriptors() - offset - (UINT)element.offset;
|
||||
|
||||
// TODO: Look up the bind point in the D3D12 state to try to get
|
||||
// a better guess at the number of descriptors
|
||||
}
|
||||
|
||||
prevTableOffset = offset + numDescriptors;
|
||||
|
||||
if(range.RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_CBV)
|
||||
continue;
|
||||
|
||||
BindingSlot slot(range.BaseShaderRegister, range.RegisterSpace);
|
||||
|
||||
bytebuf cbufData;
|
||||
for(UINT n = 0; n < numDescriptors; ++n, ++slot.shaderRegister)
|
||||
{
|
||||
const D3D12_CONSTANT_BUFFER_VIEW_DESC &cbv = desc->GetCBV();
|
||||
ResourceId resId;
|
||||
uint64_t byteOffset = 0;
|
||||
WrappedID3D12Resource::GetResIDFromAddr(cbv.BufferLocation, resId, byteOffset);
|
||||
ID3D12Resource *pCbvResource =
|
||||
device->GetResourceManager()->GetCurrentAs<ID3D12Resource>(resId);
|
||||
cbufData.clear();
|
||||
|
||||
if(cbv.SizeInBytes > 0)
|
||||
device->GetDebugManager()->GetBufferData(pCbvResource, byteOffset, cbv.SizeInBytes,
|
||||
cbufData);
|
||||
AddCBufferToGlobalState(program, global, sourceVars, refl, slot, cbufData);
|
||||
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InterpolationMode GetInterpolationModeForInputParam(const SigParameter &sig,
|
||||
const rdcarray<SigParameter> &stageInputSig,
|
||||
const DXIL::Program *program)
|
||||
@@ -568,34 +259,458 @@ void GetInterpolationModeForInputParams(const rdcarray<SigParameter> &inputSig,
|
||||
}
|
||||
}
|
||||
|
||||
D3D12APIWrapper::D3D12APIWrapper(WrappedID3D12Device *device, const DXIL::Program &dxilProgram,
|
||||
GlobalState &globalState, uint32_t eventId)
|
||||
D3D12APIWrapper::D3D12APIWrapper(WrappedID3D12Device *device, const DXIL::Program *dxilProgram,
|
||||
const ShaderReflection &refl, uint32_t eventId,
|
||||
const rdcarray<SigParameter> &inputSig)
|
||||
: m_Device(device),
|
||||
m_EntryPointInterface(dxilProgram.GetEntryPointInterface()),
|
||||
m_GlobalState(globalState),
|
||||
m_ShaderType(dxilProgram.GetShaderType()),
|
||||
m_EventId(eventId)
|
||||
m_EntryPointInterface(dxilProgram->GetEntryPointInterface()),
|
||||
m_ShaderType(dxilProgram->GetShaderType()),
|
||||
m_EventId(eventId),
|
||||
m_Program(dxilProgram),
|
||||
m_Reflection(refl)
|
||||
{
|
||||
// Create the storage layout for the constant buffers
|
||||
// The constant buffer data and details are filled in outside of this method
|
||||
size_t count = refl.constantBlocks.size();
|
||||
m_ConstantBlocks.resize(count);
|
||||
for(uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
m_ConstantBlocks[i].type = VarType::ConstantBlock;
|
||||
const ConstantBlock &cb = m_Reflection.constantBlocks[i];
|
||||
uint32_t bindCount = cb.bindArraySize;
|
||||
if(bindCount > 1)
|
||||
{
|
||||
// Create nested structure for constant buffer array
|
||||
m_ConstantBlocks[i].members.resize(bindCount);
|
||||
}
|
||||
}
|
||||
|
||||
// Add inputs to the shader trace
|
||||
const rdcarray<EntryPointInterface::Signature> &inputs = m_EntryPointInterface->inputs;
|
||||
|
||||
const uint32_t countInParams = (uint32_t)inputs.size();
|
||||
if(countInParams)
|
||||
{
|
||||
// Make fake ShaderVariable struct to hold all the inputs
|
||||
ShaderVariable &inStruct = m_InputPlaceholder;
|
||||
inStruct.name = DXIL_FAKE_INPUT_STRUCT_NAME;
|
||||
inStruct.rows = 0;
|
||||
inStruct.columns = 0;
|
||||
inStruct.type = VarType::Struct;
|
||||
inStruct.members.resize(countInParams);
|
||||
|
||||
for(uint32_t i = 0; i < countInParams; ++i)
|
||||
{
|
||||
const EntryPointInterface::Signature &sig = inputs[i];
|
||||
|
||||
ShaderVariable &v = inStruct.members[i];
|
||||
|
||||
// Get the name from the DXBC reflection
|
||||
SigParameter sigParam;
|
||||
if(FindSigParameter(inputSig, sig, sigParam))
|
||||
{
|
||||
v.name = sigParam.semanticIdxName;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.name = sig.name;
|
||||
}
|
||||
v.rows = (uint8_t)sig.rows;
|
||||
v.columns = (uint8_t)sig.cols;
|
||||
v.type = VarTypeForComponentType(sig.type);
|
||||
if(v.rows <= 1)
|
||||
{
|
||||
v.rows = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.members.resize(v.rows);
|
||||
for(uint32_t r = 0; r < v.rows; r++)
|
||||
{
|
||||
v.members[r].rows = 1;
|
||||
v.members[r].columns = (uint8_t)sig.cols;
|
||||
v.members[r].type = v.type;
|
||||
v.members[r].name = StringFormat::Fmt("[%u]", r);
|
||||
}
|
||||
}
|
||||
|
||||
SourceVariableMapping inputMapping;
|
||||
inputMapping.name = v.name;
|
||||
inputMapping.type = v.type;
|
||||
inputMapping.rows = sig.rows;
|
||||
inputMapping.columns = sig.cols;
|
||||
inputMapping.variables.reserve(sig.cols);
|
||||
inputMapping.signatureIndex = i;
|
||||
if(v.rows <= 1)
|
||||
{
|
||||
inputMapping.variables.reserve(sig.cols);
|
||||
for(uint32_t c = 0; c < sig.cols; ++c)
|
||||
{
|
||||
DebugVariableReference ref;
|
||||
ref.type = DebugVariableType::Input;
|
||||
ref.name = inStruct.name + "." + v.name;
|
||||
ref.component = c;
|
||||
inputMapping.variables.push_back(ref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugVariableReference ref;
|
||||
ref.type = DebugVariableType::Input;
|
||||
ref.name = inStruct.name + "." + v.name;
|
||||
inputMapping.variables.push_back(ref);
|
||||
}
|
||||
m_SourceVars.push_back(inputMapping);
|
||||
}
|
||||
|
||||
// Make a single source variable mapping for the whole input struct
|
||||
SourceVariableMapping inputMapping;
|
||||
inputMapping.name = inStruct.name;
|
||||
inputMapping.type = VarType::Struct;
|
||||
inputMapping.rows = 0;
|
||||
inputMapping.columns = 0;
|
||||
inputMapping.variables.resize(1);
|
||||
inputMapping.variables.push_back(DebugVariableReference(DebugVariableType::Input, inStruct.name));
|
||||
m_SourceVars.push_back(inputMapping);
|
||||
}
|
||||
}
|
||||
|
||||
D3D12APIWrapper::~D3D12APIWrapper()
|
||||
{
|
||||
// if we replayed to before the action for fetching some UAVs
|
||||
// replay back to after the action to keep the state consistent.
|
||||
if(m_DidReplay)
|
||||
ResetReplay();
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::ResetReplay()
|
||||
{
|
||||
if(!m_ResourcesDirty)
|
||||
{
|
||||
D3D12MarkerRegion region(m_Device->GetQueue()->GetReal(), "ResetReplay");
|
||||
// replay the action to get back to 'normal' state for this event
|
||||
D3D12MarkerRegion region(m_Device->GetQueue()->GetReal(), "ResetReplay");
|
||||
m_Device->ReplayLog(0, m_EventId, eReplay_OnlyDraw);
|
||||
m_ResourcesDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
void D3D12APIWrapper::PrepareReplayForResources()
|
||||
{
|
||||
// if the resources are dirty, replay back to right before it.
|
||||
if(m_ResourcesDirty)
|
||||
{
|
||||
D3D12MarkerRegion region(m_Device->GetQueue()->GetReal(), "un-dirtying resources");
|
||||
m_Device->ReplayLog(0, m_EventId, eReplay_WithoutDraw);
|
||||
m_ResourcesDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::FlattenSingleVariable(const rdcstr &cbufferName, uint32_t byteOffset,
|
||||
const rdcstr &basename, const ShaderVariable &v,
|
||||
rdcarray<ShaderVariable> &outvars)
|
||||
{
|
||||
size_t outIdx = byteOffset / 16;
|
||||
size_t outComp = (byteOffset % 16) / 4;
|
||||
|
||||
if(v.RowMajor())
|
||||
outvars.resize(RDCMAX(outIdx + v.rows, outvars.size()));
|
||||
else
|
||||
outvars.resize(RDCMAX(outIdx + v.columns, outvars.size()));
|
||||
|
||||
if(outvars[outIdx].columns > 0)
|
||||
{
|
||||
// if we already have a variable in this slot, just copy the data for this variable and add
|
||||
// the source mapping. We should not overlap into the next register as that's not allowed.
|
||||
memcpy(&outvars[outIdx].value.u32v[outComp], &v.value.u32v[0], sizeof(uint32_t) * v.columns);
|
||||
uint32_t oldColumns = outvars[outIdx].columns;
|
||||
uint32_t newColumns = (uint32_t)(outComp + v.columns);
|
||||
uint32_t numColumns = RDCMAX(oldColumns, newColumns);
|
||||
numColumns = RDCMIN(4U, numColumns);
|
||||
outvars[outIdx].columns = (uint8_t)numColumns;
|
||||
|
||||
SourceVariableMapping mapping;
|
||||
mapping.name = basename;
|
||||
mapping.type = v.type;
|
||||
mapping.rows = v.rows;
|
||||
mapping.columns = v.columns;
|
||||
mapping.offset = byteOffset;
|
||||
mapping.variables.resize(v.columns);
|
||||
|
||||
for(int i = 0; i < v.columns; i++)
|
||||
{
|
||||
mapping.variables[i].type = DebugVariableType::Constant;
|
||||
mapping.variables[i].name = StringFormat::Fmt("%s[%u]", cbufferName.c_str(), outIdx);
|
||||
mapping.variables[i].component = uint16_t(outComp + i);
|
||||
}
|
||||
|
||||
m_SourceVars.push_back(mapping);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t numRegisters = v.RowMajor() ? v.rows : v.columns;
|
||||
for(uint32_t reg = 0; reg < numRegisters; reg++)
|
||||
{
|
||||
outvars[outIdx + reg].rows = 1;
|
||||
outvars[outIdx + reg].type = v.type;
|
||||
outvars[outIdx + reg].columns = v.columns + (uint8_t)outComp;
|
||||
outvars[outIdx + reg].flags = v.flags;
|
||||
}
|
||||
|
||||
if(v.RowMajor())
|
||||
{
|
||||
for(size_t ri = 0; ri < v.rows; ri++)
|
||||
memcpy(&outvars[outIdx + ri].value.u32v[outComp], &v.value.u32v[ri * v.columns],
|
||||
sizeof(uint32_t) * v.columns);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we have a matrix stored in column major order, we need to transpose it back so we
|
||||
// can unroll it into vectors.
|
||||
for(size_t ci = 0; ci < v.columns; ci++)
|
||||
for(size_t ri = 0; ri < v.rows; ri++)
|
||||
outvars[outIdx + ci].value.u32v[ri] = v.value.u32v[ri * v.columns + ci];
|
||||
}
|
||||
|
||||
SourceVariableMapping mapping;
|
||||
mapping.name = basename;
|
||||
mapping.type = v.type;
|
||||
mapping.rows = v.rows;
|
||||
mapping.columns = v.columns;
|
||||
mapping.offset = byteOffset;
|
||||
mapping.variables.resize(v.rows * v.columns);
|
||||
|
||||
RDCASSERT(outComp == 0 || v.rows == 1, outComp, v.rows);
|
||||
|
||||
size_t i = 0;
|
||||
for(uint8_t r = 0; r < v.rows; r++)
|
||||
{
|
||||
for(uint8_t c = 0; c < v.columns; c++)
|
||||
{
|
||||
size_t regIndex = outIdx + (v.RowMajor() ? r : c);
|
||||
size_t compIndex = outComp + (v.RowMajor() ? c : r);
|
||||
|
||||
mapping.variables[i].type = DebugVariableType::Constant;
|
||||
mapping.variables[i].name = StringFormat::Fmt("%s[%zu]", cbufferName.c_str(), regIndex);
|
||||
mapping.variables[i].component = uint16_t(compIndex);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
m_SourceVars.push_back(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::FlattenVariables(const rdcstr &cbufferName,
|
||||
const rdcarray<ShaderConstant> &constants,
|
||||
const rdcarray<ShaderVariable> &invars,
|
||||
rdcarray<ShaderVariable> &outvars, const rdcstr &prefix,
|
||||
uint32_t baseOffset)
|
||||
{
|
||||
RDCASSERTEQUAL(constants.size(), invars.size());
|
||||
|
||||
for(size_t i = 0; i < constants.size(); i++)
|
||||
{
|
||||
const ShaderConstant &c = constants[i];
|
||||
const ShaderVariable &v = invars[i];
|
||||
|
||||
uint32_t byteOffset = baseOffset + c.byteOffset;
|
||||
|
||||
rdcstr basename = prefix + rdcstr(v.name);
|
||||
|
||||
if(v.type == VarType::Struct)
|
||||
{
|
||||
// check if this is an array of structs or not
|
||||
if(c.type.elements == 1)
|
||||
{
|
||||
FlattenVariables(cbufferName, c.type.members, v.members, outvars, basename + ".", byteOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int m = 0; m < v.members.count(); m++)
|
||||
{
|
||||
FlattenVariables(cbufferName, c.type.members, v.members[m].members, outvars,
|
||||
StringFormat::Fmt("%s[%zu].", basename.c_str(), m),
|
||||
byteOffset + m * c.type.arrayByteStride);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(c.type.elements > 1 || (v.rows == 0 && v.columns == 0) || !v.members.empty())
|
||||
{
|
||||
for(int m = 0; m < v.members.count(); m++)
|
||||
{
|
||||
FlattenSingleVariable(cbufferName, byteOffset + m * c.type.arrayByteStride,
|
||||
StringFormat::Fmt("%s[%zu]", basename.c_str(), m), v.members[m],
|
||||
outvars);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FlattenSingleVariable(cbufferName, byteOffset, basename, v, outvars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::FetchConstantBufferData(const D3D12RenderState::RootSignature &rootsig)
|
||||
{
|
||||
WrappedID3D12RootSignature *pD3D12RootSig =
|
||||
m_Device->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rootsig.rootsig);
|
||||
const DXBC::ShaderType shaderType = m_Program->GetShaderType();
|
||||
|
||||
size_t numParams = RDCMIN(pD3D12RootSig->sig.Parameters.size(), rootsig.sigelems.size());
|
||||
for(size_t i = 0; i < numParams; i++)
|
||||
{
|
||||
const D3D12RootSignatureParameter &rootSigParam = pD3D12RootSig->sig.Parameters[i];
|
||||
const D3D12RenderState::SignatureElement &element = rootsig.sigelems[i];
|
||||
if(IsShaderParameterVisible(shaderType, rootSigParam.ShaderVisibility))
|
||||
{
|
||||
if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS &&
|
||||
element.type == eRootConst)
|
||||
{
|
||||
BindingSlot slot(rootSigParam.Constants.ShaderRegister, rootSigParam.Constants.RegisterSpace);
|
||||
UINT sizeBytes = sizeof(uint32_t) * RDCMIN(rootSigParam.Constants.Num32BitValues,
|
||||
(UINT)element.constants.size());
|
||||
bytebuf cbufData((const byte *)element.constants.data(), sizeBytes);
|
||||
AddCBufferToGlobalState(slot, cbufData);
|
||||
}
|
||||
else if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV && element.type == eRootCBV)
|
||||
{
|
||||
BindingSlot slot(rootSigParam.Descriptor.ShaderRegister,
|
||||
rootSigParam.Descriptor.RegisterSpace);
|
||||
ID3D12Resource *cbv =
|
||||
m_Device->GetResourceManager()->GetCurrentAs<ID3D12Resource>(element.id);
|
||||
bytebuf cbufData;
|
||||
m_Device->GetDebugManager()->GetBufferData(cbv, element.offset, 0, cbufData);
|
||||
AddCBufferToGlobalState(slot, cbufData);
|
||||
}
|
||||
else if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE &&
|
||||
element.type == eRootTable)
|
||||
{
|
||||
UINT prevTableOffset = 0;
|
||||
WrappedID3D12DescriptorHeap *heap =
|
||||
m_Device->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(element.id);
|
||||
|
||||
size_t numRanges = rootSigParam.ranges.size();
|
||||
for(size_t r = 0; r < numRanges; r++)
|
||||
{
|
||||
// For this traversal we only care about CBV descriptor ranges, but we still need to
|
||||
// calculate the table offsets in case a descriptor table has a combination of
|
||||
// different range types
|
||||
const D3D12_DESCRIPTOR_RANGE1 &range = rootSigParam.ranges[r];
|
||||
|
||||
UINT offset = range.OffsetInDescriptorsFromTableStart;
|
||||
if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
|
||||
offset = prevTableOffset;
|
||||
|
||||
D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr;
|
||||
desc += element.offset;
|
||||
desc += offset;
|
||||
|
||||
UINT numDescriptors = range.NumDescriptors;
|
||||
if(numDescriptors == UINT_MAX)
|
||||
{
|
||||
// Find out how many descriptors are left after
|
||||
numDescriptors = heap->GetNumDescriptors() - offset - (UINT)element.offset;
|
||||
|
||||
// TODO: Look up the bind point in the D3D12 state to try to get
|
||||
// a better guess at the number of descriptors
|
||||
}
|
||||
|
||||
prevTableOffset = offset + numDescriptors;
|
||||
|
||||
if(range.RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_CBV)
|
||||
continue;
|
||||
|
||||
BindingSlot slot(range.BaseShaderRegister, range.RegisterSpace);
|
||||
|
||||
bytebuf cbufData;
|
||||
for(UINT n = 0; n < numDescriptors; ++n, ++slot.shaderRegister)
|
||||
{
|
||||
const D3D12_CONSTANT_BUFFER_VIEW_DESC &cbv = desc->GetCBV();
|
||||
ResourceId resId;
|
||||
uint64_t byteOffset = 0;
|
||||
WrappedID3D12Resource::GetResIDFromAddr(cbv.BufferLocation, resId, byteOffset);
|
||||
ID3D12Resource *pCbvResource =
|
||||
m_Device->GetResourceManager()->GetCurrentAs<ID3D12Resource>(resId);
|
||||
cbufData.clear();
|
||||
|
||||
if(cbv.SizeInBytes > 0)
|
||||
m_Device->GetDebugManager()->GetBufferData(pCbvResource, byteOffset, cbv.SizeInBytes,
|
||||
cbufData);
|
||||
AddCBufferToGlobalState(slot, cbufData);
|
||||
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::AddCBufferToGlobalState(const BindingSlot &slot, bytebuf &cbufData)
|
||||
{
|
||||
// Find the identifier
|
||||
size_t numCBs = m_Reflection.constantBlocks.size();
|
||||
for(size_t i = 0; i < numCBs; ++i)
|
||||
{
|
||||
const ConstantBlock &cb = m_Reflection.constantBlocks[i];
|
||||
if(slot.registerSpace == (uint32_t)cb.fixedBindSetOrSpace &&
|
||||
slot.shaderRegister >= (uint32_t)cb.fixedBindNumber &&
|
||||
slot.shaderRegister < (uint32_t)(cb.fixedBindNumber + cb.bindArraySize))
|
||||
{
|
||||
uint32_t arrayIndex = slot.shaderRegister - cb.fixedBindNumber;
|
||||
|
||||
rdcarray<ShaderVariable> &targetVars = cb.bindArraySize > 1
|
||||
? m_ConstantBlocks[i].members[arrayIndex].members
|
||||
: m_ConstantBlocks[i].members;
|
||||
RDCASSERTMSG("Reassigning previously filled cbuffer", targetVars.empty());
|
||||
|
||||
ConstantBlockReference constantBlockRef = {i, arrayIndex};
|
||||
m_ConstantBlocksDatas[constantBlockRef] = cbufData;
|
||||
rdcstr resName = Debugger::GetResourceReferenceName(m_Program, ResourceClass::CBuffer, slot);
|
||||
m_ConstantBlocks[i].name = resName;
|
||||
|
||||
SourceVariableMapping cbSourceMapping;
|
||||
cbSourceMapping.name = m_Reflection.constantBlocks[i].name;
|
||||
cbSourceMapping.variables.push_back(
|
||||
DebugVariableReference(DebugVariableType::Constant, m_ConstantBlocks[i].name));
|
||||
m_SourceVars.push_back(cbSourceMapping);
|
||||
|
||||
rdcstr identifierPrefix = m_ConstantBlocks[i].name;
|
||||
rdcstr variablePrefix = m_Reflection.constantBlocks[i].name;
|
||||
if(cb.bindArraySize > 1)
|
||||
{
|
||||
identifierPrefix = StringFormat::Fmt("%s[%u]", m_ConstantBlocks[i].name.c_str(), arrayIndex);
|
||||
variablePrefix =
|
||||
StringFormat::Fmt("%s[%u]", m_Reflection.constantBlocks[i].name.c_str(), arrayIndex);
|
||||
|
||||
// The above sourceVar is for the logical identifier, and FlattenVariables adds the
|
||||
// individual elements of the constant buffer. For CB arrays, add an extra source
|
||||
// var for the CB array index
|
||||
SourceVariableMapping cbArrayMapping;
|
||||
m_ConstantBlocks[i].members[arrayIndex].name = StringFormat::Fmt("[%u]", arrayIndex);
|
||||
cbArrayMapping.name = variablePrefix;
|
||||
cbArrayMapping.variables.push_back(
|
||||
DebugVariableReference(DebugVariableType::Constant, identifierPrefix));
|
||||
m_SourceVars.push_back(cbArrayMapping);
|
||||
}
|
||||
const rdcarray<ShaderConstant> &constants =
|
||||
(cb.bindArraySize > 1) ? m_Reflection.constantBlocks[i].variables[0].type.members
|
||||
: m_Reflection.constantBlocks[i].variables;
|
||||
|
||||
rdcarray<ShaderVariable> vars;
|
||||
StandardFillCBufferVariables(m_Reflection.resourceId, constants, vars, cbufData);
|
||||
FlattenVariables(identifierPrefix, constants, vars, targetVars, variablePrefix + ".", 0);
|
||||
for(size_t c = 0; c < targetVars.size(); c++)
|
||||
targetVars[c].name = StringFormat::Fmt("[%u]", (uint32_t)c);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SRVData &D3D12APIWrapper::FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
{
|
||||
SRVData &srvData = m_SRVs[slot];
|
||||
if(resDescriptor)
|
||||
{
|
||||
D3D12ResourceManager *rm = m_Device->GetResourceManager();
|
||||
DXILDebug::GlobalState::SRVData &srvData = m_GlobalState.srvs[slot];
|
||||
ResourceId srvId = resDescriptor->GetResResourceId();
|
||||
ID3D12Resource *pResource = rm->GetCurrentAs<ID3D12Resource>(srvId);
|
||||
if(pResource)
|
||||
@@ -632,10 +747,14 @@ void D3D12APIWrapper::FetchSRV(const D3D12Descriptor *resDescriptor, const Bindi
|
||||
// Textures are sampled via a pixel shader, so there's no need to copy their data
|
||||
}
|
||||
}
|
||||
return srvData;
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
SRVData &D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
{
|
||||
// the resources might be dirty from side-effects, replay back to right before it.
|
||||
PrepareReplayForResources();
|
||||
|
||||
// Direct access resource
|
||||
if(slot.heapType != DXDebug::HeapDescriptorType::NoHeap)
|
||||
{
|
||||
@@ -680,11 +799,11 @@ void D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
if(param.Descriptor.ShaderRegister == slot.shaderRegister &&
|
||||
param.Descriptor.RegisterSpace == slot.registerSpace)
|
||||
{
|
||||
SRVData &srvData = m_SRVs[slot];
|
||||
// Found the requested SRV
|
||||
ID3D12Resource *pResource = rm->GetCurrentAs<ID3D12Resource>(element.id);
|
||||
if(pResource)
|
||||
{
|
||||
DXILDebug::GlobalState::SRVData &srvData = m_GlobalState.srvs[slot];
|
||||
D3D12_RESOURCE_DESC resDesc = pResource->GetDesc();
|
||||
|
||||
// DXC allows root buffers to have a stride of up to 16 bytes in the shader, which
|
||||
@@ -713,7 +832,7 @@ void D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
srvData.data);
|
||||
}
|
||||
}
|
||||
return;
|
||||
return srvData;
|
||||
}
|
||||
}
|
||||
else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE &&
|
||||
@@ -767,19 +886,20 @@ void D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
|
||||
RDCERR("Couldn't find root signature parameter corresponding to SRV %u in space %u",
|
||||
slot.shaderRegister, slot.registerSpace);
|
||||
return;
|
||||
return m_SRVs[slot];
|
||||
}
|
||||
|
||||
RDCERR("No root signature bound, couldn't identify SRV %u in space %u", slot.shaderRegister,
|
||||
slot.registerSpace);
|
||||
return m_SRVs[slot];
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
UAVData &D3D12APIWrapper::FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
{
|
||||
UAVData &uavData = m_UAVs[slot];
|
||||
if(resDescriptor)
|
||||
{
|
||||
D3D12ResourceManager *rm = m_Device->GetResourceManager();
|
||||
DXILDebug::GlobalState::UAVData &uavData = m_GlobalState.uavs[slot];
|
||||
ResourceId uavId = resDescriptor->GetResResourceId();
|
||||
ID3D12Resource *pResource = rm->GetCurrentAs<ID3D12Resource>(uavId);
|
||||
|
||||
@@ -825,18 +945,13 @@ void D3D12APIWrapper::FetchUAV(const D3D12Descriptor *resDescriptor, const Bindi
|
||||
}
|
||||
}
|
||||
}
|
||||
return uavData;
|
||||
}
|
||||
|
||||
void D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
UAVData &D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
{
|
||||
// if the UAV might be dirty from side-effects from the action, replay back to right
|
||||
// before it.
|
||||
if(!m_DidReplay)
|
||||
{
|
||||
D3D12MarkerRegion region(m_Device->GetQueue()->GetReal(), "un-dirtying resources");
|
||||
m_Device->ReplayLog(0, m_EventId, eReplay_WithoutDraw);
|
||||
m_DidReplay = true;
|
||||
}
|
||||
// the resources might be dirty from side-effects, replay back to right before it.
|
||||
PrepareReplayForResources();
|
||||
|
||||
// Direct access resource
|
||||
if(slot.heapType != DXDebug::HeapDescriptorType::NoHeap)
|
||||
@@ -884,10 +999,10 @@ void D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
{
|
||||
// Found the requested UAV
|
||||
ID3D12Resource *pResource = rm->GetCurrentAs<ID3D12Resource>(element.id);
|
||||
UAVData &uavData = m_UAVs[slot];
|
||||
|
||||
if(pResource)
|
||||
{
|
||||
DXILDebug::GlobalState::UAVData &uavData = m_GlobalState.uavs[slot];
|
||||
D3D12_RESOURCE_DESC resDesc = pResource->GetDesc();
|
||||
// DXC allows root buffers to have a stride of up to 16 bytes in the shader, which
|
||||
// means encoding the byte offset into the first element here is wrong without
|
||||
@@ -918,7 +1033,7 @@ void D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return uavData;
|
||||
}
|
||||
}
|
||||
else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE &&
|
||||
@@ -972,11 +1087,54 @@ void D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
|
||||
RDCERR("Couldn't find root signature parameter corresponding to UAV %u in space %u",
|
||||
slot.shaderRegister, slot.registerSpace);
|
||||
return;
|
||||
return m_UAVs[slot];
|
||||
}
|
||||
|
||||
RDCERR("No root signature bound, couldn't identify UAV %u in space %u", slot.shaderRegister,
|
||||
slot.registerSpace);
|
||||
return m_UAVs[slot];
|
||||
}
|
||||
|
||||
bool D3D12APIWrapper::IsSRVCached(const BindingSlot &slot)
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
return m_SRVs.find(slot) != m_SRVs.end();
|
||||
}
|
||||
|
||||
const SRVData &D3D12APIWrapper::GetSRVData(const BindingSlot &slot)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
auto it = m_SRVs.find(slot);
|
||||
if(it != m_SRVs.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_WRITELOCK(m_SRVsLock);
|
||||
return FetchSRV(slot);
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D12APIWrapper::IsUAVCached(const BindingSlot &slot)
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
return m_UAVs.find(slot) != m_UAVs.end();
|
||||
}
|
||||
|
||||
const UAVData &D3D12APIWrapper::GetUAVData(const BindingSlot &slot)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
auto it = m_UAVs.find(slot);
|
||||
if(it != m_UAVs.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_WRITELOCK(m_UAVsLock);
|
||||
return FetchUAV(slot);
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D12APIWrapper::CalculateMathIntrinsic(DXIL::DXOp dxOp, const ShaderVariable &input,
|
||||
@@ -1051,7 +1209,7 @@ bool D3D12APIWrapper::CalculateSampleGather(
|
||||
|
||||
ShaderVariable D3D12APIWrapper::GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot, uint32_t mipLevel,
|
||||
const DXBC::ShaderType shaderType, int &dim)
|
||||
const DXBC::ShaderType shaderType, int &dim) const
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descType;
|
||||
switch(resClass)
|
||||
@@ -1069,7 +1227,8 @@ ShaderVariable D3D12APIWrapper::GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
|
||||
ShaderVariable D3D12APIWrapper::GetSampleInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot,
|
||||
const DXBC::ShaderType shaderType, const char *opString)
|
||||
const DXBC::ShaderType shaderType,
|
||||
const char *opString) const
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descType;
|
||||
switch(resClass)
|
||||
@@ -1086,12 +1245,12 @@ ShaderVariable D3D12APIWrapper::GetSampleInfo(DXIL::ResourceClass resClass,
|
||||
}
|
||||
|
||||
ShaderVariable D3D12APIWrapper::GetRenderTargetSampleInfo(const DXBC::ShaderType shaderType,
|
||||
const char *opString)
|
||||
const char *opString) const
|
||||
{
|
||||
return D3D12ShaderDebug::GetRenderTargetSampleInfo(m_Device, shaderType, opString);
|
||||
}
|
||||
|
||||
ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::BindingSlot &slot)
|
||||
ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) const
|
||||
{
|
||||
const HeapDescriptorType heapType = slot.heapType;
|
||||
RDCASSERT(heapType != HeapDescriptorType::NoHeap);
|
||||
@@ -1124,7 +1283,7 @@ ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::B
|
||||
if(srvDesc.ViewDimension == D3D12_SRV_DIMENSION_UNKNOWN)
|
||||
srvDesc = MakeSRVDesc(pResource->GetDesc());
|
||||
|
||||
GlobalState::ViewFmt viewFmt;
|
||||
ViewFmt viewFmt;
|
||||
if(srvDesc.Format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
resRefInfo.srvData.dim =
|
||||
@@ -1189,7 +1348,7 @@ ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::B
|
||||
}
|
||||
|
||||
ShaderDirectAccess D3D12APIWrapper::GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot)
|
||||
const DXDebug::BindingSlot &slot) const
|
||||
{
|
||||
const HeapDescriptorType heapType = slot.heapType;
|
||||
RDCASSERT(heapType != HeapDescriptorType::NoHeap);
|
||||
|
||||
@@ -33,46 +33,124 @@ namespace DXILDebug
|
||||
{
|
||||
class Debugger;
|
||||
|
||||
void FetchConstantBufferData(WrappedID3D12Device *device, const DXIL::Program *program,
|
||||
const D3D12RenderState::RootSignature &rootsig,
|
||||
const ShaderReflection &refl, DXILDebug::GlobalState &global,
|
||||
rdcarray<SourceVariableMapping> &sourceVars);
|
||||
|
||||
class D3D12APIWrapper : public DebugAPIWrapper
|
||||
{
|
||||
public:
|
||||
D3D12APIWrapper(WrappedID3D12Device *device, const DXIL::Program &dxilProgram,
|
||||
GlobalState &globalState, uint32_t eventId);
|
||||
D3D12APIWrapper(WrappedID3D12Device *device, const DXIL::Program *dxilProgram,
|
||||
const ShaderReflection &refl, uint32_t eventId,
|
||||
const rdcarray<SigParameter> &inputSig);
|
||||
~D3D12APIWrapper();
|
||||
|
||||
void FetchSRV(const BindingSlot &slot);
|
||||
void FetchUAV(const BindingSlot &slot);
|
||||
bool CalculateMathIntrinsic(DXIL::DXOp dxOp, const ShaderVariable &input, ShaderVariable &output);
|
||||
void FetchConstantBufferData(const D3D12RenderState::RootSignature &rootsig);
|
||||
|
||||
const UAVData &GetUAVData(const BindingSlot &slot) override;
|
||||
const SRVData &GetSRVData(const BindingSlot &slot) override;
|
||||
|
||||
bool CalculateMathIntrinsic(DXIL::DXOp dxOp, const ShaderVariable &input,
|
||||
ShaderVariable &output) override;
|
||||
bool CalculateSampleGather(DXIL::DXOp dxOp, SampleGatherResourceData resourceData,
|
||||
SampleGatherSamplerData samplerData, const ShaderVariable &uv,
|
||||
const ShaderVariable &ddxCalc, const ShaderVariable &ddyCalc,
|
||||
const int8_t texelOffsets[3], int multisampleIndex, float lodValue,
|
||||
float compareValue, const uint8_t swizzle[4],
|
||||
GatherChannel gatherChannel, DXBC::ShaderType shaderType,
|
||||
uint32_t instructionIdx, const char *opString, ShaderVariable &output);
|
||||
uint32_t instructionIdx, const char *opString,
|
||||
ShaderVariable &output) override;
|
||||
|
||||
ShaderVariable GetResourceInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
uint32_t mipLevel, const DXBC::ShaderType shaderType, int &dim);
|
||||
uint32_t mipLevel, const DXBC::ShaderType shaderType,
|
||||
int &dim) const override;
|
||||
ShaderVariable GetSampleInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
const DXBC::ShaderType shaderType, const char *opString);
|
||||
ShaderVariable GetRenderTargetSampleInfo(const DXBC::ShaderType shaderType, const char *opString);
|
||||
ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot);
|
||||
ShaderDirectAccess GetShaderDirectAccess(DescriptorType type, const DXDebug::BindingSlot &slot);
|
||||
const DXBC::ShaderType shaderType,
|
||||
const char *opString) const override;
|
||||
ShaderVariable GetRenderTargetSampleInfo(const DXBC::ShaderType shaderType,
|
||||
const char *opString) const override;
|
||||
ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) const override;
|
||||
ShaderDirectAccess GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot) const override;
|
||||
|
||||
bool IsSRVCached(const DXDebug::BindingSlot &slot) override;
|
||||
bool IsUAVCached(const DXDebug::BindingSlot &slot) override;
|
||||
|
||||
void ResetReplay();
|
||||
|
||||
void SetBuiltins(const BuiltinInputs &builtins) { m_Builtins = builtins; }
|
||||
void SetWorkgroupProperties(const rdcarray<DXILDebug::ThreadProperties> &workgroupProperties)
|
||||
{
|
||||
m_WorkgroupProperties = workgroupProperties;
|
||||
}
|
||||
void SetThreadsInputs(const rdcarray<ShaderVariable> &threadsInputs)
|
||||
{
|
||||
m_ThreadsInputs = threadsInputs;
|
||||
}
|
||||
void SetThreadsBuiltins(rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> &threadsBuiltins)
|
||||
{
|
||||
m_ThreadsBuiltins = threadsBuiltins;
|
||||
}
|
||||
void SetSubgroupSize(uint32_t subgroupSize) { m_SubgroupSize = subgroupSize; }
|
||||
|
||||
const rdcarray<DXIL::EntryPointInterface::Signature> &GetDXILEntryPointInputs(void) const
|
||||
{
|
||||
return m_EntryPointInterface->inputs;
|
||||
}
|
||||
|
||||
const rdcarray<DXILDebug::ThreadProperties> &GetWorkgroupProperties() const override
|
||||
{
|
||||
return m_WorkgroupProperties;
|
||||
}
|
||||
const rdcarray<ShaderVariable> &GetConstantBlocks() const override { return m_ConstantBlocks; }
|
||||
const std::map<ConstantBlockReference, bytebuf> &GetConstantBlocksDatas() const override
|
||||
{
|
||||
return m_ConstantBlocksDatas;
|
||||
}
|
||||
|
||||
const BuiltinInputs &GetBuiltins() const override { return m_Builtins; }
|
||||
uint32_t GetSubgroupSize() const override { return m_SubgroupSize; }
|
||||
const rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> &GetThreadsBuiltins() const override
|
||||
{
|
||||
return m_ThreadsBuiltins;
|
||||
}
|
||||
const rdcarray<ShaderVariable> &GetThreadsInputs() const override { return m_ThreadsInputs; }
|
||||
const rdcarray<SourceVariableMapping> &GetSourceVars() const override { return m_SourceVars; }
|
||||
const ShaderVariable &GetInputPlaceholder() const override { return m_InputPlaceholder; }
|
||||
|
||||
private:
|
||||
void FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
void FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
void PrepareReplayForResources();
|
||||
void AddCBufferToGlobalState(const BindingSlot &slot, bytebuf &cbufData);
|
||||
void FlattenSingleVariable(const rdcstr &cbufferName, uint32_t byteOffset, const rdcstr &basename,
|
||||
const ShaderVariable &v, rdcarray<ShaderVariable> &outvars);
|
||||
void FlattenVariables(const rdcstr &cbufferName, const rdcarray<ShaderConstant> &constants,
|
||||
const rdcarray<ShaderVariable> &invars, rdcarray<ShaderVariable> &outvars,
|
||||
const rdcstr &prefix, uint32_t baseOffset);
|
||||
|
||||
WrappedID3D12Device *m_Device;
|
||||
const DXIL::EntryPointInterface *m_EntryPointInterface;
|
||||
GlobalState &m_GlobalState;
|
||||
DXBC::ShaderType m_ShaderType;
|
||||
SRVData &FetchSRV(const BindingSlot &slot);
|
||||
SRVData &FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
|
||||
UAVData &FetchUAV(const BindingSlot &slot);
|
||||
UAVData &FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
|
||||
BuiltinInputs m_Builtins;
|
||||
rdcarray<DXILDebug::ThreadProperties> m_WorkgroupProperties;
|
||||
rdcarray<ShaderVariable> m_ThreadsInputs;
|
||||
rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> m_ThreadsBuiltins;
|
||||
rdcarray<SourceVariableMapping> m_SourceVars;
|
||||
rdcarray<ShaderVariable> m_ConstantBlocks;
|
||||
std::map<ConstantBlockReference, bytebuf> m_ConstantBlocksDatas;
|
||||
ShaderVariable m_InputPlaceholder;
|
||||
uint32_t m_SubgroupSize = 1;
|
||||
|
||||
Threading::RWLock m_UAVsLock;
|
||||
std::map<BindingSlot, UAVData> m_UAVs;
|
||||
Threading::RWLock m_SRVsLock;
|
||||
std::map<BindingSlot, SRVData> m_SRVs;
|
||||
|
||||
const ShaderReflection &m_Reflection;
|
||||
WrappedID3D12Device *m_Device = NULL;
|
||||
const DXIL::Program *m_Program = NULL;
|
||||
const DXIL::EntryPointInterface *m_EntryPointInterface = NULL;
|
||||
const DXBC::ShaderType m_ShaderType;
|
||||
const uint32_t m_EventId;
|
||||
bool m_DidReplay = false;
|
||||
bool m_ResourcesDirty = true;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -2351,22 +2351,29 @@ ShaderDebugTrace *D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, ui
|
||||
if(buf[0].numHits > 1)
|
||||
RDCLOG("Unexpected number of vertex hits: %u!", buf[0].numHits);
|
||||
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(eventId, dxbc, refl, buf->laneIndex, buf->subgroupSize);
|
||||
DXILDebug::D3D12APIWrapper *apiWrapper = new DXILDebug::D3D12APIWrapper(
|
||||
m_pDevice, dxbc->GetDXILByteCode(), refl, eventId, dxbc->GetReflection()->InputSig);
|
||||
|
||||
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
|
||||
const uint32_t numThreads = buf->subgroupSize;
|
||||
rdcarray<DXILDebug::ThreadProperties> workgroupProperties;
|
||||
workgroupProperties.resize(buf->subgroupSize);
|
||||
const rdcarray<DXIL::EntryPointInterface::Signature> &dxilInputs =
|
||||
debugger->GetDXILEntryPointInputs();
|
||||
|
||||
globalState.subgroupSize = buf->subgroupSize;
|
||||
for(uint32_t t = 0; t < buf->subgroupSize; t++)
|
||||
rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> threadsBuiltins;
|
||||
rdcarray<ShaderVariable> threadsInputs;
|
||||
workgroupProperties.resize(numThreads);
|
||||
threadsBuiltins.resize(numThreads);
|
||||
threadsInputs.resize(numThreads);
|
||||
|
||||
apiWrapper->SetSubgroupSize(buf->subgroupSize);
|
||||
|
||||
const rdcarray<DXIL::EntryPointInterface::Signature> &dxilInputs =
|
||||
apiWrapper->GetDXILEntryPointInputs();
|
||||
|
||||
for(uint32_t t = 0; t < numThreads; t++)
|
||||
{
|
||||
threadsInputs[t] = apiWrapper->GetInputPlaceholder();
|
||||
DXDebug::VSLaneData *lane = (DXDebug::VSLaneData *)(initialData.data() + laneDataOffset +
|
||||
t * fetcher.laneDataBufferStride);
|
||||
DXILDebug::ThreadState &state = debugger->GetLane(t);
|
||||
rdcarray<ShaderVariable> &ins = state.m_Input.members;
|
||||
rdcarray<ShaderVariable> &ins = threadsInputs[t].members;
|
||||
|
||||
byte *data = (byte *)(lane + 1);
|
||||
|
||||
@@ -2409,7 +2416,8 @@ ShaderDebugTrace *D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, ui
|
||||
data += inputElement.numwords * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
state.m_Builtins[ShaderBuiltin::IndexInSubgroup] = ShaderVariable(rdcstr(), t, 0U, 0U, 0U);
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &threadBuiltins = threadsBuiltins[t];
|
||||
threadBuiltins[ShaderBuiltin::IndexInSubgroup] = ShaderVariable(rdcstr(), t, 0U, 0U, 0U);
|
||||
|
||||
for(const DXILDebug::InputData &input : inputDatas)
|
||||
{
|
||||
@@ -2437,35 +2445,45 @@ ShaderDebugTrace *D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, ui
|
||||
}
|
||||
|
||||
if(input.sysattribute != ShaderBuiltin::Undefined)
|
||||
state.m_Builtins[input.sysattribute] = invar;
|
||||
threadBuiltins[input.sysattribute] = invar;
|
||||
}
|
||||
}
|
||||
|
||||
apiWrapper->SetWorkgroupProperties(workgroupProperties);
|
||||
apiWrapper->SetThreadsInputs(threadsInputs);
|
||||
apiWrapper->SetThreadsBuiltins(threadsBuiltins);
|
||||
|
||||
// Fetch constant buffer data from root signature
|
||||
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.graphics, refl,
|
||||
globalState, ret->sourceVars);
|
||||
apiWrapper->FetchConstantBufferData(rs.graphics);
|
||||
|
||||
debugger->InitialiseWorkgroup(workgroupProperties);
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(apiWrapper, eventId, dxbc, refl, buf->laneIndex, buf->subgroupSize);
|
||||
|
||||
ret->inputs = {debugger->GetActiveLane().m_Input};
|
||||
ret->constantBlocks = globalState.constantBlocks;
|
||||
apiWrapper->ResetReplay();
|
||||
}
|
||||
else
|
||||
{
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(eventId, dxbc, refl, 0, 1);
|
||||
const uint32_t activeLaneIndex = 0;
|
||||
const uint32_t numThreads = 1;
|
||||
DXILDebug::D3D12APIWrapper *apiWrapper = new DXILDebug::D3D12APIWrapper(
|
||||
m_pDevice, dxbc->GetDXILByteCode(), refl, eventId, dxbc->GetReflection()->InputSig);
|
||||
|
||||
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
|
||||
DXILDebug::ThreadState &activeState = debugger->GetActiveLane();
|
||||
rdcarray<ShaderVariable> &inputs = activeState.m_Input.members;
|
||||
rdcarray<DXILDebug::ThreadProperties> workgroupProperties;
|
||||
workgroupProperties.resize(1);
|
||||
rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> threadsBuiltins;
|
||||
rdcarray<ShaderVariable> threadsInputs;
|
||||
workgroupProperties.resize(numThreads);
|
||||
threadsBuiltins.resize(numThreads);
|
||||
threadsInputs.resize(numThreads);
|
||||
threadsInputs[activeLaneIndex] = apiWrapper->GetInputPlaceholder();
|
||||
|
||||
workgroupProperties[0][DXILDebug::ThreadProperty::Active] = 1;
|
||||
workgroupProperties[activeLaneIndex][DXILDebug::ThreadProperty::Active] = 1;
|
||||
|
||||
rdcarray<ShaderVariable> &inputs = threadsInputs[activeLaneIndex].members;
|
||||
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &threadBuiltins = threadsBuiltins[activeLaneIndex];
|
||||
|
||||
// Fetch constant buffer data from root signature
|
||||
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.graphics, refl,
|
||||
globalState, ret->sourceVars);
|
||||
apiWrapper->FetchConstantBufferData(rs.graphics);
|
||||
|
||||
// Set input values
|
||||
for(size_t i = 0; i < inputs.size(); i++)
|
||||
@@ -2712,14 +2730,18 @@ ShaderDebugTrace *D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, ui
|
||||
|
||||
if(sigParam.systemValue != ShaderBuiltin::Undefined)
|
||||
{
|
||||
activeState.m_Builtins[sigParam.systemValue] = inputs[i];
|
||||
threadBuiltins[sigParam.systemValue] = inputs[i];
|
||||
}
|
||||
}
|
||||
|
||||
debugger->InitialiseWorkgroup(workgroupProperties);
|
||||
apiWrapper->SetWorkgroupProperties(workgroupProperties);
|
||||
apiWrapper->SetThreadsInputs(threadsInputs);
|
||||
apiWrapper->SetThreadsBuiltins(threadsBuiltins);
|
||||
|
||||
ret->inputs = {activeState.m_Input};
|
||||
ret->constantBlocks = globalState.constantBlocks;
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(apiWrapper, eventId, dxbc, refl, activeLaneIndex, 1);
|
||||
|
||||
apiWrapper->ResetReplay();
|
||||
}
|
||||
|
||||
if(ret)
|
||||
@@ -3155,26 +3177,30 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
|
||||
}
|
||||
else
|
||||
{
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(eventId, dxbc, refl, hit->laneIndex, hit->subgroupSize);
|
||||
uint32_t numThreads = hit->subgroupSize;
|
||||
DXILDebug::D3D12APIWrapper *apiWrapper = new DXILDebug::D3D12APIWrapper(
|
||||
m_pDevice, dxbc->GetDXILByteCode(), refl, eventId, dxbc->GetReflection()->InputSig);
|
||||
|
||||
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
|
||||
rdcarray<DXILDebug::ThreadProperties> workgroupProperties;
|
||||
workgroupProperties.resize(hit->subgroupSize);
|
||||
const rdcarray<DXIL::EntryPointInterface::Signature> &dxilInputs =
|
||||
debugger->GetDXILEntryPointInputs();
|
||||
rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> threadsBuiltins;
|
||||
rdcarray<ShaderVariable> threadsInputs;
|
||||
workgroupProperties.resize(numThreads);
|
||||
threadsBuiltins.resize(numThreads);
|
||||
threadsInputs.resize(numThreads);
|
||||
|
||||
// Fetch constant buffer data from root signature
|
||||
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.graphics, refl,
|
||||
globalState, ret->sourceVars);
|
||||
apiWrapper->FetchConstantBufferData(rs.graphics);
|
||||
const rdcarray<DXIL::EntryPointInterface::Signature> &dxilInputs =
|
||||
apiWrapper->GetDXILEntryPointInputs();
|
||||
|
||||
globalState.subgroupSize = hit->subgroupSize;
|
||||
apiWrapper->SetSubgroupSize(hit->subgroupSize);
|
||||
for(uint32_t q = 0; q < hit->subgroupSize; q++)
|
||||
{
|
||||
threadsInputs[q] = apiWrapper->GetInputPlaceholder();
|
||||
DXDebug::PSLaneData *lane = (DXDebug::PSLaneData *)data;
|
||||
|
||||
DXILDebug::ThreadState &state = debugger->GetLane(q);
|
||||
rdcarray<ShaderVariable> &ins = state.m_Input.members;
|
||||
rdcarray<ShaderVariable> &ins = threadsInputs[q].members;
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &threadBuiltins = threadsBuiltins[q];
|
||||
|
||||
workgroupProperties[q][DXILDebug::ThreadProperty::Active] = lane->active;
|
||||
workgroupProperties[q][DXILDebug::ThreadProperty::Helper] = lane->isHelper;
|
||||
@@ -3223,12 +3249,12 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
|
||||
data += inputElement.numwords * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
state.m_Builtins[ShaderBuiltin::IndexInSubgroup] = ShaderVariable(rdcstr(), q, 0U, 0U, 0U);
|
||||
state.m_Builtins[ShaderBuiltin::PrimitiveIndex] =
|
||||
threadBuiltins[ShaderBuiltin::IndexInSubgroup] = ShaderVariable(rdcstr(), q, 0U, 0U, 0U);
|
||||
threadBuiltins[ShaderBuiltin::PrimitiveIndex] =
|
||||
ShaderVariable(rdcstr(), lane->primitive, 0U, 0U, 0U);
|
||||
state.m_Builtins[ShaderBuiltin::MSAACoverage] =
|
||||
threadBuiltins[ShaderBuiltin::MSAACoverage] =
|
||||
ShaderVariable(rdcstr(), lane->coverage, 0U, 0U, 0U);
|
||||
state.m_Builtins[ShaderBuiltin::IsFrontFace] =
|
||||
threadBuiltins[ShaderBuiltin::IsFrontFace] =
|
||||
ShaderVariable(rdcstr(), lane->isFrontFace, 0U, 0U, 0U);
|
||||
|
||||
for(const DXILDebug::InputData &input : inputDatas)
|
||||
@@ -3265,7 +3291,7 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
|
||||
}
|
||||
|
||||
if(input.sysattribute != ShaderBuiltin::Undefined)
|
||||
state.m_Builtins[input.sysattribute] = invar;
|
||||
threadBuiltins[input.sysattribute] = invar;
|
||||
}
|
||||
|
||||
// TODO: UPDATE INPUTS FROM SAMPLE CACHE
|
||||
@@ -3292,10 +3318,14 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
|
||||
#endif
|
||||
}
|
||||
|
||||
debugger->InitialiseWorkgroup(workgroupProperties);
|
||||
apiWrapper->SetWorkgroupProperties(workgroupProperties);
|
||||
apiWrapper->SetThreadsInputs(threadsInputs);
|
||||
apiWrapper->SetThreadsBuiltins(threadsBuiltins);
|
||||
|
||||
ret->inputs = {debugger->GetActiveLane().m_Input};
|
||||
ret->constantBlocks = globalState.constantBlocks;
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(apiWrapper, eventId, dxbc, refl, hit->laneIndex, hit->subgroupSize);
|
||||
|
||||
apiWrapper->ResetReplay();
|
||||
}
|
||||
|
||||
if(ret)
|
||||
@@ -3442,13 +3472,16 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
refl.dispatchThreadsDimension[2],
|
||||
};
|
||||
|
||||
uint32_t numThreads = 1;
|
||||
uint32_t subgroupSize = 1;
|
||||
uint32_t activeLaneIndex = 0;
|
||||
uint32_t numThreads = 1;
|
||||
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> globalBuiltins;
|
||||
rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> threadBuiltins;
|
||||
DXILDebug::D3D12APIWrapper *apiWrapper = new DXILDebug::D3D12APIWrapper(
|
||||
m_pDevice, dxbc->GetDXILByteCode(), refl, eventId, dxbc->GetReflection()->InputSig);
|
||||
|
||||
DXILDebug::BuiltinInputs globalBuiltins;
|
||||
rdcarray<DXILDebug::ThreadProperties> workgroupProperties;
|
||||
rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> threadsBuiltins;
|
||||
|
||||
// hard case - with subgroups we want the actual layout so read that from the GPU
|
||||
if(dxbc->GetThreadScope() & DXBC::ThreadScope::Subgroup)
|
||||
@@ -3594,13 +3627,13 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
if(dxbc->GetThreadScope() & DXBC::ThreadScope::Workgroup)
|
||||
numThreads = threadDim[0] * threadDim[1] * threadDim[2];
|
||||
|
||||
workgroupProperties.resize(numThreads);
|
||||
threadsBuiltins.resize(numThreads);
|
||||
|
||||
// SV_GroupID
|
||||
globalBuiltins[ShaderBuiltin::GroupIndex] =
|
||||
ShaderVariable(rdcstr(), groupid[0], groupid[1], groupid[2], 0U);
|
||||
|
||||
threadBuiltins.resize(numThreads);
|
||||
workgroupProperties.resize(numThreads);
|
||||
|
||||
// can't know our lane index from the hit if we are simulating the whole workgroup
|
||||
if(dxbc->GetThreadScope() & DXBC::ThreadScope::Workgroup)
|
||||
activeLaneIndex = ~0U;
|
||||
@@ -3632,18 +3665,19 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
workgroupProperties[lane][DXILDebug::ThreadProperty::Active] = value->active;
|
||||
workgroupProperties[lane][DXILDebug::ThreadProperty::SubgroupIdx] = t;
|
||||
|
||||
threadBuiltins[lane][ShaderBuiltin::DispatchThreadIndex] =
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &threadBuiltins = threadsBuiltins[lane];
|
||||
threadBuiltins[ShaderBuiltin::DispatchThreadIndex] =
|
||||
ShaderVariable(rdcstr(), groupid[0] * threadDim[0] + value->threadid[0],
|
||||
groupid[1] * threadDim[1] + value->threadid[1],
|
||||
groupid[2] * threadDim[2] + value->threadid[2], 0U);
|
||||
threadBuiltins[lane][ShaderBuiltin::GroupThreadIndex] =
|
||||
threadBuiltins[ShaderBuiltin::GroupThreadIndex] =
|
||||
ShaderVariable(rdcstr(), value->threadid[0], value->threadid[1], value->threadid[2], 0U);
|
||||
threadBuiltins[lane][ShaderBuiltin::GroupFlatIndex] =
|
||||
threadBuiltins[ShaderBuiltin::GroupFlatIndex] =
|
||||
ShaderVariable(rdcstr(),
|
||||
value->threadid[2] * threadDim[0] * threadDim[1] +
|
||||
value->threadid[1] * threadDim[0] + value->threadid[0],
|
||||
0U, 0U, 0U);
|
||||
threadBuiltins[lane][ShaderBuiltin::IndexInSubgroup] =
|
||||
threadBuiltins[ShaderBuiltin::IndexInSubgroup] =
|
||||
ShaderVariable(rdcstr(), value->laneIndex, 0U, 0U, 0U);
|
||||
}
|
||||
|
||||
@@ -3663,7 +3697,7 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
{
|
||||
for(uint32_t tx = 0; tx < threadDim[0]; tx++)
|
||||
{
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &thread_builtins = threadBuiltins[i];
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &thread_builtins = threadsBuiltins[i];
|
||||
|
||||
if(workgroupProperties[i][DXILDebug::ThreadProperty::Active])
|
||||
{
|
||||
@@ -3705,13 +3739,13 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
{
|
||||
numThreads = threadDim[0] * threadDim[1] * threadDim[2];
|
||||
|
||||
workgroupProperties.resize(numThreads);
|
||||
threadsBuiltins.resize(numThreads);
|
||||
|
||||
// SV_GroupID
|
||||
globalBuiltins[ShaderBuiltin::GroupIndex] =
|
||||
ShaderVariable(rdcstr(), groupid[0], groupid[1], groupid[2], 0U);
|
||||
|
||||
threadBuiltins.resize(numThreads);
|
||||
workgroupProperties.resize(numThreads);
|
||||
|
||||
// if we have workgroup scope that means we need to simulate the whole workgroup but don't
|
||||
// have subgroup ops. We assume the layout of this is irrelevant and don't attempt to read
|
||||
// it back from the GPU like we do with subgroups. We lay things out in plain linear order,
|
||||
@@ -3724,7 +3758,7 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
{
|
||||
for(uint32_t tx = 0; tx < threadDim[0]; tx++)
|
||||
{
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &thread_builtins = threadBuiltins[i];
|
||||
rdcflatmap<ShaderBuiltin, ShaderVariable> &thread_builtins = threadsBuiltins[i];
|
||||
thread_builtins[ShaderBuiltin::DispatchThreadIndex] =
|
||||
ShaderVariable(rdcstr(), groupid[0] * threadDim[0] + tx,
|
||||
groupid[1] * threadDim[1] + ty, groupid[2] * threadDim[2] + tz, 0U);
|
||||
@@ -3744,7 +3778,9 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
}
|
||||
else
|
||||
{
|
||||
workgroupProperties.resize(1);
|
||||
workgroupProperties.resize(numThreads);
|
||||
threadsBuiltins.resize(numThreads);
|
||||
|
||||
workgroupProperties[0][DXILDebug::ThreadProperty::Active] = 1;
|
||||
|
||||
// put everything in globals, no per-thread values
|
||||
@@ -3775,6 +3811,7 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
{
|
||||
uint32_t newNumThreads = numThreads + numPaddingThreads;
|
||||
workgroupProperties.resize(newNumThreads);
|
||||
threadsBuiltins.resize(newNumThreads);
|
||||
for(uint32_t i = numThreads; i < newNumThreads; ++i)
|
||||
{
|
||||
workgroupProperties[i][DXILDebug::ThreadProperty::Active] = 0;
|
||||
@@ -3782,25 +3819,24 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
}
|
||||
numThreads = newNumThreads;
|
||||
}
|
||||
rdcarray<ShaderVariable> threadsInputs;
|
||||
threadsInputs.resize(numThreads);
|
||||
for(uint32_t t = 0; t < numThreads; t++)
|
||||
threadsInputs[t] = apiWrapper->GetInputPlaceholder();
|
||||
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(eventId, dxbc, refl, activeLaneIndex, numThreads);
|
||||
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
|
||||
|
||||
globalState.builtins.swap(globalBuiltins);
|
||||
globalState.subgroupSize = subgroupSize;
|
||||
|
||||
for(uint32_t i = 0; i < threadBuiltins.size(); i++)
|
||||
debugger->GetLane(i).m_Builtins.swap(threadBuiltins[i]);
|
||||
apiWrapper->SetSubgroupSize(subgroupSize);
|
||||
apiWrapper->SetWorkgroupProperties(workgroupProperties);
|
||||
apiWrapper->SetThreadsInputs(threadsInputs);
|
||||
apiWrapper->SetThreadsBuiltins(threadsBuiltins);
|
||||
apiWrapper->SetBuiltins(globalBuiltins);
|
||||
|
||||
// Fetch constant buffer data from root signature
|
||||
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.compute, refl,
|
||||
globalState, ret->sourceVars);
|
||||
apiWrapper->FetchConstantBufferData(rs.compute);
|
||||
|
||||
debugger->InitialiseWorkgroup(workgroupProperties);
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(apiWrapper, eventId, dxbc, refl, activeLaneIndex, numThreads);
|
||||
|
||||
// ret->inputs = state.inputs;
|
||||
ret->constantBlocks = globalState.constantBlocks;
|
||||
apiWrapper->ResetReplay();
|
||||
}
|
||||
|
||||
if(ret)
|
||||
@@ -3824,10 +3860,11 @@ rdcarray<ShaderDebugState> D3D12Replay::ContinueDebug(ShaderDebugger *debugger)
|
||||
if(((DXBCContainerDebugger *)debugger)->isDXIL)
|
||||
{
|
||||
DXILDebug::Debugger *dxilDebugger = (DXILDebug::Debugger *)debugger;
|
||||
DXILDebug::D3D12APIWrapper apiWrapper(m_pDevice, dxilDebugger->GetProgram(),
|
||||
dxilDebugger->GetGlobalState(), dxilDebugger->GetEventId());
|
||||
D3D12MarkerRegion region(m_pDevice->GetQueue()->GetReal(), "ContinueDebug Simulation Loop");
|
||||
return dxilDebugger->ContinueDebug(&apiWrapper);
|
||||
rdcarray<ShaderDebugState> ret = dxilDebugger->ContinueDebug();
|
||||
DXILDebug::D3D12APIWrapper *api = (DXILDebug::D3D12APIWrapper *)dxilDebugger->GetAPIWrapper();
|
||||
api->ResetReplay();
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1220,7 +1220,7 @@ static size_t ComputeDXILTypeByteSize(const Type *type)
|
||||
return byteSize;
|
||||
}
|
||||
|
||||
static void TypedUAVStore(DXILDebug::GlobalState::ViewFmt &fmt, byte *d, const ShaderValue &value)
|
||||
static void TypedUAVStore(DXILDebug::ViewFmt &fmt, byte *d, const ShaderValue &value)
|
||||
{
|
||||
if(fmt.byteWidth == 10)
|
||||
{
|
||||
@@ -1354,7 +1354,7 @@ static void TypedUAVStore(DXILDebug::GlobalState::ViewFmt &fmt, byte *d, const S
|
||||
}
|
||||
}
|
||||
|
||||
static ShaderValue TypedUAVLoad(DXILDebug::GlobalState::ViewFmt &fmt, const byte *d)
|
||||
static ShaderValue TypedUAVLoad(DXILDebug::ViewFmt &fmt, const byte *d)
|
||||
{
|
||||
ShaderValue result;
|
||||
result.f32v[0] = 0.0f;
|
||||
@@ -1511,7 +1511,7 @@ static ShaderValue TypedUAVLoad(DXILDebug::GlobalState::ViewFmt &fmt, const byte
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConvertTypeToViewFormat(const DXIL::Type *type, DXILDebug::GlobalState::ViewFmt &fmt)
|
||||
void ConvertTypeToViewFormat(const DXIL::Type *type, DXILDebug::ViewFmt &fmt)
|
||||
{
|
||||
// variable should be a pointer to the underlying type
|
||||
RDCASSERTEQUAL(type->type, Type::Pointer);
|
||||
@@ -1562,7 +1562,7 @@ void ConvertTypeToViewFormat(const DXIL::Type *type, DXILDebug::GlobalState::Vie
|
||||
}
|
||||
}
|
||||
|
||||
static void FillViewFmtFromVarType(VarType type, DXILDebug::GlobalState::ViewFmt &fmt)
|
||||
static void FillViewFmtFromVarType(VarType type, DXILDebug::ViewFmt &fmt)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
@@ -2343,25 +2343,19 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
|
||||
uint32_t depthPitch = 0;
|
||||
uint32_t firstElem = 0;
|
||||
uint32_t numElems = 0;
|
||||
GlobalState::ViewFmt fmt;
|
||||
ViewFmt fmt;
|
||||
|
||||
// Helper lanes can't modify UAVs
|
||||
if(!load && (resClass == ResourceClass::UAV) && m_Helper)
|
||||
break;
|
||||
|
||||
RDCASSERT((resClass == ResourceClass::SRV || resClass == ResourceClass::UAV), resClass);
|
||||
GlobalState::ResourceInfo resInfo;
|
||||
ResourceInfo resInfo;
|
||||
switch(resClass)
|
||||
{
|
||||
case ResourceClass::UAV:
|
||||
{
|
||||
GlobalState::UAVIterator uavIter = m_GlobalState.uavs.find(resRefInfo.binding);
|
||||
if(uavIter == m_GlobalState.uavs.end())
|
||||
{
|
||||
apiWrapper->FetchUAV(resRefInfo.binding);
|
||||
uavIter = m_GlobalState.uavs.find(resRefInfo.binding);
|
||||
}
|
||||
const GlobalState::UAVData &uav = uavIter->second;
|
||||
const UAVData &uav = apiWrapper->GetUAVData(resRefInfo.binding);
|
||||
resInfo = uav.resInfo;
|
||||
data = uav.data.data();
|
||||
dataSize = uav.data.size();
|
||||
@@ -2372,13 +2366,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
|
||||
}
|
||||
case ResourceClass::SRV:
|
||||
{
|
||||
GlobalState::SRVIterator srvIter = m_GlobalState.srvs.find(resRefInfo.binding);
|
||||
if(srvIter == m_GlobalState.srvs.end())
|
||||
{
|
||||
apiWrapper->FetchSRV(resRefInfo.binding);
|
||||
srvIter = m_GlobalState.srvs.find(resRefInfo.binding);
|
||||
}
|
||||
const GlobalState::SRVData &srv = srvIter->second;
|
||||
const SRVData &srv = apiWrapper->GetSRVData(resRefInfo.binding);
|
||||
resInfo = srv.resInfo;
|
||||
data = srv.data.data();
|
||||
dataSize = srv.data.size();
|
||||
@@ -2895,7 +2883,7 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
|
||||
const uint32_t byteWidth = 4;
|
||||
const byte *data = cbufferData.data() + dataOffset;
|
||||
const uint32_t numComps = RDCMIN(4U, (bufferSize - dataOffset) / byteWidth);
|
||||
GlobalState::ViewFmt cbufferFmt;
|
||||
ViewFmt cbufferFmt;
|
||||
cbufferFmt.byteWidth = byteWidth;
|
||||
cbufferFmt.numComps = numComps;
|
||||
cbufferFmt.compType = CompType::Float;
|
||||
@@ -3511,17 +3499,10 @@ bool ThreadState::ExecuteInstruction(DebugAPIWrapper *apiWrapper,
|
||||
uint32_t depthPitch = 0;
|
||||
uint32_t firstElem = 0;
|
||||
uint32_t numElems = 0;
|
||||
GlobalState::ViewFmt fmt;
|
||||
ViewFmt fmt;
|
||||
|
||||
GlobalState::ResourceInfo resInfo;
|
||||
GlobalState::UAVIterator uavIter = m_GlobalState.uavs.find(resRefInfo.binding);
|
||||
if(uavIter == m_GlobalState.uavs.end())
|
||||
{
|
||||
apiWrapper->FetchUAV(resRefInfo.binding);
|
||||
uavIter = m_GlobalState.uavs.find(resRefInfo.binding);
|
||||
}
|
||||
const GlobalState::UAVData &uav = uavIter->second;
|
||||
resInfo = uav.resInfo;
|
||||
const UAVData &uav = apiWrapper->GetUAVData(resRefInfo.binding);
|
||||
const ResourceInfo resInfo = uav.resInfo;
|
||||
data = uav.data.data();
|
||||
dataSize = uav.data.size();
|
||||
texData = uav.tex;
|
||||
@@ -7668,6 +7649,11 @@ rdcstr Debugger::GetResourceReferenceName(const DXIL::Program *program,
|
||||
return "UNKNOWN_RESOURCE_HANDLE";
|
||||
}
|
||||
|
||||
Debugger::~Debugger()
|
||||
{
|
||||
SAFE_DELETE(m_ApiWrapper);
|
||||
}
|
||||
|
||||
ScopedDebugData *Debugger::FindScopedDebugData(const DXIL::Metadata *md) const
|
||||
{
|
||||
for(ScopedDebugData *s : m_DebugInfo.scopedDebugDatas)
|
||||
@@ -8887,17 +8873,19 @@ void Debugger::ParseDebugData()
|
||||
}
|
||||
}
|
||||
|
||||
ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContainer *dxbcContainer,
|
||||
ShaderDebugTrace *Debugger::BeginDebug(DebugAPIWrapper *apiWrapper, uint32_t eventId,
|
||||
const DXBC::DXBCContainer *dxbcContainer,
|
||||
const ShaderReflection &reflection, uint32_t activeLaneIndex,
|
||||
uint32_t threadsInWorkgroup)
|
||||
{
|
||||
ShaderStage shaderStage = reflection.stage;
|
||||
|
||||
m_ApiWrapper = apiWrapper;
|
||||
m_Program = dxbcContainer->GetDXILByteCode();
|
||||
m_EventId = eventId;
|
||||
m_ActiveLaneIndex = activeLaneIndex;
|
||||
m_Steps = 0;
|
||||
m_Stage = shaderStage;
|
||||
m_EntryPointInterface = m_Program->GetEntryPointInterface();
|
||||
|
||||
uint32_t outputSSAId = m_Program->m_NextSSAId;
|
||||
uint32_t maxSSAId = outputSSAId + 1;
|
||||
@@ -8905,27 +8893,30 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
ShaderDebugTrace *ret = new ShaderDebugTrace;
|
||||
ret->stage = shaderStage;
|
||||
|
||||
// Get the global state from the API wrapper
|
||||
m_GlobalState.builtins = apiWrapper->GetBuiltins();
|
||||
m_GlobalState.subgroupSize = apiWrapper->GetSubgroupSize();
|
||||
m_GlobalState.constantBlocks = apiWrapper->GetConstantBlocks();
|
||||
m_GlobalState.constantBlocksDatas = apiWrapper->GetConstantBlocksDatas();
|
||||
|
||||
for(uint32_t i = 0; i < threadsInWorkgroup; i++)
|
||||
m_Workgroup.push_back(ThreadState(*this, m_GlobalState, maxSSAId));
|
||||
|
||||
ThreadState &state = GetActiveLane();
|
||||
// Get the thread state from the API wrapper
|
||||
const rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> &threadsBuiltins =
|
||||
apiWrapper->GetThreadsBuiltins();
|
||||
const rdcarray<ShaderVariable> &threadsInputs = apiWrapper->GetThreadsInputs();
|
||||
|
||||
// Create the storage layout for the constant buffers
|
||||
// The constant buffer data and details are filled in outside of this method
|
||||
size_t count = reflection.constantBlocks.size();
|
||||
m_GlobalState.constantBlocks.resize(count);
|
||||
for(uint32_t i = 0; i < count; i++)
|
||||
for(uint32_t i = 0; i < threadsInWorkgroup; i++)
|
||||
{
|
||||
m_GlobalState.constantBlocks[i].type = VarType::ConstantBlock;
|
||||
const ConstantBlock &cbuffer = reflection.constantBlocks[i];
|
||||
uint32_t bindCount = cbuffer.bindArraySize;
|
||||
if(bindCount > 1)
|
||||
{
|
||||
// Create nested structure for constant buffer array
|
||||
m_GlobalState.constantBlocks[i].members.resize(bindCount);
|
||||
}
|
||||
m_Workgroup[i].m_Builtins = threadsBuiltins[i];
|
||||
m_Workgroup[i].m_Input = threadsInputs[i];
|
||||
}
|
||||
|
||||
ret->sourceVars = apiWrapper->GetSourceVars();
|
||||
|
||||
ThreadState &activeState = GetActiveLane();
|
||||
|
||||
struct ResourceList
|
||||
{
|
||||
VarType varType;
|
||||
@@ -8994,7 +8985,7 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
}
|
||||
|
||||
// Create the variables for Samplers
|
||||
count = reflection.samplers.size();
|
||||
size_t count = reflection.samplers.size();
|
||||
m_GlobalState.samplers.reserve(count);
|
||||
for(uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
@@ -9046,7 +9037,8 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
const MemoryTracking::Allocation &allocation = itAlloc->second;
|
||||
void *allocMemoryBackingPtr = allocation.backingMemory;
|
||||
uint64_t allocSize = allocation.size;
|
||||
state.UpdateBackingMemoryFromVariable(allocMemoryBackingPtr, allocSize, globalVar.var);
|
||||
activeState.UpdateBackingMemoryFromVariable(allocMemoryBackingPtr, allocSize,
|
||||
globalVar.var);
|
||||
RDCASSERTEQUAL(allocSize, 0);
|
||||
}
|
||||
else
|
||||
@@ -9464,120 +9456,18 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
}
|
||||
}
|
||||
|
||||
// Add inputs to the shader trace
|
||||
// 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;
|
||||
|
||||
const uint32_t countInParams = (uint32_t)inputs.size();
|
||||
if(countInParams)
|
||||
{
|
||||
// Make fake ShaderVariable struct to hold all the inputs
|
||||
ShaderVariable &inStruct = state.m_Input;
|
||||
inStruct.name = DXIL_FAKE_INPUT_STRUCT_NAME;
|
||||
inStruct.rows = 0;
|
||||
inStruct.columns = 0;
|
||||
inStruct.type = VarType::Struct;
|
||||
inStruct.members.resize(countInParams);
|
||||
|
||||
const rdcarray<SigParameter> &dxbcInParams = dxbcContainer->GetReflection()->InputSig;
|
||||
for(uint32_t i = 0; i < countInParams; ++i)
|
||||
{
|
||||
const EntryPointInterface::Signature &sig = inputs[i];
|
||||
|
||||
ShaderVariable &v = inStruct.members[i];
|
||||
|
||||
// Get the name from the DXBC reflection
|
||||
SigParameter sigParam;
|
||||
if(FindSigParameter(dxbcInParams, sig, sigParam))
|
||||
{
|
||||
v.name = sigParam.semanticIdxName;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.name = sig.name;
|
||||
}
|
||||
v.rows = (uint8_t)sig.rows;
|
||||
v.columns = (uint8_t)sig.cols;
|
||||
v.type = VarTypeForComponentType(sig.type);
|
||||
if(v.rows <= 1)
|
||||
{
|
||||
v.rows = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.members.resize(v.rows);
|
||||
for(uint32_t r = 0; r < v.rows; r++)
|
||||
{
|
||||
v.members[r].rows = 1;
|
||||
v.members[r].columns = (uint8_t)sig.cols;
|
||||
v.members[r].type = v.type;
|
||||
v.members[r].name = StringFormat::Fmt("[%u]", r);
|
||||
}
|
||||
}
|
||||
|
||||
SourceVariableMapping inputMapping;
|
||||
inputMapping.name = v.name;
|
||||
inputMapping.type = v.type;
|
||||
inputMapping.rows = sig.rows;
|
||||
inputMapping.columns = sig.cols;
|
||||
inputMapping.variables.reserve(sig.cols);
|
||||
inputMapping.signatureIndex = i;
|
||||
if(v.rows <= 1)
|
||||
{
|
||||
inputMapping.variables.reserve(sig.cols);
|
||||
for(uint32_t c = 0; c < sig.cols; ++c)
|
||||
{
|
||||
DebugVariableReference ref;
|
||||
ref.type = DebugVariableType::Input;
|
||||
ref.name = inStruct.name + "." + v.name;
|
||||
ref.component = c;
|
||||
inputMapping.variables.push_back(ref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugVariableReference ref;
|
||||
ref.type = DebugVariableType::Input;
|
||||
ref.name = inStruct.name + "." + v.name;
|
||||
inputMapping.variables.push_back(ref);
|
||||
}
|
||||
ret->sourceVars.push_back(inputMapping);
|
||||
}
|
||||
|
||||
// Make a single source variable mapping for the whole input struct
|
||||
SourceVariableMapping inputMapping;
|
||||
inputMapping.name = inStruct.name;
|
||||
inputMapping.type = VarType::Struct;
|
||||
inputMapping.rows = 0;
|
||||
inputMapping.columns = 0;
|
||||
inputMapping.variables.resize(1);
|
||||
inputMapping.variables.push_back(DebugVariableReference(DebugVariableType::Input, inStruct.name));
|
||||
ret->sourceVars.push_back(inputMapping);
|
||||
}
|
||||
|
||||
const rdcarray<SigParameter> &dxbcOutParams = dxbcContainer->GetReflection()->OutputSig;
|
||||
const rdcarray<EntryPointInterface::Signature> &outputs = m_EntryPointInterface->outputs;
|
||||
uint32_t countOutputs = (uint32_t)outputs.size();
|
||||
|
||||
// Make fake ShaderVariable struct to hold all the outputs
|
||||
ShaderVariable &outStruct = state.m_Output.var;
|
||||
ShaderVariable &outStruct = activeState.m_Output.var;
|
||||
outStruct.name = DXIL_FAKE_OUTPUT_STRUCT_NAME;
|
||||
outStruct.rows = 0;
|
||||
outStruct.columns = 0;
|
||||
outStruct.type = VarType::Struct;
|
||||
outStruct.members.resize(countOutputs);
|
||||
state.m_Output.id = outputSSAId;
|
||||
activeState.m_Output.id = outputSSAId;
|
||||
|
||||
for(uint32_t i = 0; i < countOutputs; ++i)
|
||||
{
|
||||
@@ -9707,12 +9597,12 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
{
|
||||
// Make a single source variable mapping for the whole output struct
|
||||
SourceVariableMapping outputMapping;
|
||||
outputMapping.name = state.m_Output.var.name;
|
||||
outputMapping.name = activeState.m_Output.var.name;
|
||||
outputMapping.type = VarType::Struct;
|
||||
outputMapping.rows = 0;
|
||||
outputMapping.columns = 0;
|
||||
outputMapping.variables.resize(1);
|
||||
outputMapping.variables[0].name = state.m_Output.var.name;
|
||||
outputMapping.variables[0].name = activeState.m_Output.var.name;
|
||||
outputMapping.variables[0].type = DebugVariableType::Variable;
|
||||
ret->sourceVars.push_back(outputMapping);
|
||||
}
|
||||
@@ -9731,8 +9621,8 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
ret->sourceVars.push_back(outputMapping);
|
||||
}
|
||||
|
||||
ret->inputs = {state.m_Input};
|
||||
ret->inputs.append(state.m_Input.members);
|
||||
ret->inputs = {activeState.m_Input};
|
||||
ret->inputs.append(activeState.m_Input.members);
|
||||
ret->constantBlocks = m_GlobalState.constantBlocks;
|
||||
ret->readOnlyResources = m_GlobalState.readOnlyResources;
|
||||
ret->readWriteResources = m_GlobalState.readWriteResources;
|
||||
@@ -9746,23 +9636,25 @@ ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContain
|
||||
|
||||
if(i != m_ActiveLaneIndex)
|
||||
{
|
||||
lane.m_Input = state.m_Input;
|
||||
lane.m_Variables = state.m_Variables;
|
||||
lane.m_Assigned = state.m_Assigned;
|
||||
lane.m_Live = state.m_Live;
|
||||
lane.m_IsGlobal = state.m_IsGlobal;
|
||||
lane.m_Variables = activeState.m_Variables;
|
||||
lane.m_Assigned = activeState.m_Assigned;
|
||||
lane.m_Live = activeState.m_Live;
|
||||
lane.m_IsGlobal = activeState.m_IsGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the output struct to the global state
|
||||
if(countOutputs)
|
||||
m_GlobalState.globals.push_back(state.m_Output);
|
||||
m_GlobalState.globals.push_back(activeState.m_Output);
|
||||
|
||||
InitialiseWorkgroup();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Debugger::InitialiseWorkgroup(const rdcarray<ThreadProperties> &workgroupProperties)
|
||||
void Debugger::InitialiseWorkgroup()
|
||||
{
|
||||
const rdcarray<ThreadProperties> &workgroupProperties = m_ApiWrapper->GetWorkgroupProperties();
|
||||
const uint32_t threadsInWorkgroup = (uint32_t)m_Workgroup.size();
|
||||
|
||||
if(threadsInWorkgroup == 1)
|
||||
@@ -9853,7 +9745,7 @@ void Debugger::InitialiseWorkgroup(const rdcarray<ThreadProperties> &workgroupPr
|
||||
}
|
||||
}
|
||||
|
||||
rdcarray<ShaderDebugState> Debugger::ContinueDebug(DebugAPIWrapper *apiWrapper)
|
||||
rdcarray<ShaderDebugState> Debugger::ContinueDebug()
|
||||
{
|
||||
ThreadState &active = GetActiveLane();
|
||||
|
||||
@@ -9987,12 +9879,12 @@ rdcarray<ShaderDebugState> Debugger::ContinueDebug(DebugAPIWrapper *apiWrapper)
|
||||
{
|
||||
hasDebugState = true;
|
||||
state.stepIndex = m_Steps;
|
||||
thread.StepNext(&state, apiWrapper, m_Workgroup, activeMask);
|
||||
thread.StepNext(&state, m_ApiWrapper, m_Workgroup, activeMask);
|
||||
m_Steps++;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread.StepNext(NULL, apiWrapper, m_Workgroup, activeMask);
|
||||
thread.StepNext(NULL, m_ApiWrapper, m_Workgroup, activeMask);
|
||||
}
|
||||
|
||||
threadExecutionStates[threadId] = thread.m_EnteredPoints;
|
||||
|
||||
@@ -173,13 +173,87 @@ struct ConstantBlockReference
|
||||
}
|
||||
};
|
||||
|
||||
struct ViewFmt
|
||||
{
|
||||
int byteWidth = 0;
|
||||
int numComps = 0;
|
||||
CompType compType = CompType::Typeless;
|
||||
int stride = 0;
|
||||
};
|
||||
|
||||
struct ResourceInfo
|
||||
{
|
||||
ResourceInfo() : firstElement(0), numElements(0), isByteBuffer(false), isRootDescriptor(false) {}
|
||||
|
||||
uint32_t firstElement;
|
||||
uint32_t numElements;
|
||||
|
||||
bool isByteBuffer;
|
||||
bool isRootDescriptor;
|
||||
// Buffer stride is stored in format.stride
|
||||
ViewFmt format;
|
||||
};
|
||||
|
||||
struct UAVData
|
||||
{
|
||||
UAVData() = default;
|
||||
|
||||
ResourceInfo resInfo;
|
||||
bytebuf data;
|
||||
|
||||
uint32_t rowPitch = 0;
|
||||
uint32_t depthPitch = 0;
|
||||
uint32_t hiddenCounter = 0;
|
||||
bool tex = false;
|
||||
};
|
||||
|
||||
struct SRVData
|
||||
{
|
||||
SRVData() = default;
|
||||
|
||||
ResourceInfo resInfo;
|
||||
bytebuf data;
|
||||
};
|
||||
|
||||
enum class ThreadProperty : uint32_t
|
||||
{
|
||||
Helper,
|
||||
QuadId,
|
||||
QuadLane,
|
||||
Active,
|
||||
SubgroupIdx,
|
||||
Count,
|
||||
};
|
||||
|
||||
struct ThreadProperties
|
||||
{
|
||||
rdcfixedarray<uint32_t, arraydim<ThreadProperty>()> props;
|
||||
|
||||
uint32_t &operator[](ThreadProperty p)
|
||||
{
|
||||
if(p >= ThreadProperty::Count)
|
||||
return props[0];
|
||||
return props[(uint32_t)p];
|
||||
}
|
||||
|
||||
uint32_t operator[](ThreadProperty p) const
|
||||
{
|
||||
if(p >= ThreadProperty::Count)
|
||||
return 0;
|
||||
return props[(uint32_t)p];
|
||||
}
|
||||
};
|
||||
|
||||
typedef rdcflatmap<ShaderBuiltin, ShaderVariable> BuiltinInputs;
|
||||
|
||||
class DebugAPIWrapper
|
||||
{
|
||||
public:
|
||||
// During shader debugging, when a new resource is encountered
|
||||
// These will be called to fetch the data on demand.
|
||||
virtual void FetchSRV(const BindingSlot &slot) = 0;
|
||||
virtual void FetchUAV(const BindingSlot &slot) = 0;
|
||||
virtual ~DebugAPIWrapper() {}
|
||||
|
||||
// These will fetch the data on demand.
|
||||
virtual const UAVData &GetUAVData(const BindingSlot &slot) = 0;
|
||||
virtual const SRVData &GetSRVData(const BindingSlot &slot) = 0;
|
||||
|
||||
virtual bool CalculateMathIntrinsic(DXIL::DXOp dxOp, const ShaderVariable &input,
|
||||
ShaderVariable &output) = 0;
|
||||
@@ -193,14 +267,28 @@ public:
|
||||
ShaderVariable &output) = 0;
|
||||
virtual ShaderVariable GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot, uint32_t mipLevel,
|
||||
const DXBC::ShaderType shaderType, int &dim) = 0;
|
||||
const DXBC::ShaderType shaderType, int &dim) const = 0;
|
||||
virtual ShaderVariable GetSampleInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
const DXBC::ShaderType shaderType, const char *opString) = 0;
|
||||
const DXBC::ShaderType shaderType,
|
||||
const char *opString) const = 0;
|
||||
virtual ShaderVariable GetRenderTargetSampleInfo(const DXBC::ShaderType shaderType,
|
||||
const char *opString) = 0;
|
||||
virtual ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) = 0;
|
||||
const char *opString) const = 0;
|
||||
virtual ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) const = 0;
|
||||
virtual ShaderDirectAccess GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot) = 0;
|
||||
const DXDebug::BindingSlot &slot) const = 0;
|
||||
|
||||
virtual bool IsSRVCached(const DXDebug::BindingSlot &slot) = 0;
|
||||
virtual bool IsUAVCached(const DXDebug::BindingSlot &slot) = 0;
|
||||
|
||||
virtual const ShaderVariable &GetInputPlaceholder() const = 0;
|
||||
virtual const rdcarray<DXILDebug::ThreadProperties> &GetWorkgroupProperties() const = 0;
|
||||
virtual const rdcarray<ShaderVariable> &GetConstantBlocks() const = 0;
|
||||
virtual const std::map<ConstantBlockReference, bytebuf> &GetConstantBlocksDatas() const = 0;
|
||||
virtual const BuiltinInputs &GetBuiltins() const = 0;
|
||||
virtual uint32_t GetSubgroupSize() const = 0;
|
||||
virtual const rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> &GetThreadsBuiltins() const = 0;
|
||||
virtual const rdcarray<ShaderVariable> &GetThreadsInputs() const = 0;
|
||||
virtual const rdcarray<SourceVariableMapping> &GetSourceVars() const = 0;
|
||||
};
|
||||
|
||||
struct MemoryTracking
|
||||
@@ -237,8 +325,6 @@ struct MemoryTracking
|
||||
std::map<Id, Pointer> m_Pointers;
|
||||
};
|
||||
|
||||
typedef rdcflatmap<ShaderBuiltin, ShaderVariable> BuiltinInputs;
|
||||
|
||||
struct ThreadState
|
||||
{
|
||||
ThreadState(Debugger &debugger, const GlobalState &globalState, uint32_t maxSSAId);
|
||||
@@ -401,56 +487,6 @@ struct GlobalState
|
||||
uint32_t subgroupSize = 1;
|
||||
bool waveOpsIncludeHelpers = false;
|
||||
|
||||
struct ViewFmt
|
||||
{
|
||||
int byteWidth = 0;
|
||||
int numComps = 0;
|
||||
CompType compType = CompType::Typeless;
|
||||
int stride = 0;
|
||||
};
|
||||
|
||||
struct ResourceInfo
|
||||
{
|
||||
ResourceInfo() : firstElement(0), numElements(0), isByteBuffer(false), isRootDescriptor(false)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t firstElement;
|
||||
uint32_t numElements;
|
||||
|
||||
bool isByteBuffer;
|
||||
bool isRootDescriptor;
|
||||
// Buffer stride is stored in format.stride
|
||||
ViewFmt format;
|
||||
};
|
||||
|
||||
struct UAVData
|
||||
{
|
||||
UAVData() : tex(false), rowPitch(0), depthPitch(0), hiddenCounter(0) {}
|
||||
|
||||
ResourceInfo resInfo;
|
||||
|
||||
bytebuf data;
|
||||
bool tex;
|
||||
uint32_t rowPitch, depthPitch;
|
||||
|
||||
uint32_t hiddenCounter;
|
||||
};
|
||||
|
||||
std::map<BindingSlot, UAVData> uavs;
|
||||
typedef std::map<BindingSlot, UAVData>::const_iterator UAVIterator;
|
||||
|
||||
struct SRVData
|
||||
{
|
||||
SRVData() {}
|
||||
|
||||
ResourceInfo resInfo;
|
||||
bytebuf data;
|
||||
};
|
||||
|
||||
std::map<BindingSlot, SRVData> srvs;
|
||||
typedef std::map<BindingSlot, SRVData>::const_iterator SRVIterator;
|
||||
|
||||
// allocated storage for opaque uniform blocks, does not change over the course of debugging
|
||||
rdcarray<ShaderVariable> constantBlocks;
|
||||
std::map<ConstantBlockReference, bytebuf> constantBlocksDatas;
|
||||
@@ -556,62 +592,33 @@ struct TypeData
|
||||
bool colMajorMat = false;
|
||||
};
|
||||
|
||||
enum class ThreadProperty : uint32_t
|
||||
{
|
||||
Helper,
|
||||
QuadId,
|
||||
QuadLane,
|
||||
Active,
|
||||
SubgroupIdx,
|
||||
Count,
|
||||
};
|
||||
|
||||
struct ThreadProperties
|
||||
{
|
||||
rdcfixedarray<uint32_t, arraydim<ThreadProperty>()> props;
|
||||
|
||||
uint32_t &operator[](ThreadProperty p)
|
||||
{
|
||||
if(p >= ThreadProperty::Count)
|
||||
return props[0];
|
||||
return props[(uint32_t)p];
|
||||
}
|
||||
|
||||
uint32_t operator[](ThreadProperty p) const
|
||||
{
|
||||
if(p >= ThreadProperty::Count)
|
||||
return 0;
|
||||
return props[(uint32_t)p];
|
||||
}
|
||||
};
|
||||
|
||||
class Debugger : public DXBCContainerDebugger
|
||||
{
|
||||
public:
|
||||
Debugger() : DXBCContainerDebugger(true){};
|
||||
ShaderDebugTrace *BeginDebug(uint32_t eventId, const DXBC::DXBCContainer *dxbcContainer,
|
||||
~Debugger();
|
||||
|
||||
ShaderDebugTrace *BeginDebug(DebugAPIWrapper *apiWrapper, uint32_t eventId,
|
||||
const DXBC::DXBCContainer *dxbcContainer,
|
||||
const ShaderReflection &reflection, uint32_t activeLaneIndex,
|
||||
uint32_t threadsInWorkgroup);
|
||||
void InitialiseWorkgroup(const rdcarray<ThreadProperties> &workgroupProperties);
|
||||
rdcarray<ShaderDebugState> ContinueDebug(DebugAPIWrapper *apiWrapper);
|
||||
GlobalState &GetGlobalState() { return m_GlobalState; }
|
||||
ThreadState &GetActiveLane() { return m_Workgroup[m_ActiveLaneIndex]; }
|
||||
ThreadState &GetLane(const uint32_t i) { return m_Workgroup[i]; }
|
||||
rdcarray<ThreadState> &GetWorkgroup() { return m_Workgroup; }
|
||||
const rdcarray<bool> &GetLiveGlobals() { return m_LiveGlobals; }
|
||||
static rdcstr GetResourceReferenceName(const DXIL::Program *program, DXIL::ResourceClass resClass,
|
||||
const BindingSlot &slot);
|
||||
rdcarray<ShaderDebugState> ContinueDebug();
|
||||
|
||||
const rdcarray<bool> &GetLiveGlobals() const { return m_LiveGlobals; }
|
||||
const DXIL::Program &GetProgram() const { return *m_Program; }
|
||||
const FunctionInfo *GetFunctionInfo(const DXIL::Function *function) const;
|
||||
|
||||
DebugAPIWrapper *GetAPIWrapper() const { return m_ApiWrapper; }
|
||||
|
||||
static rdcstr GetResourceBaseName(const DXIL::Program *program,
|
||||
const DXIL::ResourceReference *resRef);
|
||||
const DXIL::Program &GetProgram() const { return *m_Program; }
|
||||
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;
|
||||
}
|
||||
|
||||
static rdcstr GetResourceReferenceName(const DXIL::Program *program, DXIL::ResourceClass resClass,
|
||||
const BindingSlot &slot);
|
||||
|
||||
private:
|
||||
void InitialiseWorkgroup();
|
||||
ThreadState &GetActiveLane() { return m_Workgroup[m_ActiveLaneIndex]; }
|
||||
void ParseDbgOpDeclare(const DXIL::Instruction &inst, uint32_t instructionIndex);
|
||||
void ParseDbgOpValue(const DXIL::Instruction &inst, uint32_t instructionIndex);
|
||||
const DXIL::Metadata *GetMDScope(const DXIL::Metadata *scopeMD) const;
|
||||
@@ -622,6 +629,8 @@ private:
|
||||
void AddLocalVariable(const DXIL::SourceMappingInfo &srcMapping, uint32_t instructionIndex);
|
||||
void ParseDebugData();
|
||||
|
||||
DebugAPIWrapper *m_ApiWrapper = NULL;
|
||||
|
||||
rdcarray<ThreadState> m_Workgroup;
|
||||
std::map<const DXIL::Function *, FunctionInfo> m_FunctionInfos;
|
||||
rdcshaders::ControlFlow m_ControlFlow;
|
||||
@@ -644,7 +653,6 @@ private:
|
||||
const DXIL::EntryPointInterface *m_EntryPointInterface = NULL;
|
||||
ShaderStage m_Stage;
|
||||
|
||||
uint32_t m_EventId = 0;
|
||||
uint32_t m_ActiveLaneIndex = 0;
|
||||
int m_Steps = 0;
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user