diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 4beab0845..e3799c21c 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -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 &handles, + bool compute, const rdcarray &handles, D3D12_DESCRIPTOR_HEAP_TYPE heapType, uint32_t sigElem, std::set &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); } diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index 0d17c61c7..dd7167873 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -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 &handles, + bool compute, const rdcarray &handles, D3D12_DESCRIPTOR_HEAP_TYPE heapType, uint32_t sigElem, std::set &copiedHeaps); diff --git a/renderdoc/driver/d3d12/d3d12_overlay.cpp b/renderdoc/driver/d3d12/d3d12_overlay.cpp index 50ec23d00..00c7ae910 100644 --- a/renderdoc/driver/d3d12/d3d12_overlay.cpp +++ b/renderdoc/driver/d3d12/d3d12_overlay.cpp @@ -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 diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index b627d7cb5..522067bdb 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -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 PixelHistory(rdcarray 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, diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index 1aa1ce7b3..7d84c52b1 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -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( + 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 ¶m = 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(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 ¶m = 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 copiedHeaps; + rdcarray 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 copiedHeaps; - rdcarray 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 &ins = state.m_Input.members; workgroupProperties[q][DXILDebug::ThreadProperty::Active] = lane->active; diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.h b/renderdoc/driver/shaders/dxil/dxil_debug.h index 190104b6b..dde459cd9 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.h +++ b/renderdoc/driver/shaders/dxil/dxil_debug.h @@ -518,7 +518,6 @@ enum class ThreadProperty : uint32_t QuadId, QuadLane, Active, - SubgroupId, Count, }; @@ -552,7 +551,7 @@ public: rdcarray 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 &GetWorkgroup() { return m_Workgroup; } const rdcarray &GetLiveGlobals() { return m_LiveGlobals; } static rdcstr GetResourceReferenceName(const DXIL::Program *program, DXIL::ResourceClass resClass,