Extract PS input fetching code into common helpers to be re-used

This commit is contained in:
baldurk
2025-03-19 18:31:55 +00:00
parent 6b0604f735
commit dbb58a1179
6 changed files with 263 additions and 238 deletions
+8 -5
View File
@@ -3408,7 +3408,8 @@ uint32_t GetFreeRegSpace(const D3D12RootSignature &sig, const uint32_t registerS
for(size_t i = 0; i < numParams; i++)
{
if(sig.Parameters[i].ShaderVisibility == visibility ||
sig.Parameters[i].ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL)
sig.Parameters[i].ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL ||
visibility == D3D12_SHADER_VISIBILITY_ALL)
{
D3D12_ROOT_PARAMETER_TYPE rootType = sig.Parameters[i].ParameterType;
if(rootType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
@@ -3459,12 +3460,14 @@ uint32_t GetFreeRegSpace(const D3D12RootSignature &sig, const uint32_t registerS
}
void AddDebugDescriptorsToRenderState(WrappedID3D12Device *pDevice, D3D12RenderState &rs,
const rdcarray<PortableHandle> &handles,
bool compute, const rdcarray<PortableHandle> &handles,
D3D12_DESCRIPTOR_HEAP_TYPE heapType, uint32_t sigElem,
std::set<ResourceId> &copiedHeaps)
{
if(rs.graphics.sigelems.size() <= sigElem)
rs.graphics.sigelems.resize(sigElem + 1);
D3D12RenderState::RootSignature &sig = compute ? rs.compute : rs.graphics;
if(sig.sigelems.size() <= sigElem)
sig.sigelems.resize(sigElem + 1);
PortableHandle newHandle = handles[0];
@@ -3514,6 +3517,6 @@ void AddDebugDescriptorsToRenderState(WrappedID3D12Device *pDevice, D3D12RenderS
if(newHandle.heap == handles[0].heap)
rs.heaps.push_back(handles[0].heap);
rs.graphics.sigelems[sigElem] =
sig.sigelems[sigElem] =
D3D12RenderState::SignatureElement(eRootTable, newHandle.heap, newHandle.index);
}
+1 -1
View File
@@ -313,6 +313,6 @@ uint32_t GetFreeRegSpace(const D3D12RootSignature &sig, const uint32_t registerS
D3D12DescriptorType type, D3D12_SHADER_VISIBILITY visibility);
void AddDebugDescriptorsToRenderState(WrappedID3D12Device *pDevice, D3D12RenderState &rs,
const rdcarray<PortableHandle> &handles,
bool compute, const rdcarray<PortableHandle> &handles,
D3D12_DESCRIPTOR_HEAP_TYPE heapType, uint32_t sigElem,
std::set<ResourceId> &copiedHeaps);
+3 -2
View File
@@ -200,8 +200,9 @@ struct D3D12QuadOverdrawCallback : public D3D12ActionCallback
Unwrap(m_MSDepth));
}
AddDebugDescriptorsToRenderState(m_pDevice, rs, {m_UAV}, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
cache.sigElem, m_CopiedHeaps);
AddDebugDescriptorsToRenderState(m_pDevice, rs, false, {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
+15
View File
@@ -40,6 +40,15 @@ class D3D12DebugManager;
struct PortableHandle;
namespace DXBC
{
class DXBCContainer;
};
namespace DXDebug
{
struct InputFetcher;
};
enum TexDisplayFlags
{
eTexDisplay_None = 0,
@@ -245,6 +254,12 @@ public:
rdcarray<PixelModification> PixelHistory(rdcarray<EventUsage> events, ResourceId target, uint32_t x,
uint32_t y, const Subresource &sub, CompType typeCast);
ID3DBlob *CompileShaderDebugFetcher(DXBC::DXBCContainer *dxbc, const rdcstr &hlsl);
ID3D12Resource *CreateInputFetchBuffer(DXDebug::InputFetcher &fetcher, uint64_t &laneDataOffset,
uint64_t &evalDataOffset);
ID3D12RootSignature *CreateInputFetchRootSig(bool compute, uint32_t &uavspace, uint32_t &sigElem);
ShaderDebugTrace *DebugVertex(uint32_t eventId, uint32_t vertid, uint32_t instid, uint32_t idx,
uint32_t view);
ShaderDebugTrace *DebugPixel(uint32_t eventId, uint32_t x, uint32_t y,
+235 -228
View File
@@ -1629,6 +1629,202 @@ void GatherConstantBuffers(WrappedID3D12Device *pDevice, const DXBCBytecode::Pro
}
}
ID3DBlob *D3D12Replay::CompileShaderDebugFetcher(DXBC::DXBCContainer *dxbc, const rdcstr &hlsl)
{
ID3DBlob *psBlob = NULL;
UINT flags = D3DCOMPILE_WARNINGS_ARE_ERRORS;
if(dxbc->GetDXBCByteCode())
{
if(m_pDevice->GetShaderCache()->GetShaderBlob(hlsl.c_str(), "ExtractInputs", flags, {},
"ps_5_1", &psBlob) != "")
{
RDCERR("Failed to create shader to extract inputs");
SAFE_RELEASE(psBlob);
}
}
else
{
// get the profile and shader compile flags from the vertex shader
const uint32_t smMajor = dxbc->m_Version.Major;
const uint32_t smMinor = dxbc->m_Version.Minor;
if(smMajor < 6)
{
RDCERR("Invalid vertex shader SM %d.%d expect SM6.0+", smMajor, smMinor);
return NULL;
}
const char *profile = StringFormat::Fmt("ps_%u_%u", smMajor, smMinor).c_str();
ShaderCompileFlags compileFlags =
DXBC::EncodeFlags(m_pDevice->GetShaderCache()->GetCompileFlags(), profile);
const DXBC::GlobalShaderFlags shaderFlags = dxbc->GetGlobalShaderFlags();
if(shaderFlags & DXBC::GlobalShaderFlags::NativeLowPrecision)
compileFlags.flags.push_back({"@compile_option", "-enable-16bit-types"});
if(m_pDevice->GetShaderCache()->GetShaderBlob(hlsl.c_str(), "ExtractInputs", compileFlags, {},
profile, &psBlob) != "")
{
RDCERR("Failed to create shader to extract inputs");
SAFE_RELEASE(psBlob);
}
}
return psBlob;
}
ID3D12Resource *D3D12Replay::CreateInputFetchBuffer(DXDebug::InputFetcher &fetcher,
uint64_t &laneDataOffset,
uint64_t &evalDataOffset)
{
HRESULT hr = S_OK;
// Create buffer to store initial values captured in pixel shader
D3D12_RESOURCE_DESC rdesc;
ZeroMemory(&rdesc, sizeof(D3D12_RESOURCE_DESC));
rdesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
rdesc.Width = fetcher.hitBufferStride * (DXDebug::maxPixelHits + 1);
// if we have separate lane data, allocate that at the end
if(fetcher.laneDataBufferStride > 0)
{
rdesc.Width = AlignToMultiple(rdesc.Width, (uint64_t)fetcher.laneDataBufferStride);
laneDataOffset = rdesc.Width;
rdesc.Width +=
(fetcher.laneDataBufferStride * fetcher.numLanesPerHit) * (DXDebug::maxPixelHits + 1);
}
// Create storage for MSAA evaluations captured in pixel shader
if(!fetcher.evalSampleCacheData.empty())
{
rdesc.Width = AlignUp16(rdesc.Width);
evalDataOffset = rdesc.Width;
rdesc.Width +=
UINT(fetcher.evalSampleCacheData.size() * sizeof(Vec4f) * (DXDebug::maxPixelHits + 1));
}
rdesc.Height = 1;
rdesc.DepthOrArraySize = 1;
rdesc.MipLevels = 1;
rdesc.Format = DXGI_FORMAT_UNKNOWN;
rdesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
rdesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
rdesc.SampleDesc.Count = 1; // TODO: Support MSAA
rdesc.SampleDesc.Quality = 0;
D3D12_HEAP_PROPERTIES heapProps;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
ID3D12Resource *dataBuffer = NULL;
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
hr = m_pDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &rdesc, resourceState,
NULL, __uuidof(ID3D12Resource), (void **)&dataBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create buffer for pixel shader debugging HRESULT: %s", ToStr(hr).c_str());
return false;
}
// Create UAV of initial values buffer
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
ZeroMemory(&uavDesc, sizeof(D3D12_UNORDERED_ACCESS_VIEW_DESC));
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
uavDesc.Buffer.NumElements = DXDebug::maxPixelHits + 1;
uavDesc.Buffer.StructureByteStride = fetcher.hitBufferStride;
D3D12_CPU_DESCRIPTOR_HANDLE uav = m_pDevice->GetDebugManager()->GetCPUHandle(SHADER_DEBUG_UAV);
m_pDevice->CreateUnorderedAccessView(dataBuffer, NULL, &uavDesc, uav);
// create UAV of separate lane data, if needed
if(fetcher.laneDataBufferStride)
{
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
uavDesc.Buffer.FirstElement = laneDataOffset / fetcher.laneDataBufferStride;
uavDesc.Buffer.StructureByteStride = fetcher.laneDataBufferStride;
uavDesc.Buffer.NumElements = DXDebug::maxPixelHits + 1;
uav = m_pDevice->GetDebugManager()->GetCPUHandle(SHADER_DEBUG_LANEDATA_UAV);
m_pDevice->CreateUnorderedAccessView(dataBuffer, NULL, &uavDesc, uav);
}
// Create UAV of MSAA eval buffer
if(evalDataOffset)
{
D3D12_CPU_DESCRIPTOR_HANDLE msaaUav =
m_pDevice->GetDebugManager()->GetCPUHandle(SHADER_DEBUG_MSAA_UAV);
uavDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
uavDesc.Buffer.FirstElement = evalDataOffset / sizeof(Vec4f);
uavDesc.Buffer.NumElements =
(DXDebug::maxPixelHits + 1) * (uint32_t)fetcher.evalSampleCacheData.size();
uavDesc.Buffer.StructureByteStride = 0;
m_pDevice->CreateUnorderedAccessView(dataBuffer, NULL, &uavDesc, msaaUav);
}
uavDesc.Format = DXGI_FORMAT_R32_UINT;
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.NumElements = UINT(dataBuffer->GetDesc().Width / sizeof(uint32_t));
uavDesc.Buffer.StructureByteStride = 0;
D3D12_CPU_DESCRIPTOR_HANDLE clearUav =
m_pDevice->GetDebugManager()->GetUAVClearHandle(SHADER_DEBUG_UAV);
m_pDevice->CreateUnorderedAccessView(dataBuffer, NULL, &uavDesc, clearUav);
return dataBuffer;
}
ID3D12RootSignature *D3D12Replay::CreateInputFetchRootSig(bool compute, uint32_t &uavspace,
uint32_t &sigElem)
{
D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState;
WrappedID3D12RootSignature *sig =
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(
compute ? rs.compute.rootsig : rs.graphics.rootsig);
// Need to be able to add a descriptor table with our UAV without hitting the 64 DWORD limit
RDCASSERT(sig->sig.dwordLength < 64);
D3D12RootSignature modsig = sig->sig;
uavspace = GetFreeRegSpace(modsig, 0, D3D12DescriptorType::UAV, D3D12_SHADER_VISIBILITY_ALL);
// Create the descriptor table for our UAV
D3D12_DESCRIPTOR_RANGE1 descRange = {
D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 3, 1, uavspace, D3D12_DESCRIPTOR_RANGE_FLAG_NONE, 0,
};
modsig.Parameters.push_back(D3D12RootSignatureParameter());
D3D12RootSignatureParameter &param = modsig.Parameters.back();
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
param.DescriptorTable.NumDescriptorRanges = 1;
param.DescriptorTable.pDescriptorRanges = &descRange;
sigElem = modsig.Parameters.count() - 1;
modsig.Flags &= ~(D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS);
// Create the root signature for gathering initial pixel shader values
bytebuf root = EncodeRootSig(m_pDevice->RootSigVersion(), modsig);
ID3D12RootSignature *pRootSignature = NULL;
HRESULT hr = m_pDevice->CreateRootSignature(
0, root.data(), root.size(), __uuidof(ID3D12RootSignature), (void **)&pRootSignature);
if(FAILED(hr))
{
RDCERR("Failed to create root signature for pixel shader debugging HRESULT: %s",
ToStr(hr).c_str());
return NULL;
}
return pRootSignature;
}
ShaderDebugTrace *D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uint32_t instid,
uint32_t idx, uint32_t view)
{
@@ -2357,13 +2553,6 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
prevDxbc = vs->GetDXBC();
}
WrappedID3D12RootSignature *sig =
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rs.graphics.rootsig);
// Need to be able to add a descriptor table with our UAV without hitting the 64 DWORD limit
RDCASSERT(sig->sig.dwordLength < 64);
D3D12RootSignature modsig = sig->sig;
DXDebug::InputFetcherConfig cfg;
DXDebug::InputFetcher fetcher;
@@ -2373,11 +2562,18 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
// Store a copy of the event's render state to restore later
D3D12RenderState prevState = rs;
uint32_t sigElem = 0;
ID3D12RootSignature *pRootSignature = CreateInputFetchRootSig(false, cfg.uavspace, sigElem);
if(pRootSignature == NULL)
return new ShaderDebugTrace;
rs.graphics.rootsig = GetResID(pRootSignature);
cfg.x = x;
cfg.y = y;
cfg.uavslot = 1;
cfg.maxWaveSize = 4;
cfg.uavspace = GetFreeRegSpace(modsig, 0, D3D12DescriptorType::UAV, D3D12_SHADER_VISIBILITY_PIXEL);
cfg.outputSampleCount = RDCMAX(1U, pipeDesc.SampleDesc.Count);
if(D3D_Hack_EnableGroups() && (dxbc->GetThreadScope() & DXBC::ThreadScope::Subgroup))
@@ -2386,193 +2582,27 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
DXDebug::CreateInputFetcher(dxbc, prevDxbc, cfg, fetcher);
// Create pixel shader to get initial values from previous stage output
ID3DBlob *psBlob = NULL;
UINT flags = D3DCOMPILE_WARNINGS_ARE_ERRORS;
if(dxbc->GetDXBCByteCode())
{
if(m_pDevice->GetShaderCache()->GetShaderBlob(fetcher.hlsl.c_str(), "ExtractInputs", flags, {},
"ps_5_1", &psBlob) != "")
{
RDCERR("Failed to create shader to extract inputs");
return new ShaderDebugTrace;
}
}
else
{
// get the profile and shader compile flags from the vertex shader
rdcstr compSig = dxbc->GetDXILByteCode()->GetCompilerSig();
const uint32_t smMajor = dxbc->m_Version.Major;
const uint32_t smMinor = dxbc->m_Version.Minor;
if(smMajor < 6)
{
RDCERR("Invalid vertex shader SM %d.%d expect SM6.0+", smMajor, smMinor);
return new ShaderDebugTrace;
}
const char *profile = StringFormat::Fmt("ps_%u_%u", smMajor, smMinor).c_str();
ID3DBlob *psBlob = CompileShaderDebugFetcher(dxbc, fetcher.hlsl);
ShaderCompileFlags compileFlags =
DXBC::EncodeFlags(m_pDevice->GetShaderCache()->GetCompileFlags(), profile);
const DXBC::GlobalShaderFlags shaderFlags = dxbc->GetGlobalShaderFlags();
if(shaderFlags & DXBC::GlobalShaderFlags::NativeLowPrecision)
compileFlags.flags.push_back({"@compile_option", "-enable-16bit-types"});
if(m_pDevice->GetShaderCache()->GetShaderBlob(fetcher.hlsl.c_str(), "ExtractInputs",
compileFlags, {}, profile, &psBlob) != "")
{
RDCERR("Failed to create shader to extract inputs");
return new ShaderDebugTrace;
}
}
HRESULT hr = S_OK;
// Create buffer to store initial values captured in pixel shader
D3D12_RESOURCE_DESC rdesc;
ZeroMemory(&rdesc, sizeof(D3D12_RESOURCE_DESC));
rdesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
rdesc.Width = fetcher.hitBufferStride * (DXDebug::maxPixelHits + 1);
if(psBlob == NULL)
return new ShaderDebugTrace;
uint64_t laneDataOffset = 0;
// if we have separate lane data, allocate that at the end
if(fetcher.laneDataBufferStride > 0)
{
rdesc.Width = AlignToMultiple(rdesc.Width, (uint64_t)fetcher.laneDataBufferStride);
laneDataOffset = rdesc.Width;
rdesc.Width +=
(fetcher.laneDataBufferStride * fetcher.numLanesPerHit) * (DXDebug::maxPixelHits + 1);
}
uint64_t evalDataOffset = 0;
ID3D12Resource *dataBuffer = CreateInputFetchBuffer(fetcher, laneDataOffset, evalDataOffset);
rdesc.Height = 1;
rdesc.DepthOrArraySize = 1;
rdesc.MipLevels = 1;
rdesc.Format = DXGI_FORMAT_UNKNOWN;
rdesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
rdesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
rdesc.SampleDesc.Count = 1; // TODO: Support MSAA
rdesc.SampleDesc.Quality = 0;
D3D12_HEAP_PROPERTIES heapProps;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
ID3D12Resource *dataBuffer = NULL;
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
hr = m_pDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &rdesc, resourceState,
NULL, __uuidof(ID3D12Resource), (void **)&dataBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create buffer for pixel shader debugging HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(psBlob);
if(dataBuffer == NULL)
return new ShaderDebugTrace;
}
// Create buffer to store MSAA evaluations captured in pixel shader
ID3D12Resource *pMsaaEvalBuffer = NULL;
if(!fetcher.evalSampleCacheData.empty())
{
rdesc.Width =
UINT(fetcher.evalSampleCacheData.size() * sizeof(Vec4f) * (DXDebug::maxPixelHits + 1));
hr = m_pDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &rdesc, resourceState,
NULL, __uuidof(ID3D12Resource),
(void **)&pMsaaEvalBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create MSAA buffer for pixel shader debugging HRESULT: %s",
ToStr(hr).c_str());
SAFE_RELEASE(dataBuffer);
SAFE_RELEASE(psBlob);
return new ShaderDebugTrace;
}
}
// Create UAV of initial values buffer
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
ZeroMemory(&uavDesc, sizeof(D3D12_UNORDERED_ACCESS_VIEW_DESC));
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
uavDesc.Buffer.NumElements = DXDebug::maxPixelHits + 1;
uavDesc.Buffer.StructureByteStride = fetcher.hitBufferStride;
D3D12_CPU_DESCRIPTOR_HANDLE uav = m_pDevice->GetDebugManager()->GetCPUHandle(SHADER_DEBUG_UAV);
m_pDevice->CreateUnorderedAccessView(dataBuffer, NULL, &uavDesc, uav);
uavDesc.Format = DXGI_FORMAT_R32_UINT;
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.NumElements = UINT(dataBuffer->GetDesc().Width / sizeof(uint32_t));
uavDesc.Buffer.StructureByteStride = 0;
D3D12_CPU_DESCRIPTOR_HANDLE clearUav =
m_pDevice->GetDebugManager()->GetUAVClearHandle(SHADER_DEBUG_UAV);
m_pDevice->CreateUnorderedAccessView(dataBuffer, NULL, &uavDesc, clearUav);
// create UAV of separate lane data, if needed
if(fetcher.laneDataBufferStride)
{
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
uavDesc.Buffer.FirstElement = laneDataOffset / fetcher.laneDataBufferStride;
uavDesc.Buffer.StructureByteStride = fetcher.laneDataBufferStride;
uavDesc.Buffer.NumElements = DXDebug::maxPixelHits + 1;
uav = m_pDevice->GetDebugManager()->GetCPUHandle(SHADER_DEBUG_LANEDATA_UAV);
m_pDevice->CreateUnorderedAccessView(dataBuffer, NULL, &uavDesc, uav);
}
// Create UAV of MSAA eval buffer
D3D12_CPU_DESCRIPTOR_HANDLE msaaClearUav =
m_pDevice->GetDebugManager()->GetUAVClearHandle(SHADER_DEBUG_MSAA_UAV);
if(pMsaaEvalBuffer)
{
D3D12_CPU_DESCRIPTOR_HANDLE msaaUav =
m_pDevice->GetDebugManager()->GetCPUHandle(SHADER_DEBUG_MSAA_UAV);
uavDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
uavDesc.Buffer.NumElements =
(DXDebug::maxPixelHits + 1) * (uint32_t)fetcher.evalSampleCacheData.size();
m_pDevice->CreateUnorderedAccessView(pMsaaEvalBuffer, NULL, &uavDesc, msaaUav);
uavDesc.Format = DXGI_FORMAT_R32_UINT;
uavDesc.Buffer.NumElements =
(UINT)fetcher.evalSampleCacheData.size() * (DXDebug::maxPixelHits + 1) / sizeof(uint32_t);
m_pDevice->CreateUnorderedAccessView(pMsaaEvalBuffer, NULL, &uavDesc, msaaClearUav);
}
// Create the descriptor table for our UAV
D3D12_DESCRIPTOR_RANGE1 descRange;
descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
descRange.NumDescriptors = 3;
descRange.BaseShaderRegister = 1;
descRange.RegisterSpace = cfg.uavspace;
descRange.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
descRange.OffsetInDescriptorsFromTableStart = 0;
modsig.Parameters.push_back(D3D12RootSignatureParameter());
D3D12RootSignatureParameter &param = modsig.Parameters.back();
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
param.DescriptorTable.NumDescriptorRanges = 1;
param.DescriptorTable.pDescriptorRanges = &descRange;
uint32_t sigElem = uint32_t(modsig.Parameters.size() - 1);
modsig.Flags &= ~D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
// Create the root signature for gathering initial pixel shader values
bytebuf root = EncodeRootSig(m_pDevice->RootSigVersion(), modsig);
ID3D12RootSignature *pRootSignature = NULL;
hr = m_pDevice->CreateRootSignature(0, root.data(), root.size(), __uuidof(ID3D12RootSignature),
(void **)&pRootSignature);
if(FAILED(hr))
{
RDCERR("Failed to create root signature for pixel shader debugging HRESULT: %s",
ToStr(hr).c_str());
SAFE_RELEASE(psBlob);
SAFE_RELEASE(dataBuffer);
SAFE_RELEASE(pMsaaEvalBuffer);
return new ShaderDebugTrace;
}
// Add the descriptor for our UAV
std::set<ResourceId> copiedHeaps;
rdcarray<PortableHandle> debugHandles = {
ToPortableHandle(GetDebugManager()->GetCPUHandle(SHADER_DEBUG_UAV)),
ToPortableHandle(GetDebugManager()->GetCPUHandle(SHADER_DEBUG_MSAA_UAV)),
ToPortableHandle(GetDebugManager()->GetCPUHandle(SHADER_DEBUG_LANEDATA_UAV)),
};
AddDebugDescriptorsToRenderState(m_pDevice, rs, false, debugHandles,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, sigElem, copiedHeaps);
// All PSO state is the same as the event's, except for the pixel shader and root signature
pipeDesc.PS.BytecodeLength = psBlob->GetBufferSize();
@@ -2580,17 +2610,20 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
pipeDesc.pRootSignature = pRootSignature;
ID3D12PipelineState *initialPso = NULL;
hr = m_pDevice->CreatePipeState(pipeDesc, &initialPso);
HRESULT hr = m_pDevice->CreatePipeState(pipeDesc, &initialPso);
SAFE_RELEASE(psBlob);
if(FAILED(hr))
{
RDCERR("Failed to create PSO for pixel shader debugging HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(psBlob);
SAFE_RELEASE(dataBuffer);
SAFE_RELEASE(pMsaaEvalBuffer);
SAFE_RELEASE(pRootSignature);
return new ShaderDebugTrace;
}
rs.pipe = GetResID(initialPso);
// if we have a depth buffer bound and we are testing EQUAL grab the current depth value for our target sample
D3D12_COMPARISON_FUNC depthFunc = pipeDesc.DepthStencilState.DepthFunc;
float existingDepth = -1.0f;
@@ -2612,24 +2645,10 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
// clear our UAVs
m_pDevice->GetDebugManager()->SetDescriptorHeaps(cmdList, true, false);
D3D12_GPU_DESCRIPTOR_HANDLE gpuUav = m_pDevice->GetDebugManager()->GetGPUHandle(SHADER_DEBUG_UAV);
D3D12_CPU_DESCRIPTOR_HANDLE cpuUav =
m_pDevice->GetDebugManager()->GetUAVClearHandle(SHADER_DEBUG_UAV);
UINT zero[4] = {0, 0, 0, 0};
cmdList->ClearUnorderedAccessViewUint(gpuUav, clearUav, dataBuffer, zero, 0, NULL);
if(pMsaaEvalBuffer)
{
D3D12_GPU_DESCRIPTOR_HANDLE gpuMsaaUav =
m_pDevice->GetDebugManager()->GetGPUHandle(SHADER_DEBUG_MSAA_UAV);
cmdList->ClearUnorderedAccessViewUint(gpuMsaaUav, msaaClearUav, pMsaaEvalBuffer, zero, 0, NULL);
}
// Add the descriptor for our UAV
std::set<ResourceId> copiedHeaps;
rdcarray<PortableHandle> debugHandles;
debugHandles.push_back(ToPortableHandle(GetDebugManager()->GetCPUHandle(SHADER_DEBUG_UAV)));
debugHandles.push_back(ToPortableHandle(GetDebugManager()->GetCPUHandle(SHADER_DEBUG_MSAA_UAV)));
debugHandles.push_back(ToPortableHandle(GetDebugManager()->GetCPUHandle(SHADER_DEBUG_LANEDATA_UAV)));
AddDebugDescriptorsToRenderState(m_pDevice, rs, debugHandles,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, sigElem, copiedHeaps);
cmdList->ClearUnorderedAccessViewUint(gpuUav, cpuUav, dataBuffer, zero, 0, NULL);
rs.ApplyDescriptorHeaps(cmdList);
@@ -2638,9 +2657,7 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
if(FAILED(hr))
{
RDCERR("Failed to close command list HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(psBlob);
SAFE_RELEASE(dataBuffer);
SAFE_RELEASE(pMsaaEvalBuffer);
SAFE_RELEASE(pRootSignature);
SAFE_RELEASE(initialPso);
return new ShaderDebugTrace;
@@ -2656,30 +2673,20 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
D3D12MarkerRegion initState(m_pDevice->GetQueue()->GetReal(),
"Replaying event for initial states");
// Set the PSO and root signature
rs.pipe = GetResID(initialPso);
rs.graphics.rootsig = GetResID(pRootSignature);
// Replay the event with our modified state
m_pDevice->ReplayLog(0, eventId, eReplay_OnlyDraw);
// Restore D3D12 state to what the event uses
rs = prevState;
}
// Restore D3D12 state to what the event uses
rs = prevState;
bytebuf initialData;
m_pDevice->GetDebugManager()->GetBufferData(dataBuffer, 0, 0, initialData);
bytebuf evalData;
if(pMsaaEvalBuffer)
m_pDevice->GetDebugManager()->GetBufferData(pMsaaEvalBuffer, 0, 0, evalData);
// Replaying the event has finished, and the data has been copied out.
// Free all the resources that were created.
SAFE_RELEASE(psBlob);
SAFE_RELEASE(pRootSignature);
SAFE_RELEASE(dataBuffer);
SAFE_RELEASE(pMsaaEvalBuffer);
SAFE_RELEASE(initialPso);
DXDebug::DebugHit *buf = (DXDebug::DebugHit *)initialData.data();
@@ -2700,7 +2707,7 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
// Get depth func and determine "winner" pixel
DXDebug::DebugHit *pWinnerHit = NULL;
float *evalSampleCache = (float *)evalData.data();
float *evalSampleCache = (float *)(initialData.data() + evalDataOffset);
size_t winnerIdx = 0;
if(sample == ~0U)
@@ -2773,8 +2780,8 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
}
}
evalSampleCache =
(float *)(evalData.data() + fetcher.evalSampleCacheData.size() * sizeof(Vec4f) * 4 * winnerIdx);
evalSampleCache = (float *)(initialData.data() + evalDataOffset +
fetcher.evalSampleCacheData.size() * sizeof(Vec4f) * 4 * winnerIdx);
if(pWinnerHit == NULL)
{
@@ -2912,7 +2919,7 @@ ShaderDebugTrace *D3D12Replay::DebugPixel(uint32_t eventId, uint32_t x, uint32_t
{
DXDebug::PSLaneData *lane = (DXDebug::PSLaneData *)data;
DXILDebug::ThreadState &state = debugger->GetWorkgroup(q);
DXILDebug::ThreadState &state = debugger->GetLane(q);
rdcarray<ShaderVariable> &ins = state.m_Input.members;
workgroupProperties[q][DXILDebug::ThreadProperty::Active] = lane->active;
+1 -2
View File
@@ -518,7 +518,6 @@ enum class ThreadProperty : uint32_t
QuadId,
QuadLane,
Active,
SubgroupId,
Count,
};
@@ -552,7 +551,7 @@ public:
rdcarray<ShaderDebugState> ContinueDebug(DebugAPIWrapper *apiWrapper);
GlobalState &GetGlobalState() { return m_GlobalState; }
ThreadState &GetActiveLane() { return m_Workgroup[m_ActiveLaneIndex]; }
ThreadState &GetWorkgroup(const uint32_t i) { return m_Workgroup[i]; }
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,