mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-11-02 03:55:08 +00:00
DXIL Debugger support code in D3D12_ShaderDebug.cpp
Code is effectively disabled because DXIL GetDebugStatus() returns "Debugging DXIL is not supported" Includes minimum required helper structs/methods in DXIL Debugger
This commit is contained in:
1 parent
d1f69b5c72
commit
82005c8fee
3 files changed
+637
-12
No files matched your search
@@ -31,6 +31,7 @@
|
||||
#include "strings/string_utils.h"
|
||||
#include "d3d12_command_queue.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_dxil_debug.h"
|
||||
#include "d3d12_replay.h"
|
||||
#include "d3d12_resources.h"
|
||||
#include "d3d12_rootsig.h"
|
||||
@@ -1938,7 +1939,262 @@ ShaderDebugTrace *D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, ui
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("DXIL Vertex Shader Debugging is not supported");
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(eventId, dxbc, refl, 0);
|
||||
|
||||
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
|
||||
DXILDebug::ThreadState &activeState = debugger->GetActiveLane();
|
||||
rdcarray<ShaderVariable> &inputs = activeState.m_Input.members;
|
||||
|
||||
// Fetch constant buffer data from root signature
|
||||
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.graphics, refl,
|
||||
globalState, ret->sourceVars);
|
||||
|
||||
// Set input values
|
||||
for(size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
const SigParameter &sigParam = dxbc->GetReflection()->InputSig[i];
|
||||
switch(sigParam.systemValue)
|
||||
{
|
||||
case ShaderBuiltin::Undefined:
|
||||
case ShaderBuiltin::Position: // SV_Position seems to get promoted automatically,
|
||||
// but it's invalid for vertex input
|
||||
{
|
||||
const D3D12_INPUT_ELEMENT_DESC *el = NULL;
|
||||
rdcstr signame = strlower(sigParam.semanticName);
|
||||
|
||||
for(size_t l = 0; l < inputlayout.size(); l++)
|
||||
{
|
||||
rdcstr layoutname = strlower(inputlayout[l].SemanticName);
|
||||
if(signame == layoutname && sigParam.semanticIndex == inputlayout[l].SemanticIndex)
|
||||
{
|
||||
el = &inputlayout[l];
|
||||
break;
|
||||
}
|
||||
if(signame == layoutname + ToStr(inputlayout[l].SemanticIndex))
|
||||
{
|
||||
el = &inputlayout[l];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RDCASSERT(el);
|
||||
|
||||
if(!el)
|
||||
continue;
|
||||
|
||||
byte *srcData = NULL;
|
||||
size_t dataSize = 0;
|
||||
|
||||
if(el->InputSlotClass == D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA)
|
||||
{
|
||||
if(vertData[el->InputSlot].size() >= el->AlignedByteOffset)
|
||||
{
|
||||
srcData = &vertData[el->InputSlot][el->AlignedByteOffset];
|
||||
dataSize = vertData[el->InputSlot].size() - el->AlignedByteOffset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(el->InstanceDataStepRate == 0 || el->InstanceDataStepRate >= action->numInstances)
|
||||
{
|
||||
if(staticData[el->InputSlot].size() >= el->AlignedByteOffset)
|
||||
{
|
||||
srcData = &staticData[el->InputSlot][el->AlignedByteOffset];
|
||||
dataSize = staticData[el->InputSlot].size() - el->AlignedByteOffset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT isrIdx = el->InputSlot * MaxStepRate + (el->InstanceDataStepRate - 1);
|
||||
if(instData[isrIdx].size() >= el->AlignedByteOffset)
|
||||
{
|
||||
srcData = &instData[isrIdx][el->AlignedByteOffset];
|
||||
dataSize = instData[isrIdx].size() - el->AlignedByteOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResourceFormat fmt = MakeResourceFormat(el->Format);
|
||||
|
||||
// more data needed than is provided
|
||||
if(sigParam.compCount > fmt.compCount)
|
||||
{
|
||||
inputs[i].value.u32v[3] = 1;
|
||||
|
||||
if(fmt.compType == CompType::Float)
|
||||
inputs[i].value.f32v[3] = 1.0f;
|
||||
}
|
||||
|
||||
// interpret resource format types
|
||||
if(fmt.Special())
|
||||
{
|
||||
Vec3f *v3 = (Vec3f *)inputs[i].value.f32v.data();
|
||||
Vec4f *v4 = (Vec4f *)inputs[i].value.f32v.data();
|
||||
|
||||
// only pull in all or nothing from these,
|
||||
// if there's only e.g. 3 bytes remaining don't read and unpack some of
|
||||
// a 4-byte resource format type
|
||||
size_t packedsize = 4;
|
||||
if(fmt.type == ResourceFormatType::R5G5B5A1 || fmt.type == ResourceFormatType::R5G6B5 ||
|
||||
fmt.type == ResourceFormatType::R4G4B4A4)
|
||||
packedsize = 2;
|
||||
|
||||
if(srcData == NULL || packedsize > dataSize)
|
||||
{
|
||||
inputs[i].value.u32v[0] = inputs[i].value.u32v[1] = inputs[i].value.u32v[2] =
|
||||
inputs[i].value.u32v[3] = 0;
|
||||
}
|
||||
else if(fmt.type == ResourceFormatType::R5G5B5A1)
|
||||
{
|
||||
RDCASSERT(fmt.BGRAOrder());
|
||||
uint16_t packed = ((uint16_t *)srcData)[0];
|
||||
*v4 = ConvertFromB5G5R5A1(packed);
|
||||
}
|
||||
else if(fmt.type == ResourceFormatType::R5G6B5)
|
||||
{
|
||||
RDCASSERT(fmt.BGRAOrder());
|
||||
uint16_t packed = ((uint16_t *)srcData)[0];
|
||||
*v3 = ConvertFromB5G6R5(packed);
|
||||
}
|
||||
else if(fmt.type == ResourceFormatType::R4G4B4A4)
|
||||
{
|
||||
RDCASSERT(fmt.BGRAOrder());
|
||||
uint16_t packed = ((uint16_t *)srcData)[0];
|
||||
*v4 = ConvertFromB4G4R4A4(packed);
|
||||
}
|
||||
else if(fmt.type == ResourceFormatType::R10G10B10A2)
|
||||
{
|
||||
uint32_t packed = ((uint32_t *)srcData)[0];
|
||||
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
inputs[i].value.u32v[2] = (packed >> 0) & 0x3ff;
|
||||
inputs[i].value.u32v[1] = (packed >> 10) & 0x3ff;
|
||||
inputs[i].value.u32v[0] = (packed >> 20) & 0x3ff;
|
||||
inputs[i].value.u32v[3] = (packed >> 30) & 0x003;
|
||||
}
|
||||
else
|
||||
{
|
||||
*v4 = ConvertFromR10G10B10A2(packed);
|
||||
}
|
||||
}
|
||||
else if(fmt.type == ResourceFormatType::R11G11B10)
|
||||
{
|
||||
uint32_t packed = ((uint32_t *)srcData)[0];
|
||||
*v3 = ConvertFromR11G11B10(packed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t c = 0; c < fmt.compCount; c++)
|
||||
{
|
||||
if(srcData == NULL || fmt.compByteWidth > dataSize)
|
||||
{
|
||||
inputs[i].value.u32v[c] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
dataSize -= fmt.compByteWidth;
|
||||
|
||||
if(fmt.compByteWidth == 1)
|
||||
{
|
||||
byte *src = srcData + c * fmt.compByteWidth;
|
||||
|
||||
if(fmt.compType == CompType::UInt)
|
||||
inputs[i].value.u32v[c] = *src;
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
inputs[i].value.s32v[c] = *((int8_t *)src);
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
inputs[i].value.f32v[c] = float(*src) / 255.0f;
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
signed char *schar = (signed char *)src;
|
||||
|
||||
// -128 is mapped to -1, then -127 to -127 are mapped to -1 to 1
|
||||
if(*schar == -128)
|
||||
inputs[i].value.f32v[c] = -1.0f;
|
||||
else
|
||||
inputs[i].value.f32v[c] = float(*schar) / 127.0f;
|
||||
}
|
||||
else
|
||||
RDCERR("Unexpected component type");
|
||||
}
|
||||
else if(fmt.compByteWidth == 2)
|
||||
{
|
||||
uint16_t *src = (uint16_t *)(srcData + c * fmt.compByteWidth);
|
||||
|
||||
if(fmt.compType == CompType::Float)
|
||||
inputs[i].value.f32v[c] = ConvertFromHalf(*src);
|
||||
else if(fmt.compType == CompType::UInt)
|
||||
inputs[i].value.u32v[c] = *src;
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
inputs[i].value.s32v[c] = *((int16_t *)src);
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
inputs[i].value.f32v[c] = float(*src) / float(UINT16_MAX);
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
int16_t *sint = (int16_t *)src;
|
||||
|
||||
// -32768 is mapped to -1, then -32767 to -32767 are mapped to -1 to 1
|
||||
if(*sint == -32768)
|
||||
inputs[i].value.f32v[c] = -1.0f;
|
||||
else
|
||||
inputs[i].value.f32v[c] = float(*sint) / 32767.0f;
|
||||
}
|
||||
else
|
||||
RDCERR("Unexpected component type");
|
||||
}
|
||||
else if(fmt.compByteWidth == 4)
|
||||
{
|
||||
uint32_t *src = (uint32_t *)(srcData + c * fmt.compByteWidth);
|
||||
|
||||
if(fmt.compType == CompType::Float || fmt.compType == CompType::UInt ||
|
||||
fmt.compType == CompType::SInt)
|
||||
memcpy(&inputs[i].value.u32v[c], src, 4);
|
||||
else
|
||||
RDCERR("Unexpected component type");
|
||||
}
|
||||
}
|
||||
|
||||
if(fmt.BGRAOrder())
|
||||
{
|
||||
RDCASSERT(fmt.compCount == 4);
|
||||
std::swap(inputs[i].value.f32v[2], inputs[i].value.f32v[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ShaderBuiltin::VertexIndex:
|
||||
{
|
||||
uint32_t sv_vertid = vertid;
|
||||
|
||||
if(action->flags & ActionFlags::Indexed)
|
||||
sv_vertid = idx - action->baseVertex;
|
||||
|
||||
if(sigParam.varType == VarType::Float)
|
||||
inputs[i].value.f32v[0] = inputs[i].value.f32v[1] = inputs[i].value.f32v[2] =
|
||||
inputs[i].value.f32v[3] = (float)sv_vertid;
|
||||
else
|
||||
inputs[i].value.u32v[0] = inputs[i].value.u32v[1] = inputs[i].value.u32v[2] =
|
||||
inputs[i].value.u32v[3] = sv_vertid;
|
||||
break;
|
||||
}
|
||||
case ShaderBuiltin::InstanceIndex:
|
||||
{
|
||||
if(sigParam.varType == VarType::Float)
|
||||
inputs[i].value.f32v[0] = inputs[i].value.f32v[1] = inputs[i].value.f32v[2] =
|
||||
inputs[i].value.f32v[3] = (float)instid;
|
||||
else
|
||||
inputs[i].value.u32v[0] = inputs[i].value.u32v[1] = inputs[i].value.u32v[2] =
|
||||
inputs[i].value.u32v[3] = instid;
|
||||
break;
|
||||
}
|
||||
default: RDCERR("Unhandled system value semantic on VS input"); break;
|
||||
}
|
||||
}
|
||||
ret->inputs = {activeState.m_Input};
|
||||
delete[] instData;
|
||||
}
|
||||
|
||||
if(ret)
|
||||
@@ -1993,12 +2249,6 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
|
||||
return new ShaderDebugTrace;
|
||||
}
|
||||
|
||||
if(!dxbc->GetDXBCByteCode())
|
||||
{
|
||||
RDCERR("DXIL Pixel Shader Debugging is not supported");
|
||||
return new ShaderDebugTrace;
|
||||
}
|
||||
|
||||
dxbc->GetDisassembly(false);
|
||||
|
||||
ShaderDebugTrace *ret = NULL;
|
||||
@@ -2037,7 +2287,7 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
|
||||
if(dxbc->GetDXBCByteCode())
|
||||
DXBCDebug::GetInterpolationModeForInputParams(inputSig, dxbc->GetDXBCByteCode(), interpModes);
|
||||
else
|
||||
RDCERR("DXIL Pixel Shader Debugging is not supported");
|
||||
DXILDebug::GetInterpolationModeForInputParams(inputSig, dxbc->GetDXILByteCode(), interpModes);
|
||||
|
||||
DXDebug::GatherPSInputDataForInitialValues(inputSig, prevDxbc->GetReflection()->OutputSig,
|
||||
interpModes, initialValues, floatInputs, inputVarNames,
|
||||
@@ -2158,7 +2408,7 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("DXIL Pixel Shader Debugging is not supported");
|
||||
RDCWARN("TODO DXIL Pixel Shader Debugging support for MSAA Evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2820,7 +3070,106 @@ struct PSInitialData
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("DXIL Pixel Shader Debugging is not supported");
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
uint32_t activeLaneIdx = destIdx;
|
||||
ret = debugger->BeginDebug(eventId, dxbc, refl, activeLaneIdx);
|
||||
|
||||
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
|
||||
DXILDebug::ThreadState &activeState = debugger->GetActiveLane();
|
||||
rdcarray<ShaderVariable> &ins = activeState.m_Input.members;
|
||||
|
||||
// Fetch constant buffer data from root signature
|
||||
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.graphics, refl,
|
||||
globalState, ret->sourceVars);
|
||||
|
||||
// TODO SAMPLE EVALUTE MASK
|
||||
// globalState.sampleEvalRegisterMask = sampleEvalRegisterMask;
|
||||
|
||||
rdcarray<DXILDebug::PSInputData> psInputDatas;
|
||||
for(int i = 0; i < initialValues.count(); i++)
|
||||
{
|
||||
PSInputElement &elem = initialValues[i];
|
||||
if(elem.reg >= 0)
|
||||
psInputDatas.emplace_back(i, elem.numwords, elem.sysattribute, elem.included, data);
|
||||
|
||||
if(elem.included)
|
||||
data += elem.numwords;
|
||||
}
|
||||
|
||||
{
|
||||
if(!ins.empty() && ins.back().name == "vCoverage")
|
||||
ins.back().value.u32v[0] = pHit->coverage;
|
||||
|
||||
activeState.m_Semantics.coverage = pHit->coverage;
|
||||
activeState.m_Semantics.primID = pHit->primitive;
|
||||
activeState.m_Semantics.isFrontFace = pHit->isFrontFace;
|
||||
|
||||
for(const DXILDebug::PSInputData &psInput : psInputDatas)
|
||||
{
|
||||
int32_t *rawout = NULL;
|
||||
|
||||
ShaderVariable &invar = ins[psInput.input];
|
||||
|
||||
if(psInput.sysattribute == ShaderBuiltin::PrimitiveIndex)
|
||||
{
|
||||
invar.value.u32v[0] = pHit->primitive;
|
||||
}
|
||||
else if(psInput.sysattribute == ShaderBuiltin::MSAASampleIndex)
|
||||
{
|
||||
invar.value.u32v[0] = pHit->sample;
|
||||
}
|
||||
else if(psInput.sysattribute == ShaderBuiltin::MSAACoverage)
|
||||
{
|
||||
invar.value.u32v[0] = pHit->coverage;
|
||||
}
|
||||
else if(psInput.sysattribute == ShaderBuiltin::IsFrontFace)
|
||||
{
|
||||
invar.value.u32v[0] = pHit->isFrontFace ? ~0U : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rawout = &invar.value.s32v[0];
|
||||
memcpy(rawout, psInput.data, psInput.numwords * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
if(i != destIdx)
|
||||
{
|
||||
DXILDebug::ThreadState &workgroup = debugger->GetWorkgroup(i);
|
||||
workgroup.InitialiseHelper(activeState);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO UPDATE INPUTS FROM SAMPLE CACHE
|
||||
#if 0
|
||||
for(const GlobalState::SampleEvalCacheKey &key : evalSampleCacheData)
|
||||
{
|
||||
// start with the basic input value
|
||||
ShaderVariable var = activeState.m_Input.members[key.inputRegisterIndex];
|
||||
|
||||
// copy over the value into the variable
|
||||
memcpy(var.value.f32v.data(), evalSampleCache, var.columns * sizeof(float));
|
||||
|
||||
// store in the global cache for each quad. We'll apply derivatives below to adjust for each
|
||||
GlobalState::SampleEvalCacheKey k = key;
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
k.quadIndex = i;
|
||||
activeState.sampleEvalCache[k] = var;
|
||||
}
|
||||
|
||||
// advance past this data - always by float4 as that's the buffer stride
|
||||
evalSampleCache += 4;
|
||||
}
|
||||
#endif
|
||||
DXILDebug::ApplyAllDerivatives(globalState, debugger->GetWorkgroups(), destIdx, psInputDatas,
|
||||
(float *)data);
|
||||
|
||||
ret->inputs = {activeState.m_Input};
|
||||
ret->constantBlocks = globalState.constantBlocks;
|
||||
}
|
||||
|
||||
if(ret)
|
||||
@@ -2954,7 +3303,47 @@ ShaderDebugTrace *D3D12Replay::DebugThread(uint32_t eventId,
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("DXIL Compute Shader Debugging is not supported");
|
||||
// get ourselves in pristine state before this dispatch (without any side effects it may have had)
|
||||
m_pDevice->ReplayLog(0, eventId, eReplay_WithoutDraw);
|
||||
|
||||
DXILDebug::Debugger *debugger = new DXILDebug::Debugger();
|
||||
ret = debugger->BeginDebug(eventId, dxbc, refl, 0);
|
||||
DXILDebug::GlobalState &globalState = debugger->GetGlobalState();
|
||||
|
||||
std::map<ShaderBuiltin, ShaderVariable> &builtins = globalState.builtinInputs;
|
||||
|
||||
uint32_t threadDim[3] = {
|
||||
refl.dispatchThreadsDimension[0],
|
||||
refl.dispatchThreadsDimension[1],
|
||||
refl.dispatchThreadsDimension[2],
|
||||
};
|
||||
|
||||
// SV_DispatchThreadID
|
||||
builtins[ShaderBuiltin::DispatchThreadIndex] = ShaderVariable(
|
||||
rdcstr(), groupid[0] * threadDim[0] + threadid[0], groupid[1] * threadDim[1] + threadid[1],
|
||||
groupid[2] * threadDim[2] + threadid[2], 0U);
|
||||
|
||||
// SV_GroupID
|
||||
builtins[ShaderBuiltin::GroupIndex] =
|
||||
ShaderVariable(rdcstr(), groupid[0], groupid[1], groupid[2], 0U);
|
||||
|
||||
// SV_GroupThreadID
|
||||
builtins[ShaderBuiltin::GroupThreadIndex] =
|
||||
ShaderVariable(rdcstr(), threadid[0], threadid[1], threadid[2], 0U);
|
||||
|
||||
// SV_GroupIndex
|
||||
builtins[ShaderBuiltin::GroupFlatIndex] = ShaderVariable(
|
||||
rdcstr(),
|
||||
threadid[2] * threadDim[0] * threadDim[1] + threadid[1] * threadDim[0] + threadid[0], 0U,
|
||||
0U, 0U);
|
||||
|
||||
// TODO ADD ANY OTHER INPUTS
|
||||
|
||||
// Fetch constant buffer data from root signature
|
||||
DXILDebug::FetchConstantBufferData(m_pDevice, dxbc->GetDXILByteCode(), rs.compute, refl,
|
||||
globalState, ret->sourceVars);
|
||||
// ret->inputs = state.inputs;
|
||||
ret->constantBlocks = globalState.constantBlocks;
|
||||
}
|
||||
|
||||
if(ret)
|
||||
@@ -2969,7 +3358,11 @@ rdcarray<ShaderDebugState> D3D12Replay::ContinueDebug(ShaderDebugger *debugger)
|
||||
|
||||
if(((DXBCContainerDebugger *)debugger)->isDXIL)
|
||||
{
|
||||
return {};
|
||||
DXILDebug::Debugger *dxilDebugger = (DXILDebug::Debugger *)debugger;
|
||||
DXILDebug::D3D12APIWrapper apiWrapper(m_pDevice, dxilDebugger->GetDXBCContainer(),
|
||||
dxilDebugger->GetGlobalState(), dxilDebugger->GetEventId());
|
||||
D3D12MarkerRegion region(m_pDevice->GetQueue()->GetReal(), "ContinueDebug Simulation Loop");
|
||||
return dxilDebugger->ContinueDebug(&apiWrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -32,6 +32,159 @@ using namespace DXDebug;
|
||||
namespace DXILDebug
|
||||
{
|
||||
|
||||
static void ApplyDerivatives(GlobalState &global, rdcarray<ThreadState> &quad, int input,
|
||||
int numWords, float *data, float signmul, int32_t quadIdxA,
|
||||
int32_t quadIdxB)
|
||||
{
|
||||
for(int w = 0; w < numWords; w++)
|
||||
{
|
||||
quad[quadIdxA].m_Input.members[input].value.f32v[w] += signmul * data[w];
|
||||
if(quadIdxB >= 0)
|
||||
quad[quadIdxB].m_Input.members[input].value.f32v[w] += signmul * data[w];
|
||||
}
|
||||
|
||||
// TODO: SAMPLE EVALUATE
|
||||
#if 0
|
||||
// quick check to see if this register was evaluated
|
||||
if(global.sampleEvalRegisterMask & (1ULL << reg))
|
||||
{
|
||||
// apply derivative to any cached sample evaluations on these quad indices
|
||||
for(auto it = global.sampleEvalCache.begin(); it != global.sampleEvalCache.end(); ++it)
|
||||
{
|
||||
if((it->first.quadIndex == quadIdxA || it->first.quadIndex == quadIdxB) &&
|
||||
reg == it->first.inputRegisterIndex)
|
||||
{
|
||||
for(int w = 0; w < numWords; w++)
|
||||
it->second.value.f32v[w] += data[w];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ApplyAllDerivatives(GlobalState &global, rdcarray<ThreadState> &quad, int destIdx,
|
||||
const rdcarray<PSInputData> &psInputs, float *data)
|
||||
{
|
||||
// We make the assumption that the coarse derivatives are generated from (0,0) in the quad, and
|
||||
// fine derivatives are generated from the destination index and its neighbours in X and Y.
|
||||
// This isn't spec'd but we must assume something and this will hopefully get us closest to
|
||||
// reproducing actual results.
|
||||
//
|
||||
// For debugging, we need members of the quad to be able to generate coarse and fine
|
||||
// derivatives.
|
||||
//
|
||||
// For (0,0) we only need the coarse derivatives to get our neighbours (1,0) and (0,1) which
|
||||
// will give us coarse and fine derivatives being identical.
|
||||
//
|
||||
// For the others we will need to use a combination of coarse and fine derivatives to get the
|
||||
// diagonal element in the quad. In the examples below, remember that the quad indices are:
|
||||
//
|
||||
// +---+---+
|
||||
// | 0 | 1 |
|
||||
// +---+---+
|
||||
// | 2 | 3 |
|
||||
// +---+---+
|
||||
//
|
||||
// And that we have definitions of the derivatives:
|
||||
//
|
||||
// ddx_coarse = (1,0) - (0,0)
|
||||
// ddy_coarse = (0,1) - (0,0)
|
||||
//
|
||||
// i.e. the same for all members of the quad
|
||||
//
|
||||
// ddx_fine = (x,y) - (1-x,y)
|
||||
// ddy_fine = (x,y) - (x,1-y)
|
||||
//
|
||||
// i.e. the difference to the neighbour of our desired invocation (the one we have the actual
|
||||
// inputs for, from gathering above).
|
||||
//
|
||||
// So e.g. if our thread is at (1,1) destIdx = 3
|
||||
//
|
||||
// (1,0) = (1,1) - ddx_fine
|
||||
// (0,1) = (1,1) - ddy_fine
|
||||
// (0,0) = (1,1) - ddy_fine - ddx_coarse
|
||||
//
|
||||
// and ddy_coarse is unused. For (1,0) destIdx = 1:
|
||||
//
|
||||
// (1,1) = (1,0) + ddy_fine
|
||||
// (0,1) = (1,0) - ddx_coarse + ddy_coarse
|
||||
// (0,0) = (1,0) - ddx_coarse
|
||||
//
|
||||
// and ddx_fine is unused (it's identical to ddx_coarse anyway)
|
||||
|
||||
// this is the value of input[1] - input[0]
|
||||
float *ddx_coarse = (float *)data;
|
||||
|
||||
for(const PSInputData &psInput : psInputs)
|
||||
{
|
||||
const int input = psInput.input;
|
||||
const int numWords = psInput.numwords;
|
||||
if(destIdx == 0)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddx_coarse, 1.0f, 1, 3);
|
||||
else if(destIdx == 1)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddx_coarse, -1.0f, 0, 2);
|
||||
else if(destIdx == 2)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddx_coarse, 1.0f, 1, -1);
|
||||
else if(destIdx == 3)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddx_coarse, -1.0f, 0, -1);
|
||||
|
||||
ddx_coarse += numWords;
|
||||
}
|
||||
|
||||
// this is the value of input[2] - input[0]
|
||||
float *ddy_coarse = ddx_coarse;
|
||||
|
||||
for(const PSInputData &psInput : psInputs)
|
||||
{
|
||||
const int input = psInput.input;
|
||||
const int numWords = psInput.numwords;
|
||||
if(destIdx == 0)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddy_coarse, 1.0f, 2, 3);
|
||||
else if(destIdx == 1)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddy_coarse, -1.0f, 2, -1);
|
||||
else if(destIdx == 2)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddy_coarse, 1.0f, 0, 1);
|
||||
|
||||
ddy_coarse += numWords;
|
||||
}
|
||||
|
||||
float *ddxfine = ddy_coarse;
|
||||
|
||||
for(const PSInputData &psInput : psInputs)
|
||||
{
|
||||
const int input = psInput.input;
|
||||
const int numWords = psInput.numwords;
|
||||
|
||||
if(destIdx == 2)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddxfine, 1.0f, 3, -1);
|
||||
else if(destIdx == 3)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddxfine, -1.0f, 2, -1);
|
||||
|
||||
ddxfine += numWords;
|
||||
}
|
||||
|
||||
float *ddyfine = ddxfine;
|
||||
|
||||
for(const PSInputData &psInput : psInputs)
|
||||
{
|
||||
const int input = psInput.input;
|
||||
const int numWords = psInput.numwords;
|
||||
|
||||
if(destIdx == 1)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddyfine, 1.0f, 3, -1);
|
||||
else if(destIdx == 3)
|
||||
ApplyDerivatives(global, quad, input, numWords, ddyfine, -1.0f, 0, 1);
|
||||
|
||||
ddyfine += numWords;
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadState::InitialiseHelper(const ThreadState &activeState)
|
||||
{
|
||||
m_Input = activeState.m_Input;
|
||||
m_Semantics = activeState.m_Semantics;
|
||||
}
|
||||
|
||||
// static helper function
|
||||
rdcstr Debugger::GetResourceReferenceName(const DXIL::Program *program,
|
||||
DXIL::ResourceClass resClass, const BindingSlot &slot)
|
||||
@@ -55,4 +208,28 @@ rdcstr Debugger::GetResourceReferenceName(const DXIL::Program *program,
|
||||
return "UNKNOWN_RESOURCE_HANDLE";
|
||||
}
|
||||
|
||||
// member functions
|
||||
|
||||
ShaderDebugTrace *Debugger::BeginDebug(uint32_t eventId, const DXBC::DXBCContainer *dxbcContainer,
|
||||
const ShaderReflection &reflection, uint32_t activeLaneIndex)
|
||||
{
|
||||
ShaderStage shaderStage = reflection.stage;
|
||||
|
||||
m_DXBC = dxbcContainer;
|
||||
m_EventId = eventId;
|
||||
m_ActiveLaneIndex = activeLaneIndex;
|
||||
|
||||
ShaderDebugTrace *ret = new ShaderDebugTrace;
|
||||
ret->stage = shaderStage;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdcarray<ShaderDebugState> Debugger::ContinueDebug(DebugAPIWrapper *apiWrapper)
|
||||
{
|
||||
rdcarray<ShaderDebugState> ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}; // namespace DXILDebug
|
||||
@@ -44,12 +44,48 @@ class Debugger;
|
||||
struct GlobalState;
|
||||
|
||||
typedef std::map<ShaderBuiltin, ShaderVariable> BuiltinInputs;
|
||||
|
||||
void GetInterpolationModeForInputParams(const rdcarray<SigParameter> &stageInputSig,
|
||||
const DXIL::Program *program,
|
||||
rdcarray<DXBC::InterpolationMode> &interpModes);
|
||||
|
||||
struct PSInputData
|
||||
{
|
||||
PSInputData(int inputIndex, int numWords, ShaderBuiltin sysAttribute, bool inc, void *pData)
|
||||
{
|
||||
input = inputIndex;
|
||||
numwords = numWords;
|
||||
sysattribute = sysAttribute;
|
||||
included = inc;
|
||||
data = pData;
|
||||
}
|
||||
|
||||
void *data;
|
||||
ShaderBuiltin sysattribute;
|
||||
int input;
|
||||
int numwords;
|
||||
bool included;
|
||||
};
|
||||
|
||||
void ApplyAllDerivatives(GlobalState &global, rdcarray<ThreadState> &quad, int destIdx,
|
||||
const rdcarray<PSInputData> &psInputs, float *data);
|
||||
|
||||
class DebugAPIWrapper
|
||||
{
|
||||
};
|
||||
|
||||
struct ThreadState
|
||||
{
|
||||
void InitialiseHelper(const ThreadState &activeState);
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t coverage;
|
||||
uint32_t primID;
|
||||
uint32_t isFrontFace;
|
||||
} m_Semantics;
|
||||
|
||||
ShaderVariable m_Input;
|
||||
};
|
||||
|
||||
struct GlobalState
|
||||
@@ -128,8 +164,27 @@ class Debugger : public DXBCContainerDebugger
|
||||
{
|
||||
public:
|
||||
Debugger() : DXBCContainerDebugger(true){};
|
||||
ShaderDebugTrace *BeginDebug(uint32_t eventId, const DXBC::DXBCContainer *dxbcContainer,
|
||||
const ShaderReflection &reflection, uint32_t activeLaneIndex);
|
||||
rdcarray<ShaderDebugState> ContinueDebug(DebugAPIWrapper *apiWrapper);
|
||||
GlobalState &GetGlobalState() { return m_GlobalState; }
|
||||
ThreadState &GetActiveLane() { return m_Workgroups[m_ActiveLaneIndex]; }
|
||||
ThreadState &GetWorkgroup(const uint32_t i) { return m_Workgroups[i]; }
|
||||
rdcarray<ThreadState> &GetWorkgroups() { return m_Workgroups; }
|
||||
static rdcstr GetResourceReferenceName(const DXIL::Program *program, DXIL::ResourceClass resClass,
|
||||
const BindingSlot &slot);
|
||||
const DXBC::DXBCContainer *const GetDXBCContainer() { return m_DXBC; }
|
||||
uint32_t GetEventId() { return m_EventId; }
|
||||
|
||||
private:
|
||||
rdcarray<ThreadState> m_Workgroups;
|
||||
|
||||
GlobalState m_GlobalState;
|
||||
|
||||
const DXBC::DXBCContainer *m_DXBC = NULL;
|
||||
|
||||
uint32_t m_EventId = 0;
|
||||
uint32_t m_ActiveLaneIndex = 0;
|
||||
};
|
||||
|
||||
}; // namespace DXILDebug
|
||||
Reference in new issue
Block a user