From 3927d82e245706c1e922f7655a948aab8a1d19ff Mon Sep 17 00:00:00 2001 From: Steve Karolewics Date: Sat, 22 Feb 2020 15:38:10 -0800 Subject: [PATCH] Improve D3D12 compute shader debugging Added fetching of texture data for UAVs, to allow stores to occur. Fixed issues with sample/gather when debugging a compute shader. Added a demo for dispatch in D3D12. --- renderdoc/driver/d3d12/d3d12_shaderdebug.cpp | 26 +++- .../demos/d3d12/d3d12_simple_dispatch.cpp | 146 ++++++++++++++++++ util/test/demos/demos.vcxproj | 1 + util/test/demos/demos.vcxproj.filters | 3 + 4 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 util/test/demos/d3d12/d3d12_simple_dispatch.cpp diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index db779508d..af152f874 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -379,8 +379,9 @@ bool D3D12DebugAPIWrapper::FetchUAV(const DXBCDebug::BindingSlot &slot) } else { - // TODO: Handle texture resources in UAVs - need to copy/map to fetch the data uavData.tex = true; + m_pDevice->GetReplay()->GetTextureData(uavId, Subresource(), + GetTextureDataParams(), uavData.data); } return true; @@ -1341,8 +1342,13 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( // Create a PSO with our VS/PS and all other state from the original event D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState; D3D12RenderState prevState = rs; + + // If we're debugging a compute shader, we should be able to reuse the rootsig for a + // pixel shader, since the entries will have to use shader visibility all + bool isCompute = m_dxbc->m_Type == DXBC::ShaderType::Compute; + ResourceId sigId = isCompute ? rs.compute.rootsig : rs.graphics.rootsig; WrappedID3D12RootSignature *pRootSig = - m_pDevice->GetResourceManager()->GetCurrentAs(rs.graphics.rootsig); + m_pDevice->GetResourceManager()->GetCurrentAs(sigId); D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeDesc; ZeroMemory(&pipeDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); @@ -1378,6 +1384,22 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( ID3D12GraphicsCommandListX *cmdList = m_pDevice->GetDebugManager()->ResetDebugList(); rs.pipe = GetResID(samplePso); + rs.rts.clear(); + // Set viewport/scissor unconditionally - we need to set this all the time for sampling for a + // compute shader, but also a graphics draw might exclude pixel (0, 0) from its view or scissor + rs.views.clear(); + rs.views.push_back({0, 0, 1, 1, 0, 1}); + rs.scissors.clear(); + rs.scissors.push_back({0, 0, 1, 1}); + if(isCompute) + { + // When debugging compute, we need to move the root sig and elems to the graphics portion + rs.graphics.rootsig = sigId; + rs.graphics.sigelems = rs.compute.sigelems; + rs.compute.rootsig = ResourceId(); + rs.compute.sigelems.clear(); + } + rs.topo = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; rs.ApplyState(m_pDevice, cmdList); // Create a 1x1 texture to store the sample result diff --git a/util/test/demos/d3d12/d3d12_simple_dispatch.cpp b/util/test/demos/d3d12/d3d12_simple_dispatch.cpp new file mode 100644 index 000000000..84d571b1f --- /dev/null +++ b/util/test/demos/d3d12/d3d12_simple_dispatch.cpp @@ -0,0 +1,146 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "d3d12_test.h" + +RD_TEST(D3D12_Simple_Dispatch, D3D12GraphicsTest) +{ + static constexpr const char *Description = + "Test that just does a dispatch and some copies, for checking basic compute stuff"; + + std::string compute = R"EOSHADER( + +Texture2D texin : register(t0); +RWTexture2D texout : register(u0); + +[numthreads(1,1,1)] +void main() +{ + texout[uint2(3,4)] = texin[uint2(4,3)]; + texout[uint2(4,4)] = texin[uint2(3,3)]; + texout[uint2(4,3)] = texin[uint2(3,4)]; + texout[uint2(3,3)] = texin[uint2(4,4)]; + texout[uint2(0,0)] = texin[uint2(0,0)] + 3; +} + +)EOSHADER"; + + int main() + { + // initialise, create window, create device, etc + if(!Init()) + return 3; + + ID3DBlobPtr csblob = Compile(compute, "main", "cs_5_0"); + + ID3D12RootSignaturePtr sig = MakeSig({ + tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 0, 1, 0), + tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 0, 1, 1), + }); + ID3D12PipelineStatePtr pso = MakePSO().RootSig(sig).CS(csblob); + + ID3D12ResourcePtr texin = MakeTexture(DXGI_FORMAT_R32_UINT, 8, 8) + .InitialState(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE) + .UAV(); + ID3D12ResourcePtr texout = MakeTexture(DXGI_FORMAT_R32_UINT, 8, 8) + .InitialState(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE) + .UAV(); + D3D12_TEXTURE_COPY_LOCATION dstLocation; + dstLocation.pResource = texin; + dstLocation.SubresourceIndex = 0; + dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + + MakeSRV(texin).CreateGPU(0); + MakeUAV(texout).CreateGPU(1); + + D3D12_TEXTURE_COPY_LOCATION srcLocation; + srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + D3D12_RESOURCE_DESC srcDesc = texin->GetDesc(); + dev->GetCopyableFootprints(&srcDesc, 0, 1, 0, &srcLocation.PlacedFootprint, NULL, NULL, NULL); + UINT dataSize = srcLocation.PlacedFootprint.Footprint.RowPitch * + srcLocation.PlacedFootprint.Footprint.Height; + std::vector data; + data.reserve(dataSize); + for(size_t i = 0; i < dataSize; i++) + { + data.push_back(5 + rand() % 100); + } + + ID3D12ResourcePtr copybuffer = MakeBuffer().Data(data).Upload(); + srcLocation.pResource = copybuffer; + + D3D12_RESOURCE_BARRIER toDestState[2] = {}; + toDestState[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + toDestState[0].Transition.pResource = texin; + toDestState[0].Transition.Subresource = 0; + toDestState[0].Transition.StateBefore = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + toDestState[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; + toDestState[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + toDestState[1].Transition.pResource = texout; + toDestState[1].Transition.Subresource = 0; + toDestState[1].Transition.StateBefore = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + toDestState[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; + + D3D12_RESOURCE_BARRIER toUseState[2] = {}; + toUseState[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + toUseState[0].Transition.pResource = texin; + toUseState[0].Transition.Subresource = 0; + toUseState[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + toUseState[0].Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + toUseState[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + toUseState[1].Transition.pResource = texout; + toUseState[1].Transition.Subresource = 0; + toUseState[1].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + toUseState[1].Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + + while(Running()) + { + ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer(); + Reset(cmd); + + { + cmd->ResourceBarrier(2, toDestState); + cmd->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL); + dstLocation.pResource = texout; + cmd->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL); + cmd->ResourceBarrier(2, toUseState); + } + + cmd->SetComputeRootSignature(sig); + cmd->SetPipelineState(pso); + cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr()); + cmd->SetComputeRootDescriptorTable(0, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->SetComputeRootDescriptorTable(1, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart()); + cmd->Dispatch(1, 1, 1); + + cmd->Close(); + Submit({cmd}); + Present(); + } + + return 0; + } +}; + +REGISTER_TEST(); diff --git a/util/test/demos/demos.vcxproj b/util/test/demos/demos.vcxproj index 7af777531..828ade96b 100644 --- a/util/test/demos/demos.vcxproj +++ b/util/test/demos/demos.vcxproj @@ -177,6 +177,7 @@ + diff --git a/util/test/demos/demos.vcxproj.filters b/util/test/demos/demos.vcxproj.filters index b2c62f030..e76366bc1 100644 --- a/util/test/demos/demos.vcxproj.filters +++ b/util/test/demos/demos.vcxproj.filters @@ -448,6 +448,9 @@ D3D11\demos + + D3D12\demos +