Implement func to compute math intrinsics for D3D12 shader debugging

This commit is contained in:
Steve Karolewics
2019-12-18 10:42:22 +00:00
committed by Baldur Karlsson
parent 2c80a7206b
commit 99b578e5a3
3 changed files with 219 additions and 2 deletions
+152
View File
@@ -27,6 +27,7 @@
#include "data/resource.h"
#include "driver/dx/official/d3dcompiler.h"
#include "driver/dxgi/dxgi_common.h"
#include "driver/shaders/dxbc/dxbc_bytecode.h"
#include "maths/formatpacking.h"
#include "maths/matrix.h"
#include "maths/vec.h"
@@ -255,6 +256,14 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
rm->SetInternalResource(m_MeshRootSig);
}
if(!CreateMathIntrinsicsResources())
{
RDCERR("Failed to create resources for shader debugging math intrinsics");
SAFE_RELEASE(m_MathIntrinsicsRootSig);
SAFE_RELEASE(m_MathIntrinsicsPso);
SAFE_RELEASE(m_MathIntrinsicsResultBuffer);
}
{
rdcstr meshhlsl = GetEmbeddedResource(mesh_hlsl);
@@ -372,6 +381,10 @@ D3D12DebugManager::~D3D12DebugManager()
SAFE_RELEASE(m_MeshPS);
SAFE_RELEASE(m_MeshRootSig);
SAFE_RELEASE(m_MathIntrinsicsRootSig);
SAFE_RELEASE(m_MathIntrinsicsPso);
SAFE_RELEASE(m_MathIntrinsicsResultBuffer);
SAFE_RELEASE(m_ArrayMSAARootSig);
SAFE_RELEASE(m_FullscreenVS);
@@ -396,6 +409,145 @@ D3D12DebugManager::~D3D12DebugManager()
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
}
bool D3D12DebugManager::CreateMathIntrinsicsResources()
{
rdcstr csProgram =
"RWStructuredBuffer<float4> outval : register(u0);\n"
"cbuffer srcOper : register(b0) { float4 inval; };\n"
"cbuffer srcInstr : register(b1) { uint operation; };\n";
// Assign constants to each supported instruction
csProgram += StringFormat::Fmt("static const uint OPCODE_RCP = %u;\n", DXBCBytecode::OPCODE_RCP);
csProgram += StringFormat::Fmt("static const uint OPCODE_RSQ = %u;\n", DXBCBytecode::OPCODE_RSQ);
csProgram += StringFormat::Fmt("static const uint OPCODE_EXP = %u;\n", DXBCBytecode::OPCODE_EXP);
csProgram += StringFormat::Fmt("static const uint OPCODE_LOG = %u;\n", DXBCBytecode::OPCODE_LOG);
csProgram +=
StringFormat::Fmt("static const uint OPCODE_SINCOS = %u;\n", DXBCBytecode::OPCODE_SINCOS);
csProgram +=
"[numthreads(1, 1, 1)]\n"
"void main(){\n"
" switch(operation){\n"
" case OPCODE_RCP: outval[0] = rcp(inval); break;\n"
" case OPCODE_RSQ: outval[0] = rsqrt(inval); break;\n"
" case OPCODE_EXP: outval[0] = exp2(inval); break;\n"
" case OPCODE_LOG: outval[0] = log2(inval); break;\n"
" case OPCODE_SINCOS: sincos(inval, outval[0], outval[1]); break;\n"
" }\n}\n";
ID3DBlob *csBlob = NULL;
UINT flags = D3DCOMPILE_DEBUG | D3DCOMPILE_WARNINGS_ARE_ERRORS | D3DCOMPILE_DEBUG_NAME_FOR_SOURCE;
if(m_pDevice->GetShaderCache()->GetShaderBlob(csProgram.c_str(), "main", flags, "cs_5_0",
&csBlob) != "")
{
RDCERR("Failed to create shader to calculate math intrinsic");
return false;
}
D3D12RootSignature rootSig;
// Constants param for the operation inputs
D3D12RootSignatureParameter constantParam;
constantParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
constantParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
constantParam.Constants.Num32BitValues = 4; // Input is 4 floats
constantParam.Constants.ShaderRegister = 0;
constantParam.Constants.RegisterSpace = 0;
rootSig.Parameters.push_back(constantParam);
// Constants param for the opcode
constantParam.Constants.Num32BitValues = 1;
constantParam.Constants.ShaderRegister = 1;
constantParam.Constants.RegisterSpace = 0;
rootSig.Parameters.push_back(constantParam);
// UAV param for the output
D3D12RootSignatureParameter uavParam;
uavParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
uavParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
uavParam.Descriptor.ShaderRegister = 0;
uavParam.Descriptor.RegisterSpace = 0;
uavParam.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE;
rootSig.Parameters.push_back(uavParam);
ID3DBlob *root = m_pDevice->GetShaderCache()->MakeRootSig(rootSig);
if(root == NULL)
{
RDCERR("Failed to create root signature for shader debugging");
SAFE_RELEASE(csBlob);
return false;
}
HRESULT hr = m_pDevice->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(),
__uuidof(ID3D12RootSignature),
(void **)&m_MathIntrinsicsRootSig);
m_pDevice->InternalRef();
SAFE_RELEASE(root);
if(FAILED(hr))
{
RDCERR("Failed to create root signature for shader debugging HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(csBlob);
return false;
}
m_pDevice->GetResourceManager()->SetInternalResource(m_MathIntrinsicsRootSig);
D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc;
psoDesc.pRootSignature = m_MathIntrinsicsRootSig;
psoDesc.CS.BytecodeLength = csBlob->GetBufferSize();
psoDesc.CS.pShaderBytecode = csBlob->GetBufferPointer();
psoDesc.NodeMask = 0;
psoDesc.CachedPSO.pCachedBlob = NULL;
psoDesc.CachedPSO.CachedBlobSizeInBytes = 0;
psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
hr = m_pDevice->CreateComputePipelineState(&psoDesc, __uuidof(ID3D12PipelineState),
(void **)&m_MathIntrinsicsPso);
m_pDevice->InternalRef();
SAFE_RELEASE(csBlob);
if(FAILED(hr))
{
RDCERR("Failed to create PSO for shader debugging HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(m_MathIntrinsicsRootSig);
return false;
}
m_pDevice->GetResourceManager()->SetInternalResource(m_MathIntrinsicsPso);
// Create buffer to store computed result
D3D12_RESOURCE_DESC rdesc;
ZeroMemory(&rdesc, sizeof(D3D12_RESOURCE_DESC));
rdesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
rdesc.Width = sizeof(float) * 8; // Output buffer is 2x float4
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;
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;
hr = m_pDevice->CreateCommittedResource(
&heapProps, D3D12_HEAP_FLAG_NONE, &rdesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, NULL,
__uuidof(ID3D12Resource), (void **)&m_MathIntrinsicsResultBuffer);
m_pDevice->InternalRef();
if(FAILED(hr))
{
RDCERR("Failed to create buffer for pixel shader debugging HRESULT: %s", ToStr(hr).c_str());
SAFE_RELEASE(m_MathIntrinsicsRootSig);
SAFE_RELEASE(m_MathIntrinsicsPso);
return false;
}
m_pDevice->GetResourceManager()->SetInternalResource(m_MathIntrinsicsResultBuffer);
return true;
}
ID3D12Resource *D3D12DebugManager::MakeCBuffer(UINT64 size)
{
ID3D12Resource *ret;
+10
View File
@@ -141,6 +141,9 @@ public:
D3D12_GPU_VIRTUAL_ADDRESS UploadConstants(const void *data, size_t size);
ID3D12RootSignature *GetMeshRootSig() { return m_MeshRootSig; }
ID3D12RootSignature *GetMathIntrinsicsRootSig() { return m_MathIntrinsicsRootSig; }
ID3D12PipelineState *GetMathIntrinsicsPso() { return m_MathIntrinsicsPso; }
ID3D12Resource *GetMathIntrinsicsResultBuffer() { return m_MathIntrinsicsResultBuffer; }
ID3D12GraphicsCommandListX *ResetDebugList();
void ResetDebugAlloc();
@@ -171,6 +174,8 @@ public:
void CreateShaderGlobalState(ShaderDebug::GlobalState &global, DXBC::DXBCContainer *dxbc);
private:
bool CreateMathIntrinsicsResources();
WrappedID3D12Device *m_pDevice = NULL;
// heaps
@@ -194,6 +199,11 @@ private:
ID3D12RootSignature *m_MeshRootSig = NULL;
std::map<uint64_t, MeshDisplayPipelines> m_CachedMeshPipelines;
// Shader debugging resources
ID3D12RootSignature *m_MathIntrinsicsRootSig = NULL;
ID3D12PipelineState *m_MathIntrinsicsPso = NULL;
ID3D12Resource *m_MathIntrinsicsResultBuffer = NULL;
// GetBufferData
static const uint64_t m_ReadbackSize = 16 * 1024 * 1024;
+57 -2
View File
@@ -96,8 +96,61 @@ bool D3D12DebugAPIWrapper::CalculateMathIntrinsic(DXBCBytecode::OpcodeType opcod
const ShaderVariable &input,
ShaderVariable &output1, ShaderVariable &output2)
{
RDCUNIMPLEMENTED("CalculateMathIntrinsic not yet implemented for D3D12");
return false;
D3D12MarkerRegion region(m_pDevice->GetQueue()->GetReal(), "CalculateMathIntrinsic");
if(opcode != DXBCBytecode::OPCODE_RCP && opcode != DXBCBytecode::OPCODE_RSQ &&
opcode != DXBCBytecode::OPCODE_EXP && opcode != DXBCBytecode::OPCODE_LOG &&
opcode != DXBCBytecode::OPCODE_SINCOS)
{
// To support a new instruction, the shader created in
// D3D12DebugManager::CreateMathIntrinsicsResources will need updated
RDCERR("Unsupported instruction for CalculateMathIntrinsic: %u", opcode);
return false;
}
// Create UAV to store the computed results
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 = 2;
uavDesc.Buffer.StructureByteStride = sizeof(float) * 4;
ID3D12Resource *pResultBuffer = m_pDevice->GetDebugManager()->GetMathIntrinsicsResultBuffer();
D3D12_CPU_DESCRIPTOR_HANDLE uav = m_pDevice->GetDebugManager()->GetCPUHandle(SHADER_DEBUG_UAV);
m_pDevice->CreateUnorderedAccessView(pResultBuffer, NULL, &uavDesc, uav);
// Set root signature & sig params on command list, then execute the shader
ID3D12GraphicsCommandListX *cmdList = m_pDevice->GetDebugManager()->ResetDebugList();
m_pDevice->GetDebugManager()->SetDescriptorHeaps(cmdList, true, false);
cmdList->SetPipelineState(m_pDevice->GetDebugManager()->GetMathIntrinsicsPso());
cmdList->SetComputeRootSignature(m_pDevice->GetDebugManager()->GetMathIntrinsicsRootSig());
cmdList->SetComputeRoot32BitConstants(0, 4, &input.value.uv[0], 0);
cmdList->SetComputeRoot32BitConstants(1, 1, &opcode, 0);
cmdList->SetComputeRootUnorderedAccessView(2, pResultBuffer->GetGPUVirtualAddress());
cmdList->Dispatch(1, 1, 1);
HRESULT hr = cmdList->Close();
if(FAILED(hr))
{
RDCERR("Failed to close command list HRESULT: %s", ToStr(hr).c_str());
return false;
}
{
ID3D12CommandList *l = cmdList;
m_pDevice->GetQueue()->ExecuteCommandLists(1, &l);
m_pDevice->GPUSync();
}
bytebuf results;
m_pDevice->GetDebugManager()->GetBufferData(pResultBuffer, 0, 0, results);
RDCASSERT(results.size() >= sizeof(uint32_t) * 8);
memcpy(output1.value.uv, results.data(), sizeof(uint32_t) * 4);
memcpy(output2.value.uv, results.data() + 4, sizeof(uint32_t) * 4);
return true;
}
ShaderVariable D3D12DebugAPIWrapper::GetSampleInfo(DXBCBytecode::OperandType type,
@@ -647,6 +700,8 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather(
m_pDevice->GPUSync();
}
rs = prevState;
bytebuf sampleResult;
m_pDevice->GetReplay()->GetTextureData(GetResID(pSampleResult), Subresource(),
GetTextureDataParams(), sampleResult);