From 5179c99f7d03c442ead9fcbc138eac37204e9292 Mon Sep 17 00:00:00 2001 From: Steve Karolewics Date: Mon, 18 Nov 2019 20:45:39 -0800 Subject: [PATCH] Add impl for creating a D3D12 global state for shader debugging. --- renderdoc/driver/d3d11/d3d11_shaderdebug.cpp | 29 +-- renderdoc/driver/d3d12/d3d12_shaderdebug.cpp | 203 ++++++++++++++++++- renderdoc/driver/shaders/dxbc/dxbc_debug.cpp | 32 +++ renderdoc/driver/shaders/dxbc/dxbc_debug.h | 2 + 4 files changed, 237 insertions(+), 29 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp index 636161844..464d69c2f 100644 --- a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp +++ b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp @@ -1690,34 +1690,7 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global } } - for(size_t i = 0; i < dxbc->GetDXBCByteCode()->GetNumDeclarations(); i++) - { - const DXBCBytecode::Declaration &decl = dxbc->GetDXBCByteCode()->GetDeclaration(i); - - if(decl.declaration == DXBCBytecode::OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW || - decl.declaration == DXBCBytecode::OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED) - { - uint32_t slot = (uint32_t)decl.operand.indices[0].index; - - if(global.groupshared.size() <= slot) - { - global.groupshared.resize(slot + 1); - - ShaderDebug::GlobalState::groupsharedMem &mem = global.groupshared[slot]; - - mem.structured = - (decl.declaration == DXBCBytecode::OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED); - - mem.count = decl.count; - if(mem.structured) - mem.bytestride = decl.stride; - else - mem.bytestride = 4; // raw groupshared is implicitly uint32s - - mem.data.resize(mem.bytestride * mem.count); - } - } - } + global.PopulateGroupshared(dxbc->GetDXBCByteCode()); } ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uint32_t instid, diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index 39ddcac82..294cf4090 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "driver/shaders/dxbc/dxbc_debug.h" +#include "d3d12_command_queue.h" #include "d3d12_debug.h" #include "d3d12_resources.h" @@ -117,10 +118,210 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( return false; } +bool IsShaderParameterVisible(DXBC::ShaderType shaderType, D3D12_SHADER_VISIBILITY shaderVisibility) +{ + if(shaderVisibility == D3D12_SHADER_VISIBILITY_ALL) + return true; + + if(shaderType == DXBC::ShaderType::Vertex && shaderVisibility == D3D12_SHADER_VISIBILITY_VERTEX) + return true; + + if(shaderType == DXBC::ShaderType::Pixel && shaderVisibility == D3D12_SHADER_VISIBILITY_PIXEL) + return true; + + return false; +} + void D3D12DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global, DXBC::DXBCContainer *dxbc) { - RDCUNIMPLEMENTED("CreateShaderGlobalState not yet implemented for D3D12"); + D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState; + D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); + + // Get the root signature + const D3D12RenderState::RootSignature *pRootSignature = NULL; + if(dxbc->m_Type == DXBC::ShaderType::Compute) + { + if(rs.compute.rootsig != ResourceId()) + { + pRootSignature = &rs.compute; + } + } + else if(rs.graphics.rootsig != ResourceId()) + { + pRootSignature = &rs.graphics; + } + + if(pRootSignature) + { + WrappedID3D12RootSignature *pD3D12RootSig = + rm->GetCurrentAs(pRootSignature->rootsig); + + size_t numParams = RDCMIN(pD3D12RootSig->sig.params.size(), pRootSignature->sigelems.size()); + for(size_t i = 0; i < numParams; ++i) + { + const D3D12RootSignatureParameter ¶m = pD3D12RootSig->sig.params[i]; + const D3D12RenderState::SignatureElement &element = pRootSignature->sigelems[i]; + if(IsShaderParameterVisible(dxbc->m_Type, param.ShaderVisibility)) + { + // Note that constant buffers are not handled as part of the shader global state + + if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV && element.type == eRootSRV) + { + UINT shaderReg = param.Descriptor.ShaderRegister; + ID3D12Resource *pResource = rm->GetCurrentAs(element.id); + D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); + + // TODO: Root buffers can be 32-bit UINT/SINT/FLOAT. Using UINT for now, but the + // resource desc format or the DXBC reflection info might be more correct. + ShaderDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, global.srvs[shaderReg].format); + global.srvs[shaderReg].firstElement = (uint32_t)(element.offset / sizeof(uint32_t)); + global.srvs[shaderReg].numElements = + (uint32_t)((resDesc.Width - element.offset) / sizeof(uint32_t)); + + if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + GetBufferData(pResource, 0, 0, global.srvs[shaderReg].data); + } + else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV && element.type == eRootUAV) + { + UINT shaderReg = param.Descriptor.ShaderRegister; + ID3D12Resource *pResource = rm->GetCurrentAs(element.id); + D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); + + // TODO: Root buffers can be 32-bit UINT/SINT/FLOAT. Using UINT for now, but the + // resource desc format or the DXBC reflection info might be more correct. + ShaderDebug::FillViewFmt(DXGI_FORMAT_R32_UINT, global.uavs[shaderReg].format); + global.uavs[shaderReg].firstElement = (uint32_t)(element.offset / sizeof(uint32_t)); + global.uavs[shaderReg].numElements = + (uint32_t)((resDesc.Width - element.offset) / sizeof(uint32_t)); + + if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + GetBufferData(pResource, 0, 0, global.uavs[shaderReg].data); + } + else if(param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && + element.type == eRootTable) + { + UINT prevTableOffset = 0; + WrappedID3D12DescriptorHeap *heap = + rm->GetCurrentAs(element.id); + + size_t numRanges = param.ranges.size(); + for(size_t r = 0; r < numRanges; ++r) + { + const D3D12_DESCRIPTOR_RANGE1 &range = param.ranges[r]; + + UINT offset = range.OffsetInDescriptorsFromTableStart; + if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + offset = prevTableOffset; + + D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr; + desc += element.offset; + desc += offset; + + UINT numDescriptors = range.NumDescriptors; + if(numDescriptors == UINT_MAX) + { + // Find out how many descriptors are left after + numDescriptors = heap->GetNumDescriptors() - offset - (UINT)element.offset; + + // TODO: Should we look up the bind point in the D3D12 state to try to get + // a better guess at the number of descriptors? + } + + prevTableOffset = offset + numDescriptors; + + UINT shaderReg = range.BaseShaderRegister; + + if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV) + { + for(UINT n = 0; n < numDescriptors; ++n, ++shaderReg) + { + if(desc) + { + ResourceId srvId = desc->GetResResourceId(); + ID3D12Resource *pResource = rm->GetCurrentAs(srvId); + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = desc->GetSRV(); + if(srvDesc.Format != DXGI_FORMAT_UNKNOWN) + { + ShaderDebug::FillViewFmt(srvDesc.Format, global.srvs[shaderReg].format); + } + else + { + D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); + if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + global.srvs[shaderReg].format.stride = srvDesc.Buffer.StructureByteStride; + + // If we didn't get a type from the SRV description, try to pull it from the + // shader reflection info + ShaderDebug::LookupSRVFormatFromShaderReflection( + *dxbc->GetReflection(), (uint32_t)shaderReg, global.srvs[shaderReg].format); + } + } + + if(srvDesc.ViewDimension == D3D12_SRV_DIMENSION_BUFFER) + { + global.srvs[shaderReg].firstElement = (uint32_t)srvDesc.Buffer.FirstElement; + global.srvs[shaderReg].numElements = srvDesc.Buffer.NumElements; + + GetBufferData(pResource, 0, 0, global.srvs[shaderReg].data); + } + // Textures are sampled via a pixel shader, so there's no need to copy their data + + desc++; + } + } + } + else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) + { + for(UINT n = 0; n < numDescriptors; ++n, ++shaderReg) + { + if(desc) + { + ResourceId uavId = desc->GetResResourceId(); + ID3D12Resource *pResource = rm->GetCurrentAs(uavId); + + // TODO: Need to fetch counter resource if applicable + + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = desc->GetUAV(); + if(uavDesc.Format != DXGI_FORMAT_UNKNOWN) + { + ShaderDebug::FillViewFmt(uavDesc.Format, global.uavs[shaderReg].format); + } + else + { + D3D12_RESOURCE_DESC resDesc = pResource->GetDesc(); + if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + global.uavs[shaderReg].format.stride = uavDesc.Buffer.StructureByteStride; + + // TODO: Try looking up UAV from shader reflection info? + } + } + + if(uavDesc.ViewDimension == D3D12_UAV_DIMENSION_BUFFER) + { + global.uavs[shaderReg].firstElement = (uint32_t)uavDesc.Buffer.FirstElement; + global.uavs[shaderReg].numElements = uavDesc.Buffer.NumElements; + + GetBufferData(pResource, 0, 0, global.uavs[shaderReg].data); + } + else + { + // TODO: Handle texture resources in UAVs - need to copy/map to fetch the data + global.uavs[shaderReg].tex = true; + } + } + } + } + } + } + } + } + } + + global.PopulateGroupshared(dxbc->GetDXBCByteCode()); } ShaderDebugTrace D3D12Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uint32_t instid, diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 9f0a2d0c4..353c8a5f4 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -3985,6 +3985,38 @@ State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State qua return s; } +void GlobalState::PopulateGroupshared(const DXBCBytecode::Program *pBytecode) +{ + for(size_t i = 0; i < pBytecode->GetNumDeclarations(); i++) + { + const DXBCBytecode::Declaration &decl = pBytecode->GetDeclaration(i); + + if(decl.declaration == DXBCBytecode::OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW || + decl.declaration == DXBCBytecode::OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED) + { + uint32_t slot = (uint32_t)decl.operand.indices[0].index; + + if(groupshared.size() <= slot) + { + groupshared.resize(slot + 1); + + groupsharedMem &mem = groupshared[slot]; + + mem.structured = + (decl.declaration == DXBCBytecode::OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED); + + mem.count = decl.count; + if(mem.structured) + mem.bytestride = decl.stride; + else + mem.bytestride = 4; // raw groupshared is implicitly uint32s + + mem.data.resize(mem.bytestride * mem.count); + } + } + } +} + void CreateShaderDebugStateAndTrace(ShaderDebug::State &initialState, ShaderDebugTrace &trace, int quadIdx, DXBC::DXBCContainer *dxbc, const ShaderReflection &refl, bytebuf *cbufData) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index bf1dbd46f..730dcbd00 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -57,6 +57,8 @@ public: srvs[i].firstElement = srvs[i].numElements = 0; } + void PopulateGroupshared(const DXBCBytecode::Program *pBytecode); + struct ViewFmt { int byteWidth = 0;