diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index 83456f6f0..428ed1c68 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -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); diff --git a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp index 9667ef91a..7ff50d2bc 100644 --- a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp +++ b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp @@ -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 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 &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++) { diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index cd363dd09..469e9b218 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -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 &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(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(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); +} diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index 4612a4bab..afae80454 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -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 &copiedHeaps); diff --git a/renderdoc/driver/d3d12/d3d12_overlay.cpp b/renderdoc/driver/d3d12/d3d12_overlay.cpp index 48240b36a..8df7c5602 100644 --- a/renderdoc/driver/d3d12/d3d12_overlay.cpp +++ b/renderdoc/driver/d3d12/d3d12_overlay.cpp @@ -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 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(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(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 diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index b4dee758d..39ddcac82 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -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) { diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 52743cc9f..9f0a2d0c4 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -25,8 +25,11 @@ #include "dxbc_debug.h" #include +#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 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 &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) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index 7dc8d7da5..bf1dbd46f 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -37,6 +37,7 @@ struct CBufferVariable; } class WrappedID3D11Device; +enum DXGI_FORMAT; namespace ShaderDebug { @@ -185,6 +186,11 @@ void FlattenVariables(const rdcarray &constants, void FlattenVariables(const rdcarray &constants, const rdcarray &invars, rdcarray &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