mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-26 00:16:45 +00:00
Move some functions to common locations for upcoming D3D12 usage.
Some work for shader debugging is identical to setting up the quad overlay, so I've moved that logic to their own functions. Some portions of creating a global shader debug state, and the entirety of the initial shader debug state were agnostic of D3D API, so they now exist in DXBC code.
This commit is contained in:
committed by
Baldur Karlsson
parent
b5890155b5
commit
9b141086c0
@@ -119,9 +119,6 @@ public:
|
||||
|
||||
void PixelHistoryCopyPixel(CopyPixelParams ¶ms, uint32_t x, uint32_t y);
|
||||
|
||||
ShaderDebug::State CreateShaderDebugState(ShaderDebugTrace &trace, int quadIdx,
|
||||
DXBC::DXBCContainer *dxbc, const ShaderReflection &refl,
|
||||
bytebuf *cbufData);
|
||||
void CreateShaderGlobalState(ShaderDebug::GlobalState &global, DXBC::DXBCContainer *dxbc,
|
||||
uint32_t UAVStartSlot, ID3D11UnorderedAccessView **UAVs,
|
||||
ID3D11ShaderResourceView **SRVs);
|
||||
|
||||
@@ -1416,171 +1416,6 @@ bool D3D11DebugAPIWrapper::CalculateMathIntrinsic(DXBCBytecode::OpcodeType opcod
|
||||
return true;
|
||||
}
|
||||
|
||||
ShaderDebug::State D3D11DebugManager::CreateShaderDebugState(ShaderDebugTrace &trace, int quadIdx,
|
||||
DXBC::DXBCContainer *dxbc,
|
||||
const ShaderReflection &refl,
|
||||
bytebuf *cbufData)
|
||||
{
|
||||
using namespace DXBCBytecode;
|
||||
using namespace ShaderDebug;
|
||||
|
||||
State initialState = State(quadIdx, &trace, dxbc->GetReflection(), dxbc->GetDXBCByteCode());
|
||||
|
||||
// use pixel shader here to get inputs
|
||||
|
||||
int32_t maxReg = -1;
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->InputSig.size(); i++)
|
||||
maxReg = RDCMAX(maxReg, (int32_t)dxbc->GetReflection()->InputSig[i].regIndex);
|
||||
|
||||
bool inputCoverage = false;
|
||||
|
||||
for(size_t i = 0; i < dxbc->GetDXBCByteCode()->GetNumDeclarations(); i++)
|
||||
{
|
||||
const DXBCBytecode::Declaration &decl = dxbc->GetDXBCByteCode()->GetDeclaration(i);
|
||||
|
||||
if(decl.declaration == OPCODE_DCL_INPUT && decl.operand.type == TYPE_INPUT_COVERAGE_MASK)
|
||||
{
|
||||
inputCoverage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(maxReg >= 0 || inputCoverage)
|
||||
{
|
||||
trace.inputs.resize(maxReg + 1 + (inputCoverage ? 1 : 0));
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->InputSig.size(); i++)
|
||||
{
|
||||
const SigParameter &sig = dxbc->GetReflection()->InputSig[i];
|
||||
|
||||
ShaderVariable v;
|
||||
|
||||
v.name = StringFormat::Fmt("v%d (%s)", sig.regIndex, sig.semanticIdxName.c_str());
|
||||
v.rows = 1;
|
||||
v.columns = sig.regChannelMask & 0x8 ? 4 : sig.regChannelMask & 0x4
|
||||
? 3
|
||||
: sig.regChannelMask & 0x2
|
||||
? 2
|
||||
: sig.regChannelMask & 0x1 ? 1 : 0;
|
||||
|
||||
if(sig.compType == CompType::UInt)
|
||||
v.type = VarType::UInt;
|
||||
else if(sig.compType == CompType::SInt)
|
||||
v.type = VarType::SInt;
|
||||
|
||||
if(trace.inputs[sig.regIndex].columns == 0)
|
||||
trace.inputs[sig.regIndex] = v;
|
||||
else
|
||||
trace.inputs[sig.regIndex].columns = RDCMAX(trace.inputs[sig.regIndex].columns, v.columns);
|
||||
}
|
||||
|
||||
if(inputCoverage)
|
||||
{
|
||||
trace.inputs[maxReg + 1] = ShaderVariable("vCoverage", 0U, 0U, 0U, 0U);
|
||||
trace.inputs[maxReg + 1].columns = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t specialOutputs = 0;
|
||||
maxReg = -1;
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->OutputSig.size(); i++)
|
||||
{
|
||||
if(dxbc->GetReflection()->OutputSig[i].regIndex == ~0U)
|
||||
specialOutputs++;
|
||||
else
|
||||
maxReg = RDCMAX(maxReg, (int32_t)dxbc->GetReflection()->OutputSig[i].regIndex);
|
||||
}
|
||||
|
||||
if(maxReg >= 0 || specialOutputs > 0)
|
||||
{
|
||||
initialState.outputs.resize(maxReg + 1 + specialOutputs);
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->OutputSig.size(); i++)
|
||||
{
|
||||
const SigParameter &sig = dxbc->GetReflection()->OutputSig[i];
|
||||
|
||||
if(sig.regIndex == ~0U)
|
||||
continue;
|
||||
|
||||
ShaderVariable v;
|
||||
|
||||
v.name = StringFormat::Fmt("o%d (%s)", sig.regIndex, sig.semanticIdxName.c_str());
|
||||
v.rows = 1;
|
||||
v.columns = sig.regChannelMask & 0x8 ? 4 : sig.regChannelMask & 0x4
|
||||
? 3
|
||||
: sig.regChannelMask & 0x2
|
||||
? 2
|
||||
: sig.regChannelMask & 0x1 ? 1 : 0;
|
||||
|
||||
if(initialState.outputs[sig.regIndex].columns == 0)
|
||||
initialState.outputs[sig.regIndex] = v;
|
||||
else
|
||||
initialState.outputs[sig.regIndex].columns =
|
||||
RDCMAX(initialState.outputs[sig.regIndex].columns, v.columns);
|
||||
}
|
||||
|
||||
int32_t outIdx = maxReg + 1;
|
||||
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->OutputSig.size(); i++)
|
||||
{
|
||||
const SigParameter &sig = dxbc->GetReflection()->OutputSig[i];
|
||||
|
||||
if(sig.regIndex != ~0U)
|
||||
continue;
|
||||
|
||||
ShaderVariable v;
|
||||
|
||||
if(sig.systemValue == ShaderBuiltin::OutputControlPointIndex)
|
||||
v.name = "vOutputControlPointID";
|
||||
else if(sig.systemValue == ShaderBuiltin::DepthOutput)
|
||||
v.name = "oDepth";
|
||||
else if(sig.systemValue == ShaderBuiltin::DepthOutputLessEqual)
|
||||
v.name = "oDepthLessEqual";
|
||||
else if(sig.systemValue == ShaderBuiltin::DepthOutputGreaterEqual)
|
||||
v.name = "oDepthGreaterEqual";
|
||||
else if(sig.systemValue == ShaderBuiltin::MSAACoverage)
|
||||
v.name = "oMask";
|
||||
else if(sig.systemValue == ShaderBuiltin::StencilReference)
|
||||
v.name = "oStencilRef";
|
||||
// if(sig.systemValue == TYPE_OUTPUT_CONTROL_POINT) str = "oOutputControlPoint";
|
||||
else
|
||||
{
|
||||
RDCERR("Unhandled output: %s (%d)", sig.semanticName.c_str(), sig.systemValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
v.rows = 1;
|
||||
v.columns = sig.regChannelMask & 0x8 ? 4 : sig.regChannelMask & 0x4
|
||||
? 3
|
||||
: sig.regChannelMask & 0x2
|
||||
? 2
|
||||
: sig.regChannelMask & 0x1 ? 1 : 0;
|
||||
|
||||
initialState.outputs[outIdx++] = v;
|
||||
}
|
||||
}
|
||||
|
||||
trace.constantBlocks.resize(dxbc->GetReflection()->CBuffers.size());
|
||||
for(size_t i = 0; i < dxbc->GetReflection()->CBuffers.size(); i++)
|
||||
{
|
||||
rdcarray<ShaderVariable> vars;
|
||||
|
||||
// fetch the cbuffer data into vars, which will be 'natural' - structs with members, non merged
|
||||
// vectors
|
||||
StandardFillCBufferVariables(refl.constantBlocks[i].variables, vars,
|
||||
cbufData[dxbc->GetReflection()->CBuffers[i].reg]);
|
||||
|
||||
FlattenVariables(refl.constantBlocks[i].variables, vars, trace.constantBlocks[i].members);
|
||||
|
||||
for(size_t c = 0; c < trace.constantBlocks[i].members.size(); c++)
|
||||
trace.constantBlocks[i].members[c].name =
|
||||
StringFormat::Fmt("cb%u[%u] (%s)", dxbc->GetReflection()->CBuffers[i].reg, (uint32_t)c,
|
||||
trace.constantBlocks[i].members[c].name.c_str());
|
||||
}
|
||||
|
||||
initialState.Init();
|
||||
|
||||
return initialState;
|
||||
}
|
||||
|
||||
void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global,
|
||||
DXBC::DXBCContainer *dxbc, uint32_t UAVStartSlot,
|
||||
ID3D11UnorderedAccessView **UAVs,
|
||||
@@ -1809,17 +1644,7 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global
|
||||
|
||||
if(sdesc.Format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
ResourceFormat fmt = MakeResourceFormat(sdesc.Format);
|
||||
|
||||
global.srvs[i].format.byteWidth = fmt.compByteWidth;
|
||||
global.srvs[i].format.numComps = fmt.compCount;
|
||||
global.srvs[i].format.fmt = fmt.compType;
|
||||
|
||||
if(sdesc.Format == DXGI_FORMAT_R11G11B10_FLOAT)
|
||||
global.srvs[i].format.byteWidth = 11;
|
||||
if(sdesc.Format == DXGI_FORMAT_R10G10B10A2_UINT ||
|
||||
sdesc.Format == DXGI_FORMAT_R10G10B10A2_UNORM)
|
||||
global.srvs[i].format.byteWidth = 10;
|
||||
ShaderDebug::FillViewFmt(sdesc.Format, global.srvs[i].format);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1835,28 +1660,8 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global
|
||||
global.srvs[i].format.stride = bufdesc.StructureByteStride;
|
||||
|
||||
// if we didn't get a type from the SRV description, try to pull it from the declaration
|
||||
for(const DXBC::ShaderInputBind &bind : dxbc->GetReflection()->SRVs)
|
||||
{
|
||||
if(bind.reg == (uint32_t)i && bind.dimension == DXBC::ShaderInputBind::DIM_BUFFER &&
|
||||
bind.retType < DXBC::RETURN_TYPE_MIXED && bind.retType != DXBC::RETURN_TYPE_UNKNOWN)
|
||||
{
|
||||
global.srvs[i].format.byteWidth = 4;
|
||||
global.srvs[i].format.numComps = bind.numSamples;
|
||||
|
||||
if(bind.retType == DXBC::RETURN_TYPE_UNORM)
|
||||
global.srvs[i].format.fmt = CompType::UNorm;
|
||||
else if(bind.retType == DXBC::RETURN_TYPE_SNORM)
|
||||
global.srvs[i].format.fmt = CompType::SNorm;
|
||||
else if(bind.retType == DXBC::RETURN_TYPE_UINT)
|
||||
global.srvs[i].format.fmt = CompType::UInt;
|
||||
else if(bind.retType == DXBC::RETURN_TYPE_SINT)
|
||||
global.srvs[i].format.fmt = CompType::SInt;
|
||||
else
|
||||
global.srvs[i].format.fmt = CompType::Float;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
ShaderDebug::LookupSRVFormatFromShaderReflection(*dxbc->GetReflection(), (uint32_t)i,
|
||||
global.srvs[i].format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2020,7 +1825,8 @@ ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uin
|
||||
|
||||
GlobalState global;
|
||||
GetDebugManager()->CreateShaderGlobalState(global, dxbc, 0, NULL, rs->VS.SRVs);
|
||||
State initialState = GetDebugManager()->CreateShaderDebugState(ret, -1, dxbc, refl, cbufData);
|
||||
State initialState;
|
||||
CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl, cbufData);
|
||||
|
||||
for(size_t i = 0; i < ret.inputs.size(); i++)
|
||||
{
|
||||
@@ -3235,8 +3041,8 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim
|
||||
{
|
||||
DebugHit *hit = winner;
|
||||
|
||||
State initialState =
|
||||
GetDebugManager()->CreateShaderDebugState(traces[destIdx], destIdx, dxbc, refl, cbufData);
|
||||
State initialState;
|
||||
CreateShaderDebugStateAndTrace(initialState, traces[destIdx], destIdx, dxbc, refl, cbufData);
|
||||
|
||||
rdcarray<ShaderVariable> &ins = traces[destIdx].inputs;
|
||||
if(!ins.empty() && ins.back().name == "vCoverage")
|
||||
@@ -3536,7 +3342,8 @@ ShaderDebugTrace D3D11Replay::DebugThread(uint32_t eventId, const uint32_t group
|
||||
|
||||
GlobalState global;
|
||||
GetDebugManager()->CreateShaderGlobalState(global, dxbc, 0, rs->CSUAVs, rs->CS.SRVs);
|
||||
State initialState = GetDebugManager()->CreateShaderDebugState(ret, -1, dxbc, refl, cbufData);
|
||||
State initialState;
|
||||
CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl, cbufData);
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
|
||||
@@ -1579,3 +1579,110 @@ void D3D12Replay::HistogramMinMax::Release()
|
||||
SAFE_RELEASE(MinMaxResultBuffer);
|
||||
SAFE_RELEASE(MinMaxTileBuffer);
|
||||
}
|
||||
|
||||
void MoveRootSignatureElementsToRegisterSpace(D3D12RootSignature &sig, uint32_t registerSpace,
|
||||
D3D12DescriptorType type,
|
||||
D3D12_SHADER_VISIBILITY visibility)
|
||||
{
|
||||
// This function is used when root signature elements need to be added to a specific register
|
||||
// space, such as for debug overlays. We can't remove elements from the root signature entirely
|
||||
// because then then the root signature indices wouldn't match up as expected. Instead move them
|
||||
// into the specified register space so that another register space (commonly space0) can be used
|
||||
// for other purposes.
|
||||
size_t numParams = sig.params.size();
|
||||
for(size_t i = 0; i < numParams; i++)
|
||||
{
|
||||
if(sig.params[i].ShaderVisibility == visibility ||
|
||||
sig.params[i].ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL)
|
||||
{
|
||||
D3D12_ROOT_PARAMETER_TYPE rootType = sig.params[i].ParameterType;
|
||||
if(rootType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
|
||||
{
|
||||
size_t numRanges = sig.params[i].ranges.size();
|
||||
for(size_t r = 0; r < numRanges; r++)
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE rangeType = sig.params[i].ranges[r].RangeType;
|
||||
if(rangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV && type == D3D12DescriptorType::CBV)
|
||||
{
|
||||
sig.params[i].ranges[r].RegisterSpace = registerSpace;
|
||||
}
|
||||
else if(rangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV && type == D3D12DescriptorType::SRV)
|
||||
{
|
||||
sig.params[i].ranges[r].RegisterSpace = registerSpace;
|
||||
}
|
||||
else if(rangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV && type == D3D12DescriptorType::UAV)
|
||||
{
|
||||
sig.params[i].ranges[r].RegisterSpace = registerSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(rootType == D3D12_ROOT_PARAMETER_TYPE_CBV && type == D3D12DescriptorType::CBV)
|
||||
{
|
||||
sig.params[i].Descriptor.RegisterSpace = registerSpace;
|
||||
}
|
||||
else if(rootType == D3D12_ROOT_PARAMETER_TYPE_SRV && type == D3D12DescriptorType::SRV)
|
||||
{
|
||||
sig.params[i].Descriptor.RegisterSpace = registerSpace;
|
||||
}
|
||||
else if(rootType == D3D12_ROOT_PARAMETER_TYPE_UAV && type == D3D12DescriptorType::UAV)
|
||||
{
|
||||
sig.params[i].Descriptor.RegisterSpace = registerSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddDebugDescriptorToRenderState(WrappedID3D12Device *pDevice, D3D12RenderState &rs,
|
||||
const PortableHandle &handle,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE heapType, uint32_t sigElem,
|
||||
std::set<ResourceId> &copiedHeaps)
|
||||
{
|
||||
if(rs.graphics.sigelems.size() <= sigElem)
|
||||
rs.graphics.sigelems.resize(sigElem + 1);
|
||||
|
||||
PortableHandle newHandle = handle;
|
||||
|
||||
// If a CBV_SRV_UAV heap is already set and hasn't had a debug descriptor copied in,
|
||||
// copy the desired descriptor in and add the heap to the set of heaps that have had
|
||||
// a debug descriptor set. If there's no available heapOtherwise we can set our own heap.
|
||||
|
||||
// It is the responsibility of the caller to keep track of the set of copied heaps to
|
||||
// avoid overwriting another debug descriptor that may be needed.
|
||||
|
||||
for(size_t i = 0; i < rs.heaps.size(); i++)
|
||||
{
|
||||
WrappedID3D12DescriptorHeap *h =
|
||||
pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(rs.heaps[i]);
|
||||
if(h->GetDesc().Type == heapType)
|
||||
{
|
||||
// use the last descriptor
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dst = h->GetCPUDescriptorHandleForHeapStart();
|
||||
dst.ptr += (h->GetDesc().NumDescriptors - 1) * sizeof(D3D12Descriptor);
|
||||
|
||||
if(copiedHeaps.find(rs.heaps[i]) == copiedHeaps.end())
|
||||
{
|
||||
WrappedID3D12DescriptorHeap *h2 =
|
||||
pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(handle.heap);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE src = h2->GetCPUDescriptorHandleForHeapStart();
|
||||
src.ptr += handle.index * sizeof(D3D12Descriptor);
|
||||
|
||||
// can't do a copy because the src heap is CPU write-only (shader visible). So instead,
|
||||
// create directly
|
||||
D3D12Descriptor *srcDesc = (D3D12Descriptor *)src.ptr;
|
||||
srcDesc->Create(heapType, pDevice, dst);
|
||||
|
||||
copiedHeaps.insert(rs.heaps[i]);
|
||||
}
|
||||
|
||||
newHandle = ToPortableHandle(dst);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(newHandle.heap == handle.heap)
|
||||
rs.heaps.push_back(handle.heap);
|
||||
|
||||
rs.graphics.sigelems[sigElem] =
|
||||
D3D12RenderState::SignatureElement(eRootTable, newHandle.heap, newHandle.index);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "core/core.h"
|
||||
#include "replay/replay_driver.h"
|
||||
#include "d3d12_common.h"
|
||||
#include "d3d12_state.h"
|
||||
|
||||
class WrappedID3D12Device;
|
||||
class D3D12ResourceManager;
|
||||
@@ -165,9 +166,6 @@ public:
|
||||
void CopyTex2DMSToArray(ID3D12Resource *destArray, ID3D12Resource *srcMS);
|
||||
void CopyArrayToTex2DMS(ID3D12Resource *destMS, ID3D12Resource *srcArray, UINT selectedSlice);
|
||||
|
||||
ShaderDebug::State CreateShaderDebugState(ShaderDebugTrace &trace, int quadIdx,
|
||||
DXBC::DXBCContainer *dxbc, const ShaderReflection &refl,
|
||||
bytebuf *cbufData);
|
||||
void CreateShaderGlobalState(ShaderDebug::GlobalState &global, DXBC::DXBCContainer *dxbc);
|
||||
|
||||
private:
|
||||
@@ -215,3 +213,12 @@ private:
|
||||
ID3D12GraphicsCommandListX *m_DebugList = NULL;
|
||||
ID3D12CommandAllocator *m_DebugAlloc = NULL;
|
||||
};
|
||||
|
||||
void MoveRootSignatureElementsToRegisterSpace(D3D12RootSignature &sig, uint32_t registerSpace,
|
||||
D3D12DescriptorType type,
|
||||
D3D12_SHADER_VISIBILITY visibility);
|
||||
|
||||
void AddDebugDescriptorToRenderState(WrappedID3D12Device *pDevice, D3D12RenderState &rs,
|
||||
const PortableHandle &handle,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE heapType, uint32_t sigElem,
|
||||
std::set<ResourceId> &copiedHeaps);
|
||||
|
||||
@@ -81,30 +81,9 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback
|
||||
|
||||
D3D12RootSignature modsig = sig->sig;
|
||||
|
||||
// make sure no other UAV tables overlap. We can't remove elements entirely because then the
|
||||
// root signature indices wouldn't match up as expected.
|
||||
// Instead move them into an unused space.
|
||||
for(size_t i = 0; i < modsig.params.size(); i++)
|
||||
{
|
||||
if(modsig.params[i].ShaderVisibility == D3D12_SHADER_VISIBILITY_PIXEL ||
|
||||
modsig.params[i].ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL)
|
||||
{
|
||||
// use different register spaces for each just in case
|
||||
UINT regSpace = modsig.maxSpaceIndex + modsig.params[i].ShaderVisibility;
|
||||
|
||||
if(modsig.params[i].ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV)
|
||||
{
|
||||
modsig.params[i].Descriptor.RegisterSpace = regSpace;
|
||||
}
|
||||
else if(modsig.params[i].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
|
||||
{
|
||||
for(size_t r = 0; r < modsig.params[i].ranges.size(); r++)
|
||||
{
|
||||
modsig.params[i].ranges[r].RegisterSpace = regSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UINT regSpace = modsig.maxSpaceIndex + 1;
|
||||
MoveRootSignatureElementsToRegisterSpace(modsig, regSpace, D3D12DescriptorType::UAV,
|
||||
D3D12_SHADER_VISIBILITY_PIXEL);
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE1 range;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
||||
@@ -123,11 +102,6 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback
|
||||
|
||||
cache.sigElem = uint32_t(modsig.params.size() - 1);
|
||||
|
||||
std::vector<D3D12_ROOT_PARAMETER1> params;
|
||||
params.resize(modsig.params.size());
|
||||
for(size_t i = 0; i < params.size(); i++)
|
||||
params[i] = modsig.params[i];
|
||||
|
||||
ID3DBlob *root = m_pDevice->GetShaderCache()->MakeRootSig(modsig);
|
||||
|
||||
hr = m_pDevice->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(),
|
||||
@@ -171,49 +145,8 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback
|
||||
rs.pipe = GetResID(cache.pipe);
|
||||
rs.graphics.rootsig = GetResID(cache.sig);
|
||||
|
||||
if(rs.graphics.sigelems.size() <= cache.sigElem)
|
||||
rs.graphics.sigelems.resize(cache.sigElem + 1);
|
||||
|
||||
PortableHandle uav = m_UAV;
|
||||
|
||||
// if a CBV_SRV_UAV heap is already set, we need to copy our descriptor in
|
||||
// if we haven't already. Otherwise we can set our own heap.
|
||||
for(size_t i = 0; i < rs.heaps.size(); i++)
|
||||
{
|
||||
WrappedID3D12DescriptorHeap *h =
|
||||
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(rs.heaps[i]);
|
||||
if(h->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
|
||||
{
|
||||
// use the last descriptor
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dst = h->GetCPUDescriptorHandleForHeapStart();
|
||||
dst.ptr += (h->GetDesc().NumDescriptors - 1) * sizeof(D3D12Descriptor);
|
||||
|
||||
if(m_CopiedHeaps.find(rs.heaps[i]) == m_CopiedHeaps.end())
|
||||
{
|
||||
WrappedID3D12DescriptorHeap *h2 =
|
||||
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(m_UAV.heap);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE src = h2->GetCPUDescriptorHandleForHeapStart();
|
||||
src.ptr += m_UAV.index * sizeof(D3D12Descriptor);
|
||||
|
||||
// can't do a copy because the src heap is CPU write-only (shader visible). So instead,
|
||||
// create directly
|
||||
D3D12Descriptor *srcDesc = (D3D12Descriptor *)src.ptr;
|
||||
srcDesc->Create(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pDevice, dst);
|
||||
|
||||
m_CopiedHeaps.insert(rs.heaps[i]);
|
||||
}
|
||||
|
||||
uav = ToPortableHandle(dst);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(uav.heap == m_UAV.heap)
|
||||
rs.heaps.push_back(m_UAV.heap);
|
||||
|
||||
rs.graphics.sigelems[cache.sigElem] =
|
||||
D3D12RenderState::SignatureElement(eRootTable, uav.heap, uav.index);
|
||||
AddDebugDescriptorToRenderState(m_pDevice, rs, m_UAV, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
cache.sigElem, m_CopiedHeaps);
|
||||
|
||||
// as we're changing the root signature, we need to reapply all elements,
|
||||
// so just apply all state
|
||||
|
||||
@@ -117,22 +117,6 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather(
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderDebug::State D3D12DebugManager::CreateShaderDebugState(ShaderDebugTrace &trace, int quadIdx,
|
||||
DXBC::DXBCContainer *dxbc,
|
||||
const ShaderReflection &refl,
|
||||
bytebuf *cbufData)
|
||||
{
|
||||
RDCUNIMPLEMENTED("CreateShaderDebugState not yet implemented for D3D12");
|
||||
|
||||
using namespace DXBCBytecode;
|
||||
using namespace ShaderDebug;
|
||||
|
||||
State initialState = State(quadIdx, &trace, dxbc->GetReflection(), dxbc->GetDXBCByteCode());
|
||||
|
||||
initialState.Init();
|
||||
return initialState;
|
||||
}
|
||||
|
||||
void D3D12DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global,
|
||||
DXBC::DXBCContainer *dxbc)
|
||||
{
|
||||
|
||||
@@ -25,8 +25,11 @@
|
||||
|
||||
#include "dxbc_debug.h"
|
||||
#include <algorithm>
|
||||
#include "driver/dxgi/dxgi_common.h"
|
||||
#include "maths/formatpacking.h"
|
||||
#include "replay/replay_driver.h"
|
||||
#include "dxbc_bytecode.h"
|
||||
#include "dxbc_container.h"
|
||||
|
||||
using namespace DXBCBytecode;
|
||||
|
||||
@@ -3982,6 +3985,172 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua
|
||||
return s;
|
||||
}
|
||||
|
||||
void CreateShaderDebugStateAndTrace(ShaderDebug::State &initialState, ShaderDebugTrace &trace,
|
||||
int quadIdx, DXBC::DXBCContainer *dxbc,
|
||||
const ShaderReflection &refl, bytebuf *cbufData)
|
||||
{
|
||||
initialState = ShaderDebug::State(quadIdx, &trace, dxbc->GetReflection(), dxbc->GetDXBCByteCode());
|
||||
|
||||
size_t numInputs = dxbc->GetReflection()->InputSig.size();
|
||||
size_t numOutputs = dxbc->GetReflection()->OutputSig.size();
|
||||
|
||||
int32_t maxReg = -1;
|
||||
for(size_t i = 0; i < numInputs; i++)
|
||||
maxReg = RDCMAX(maxReg, (int32_t)dxbc->GetReflection()->InputSig[i].regIndex);
|
||||
|
||||
bool inputCoverage = false;
|
||||
|
||||
// Check if the shader uses the coverage mask
|
||||
for(size_t i = 0; i < dxbc->GetDXBCByteCode()->GetNumDeclarations(); i++)
|
||||
{
|
||||
const Declaration &decl = dxbc->GetDXBCByteCode()->GetDeclaration(i);
|
||||
|
||||
if(decl.declaration == OPCODE_DCL_INPUT && decl.operand.type == TYPE_INPUT_COVERAGE_MASK)
|
||||
{
|
||||
inputCoverage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add inputs to the shader trace
|
||||
if(maxReg >= 0 || inputCoverage)
|
||||
{
|
||||
trace.inputs.resize(maxReg + 1 + (inputCoverage ? 1 : 0));
|
||||
for(size_t i = 0; i < numInputs; i++)
|
||||
{
|
||||
const SigParameter &sig = dxbc->GetReflection()->InputSig[i];
|
||||
|
||||
ShaderVariable v;
|
||||
|
||||
v.name = StringFormat::Fmt("v%d (%s)", sig.regIndex, sig.semanticIdxName.c_str());
|
||||
v.rows = 1;
|
||||
v.columns = sig.regChannelMask & 0x8 ? 4 : sig.regChannelMask & 0x4
|
||||
? 3
|
||||
: sig.regChannelMask & 0x2
|
||||
? 2
|
||||
: sig.regChannelMask & 0x1 ? 1 : 0;
|
||||
|
||||
if(sig.compType == CompType::UInt)
|
||||
v.type = VarType::UInt;
|
||||
else if(sig.compType == CompType::SInt)
|
||||
v.type = VarType::SInt;
|
||||
|
||||
if(trace.inputs[sig.regIndex].columns == 0)
|
||||
trace.inputs[sig.regIndex] = v;
|
||||
else
|
||||
trace.inputs[sig.regIndex].columns = RDCMAX(trace.inputs[sig.regIndex].columns, v.columns);
|
||||
}
|
||||
|
||||
// Put the coverage mask at the end
|
||||
if(inputCoverage)
|
||||
{
|
||||
trace.inputs[maxReg + 1] = ShaderVariable("vCoverage", 0U, 0U, 0U, 0U);
|
||||
trace.inputs[maxReg + 1].columns = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add outputs to the shader state
|
||||
uint32_t specialOutputs = 0;
|
||||
maxReg = -1;
|
||||
for(size_t i = 0; i < numOutputs; i++)
|
||||
{
|
||||
if(dxbc->GetReflection()->OutputSig[i].regIndex == ~0U)
|
||||
specialOutputs++;
|
||||
else
|
||||
maxReg = RDCMAX(maxReg, (int32_t)dxbc->GetReflection()->OutputSig[i].regIndex);
|
||||
}
|
||||
|
||||
if(maxReg >= 0 || specialOutputs > 0)
|
||||
{
|
||||
initialState.outputs.resize(maxReg + 1 + specialOutputs);
|
||||
for(size_t i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const SigParameter &sig = dxbc->GetReflection()->OutputSig[i];
|
||||
|
||||
if(sig.regIndex == ~0U)
|
||||
continue;
|
||||
|
||||
ShaderVariable v;
|
||||
|
||||
v.name = StringFormat::Fmt("o%d (%s)", sig.regIndex, sig.semanticIdxName.c_str());
|
||||
v.rows = 1;
|
||||
v.columns = sig.regChannelMask & 0x8 ? 4 : sig.regChannelMask & 0x4
|
||||
? 3
|
||||
: sig.regChannelMask & 0x2
|
||||
? 2
|
||||
: sig.regChannelMask & 0x1 ? 1 : 0;
|
||||
|
||||
if(initialState.outputs[sig.regIndex].columns == 0)
|
||||
initialState.outputs[sig.regIndex] = v;
|
||||
else
|
||||
initialState.outputs[sig.regIndex].columns =
|
||||
RDCMAX(initialState.outputs[sig.regIndex].columns, v.columns);
|
||||
}
|
||||
|
||||
int32_t outIdx = maxReg + 1;
|
||||
|
||||
for(size_t i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const SigParameter &sig = dxbc->GetReflection()->OutputSig[i];
|
||||
|
||||
if(sig.regIndex != ~0U)
|
||||
continue;
|
||||
|
||||
ShaderVariable v;
|
||||
|
||||
if(sig.systemValue == ShaderBuiltin::OutputControlPointIndex)
|
||||
v.name = "vOutputControlPointID";
|
||||
else if(sig.systemValue == ShaderBuiltin::DepthOutput)
|
||||
v.name = "oDepth";
|
||||
else if(sig.systemValue == ShaderBuiltin::DepthOutputLessEqual)
|
||||
v.name = "oDepthLessEqual";
|
||||
else if(sig.systemValue == ShaderBuiltin::DepthOutputGreaterEqual)
|
||||
v.name = "oDepthGreaterEqual";
|
||||
else if(sig.systemValue == ShaderBuiltin::MSAACoverage)
|
||||
v.name = "oMask";
|
||||
else if(sig.systemValue == ShaderBuiltin::StencilReference)
|
||||
v.name = "oStencilRef";
|
||||
else
|
||||
{
|
||||
RDCERR("Unhandled output: %s (%d)", sig.semanticName.c_str(), sig.systemValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
v.rows = 1;
|
||||
v.columns = sig.regChannelMask & 0x8 ? 4 : sig.regChannelMask & 0x4
|
||||
? 3
|
||||
: sig.regChannelMask & 0x2
|
||||
? 2
|
||||
: sig.regChannelMask & 0x1 ? 1 : 0;
|
||||
|
||||
initialState.outputs[outIdx++] = v;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill constant buffers and add them to the trace
|
||||
size_t numCBuffers = dxbc->GetReflection()->CBuffers.size();
|
||||
trace.constantBlocks.resize(numCBuffers);
|
||||
for(size_t i = 0; i < numCBuffers; i++)
|
||||
{
|
||||
rdcarray<ShaderVariable> vars;
|
||||
|
||||
// Fetch cbuffers into vars, which will be 'natural': structs with members, non merged vectors
|
||||
StandardFillCBufferVariables(refl.constantBlocks[i].variables, vars,
|
||||
cbufData[dxbc->GetReflection()->CBuffers[i].reg]);
|
||||
|
||||
FlattenVariables(refl.constantBlocks[i].variables, vars, trace.constantBlocks[i].members);
|
||||
|
||||
for(size_t c = 0; c < trace.constantBlocks[i].members.size(); c++)
|
||||
{
|
||||
trace.constantBlocks[i].members[c].name =
|
||||
StringFormat::Fmt("cb%u[%u] (%s)", dxbc->GetReflection()->CBuffers[i].reg, (uint32_t)c,
|
||||
trace.constantBlocks[i].members[c].name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
initialState.Init();
|
||||
}
|
||||
|
||||
bool PromptDebugTimeout(uint32_t cycleCounter)
|
||||
{
|
||||
std::string msg = StringFormat::Fmt(
|
||||
@@ -4288,6 +4457,50 @@ void FlattenVariables(const rdcarray<ShaderConstant> &constants,
|
||||
FlattenVariables(constants, invars, outvars, "", 0);
|
||||
}
|
||||
|
||||
void FillViewFmt(DXGI_FORMAT format, GlobalState::ViewFmt &viewFmt)
|
||||
{
|
||||
if(format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
ResourceFormat fmt = MakeResourceFormat(format);
|
||||
|
||||
viewFmt.byteWidth = fmt.compByteWidth;
|
||||
viewFmt.numComps = fmt.compCount;
|
||||
viewFmt.fmt = fmt.compType;
|
||||
|
||||
if(format == DXGI_FORMAT_R11G11B10_FLOAT)
|
||||
viewFmt.byteWidth = 11;
|
||||
else if(format == DXGI_FORMAT_R10G10B10A2_UINT || format == DXGI_FORMAT_R10G10B10A2_UNORM)
|
||||
viewFmt.byteWidth = 10;
|
||||
}
|
||||
}
|
||||
|
||||
void LookupSRVFormatFromShaderReflection(const DXBC::Reflection &reflection,
|
||||
uint32_t shaderRegister, GlobalState::ViewFmt &viewFmt)
|
||||
{
|
||||
for(const DXBC::ShaderInputBind &bind : reflection.SRVs)
|
||||
{
|
||||
if(bind.reg == shaderRegister && bind.dimension == DXBC::ShaderInputBind::DIM_BUFFER &&
|
||||
bind.retType < DXBC::RETURN_TYPE_MIXED && bind.retType != DXBC::RETURN_TYPE_UNKNOWN)
|
||||
{
|
||||
viewFmt.byteWidth = 4;
|
||||
viewFmt.numComps = bind.numSamples;
|
||||
|
||||
if(bind.retType == DXBC::RETURN_TYPE_UNORM)
|
||||
viewFmt.fmt = CompType::UNorm;
|
||||
else if(bind.retType == DXBC::RETURN_TYPE_SNORM)
|
||||
viewFmt.fmt = CompType::SNorm;
|
||||
else if(bind.retType == DXBC::RETURN_TYPE_UINT)
|
||||
viewFmt.fmt = CompType::UInt;
|
||||
else if(bind.retType == DXBC::RETURN_TYPE_SINT)
|
||||
viewFmt.fmt = CompType::SInt;
|
||||
else
|
||||
viewFmt.fmt = CompType::Float;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace ShaderDebug
|
||||
|
||||
#if ENABLED(ENABLE_UNIT_TESTS)
|
||||
|
||||
@@ -37,6 +37,7 @@ struct CBufferVariable;
|
||||
}
|
||||
|
||||
class WrappedID3D11Device;
|
||||
enum DXGI_FORMAT;
|
||||
|
||||
namespace ShaderDebug
|
||||
{
|
||||
@@ -185,6 +186,11 @@ void FlattenVariables(const rdcarray<ShaderConstant> &constants,
|
||||
void FlattenVariables(const rdcarray<ShaderConstant> &constants,
|
||||
const rdcarray<ShaderVariable> &invars, rdcarray<ShaderVariable> &outvars);
|
||||
|
||||
void FillViewFmt(DXGI_FORMAT format, GlobalState::ViewFmt &viewFmt);
|
||||
|
||||
void LookupSRVFormatFromShaderReflection(const DXBC::Reflection &reflection,
|
||||
uint32_t shaderRegister, GlobalState::ViewFmt &viewFmt);
|
||||
|
||||
struct SampleGatherResourceData
|
||||
{
|
||||
DXBCBytecode::ResourceDimension dim;
|
||||
@@ -317,4 +323,8 @@ private:
|
||||
const ShaderDebugTrace *trace;
|
||||
};
|
||||
|
||||
void CreateShaderDebugStateAndTrace(ShaderDebug::State &initialState, ShaderDebugTrace &trace,
|
||||
int quadIdx, DXBC::DXBCContainer *dxbc,
|
||||
const ShaderReflection &refl, bytebuf *cbufData);
|
||||
|
||||
}; // namespace ShaderDebug
|
||||
|
||||
Reference in New Issue
Block a user