mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-08 16:50:44 +00:00
Add impl for creating a D3D12 global state for shader debugging.
This commit is contained in:
committed by
Baldur Karlsson
parent
0867435a7e
commit
5179c99f7d
@@ -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,
|
||||
|
||||
@@ -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<WrappedID3D12RootSignature>(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<ID3D12Resource>(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<ID3D12Resource>(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<WrappedID3D12DescriptorHeap>(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<ID3D12Resource>(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<ID3D12Resource>(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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -57,6 +57,8 @@ public:
|
||||
srvs[i].firstElement = srvs[i].numElements = 0;
|
||||
}
|
||||
|
||||
void PopulateGroupshared(const DXBCBytecode::Program *pBytecode);
|
||||
|
||||
struct ViewFmt
|
||||
{
|
||||
int byteWidth = 0;
|
||||
|
||||
Reference in New Issue
Block a user