From 1c44f91cb81ec548eccbe2e6958a18f4006be08b Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Dec 2017 18:15:57 +0000 Subject: [PATCH] Change vulkan/D3D12 to always re-record any cmd buffers being submitted * Previously we'd cache a copy of each command buffer at load time, and submit it any time we're not partially re-recording. This has a couple of drawbacks though: - Technically we do some things that invalidate those command buffers, like updating descriptor sets (with initial state application) and so for 100% correctness we'd need to re-record. - It also means that any edits we apply, like modified shaders, don't properly apply to the whole frame, they only apply to whichever command buffer is currently being partially recorded. * We refactor out the 're-record all commands' behaviour previously reserved just for applying GPU counters, and use that for re-recording any command buffers that are wholly or partially submitted. Note that it's still true that only one primary and one secondary at most are actually *partially* re-recorded. The others are re-recorded in their entirety. --- renderdoc/driver/d3d12/d3d12_command_list.h | 2 +- .../driver/d3d12/d3d12_command_list_wrap.cpp | 534 ++++++++++-------- .../driver/d3d12/d3d12_command_queue_wrap.cpp | 103 +--- renderdoc/driver/d3d12/d3d12_commands.cpp | 80 ++- renderdoc/driver/d3d12/d3d12_commands.h | 68 +-- renderdoc/driver/d3d12/d3d12_common.h | 2 +- renderdoc/driver/d3d12/d3d12_counters.cpp | 1 - renderdoc/driver/d3d12/d3d12_debug.cpp | 1 - renderdoc/driver/d3d12/d3d12_device.cpp | 11 +- renderdoc/driver/d3d12/d3d12_replay.cpp | 1 - renderdoc/driver/vulkan/vk_common.h | 2 +- renderdoc/driver/vulkan/vk_core.cpp | 103 ++-- renderdoc/driver/vulkan/vk_core.h | 95 ++-- renderdoc/driver/vulkan/vk_counters.cpp | 1 - renderdoc/driver/vulkan/vk_debug.cpp | 1 - renderdoc/driver/vulkan/vk_replay.cpp | 1 - .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 477 ++++++++-------- .../driver/vulkan/wrappers/vk_draw_funcs.cpp | 83 ++- .../vulkan/wrappers/vk_dynamic_funcs.cpp | 95 ++-- .../driver/vulkan/wrappers/vk_queue_funcs.cpp | 157 ++--- .../driver/vulkan/wrappers/vk_sync_funcs.cpp | 6 +- 21 files changed, 811 insertions(+), 1013 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_command_list.h b/renderdoc/driver/d3d12/d3d12_command_list.h index b96f345d5..88dfe20cf 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list.h +++ b/renderdoc/driver/d3d12/d3d12_command_list.h @@ -381,7 +381,7 @@ public: void ReserveExecuteIndirect(ID3D12GraphicsCommandList *list, WrappedID3D12CommandSignature *comSig, UINT maxCount); void PatchExecuteIndirect(BakedCmdListInfo &info, uint32_t executeIndex); - void ReplayExecuteIndirect(ID3D12GraphicsCommandList *list, BakedCmdListInfo &info); + void ReplayExecuteIndirect(ID3D12GraphicsCommandList *list); IMPLEMENT_FUNCTION_SERIALISED(virtual void STDMETHODCALLTYPE, ExecuteIndirect, ID3D12CommandSignature *pCommandSignature, UINT MaxCommandCount, diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index 89c0d33db..49ebb31d0 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -61,11 +61,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close(SerialiserType &ser) if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(BakedCommandList)) + if(m_Cmd->HasRerecordCmdList(BakedCommandList)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(BakedCommandList); #if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Ending partial command list for %llu baked to %llu", CommandList, BakedCommandList); + RDCDEBUG("Ending re-recorded command list for %llu baked to %llu", CommandList, + BakedCommandList); #endif int &markerCount = m_Cmd->m_BakedCmdListInfo[BakedCommandList].markerCount; @@ -75,10 +76,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close(SerialiserType &ser) list->Close(); - // erase the non-baked reference to this command list so that we don't have - // duplicates when it comes time to clean up. See below in in Reset() - m_Cmd->m_RerecordCmds.erase(CommandList); - if(m_Cmd->m_Partial[D3D12CommandData::Primary].partialParent == CommandList) m_Cmd->m_Partial[D3D12CommandData::Primary].partialParent = ResourceId(); } @@ -183,6 +180,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser, { const uint32_t length = m_Cmd->m_BakedCmdListInfo[BakedCommandList].eventCount; + bool rerecord = false; bool partial = false; int partialType = D3D12CommandData::ePartialNum; @@ -203,13 +201,24 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser, m_Cmd->m_Partial[p].partialParent = BakedCommandList; m_Cmd->m_Partial[p].baseEvent = *it; + rerecord = true; partial = true; partialType = p; } + else if(*it <= m_Cmd->m_LastEventID) + { +#if ENABLED(VERBOSE_PARTIAL_REPLAY) + RDCDEBUG("Reset() - full re-record detected %u < %u <= %u, %llu -> %llu", *it, + *it + length, m_Cmd->m_LastEventID, m_Cmd->m_LastCmdListID, BakedCommandList); +#endif + + // this submission is completely within the range, so it should still be re-recorded + rerecord = true; + } } } - if(partial || (m_Cmd->m_DrawcallCallback && m_Cmd->m_DrawcallCallback->RecordAllCmds())) + if(rerecord) { ID3D12GraphicsCommandList *list = NULL; HRESULT hr = m_pDevice->CreateCommandList(nodeMask, type, pAllocator, pInitialState, riid, @@ -221,26 +230,22 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser, return false; } - if(partial) - { - m_Cmd->m_Partial[partialType].resultPartialCmdList = list; - } - else - { - // we store under both baked and non baked ID. - // The baked ID is the 'real' entry, the non baked is simply so it - // can be found in the subsequent serialised commands that ref the - // non-baked ID. The baked ID is referenced by the submit itself. - // - // In Close() we erase the non-baked reference, and since - // we know you can only be recording a command list once at a time - // (even if it's baked to several command listsin the frame) - // there's no issue with clashes here. - m_Cmd->m_RerecordCmds[BakedCommandList] = list; - m_Cmd->m_RerecordCmds[CommandList] = list; - } + // we store under both baked and non baked ID. + // The baked ID is the 'real' entry, the non baked is simply so it + // can be found in the subsequent serialised commands that ref the + // non-baked ID. The baked ID is referenced by the submit itself. + // + // In Close() we erase the non-baked reference, and since + // we know you can only be recording a command list once at a time + // (even if it's baked to several command listsin the frame) + // there's no issue with clashes here. + m_Cmd->m_RerecordCmds[BakedCommandList] = list; + m_Cmd->m_RerecordCmds[CommandList] = list; - m_Cmd->m_RenderState.pipe = GetResID(pInitialState); + m_Cmd->m_RerecordCmdList.push_back(list); + + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + m_Cmd->m_RenderState.pipe = GetResID(pInitialState); } // whenever a command-building chunk asks for the command list, it @@ -449,8 +454,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResourceBarrier( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { pCommandList = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -540,12 +544,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetPrimitiveTopology( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->IASetPrimitiveTopology(PrimitiveTopology); - m_Cmd->m_RenderState.topo = PrimitiveTopology; + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + m_Cmd->m_RenderState.topo = PrimitiveTopology; } } else @@ -591,16 +595,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetViewports(SerialiserType & if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->RSSetViewports(NumViewports, pViewports); - if(m_Cmd->m_RenderState.views.size() < NumViewports) - m_Cmd->m_RenderState.views.resize(NumViewports); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.views.size() < NumViewports) + m_Cmd->m_RenderState.views.resize(NumViewports); - for(UINT i = 0; i < NumViewports; i++) - m_Cmd->m_RenderState.views[i] = pViewports[i]; + for(UINT i = 0; i < NumViewports; i++) + m_Cmd->m_RenderState.views[i] = pViewports[i]; + } } } else @@ -652,16 +658,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetScissorRects(SerialiserTyp if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->RSSetScissorRects(NumRects, pRects); - if(m_Cmd->m_RenderState.scissors.size() < NumRects) - m_Cmd->m_RenderState.scissors.resize(NumRects); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.scissors.size() < NumRects) + m_Cmd->m_RenderState.scissors.resize(NumRects); - for(UINT i = 0; i < NumRects; i++) - m_Cmd->m_RenderState.scissors[i] = pRects[i]; + for(UINT i = 0; i < NumRects; i++) + m_Cmd->m_RenderState.scissors[i] = pRects[i]; + } } } else @@ -712,12 +720,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetBlendFactor(SerialiserType if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->OMSetBlendFactor(BlendFactor); - memcpy(m_Cmd->m_RenderState.blendFactor, BlendFactor, sizeof(float) * 4); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + memcpy(m_Cmd->m_RenderState.blendFactor, BlendFactor, sizeof(float) * 4); } } else @@ -762,12 +770,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetStencilRef(SerialiserType if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->OMSetStencilRef(StencilRef); - m_Cmd->m_RenderState.stencilRef = StencilRef; + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + m_Cmd->m_RenderState.stencilRef = StencilRef; } } else @@ -812,8 +820,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetDescriptorHeaps( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { std::vector heaps; heaps.resize(NumDescriptorHeaps); @@ -823,9 +830,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetDescriptorHeaps( Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetDescriptorHeaps(NumDescriptorHeaps, heaps.data()); - m_Cmd->m_RenderState.heaps.resize(heaps.size()); - for(size_t i = 0; i < heaps.size(); i++) - m_Cmd->m_RenderState.heaps[i] = GetResID(ppDescriptorHeaps[i]); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + m_Cmd->m_RenderState.heaps.resize(heaps.size()); + for(size_t i = 0; i < heaps.size(); i++) + m_Cmd->m_RenderState.heaps[i] = GetResID(ppDescriptorHeaps[i]); + } } } else @@ -886,26 +896,28 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetIndexBuffer(SerialiserType if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); Unwrap(list)->IASetIndexBuffer(pView); - if(pView) + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) { - WrappedID3D12Resource::GetResIDFromAddr(pView->BufferLocation, - m_Cmd->m_RenderState.ibuffer.buf, - m_Cmd->m_RenderState.ibuffer.offs); - m_Cmd->m_RenderState.ibuffer.bytewidth = (pView->Format == DXGI_FORMAT_R32_UINT ? 4 : 2); - m_Cmd->m_RenderState.ibuffer.size = pView->SizeInBytes; - } - else - { - m_Cmd->m_RenderState.ibuffer.buf = ResourceId(); - m_Cmd->m_RenderState.ibuffer.offs = 0; - m_Cmd->m_RenderState.ibuffer.bytewidth = 2; + if(pView) + { + WrappedID3D12Resource::GetResIDFromAddr(pView->BufferLocation, + m_Cmd->m_RenderState.ibuffer.buf, + m_Cmd->m_RenderState.ibuffer.offs); + m_Cmd->m_RenderState.ibuffer.bytewidth = (pView->Format == DXGI_FORMAT_R32_UINT ? 4 : 2); + m_Cmd->m_RenderState.ibuffer.size = pView->SizeInBytes; + } + else + { + m_Cmd->m_RenderState.ibuffer.buf = ResourceId(); + m_Cmd->m_RenderState.ibuffer.offs = 0; + m_Cmd->m_RenderState.ibuffer.bytewidth = 2; + } } } } @@ -971,23 +983,25 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetVertexBuffers( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->IASetVertexBuffers(StartSlot, NumViews, pViews); - if(m_Cmd->m_RenderState.vbuffers.size() < StartSlot + NumViews) - m_Cmd->m_RenderState.vbuffers.resize(StartSlot + NumViews); - - for(UINT i = 0; i < NumViews; i++) + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) { - WrappedID3D12Resource::GetResIDFromAddr(pViews[i].BufferLocation, - m_Cmd->m_RenderState.vbuffers[StartSlot + i].buf, - m_Cmd->m_RenderState.vbuffers[StartSlot + i].offs); + if(m_Cmd->m_RenderState.vbuffers.size() < StartSlot + NumViews) + m_Cmd->m_RenderState.vbuffers.resize(StartSlot + NumViews); - m_Cmd->m_RenderState.vbuffers[StartSlot + i].stride = pViews[i].StrideInBytes; - m_Cmd->m_RenderState.vbuffers[StartSlot + i].size = pViews[i].SizeInBytes; + for(UINT i = 0; i < NumViews; i++) + { + WrappedID3D12Resource::GetResIDFromAddr( + pViews[i].BufferLocation, m_Cmd->m_RenderState.vbuffers[StartSlot + i].buf, + m_Cmd->m_RenderState.vbuffers[StartSlot + i].offs); + + m_Cmd->m_RenderState.vbuffers[StartSlot + i].stride = pViews[i].StrideInBytes; + m_Cmd->m_RenderState.vbuffers[StartSlot + i].size = pViews[i].SizeInBytes; + } } } } @@ -1051,24 +1065,26 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SOSetTargets( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->SOSetTargets(StartSlot, NumViews, pViews); - if(m_Cmd->m_RenderState.streamouts.size() < StartSlot + NumViews) - m_Cmd->m_RenderState.streamouts.resize(StartSlot + NumViews); - - for(UINT i = 0; i < NumViews; i++) + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) { - D3D12RenderState::StreamOut &so = m_Cmd->m_RenderState.streamouts[StartSlot + i]; + if(m_Cmd->m_RenderState.streamouts.size() < StartSlot + NumViews) + m_Cmd->m_RenderState.streamouts.resize(StartSlot + NumViews); - WrappedID3D12Resource::GetResIDFromAddr(pViews[i].BufferLocation, so.buf, so.offs); + for(UINT i = 0; i < NumViews; i++) + { + D3D12RenderState::StreamOut &so = m_Cmd->m_RenderState.streamouts[StartSlot + i]; - WrappedID3D12Resource::GetResIDFromAddr(pViews[i].BufferFilledSizeLocation, so.countbuf, - so.countoffs); + WrappedID3D12Resource::GetResIDFromAddr(pViews[i].BufferLocation, so.buf, so.offs); - so.size = pViews[i].SizeInBytes; + WrappedID3D12Resource::GetResIDFromAddr(pViews[i].BufferFilledSizeLocation, so.countbuf, + so.countoffs); + + so.size = pViews[i].SizeInBytes; + } } } } @@ -1133,12 +1149,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetPipelineState(SerialiserType if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID))->SetPipelineState(Unwrap(pPipelineState)); - m_Cmd->m_RenderState.pipe = GetResID(pPipelineState); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + m_Cmd->m_RenderState.pipe = GetResID(pPipelineState); } } else @@ -1203,23 +1219,25 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetRenderTargets( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->OMSetRenderTargets(NumRenderTargetDescriptors, unwrappedRTs.data(), RTsSingleHandleToDescriptorRange, pDepthStencilDescriptor ? &unwrappedDSV : NULL); - m_Cmd->m_RenderState.rts.resize(numHandles); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + m_Cmd->m_RenderState.rts.resize(numHandles); - for(UINT i = 0; i < numHandles; i++) - m_Cmd->m_RenderState.rts[i] = pRenderTargetDescriptors[i]; + for(UINT i = 0; i < numHandles; i++) + m_Cmd->m_RenderState.rts[i] = pRenderTargetDescriptors[i]; - m_Cmd->m_RenderState.rtSingle = RTsSingleHandleToDescriptorRange != FALSE; + m_Cmd->m_RenderState.rtSingle = RTsSingleHandleToDescriptorRange != FALSE; - m_Cmd->m_RenderState.dsv = - pDepthStencilDescriptor ? *pDepthStencilDescriptor : D3D12_CPU_DESCRIPTOR_HANDLE(); + m_Cmd->m_RenderState.dsv = + pDepthStencilDescriptor ? *pDepthStencilDescriptor : D3D12_CPU_DESCRIPTOR_HANDLE(); + } } } else @@ -1309,22 +1327,24 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetComputeRootSignature( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetComputeRootSignature(Unwrap(pRootSignature)); - // From the docs - // (https://msdn.microsoft.com/en-us/library/windows/desktop/dn903950(v=vs.85).aspx) - // "If a root signature is changed on a command list, all previous root signature bindings - // become stale and all newly expected bindings must be set before Draw/Dispatch; otherwise, - // the behavior is undefined. If the root signature is redundantly set to the same one - // currently set, existing root signature bindings do not become stale." - if(m_Cmd->m_RenderState.compute.rootsig != GetResID(pRootSignature)) - m_Cmd->m_RenderState.compute.sigelems.clear(); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + // From the docs + // (https://msdn.microsoft.com/en-us/library/windows/desktop/dn903950(v=vs.85).aspx) + // "If a root signature is changed on a command list, all previous root signature bindings + // become stale and all newly expected bindings must be set before Draw/Dispatch; + // otherwise, the behavior is undefined. If the root signature is redundantly set to the + // same one currently set, existing root signature bindings do not become stale." + if(m_Cmd->m_RenderState.compute.rootsig != GetResID(pRootSignature)) + m_Cmd->m_RenderState.compute.sigelems.clear(); - m_Cmd->m_RenderState.compute.rootsig = GetResID(pRootSignature); + m_Cmd->m_RenderState.compute.rootsig = GetResID(pRootSignature); + } } } else @@ -1378,8 +1398,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetComputeRootDescriptorTable( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetComputeRootDescriptorTable(RootParameterIndex, Unwrap(BaseDescriptor)); @@ -1485,17 +1504,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetComputeRoot32BitConstant( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetComputeRoot32BitConstant(RootParameterIndex, SrcData, DestOffsetIn32BitValues); - if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex].SetConstant( - DestOffsetIn32BitValues, SrcData); + m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex].SetConstant( + DestOffsetIn32BitValues, SrcData); + } } } else @@ -1555,18 +1576,20 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetComputeRoot32BitConstants( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetComputeRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); - if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex].SetConstants( - Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); + m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex].SetConstants( + Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); + } } } else @@ -1634,17 +1657,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetComputeRootConstantBufferVie if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetComputeRootConstantBufferView(RootParameterIndex, BufferLocation); - if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex] = - D3D12RenderState::SignatureElement(eRootCBV, id, offs); + m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex] = + D3D12RenderState::SignatureElement(eRootCBV, id, offs); + } } } else @@ -1710,17 +1735,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetComputeRootShaderResourceVie if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetComputeRootShaderResourceView(RootParameterIndex, BufferLocation); - if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex] = - D3D12RenderState::SignatureElement(eRootSRV, id, offs); + m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex] = + D3D12RenderState::SignatureElement(eRootSRV, id, offs); + } } } else @@ -1786,17 +1813,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetComputeRootUnorderedAccessVi if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetComputeRootUnorderedAccessView(RootParameterIndex, BufferLocation); - if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.compute.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.compute.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex] = - D3D12RenderState::SignatureElement(eRootUAV, id, offs); + m_Cmd->m_RenderState.compute.sigelems[RootParameterIndex] = + D3D12RenderState::SignatureElement(eRootUAV, id, offs); + } } } else @@ -1857,22 +1886,24 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootSignature( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetGraphicsRootSignature(Unwrap(pRootSignature)); - // From the docs - // (https://msdn.microsoft.com/en-us/library/windows/desktop/dn903950(v=vs.85).aspx) - // "If a root signature is changed on a command list, all previous root signature bindings - // become stale and all newly expected bindings must be set before Draw/Dispatch; otherwise, - // the behavior is undefined. If the root signature is redundantly set to the same one - // currently set, existing root signature bindings do not become stale." - if(m_Cmd->m_RenderState.graphics.rootsig != GetResID(pRootSignature)) - m_Cmd->m_RenderState.graphics.sigelems.clear(); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + // From the docs + // (https://msdn.microsoft.com/en-us/library/windows/desktop/dn903950(v=vs.85).aspx) + // "If a root signature is changed on a command list, all previous root signature bindings + // become stale and all newly expected bindings must be set before Draw/Dispatch; + // otherwise, the behavior is undefined. If the root signature is redundantly set to the + // same one currently set, existing root signature bindings do not become stale." + if(m_Cmd->m_RenderState.graphics.rootsig != GetResID(pRootSignature)) + m_Cmd->m_RenderState.graphics.sigelems.clear(); - m_Cmd->m_RenderState.graphics.rootsig = GetResID(pRootSignature); + m_Cmd->m_RenderState.graphics.rootsig = GetResID(pRootSignature); + } } } else @@ -1926,19 +1957,21 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootDescriptorTable( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetGraphicsRootDescriptorTable(RootParameterIndex, Unwrap(BaseDescriptor)); - if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = - D3D12RenderState::SignatureElement(eRootTable, - GetResID(GetWrapped(BaseDescriptor)->nonsamp.heap), - (UINT64)GetWrapped(BaseDescriptor)->nonsamp.idx); + m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = + D3D12RenderState::SignatureElement(eRootTable, + GetResID(GetWrapped(BaseDescriptor)->nonsamp.heap), + (UINT64)GetWrapped(BaseDescriptor)->nonsamp.idx); + } } } else @@ -2033,17 +2066,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRoot32BitConstant( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetGraphicsRoot32BitConstant(RootParameterIndex, SrcData, DestOffsetIn32BitValues); - if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex].SetConstant( - DestOffsetIn32BitValues, SrcData); + m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex].SetConstant( + DestOffsetIn32BitValues, SrcData); + } } } else @@ -2103,18 +2138,20 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRoot32BitConstants( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetGraphicsRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); - if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex].SetConstants( - Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); + m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex].SetConstants( + Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); + } } } else @@ -2182,17 +2219,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootConstantBufferVi if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetGraphicsRootConstantBufferView(RootParameterIndex, BufferLocation); - if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = - D3D12RenderState::SignatureElement(eRootCBV, id, offs); + m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = + D3D12RenderState::SignatureElement(eRootCBV, id, offs); + } } } else @@ -2258,17 +2297,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootShaderResourceVi if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetGraphicsRootShaderResourceView(RootParameterIndex, BufferLocation); - if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = - D3D12RenderState::SignatureElement(eRootSRV, id, offs); + m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = + D3D12RenderState::SignatureElement(eRootSRV, id, offs); + } } } else @@ -2334,17 +2375,19 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootUnorderedAccessV if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->SetGraphicsRootUnorderedAccessView(RootParameterIndex, BufferLocation); - if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) - m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); + if(m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + if(m_Cmd->m_RenderState.graphics.sigelems.size() < RootParameterIndex + 1) + m_Cmd->m_RenderState.graphics.sigelems.resize(RootParameterIndex + 1); - m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = - D3D12RenderState::SignatureElement(eRootUAV, id, offs); + m_Cmd->m_RenderState.graphics.sigelems[RootParameterIndex] = + D3D12RenderState::SignatureElement(eRootUAV, id, offs); + } } } else @@ -2408,8 +2451,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_BeginQuery(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { } } @@ -2457,8 +2499,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_EndQuery(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { } } @@ -2510,8 +2551,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResolveQueryData( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { } } @@ -2797,8 +2837,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetMarker(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -2879,8 +2918,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_BeginEvent(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -2937,8 +2975,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_EndEvent(SerialiserType &ser) if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -3019,8 +3056,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DrawInstanced(SerialiserType &s if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -3104,8 +3140,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DrawIndexedInstanced( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -3191,8 +3226,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Dispatch(SerialiserType &ser, U if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -3264,8 +3298,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ExecuteBundle(SerialiserType &s if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); @@ -3646,30 +3679,29 @@ void WrappedID3D12GraphicsCommandList::PatchExecuteIndirect(BakedCmdListInfo &in } } -void WrappedID3D12GraphicsCommandList::ReplayExecuteIndirect(ID3D12GraphicsCommandList *list, - BakedCmdListInfo &info) +void WrappedID3D12GraphicsCommandList::ReplayExecuteIndirect(ID3D12GraphicsCommandList *list) { BakedCmdListInfo &cmdInfo = m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID]; - size_t executeIndex = info.executeEvents.size(); + size_t executeIndex = cmdInfo.executeEvents.size(); - for(size_t i = 0; i < info.executeEvents.size(); i++) + for(size_t i = 0; i < cmdInfo.executeEvents.size(); i++) { - if(info.executeEvents[i].baseEvent <= cmdInfo.curEventID && - cmdInfo.curEventID < info.executeEvents[i].lastEvent) + if(cmdInfo.executeEvents[i].baseEvent <= cmdInfo.curEventID && + cmdInfo.curEventID < cmdInfo.executeEvents[i].lastEvent) { executeIndex = i; break; } } - if(executeIndex >= info.executeEvents.size()) + if(executeIndex >= cmdInfo.executeEvents.size()) { RDCERR("Couldn't find ExecuteIndirect to replay!"); return; } - BakedCmdListInfo::ExecuteData &exec = info.executeEvents[executeIndex]; + BakedCmdListInfo::ExecuteData &exec = cmdInfo.executeEvents[executeIndex]; WrappedID3D12CommandSignature *comSig = exec.sig; @@ -3678,15 +3710,31 @@ void WrappedID3D12GraphicsCommandList::ReplayExecuteIndirect(ID3D12GraphicsComma const bool multidraw = (count > 1 || comSig->sig.numDraws > 1); + const bool gfx = comSig->sig.graphics; + const uint32_t sigSize = (uint32_t)comSig->sig.arguments.size(); + + // if we're partial then continue to emulate & replay, otherwise use the patched buffer + if(!m_Cmd->IsPartialCmdList(m_Cmd->m_LastCmdListID)) + { + list->ExecuteIndirect(comSig->GetReal(), exec.maxCount, Unwrap(exec.argBuf), exec.argOffs, + Unwrap(exec.countBuf), exec.countOffs); + + // skip past all the events + cmdInfo.curEventID += origCount * sigSize; + + // skip past the pop event + if(multidraw) + cmdInfo.curEventID++; + + return; + } + bytebuf data; m_pDevice->GetDebugManager()->GetBufferData(exec.argBuf, exec.argOffs, count * comSig->sig.ByteStride, data); byte *dataPtr = &data[0]; - const bool gfx = comSig->sig.graphics; - const uint32_t sigSize = (uint32_t)comSig->sig.arguments.size(); - vector &sigelems = gfx ? m_Cmd->m_RenderState.graphics.sigelems : m_Cmd->m_RenderState.compute.sigelems; @@ -3724,8 +3772,8 @@ void WrappedID3D12GraphicsCommandList::ReplayExecuteIndirect(ID3D12GraphicsComma { uint32_t baseEventID = it->eventID; - // TODO when re-recording all, we should submit every drawcall individually - if(m_Cmd->m_DrawcallCallback && m_Cmd->m_DrawcallCallback->RecordAllCmds()) + // TODO when using a drawcall callback, we should submit every drawcall individually + if(m_Cmd->m_DrawcallCallback) { firstCommand = 0; firstArg = 0; @@ -4027,14 +4075,11 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ExecuteIndirect( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); - BakedCmdListInfo &bakeInfo = m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID]; - - ReplayExecuteIndirect(Unwrap(list), bakeInfo); + ReplayExecuteIndirect(Unwrap(list)); } } else @@ -4190,8 +4235,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearDepthStencilView( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->ClearDepthStencilView(Unwrap(DepthStencilView), ClearFlags, Depth, Stencil, NumRects, @@ -4275,8 +4319,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearRenderTargetView( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->ClearRenderTargetView(Unwrap(RenderTargetView), ColorRGBA, NumRects, pRects); @@ -4359,8 +4402,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearUnorderedAccessViewUint( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->ClearUnorderedAccessViewUint(Unwrap(ViewGPUHandleInCurrentHeap), Unwrap(ViewCPUHandle), @@ -4452,8 +4494,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ClearUnorderedAccessViewFloat( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->ClearUnorderedAccessViewFloat(Unwrap(ViewGPUHandleInCurrentHeap), Unwrap(ViewCPUHandle), @@ -4541,8 +4582,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DiscardResource(SerialiserType if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { Unwrap(m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID)) ->DiscardResource(Unwrap(pResource), pRegion); @@ -4601,8 +4641,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyBufferRegion(SerialiserType if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); Unwrap(list)->CopyBufferRegion(Unwrap(pDstBuffer), DstOffset, Unwrap(pSrcBuffer), SrcOffset, @@ -4697,8 +4736,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyTextureRegion( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); Unwrap(list)->CopyTextureRegion(&unwrappedDst, DstX, DstY, DstZ, &unwrappedSrc, pSrcBox); @@ -4793,8 +4831,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_CopyResource(SerialiserType &se if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); Unwrap(list)->CopyResource(Unwrap(pDstResource), Unwrap(pSrcResource)); @@ -4878,8 +4915,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResolveSubresource( if(IsActiveReplaying(m_State)) { - if(m_Cmd->ShouldRerecordCmd(m_Cmd->m_LastCmdListID) && - m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) + if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID)) { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID); Unwrap(list)->ResolveSubresource(Unwrap(pDstResource), DstSubresource, Unwrap(pSrcResource), diff --git a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp index d60c1f0a9..ab7bc562f 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp @@ -250,48 +250,15 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se RDCDEBUG("Queue Submit no replay %u == %u", m_Cmd.m_LastEventID, startEID); #endif } - else if(m_Cmd.m_DrawcallCallback && m_Cmd.m_DrawcallCallback->RecordAllCmds()) + else { #if ENABLED(VERBOSE_PARTIAL_REPLAY) RDCDEBUG("Queue Submit re-recording from %u", m_Cmd.m_RootEventID); #endif - vector rerecordedCmds; - - for(uint32_t c = 0; c < NumCommandLists; c++) - { - ResourceId cmdId = GetResourceManager()->GetOriginalID(GetResID(ppCommandLists[c])); - - ID3D12CommandList *cmd = m_Cmd.RerecordCmdList(cmdId); - ResourceId rerecord = GetResID(cmd); -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit fully re-recorded replay of %llu, using %llu", cmdId, rerecord); -#endif - rerecordedCmds.push_back(Unwrap(cmd)); - - m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[rerecord].barriers); - } - -#if ENABLED(SINGLE_FLUSH_VALIDATE) - for(size_t i = 0; i < rerecordedCmds.size(); i++) - { - real->ExecuteCommandLists(1, &rerecordedCmds[i]); - m_pDevice->GPUSync(); - } -#else - real->ExecuteCommandLists((UINT)rerecordedCmds.size(), &rerecordedCmds[0]); -#endif - } - else if(m_Cmd.m_LastEventID > startEID && m_Cmd.m_LastEventID < m_Cmd.m_RootEventID) - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit partial replay %u < %u", m_Cmd.m_LastEventID, m_Cmd.m_RootEventID); -#endif - uint32_t eid = startEID; - vector trimmedCmdIds; - vector trimmedCmds; + std::vector rerecordedCmds; for(uint32_t c = 0; c < NumCommandLists; c++) { @@ -301,25 +268,21 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se // so it matches up to baseEvent eid++; +#if ENABLED(VERBOSE_PARTIAL_REPLAY) uint32_t end = eid + m_Cmd.m_BakedCmdListInfo[cmdId].eventCount; +#endif - if(eid == m_Cmd.m_Partial[D3D12CommandData::Primary].baseEvent) + if(eid <= m_Cmd.m_LastEventID) { - ID3D12GraphicsCommandList *list = m_Cmd.RerecordCmdList(cmdId, D3D12CommandData::Primary); - ResourceId partial = GetResID(list); + ID3D12CommandList *cmd = m_Cmd.RerecordCmdList(cmdId); + ResourceId rerecord = GetResID(cmd); #if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit partial replay of %llu at %u, using %llu", cmdId, eid, partial); + RDCDEBUG("Queue submit re-recorded replay of %llu, using %llu (%u -> %u <= %u)", cmdId, + rerecord, eid, end, m_Cmd.m_LastEventID); #endif - trimmedCmdIds.push_back(partial); - trimmedCmds.push_back(Unwrap(list)); - } - else if(m_Cmd.m_LastEventID >= end) - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit full replay %llu", cmdId); -#endif - trimmedCmdIds.push_back(cmdId); - trimmedCmds.push_back(Unwrap(ppCommandLists[c])); + rerecordedCmds.push_back(Unwrap(cmd)); + + m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[rerecord].barriers); } else { @@ -333,51 +296,15 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se eid += 1 + m_Cmd.m_BakedCmdListInfo[cmdId].eventCount; } - RDCASSERT(trimmedCmds.size() > 0); - #if ENABLED(SINGLE_FLUSH_VALIDATE) - for(size_t i = 0; i < trimmedCmds.size(); i++) + for(size_t i = 0; i < rerecordedCmds.size(); i++) { - real->ExecuteCommandLists(1, &trimmedCmds[i]); + real->ExecuteCommandLists(1, &rerecordedCmds[i]); m_pDevice->GPUSync(); } #else - real->ExecuteCommandLists((UINT)trimmedCmds.size(), &trimmedCmds[0]); + real->ExecuteCommandLists((UINT)rerecordedCmds.size(), &rerecordedCmds[0]); #endif - - for(uint32_t i = 0; i < trimmedCmdIds.size(); i++) - { - ResourceId cmd = trimmedCmdIds[i]; - m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[cmd].barriers); - } - } - else - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit full replay %u >= %u", m_Cmd.m_LastEventID, m_Cmd.m_RootEventID); -#endif - - ID3D12CommandList **unwrapped = new ID3D12CommandList *[NumCommandLists]; - for(uint32_t i = 0; i < NumCommandLists; i++) - unwrapped[i] = Unwrap(ppCommandLists[i]); - -#if ENABLED(SINGLE_FLUSH_VALIDATE) - for(UINT i = 0; i < NumCommandLists; i++) - { - real->ExecuteCommandLists(1, &unwrapped[i]); - m_pDevice->GPUSync(); - } -#else - real->ExecuteCommandLists(NumCommandLists, unwrapped); -#endif - - SAFE_DELETE_ARRAY(unwrapped); - - for(uint32_t i = 0; i < NumCommandLists; i++) - { - ResourceId cmd = GetResID(ppCommandLists[i]); - m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[cmd].barriers); - } } } } diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index 35c5578b1..90a4eeef8 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -674,13 +674,11 @@ ReplayStatus WrappedID3D12CommandQueue::ReplayLog(CaptureState readType, uint32_ std::sort(m_Cmd.m_Events.begin(), m_Cmd.m_Events.end(), SortEID()); } - for(int p = 0; p < D3D12CommandData::ePartialNum; p++) - SAFE_RELEASE(m_Cmd.m_Partial[p].resultPartialCmdList); - - for(auto it = m_Cmd.m_RerecordCmds.begin(); it != m_Cmd.m_RerecordCmds.end(); ++it) - SAFE_RELEASE(it->second); + for(size_t i = 0; i < m_Cmd.m_RerecordCmdList.size(); i++) + SAFE_RELEASE(m_Cmd.m_RerecordCmdList[i]); m_Cmd.m_RerecordCmds.clear(); + m_Cmd.m_RerecordCmdList.clear(); return ReplayStatus::Succeeded; } @@ -1007,25 +1005,15 @@ uint32_t D3D12CommandData::HandlePreCallback(ID3D12GraphicsCommandList *list, bo return eventID; } -bool D3D12CommandData::ShouldRerecordCmd(ResourceId cmdid) -{ - if(m_Partial[Primary].outsideCmdList != NULL) - return true; - - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) - return true; - - return cmdid == m_Partial[Primary].partialParent || cmdid == m_Partial[Secondary].partialParent; -} - bool D3D12CommandData::InRerecordRange(ResourceId cmdid) { - if(m_Partial[Primary].outsideCmdList != NULL) - return true; - - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) + // if we have an outside command list, assume the range is valid and we're replaying all events + // onto it. + if(m_OutsideCmdList != NULL) return true; + // if not, check if we're one of the actual partial command buffers and check to see if we're in + // the range for their partial replay. for(int p = 0; p < ePartialNum; p++) { if(cmdid == m_Partial[p].partialParent) @@ -1035,38 +1023,46 @@ bool D3D12CommandData::InRerecordRange(ResourceId cmdid) } } + // otherwise just check if we have a re-record command list for this, as then we're doing a full + // re-record and replay + return m_RerecordCmds.find(cmdid) != m_RerecordCmds.end(); +} + +bool D3D12CommandData::HasRerecordCmdList(ResourceId cmdid) +{ + if(m_OutsideCmdList != NULL) + return true; + + return m_RerecordCmds.find(cmdid) != m_RerecordCmds.end(); +} + +bool D3D12CommandData::IsPartialCmdList(ResourceId cmdid) +{ + if(m_OutsideCmdList != NULL) + return true; + + for(int p = 0; p < ePartialNum; p++) + if(cmdid == m_Partial[p].partialParent) + return true; + return false; } ID3D12GraphicsCommandList *D3D12CommandData::RerecordCmdList(ResourceId cmdid, PartialReplayIndex partialType) { - if(m_Partial[Primary].outsideCmdList != NULL) - return m_Partial[Primary].outsideCmdList; + if(m_OutsideCmdList != NULL) + return m_OutsideCmdList; - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) + auto it = m_RerecordCmds.find(cmdid); + + if(it == m_RerecordCmds.end()) { - auto it = m_RerecordCmds.find(cmdid); - - if(it == m_RerecordCmds.end()) - { - RDCERR("Didn't generate re-record command for %llu", cmdid); - return NULL; - } - - return it->second; + RDCERR("Didn't generate re-record command for %llu", cmdid); + return NULL; } - if(partialType != ePartialNum) - return m_Partial[partialType].resultPartialCmdList; - - for(int p = 0; p < ePartialNum; p++) - if(cmdid == m_Partial[p].partialParent) - return m_Partial[p].resultPartialCmdList; - - RDCERR("Calling re-record for invalid command list id"); - - return NULL; + return it->second; } void D3D12CommandData::AddEvent() diff --git a/renderdoc/driver/d3d12/d3d12_commands.h b/renderdoc/driver/d3d12/d3d12_commands.h index d9477edee..39e655e9d 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.h +++ b/renderdoc/driver/d3d12/d3d12_commands.h @@ -109,11 +109,6 @@ struct D3D12DrawcallCallback virtual bool PostDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) = 0; virtual void PostRedispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) = 0; - // should we re-record all command lists? this needs to be true if the range - // being replayed is larger than one command list (which usually means the - // whole frame). - virtual bool RecordAllCmds() = 0; - // if a command list is recorded once and submitted N > 1 times, then the same // drawcall will have several EIDs that refer to it. We'll only do the full // callbacks above for the first EID, then call this function for the others @@ -198,51 +193,36 @@ struct D3D12CommandData ePartialNum }; + // by definition, when replaying we must have N completely submitted command lists, and at most + // two partially-submitted command lists. One primary, that we're part-way through, and then + // if we're part-way through a ExecuteBundle inside that primary then there's one + // secondary. struct PartialReplayData { PartialReplayData() { Reset(); } void Reset() { - resultPartialCmdList = NULL; - outsideCmdList = NULL; partialParent = ResourceId(); baseEvent = 0; } - // if we're doing a partial replay, by definition only one command - // list will be partial at any one time. While replaying through - // the command list chunks, the partial command list will be - // created as a temporary new command list and when it comes to - // the queue that should execute it, it can execute this instead. - ID3D12GraphicsCommandList *resultPartialCmdList; - - // if we're replaying just a single draw or a particular command - // list subsection of command events, we don't go through the - // whole original command lists to set up the partial replay, - // so we just set this command list - ID3D12GraphicsCommandList *outsideCmdList; - - // this records where in the frame a command list was executed, - // so that we know if our replay range ends in one of these ranges - // we need to construct a partial command list for future - // replaying. Note that we always have the complete command list - // around - it's the bakeID itself. - // Since we only ever record a bakeID once the key is unique - note - // that the same command list could be reset multiple times - // a frame, so the parent command list ID (the one recorded in + // this records where in the frame a command list was executed, so that we know if our replay + // range ends in one of these ranges we need to construct a partial command list for future + // replaying. Note that we always have the complete command list around - it's the bakeID + // itself. + // Since we only ever record a bakeID once the key is unique - note that the same command list + // could be reset multiple times a frame, so the parent command list ID (the one recorded in // CmdList chunks) is NOT unique. - // However, a single baked command list can be executed multiple - // times - so we have to have a list of base events + // However, a single baked command list can be executed multiple times - so we have to have a + // list of base events // Map from bakeID -> vector - map > cmdListExecs; + std::map > cmdListExecs; - // This is just the ResourceId of the original parent command list - // and it's baked id. - // If we are in the middle of a partial replay - allows fast checking - // in all CmdList chunks, with the iteration through the above list - // only in Reset. - // partialParent gets reset to ResourceId() in the Close so that - // other baked command lists from the same parent don't pick it up + // This is just the baked ID of the parent command list that's partially replayed + // If we are in the middle of a partial replay - allows fast checking in all CmdList chunks, + // with the iteration through the above list only in Reset. + // partialParent gets reset to ResourceId() in the Close so that other baked command lists from + // the same parent don't pick it up // Also reset each overall replay ResourceId partialParent; @@ -253,6 +233,12 @@ struct D3D12CommandData uint32_t baseEvent; } m_Partial[ePartialNum]; + // if we're replaying just a single draw or a particular command + // list subsection of command events, we don't go through the + // whole original command lists to set up the partial replay, + // so we just set this command list + ID3D12GraphicsCommandList *m_OutsideCmdList = NULL; + void InsertDrawsAndRefreshIDs(ResourceId cmd, vector &cmdBufNodes); // this is a list of uint64_t file offset -> uint32_t EIDs of where each @@ -281,7 +267,8 @@ struct D3D12CommandData vector m_EventMessages; - map m_RerecordCmds; + std::map m_RerecordCmds; + std::vector m_RerecordCmdList; bool m_AddedDrawcall; @@ -315,8 +302,9 @@ struct D3D12CommandData uint32_t HandlePreCallback(ID3D12GraphicsCommandList *list, bool dispatch = false, uint32_t multiDrawOffset = 0); - bool ShouldRerecordCmd(ResourceId cmdid); bool InRerecordRange(ResourceId cmdid); + bool HasRerecordCmdList(ResourceId cmdid); + bool IsPartialCmdList(ResourceId cmdid); ID3D12GraphicsCommandList *RerecordCmdList(ResourceId cmdid, PartialReplayIndex partialType = ePartialNum); diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index 57cc28af7..f9740de06 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -90,7 +90,7 @@ StencilOp MakeStencilOp(D3D12_STENCIL_OP op); // uncomment this to get verbose debugging about when/where/why partial command // buffer replay is happening -#define VERBOSE_PARTIAL_REPLAY OPTION_ON +#define VERBOSE_PARTIAL_REPLAY OPTION_OFF ShaderStageMask ConvertVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility); UINT GetNumSubresources(ID3D12Device *dev, const D3D12_RESOURCE_DESC *desc); diff --git a/renderdoc/driver/d3d12/d3d12_counters.cpp b/renderdoc/driver/d3d12/d3d12_counters.cpp index 2321e507b..5dd5bbb7d 100644 --- a/renderdoc/driver/d3d12/d3d12_counters.cpp +++ b/renderdoc/driver/d3d12/d3d12_counters.cpp @@ -228,7 +228,6 @@ struct D3D12GPUTimerCallback : public D3D12DrawcallCallback void PreDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) { PreDraw(eid, cmd); } bool PostDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) { return PostDraw(eid, cmd); } void PostRedispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) { PostRedraw(eid, cmd); } - bool RecordAllCmds() { return true; } void AliasEvent(uint32_t primary, uint32_t alias) { m_AliasEvents.push_back(std::make_pair(primary, alias)); diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 297da7002..330eb0d10 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -6784,7 +6784,6 @@ struct D3D12QuadOverdrawCallback : public D3D12DrawcallCallback void PreDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) {} bool PostDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) { return false; } void PostRedispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) {} - bool RecordAllCmds() { return false; } void AliasEvent(uint32_t primary, uint32_t alias) { // don't care diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 8788b1bd5..baad4c0d5 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -2578,8 +2578,6 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID, if(!partial) { - RDCASSERT(cmd.m_Partial[D3D12CommandData::Primary].resultPartialCmdList == NULL); - RDCASSERT(cmd.m_Partial[D3D12CommandData::Secondary].resultPartialCmdList == NULL); cmd.m_Partial[D3D12CommandData::Primary].Reset(); cmd.m_Partial[D3D12CommandData::Secondary].Reset(); cmd.m_RenderState = D3D12RenderState(); @@ -2592,8 +2590,7 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID, // has chosen a subsection that lies within a command list if(partial) { - ID3D12GraphicsCommandList *list = cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList = - GetNewList(); + ID3D12GraphicsCommandList *list = cmd.m_OutsideCmdList = GetNewList(); cmd.m_RenderState.ApplyState(list); } @@ -2611,15 +2608,15 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID, RDCASSERTEQUAL(status, ReplayStatus::Succeeded); - if(cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList != NULL) + if(cmd.m_OutsideCmdList != NULL) { - ID3D12GraphicsCommandList *list = cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList; + ID3D12GraphicsCommandList *list = cmd.m_OutsideCmdList; list->Close(); ExecuteLists(); - cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList = NULL; + cmd.m_OutsideCmdList = NULL; } #if ENABLED(SINGLE_FLUSH_VALIDATE) diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index d882150e9..453535ed4 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -1440,7 +1440,6 @@ struct D3D12InitPostVSCallback : public D3D12DrawcallCallback void PreDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) {} bool PostDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) { return false; } void PostRedispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) {} - bool RecordAllCmds() { return false; } void AliasEvent(uint32_t primary, uint32_t alias) { if(std::find(m_Events.begin(), m_Events.end(), primary) != m_Events.end()) diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index eaf006b11..11a2a89a8 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -74,7 +74,7 @@ // uncomment this to enable validation layers on replay, useful for debugging // problems with new replay code -#define FORCE_VALIDATION_LAYERS OPTION_OFF +#define FORCE_VALIDATION_LAYERS OPTION_ON ResourceFormat MakeResourceFormat(VkFormat fmt); VkFormat MakeVkFormat(ResourceFormat fmt); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 72039716d..f7860a8c0 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1733,26 +1733,11 @@ ReplayStatus WrappedVulkan::ContextReplayLog(CaptureState readType, uint32_t sta m_CleanupEvents.clear(); - for(int p = 0; p < ePartialNum; p++) - { - if(m_Partial[p].resultPartialCmdBuffer != VK_NULL_HANDLE) - { - // deliberately call our own function, so this is destroyed as a wrapped object - vkFreeCommandBuffers(m_Partial[p].partialDevice, m_Partial[p].resultPartialCmdPool, 1, - &m_Partial[p].resultPartialCmdBuffer); - m_Partial[p].resultPartialCmdBuffer = VK_NULL_HANDLE; - } - } - - for(auto it = m_RerecordCmds.begin(); it != m_RerecordCmds.end(); ++it) - { - VkCommandBuffer cmd = it->second; - - // same as above (these are created in an identical way) - vkFreeCommandBuffers(GetDev(), m_InternalCmds.cmdpool, 1, &cmd); - } + vkFreeCommandBuffers(GetDev(), m_InternalCmds.cmdpool, (uint32_t)m_RerecordCmdList.size(), + m_RerecordCmdList.data()); m_RerecordCmds.clear(); + m_RerecordCmdList.clear(); return ReplayStatus::Succeeded; } @@ -2252,8 +2237,6 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay { if(!partial) { - RDCASSERT(m_Partial[Primary].resultPartialCmdBuffer == VK_NULL_HANDLE); - RDCASSERT(m_Partial[Secondary].resultPartialCmdBuffer == VK_NULL_HANDLE); m_Partial[Primary].Reset(); m_Partial[Secondary].Reset(); m_RenderState = VulkanRenderState(this, &m_CreationInfo); @@ -2269,7 +2252,7 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay // has chosen a subsection that lies within a command buffer if(partial) { - VkCommandBuffer cmd = m_Partial[Primary].outsideCmdBuffer = GetNextCmd(); + VkCommandBuffer cmd = m_OutsideCmdBuffer = GetNextCmd(); VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT}; @@ -2348,9 +2331,9 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay RDCASSERTEQUAL(status, ReplayStatus::Succeeded); - if(m_Partial[Primary].outsideCmdBuffer != VK_NULL_HANDLE) + if(m_OutsideCmdBuffer != VK_NULL_HANDLE) { - VkCommandBuffer cmd = m_Partial[Primary].outsideCmdBuffer; + VkCommandBuffer cmd = m_OutsideCmdBuffer; // check if the render pass is active - it could have become active // even if it wasn't before (if the above event was a CmdBeginRenderPass) @@ -2366,7 +2349,7 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay SubmitCmds(); - m_Partial[Primary].outsideCmdBuffer = VK_NULL_HANDLE; + m_OutsideCmdBuffer = VK_NULL_HANDLE; } #if ENABLED(SINGLE_FLUSH_VALIDATE) @@ -2548,25 +2531,15 @@ VkBool32 WrappedVulkan::DebugCallback(VkDebugReportFlagsEXT flags, return false; } -bool WrappedVulkan::ShouldRerecordCmd(ResourceId cmdid) -{ - if(m_Partial[Primary].outsideCmdBuffer != VK_NULL_HANDLE) - return true; - - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) - return true; - - return cmdid == m_Partial[Primary].partialParent || cmdid == m_Partial[Secondary].partialParent; -} - bool WrappedVulkan::InRerecordRange(ResourceId cmdid) { - if(m_Partial[Primary].outsideCmdBuffer != VK_NULL_HANDLE) - return true; - - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) + // if we have an outside command buffer, assume the range is valid and we're replaying all events + // onto it. + if(m_OutsideCmdBuffer != VK_NULL_HANDLE) return true; + // if not, check if we're one of the actual partial command buffers and check to see if we're in + // the range for their partial replay. for(int p = 0; p < ePartialNum; p++) { if(cmdid == m_Partial[p].partialParent) @@ -2576,37 +2549,45 @@ bool WrappedVulkan::InRerecordRange(ResourceId cmdid) } } + // otherwise just check if we have a re-record command buffer for this, as then we're doing a full + // re-record and replay + return m_RerecordCmds.find(cmdid) != m_RerecordCmds.end(); +} + +bool WrappedVulkan::HasRerecordCmdBuf(ResourceId cmdid) +{ + if(m_OutsideCmdBuffer != VK_NULL_HANDLE) + return true; + + return m_RerecordCmds.find(cmdid) != m_RerecordCmds.end(); +} + +bool WrappedVulkan::IsPartialCmdBuf(ResourceId cmdid) +{ + if(m_OutsideCmdBuffer != VK_NULL_HANDLE) + return true; + + for(int p = 0; p < ePartialNum; p++) + if(cmdid == m_Partial[p].partialParent) + return true; + return false; } VkCommandBuffer WrappedVulkan::RerecordCmdBuf(ResourceId cmdid, PartialReplayIndex partialType) { - if(m_Partial[Primary].outsideCmdBuffer != VK_NULL_HANDLE) - return m_Partial[Primary].outsideCmdBuffer; + if(m_OutsideCmdBuffer != VK_NULL_HANDLE) + return m_OutsideCmdBuffer; - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) + auto it = m_RerecordCmds.find(cmdid); + + if(it == m_RerecordCmds.end()) { - auto it = m_RerecordCmds.find(cmdid); - - if(it == m_RerecordCmds.end()) - { - RDCERR("Didn't generate re-record command for %llu", cmdid); - return NULL; - } - - return it->second; + RDCERR("Didn't generate re-record command for %llu", cmdid); + return NULL; } - if(partialType != ePartialNum) - return m_Partial[partialType].resultPartialCmdBuffer; - - for(int p = 0; p < ePartialNum; p++) - if(cmdid == m_Partial[p].partialParent) - return m_Partial[p].resultPartialCmdBuffer; - - RDCERR("Calling re-record for invalid command buffer id"); - - return VK_NULL_HANDLE; + return it->second; } void WrappedVulkan::AddDrawcall(const DrawcallDescription &d, bool hasEvents) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 903e6e6f9..465330938 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -168,11 +168,6 @@ struct VulkanDrawcallCallback virtual bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) = 0; virtual void PostRemisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) = 0; - // should we re-record all command buffers? this needs to be true if the range - // being replayed is larger than one command buffer (which usually means the - // whole frame). - virtual bool RecordAllCmds() = 0; - // if a command buffer is recorded once and submitted N > 1 times, then the same // drawcall will have several EIDs that refer to it. We'll only do the full // callbacks above for the first EID, then call this function for the others @@ -500,84 +495,70 @@ private: bool rebased = false; }; + // by definition, when replaying we must have N completely submitted command buffers, and at most + // two partially-submitted command buffers. One primary, that we're part-way through, and then + // if we're part-way through a vkCmdExecuteCommandBuffers inside that primary then there's one + // secondary. struct PartialReplayData { PartialReplayData() { Reset(); } void Reset() { - resultPartialCmdPool = VK_NULL_HANDLE; - resultPartialCmdBuffer = VK_NULL_HANDLE; - partialDevice = VK_NULL_HANDLE; - outsideCmdBuffer = VK_NULL_HANDLE; partialParent = ResourceId(); baseEvent = 0; renderPassActive = false; } - // if we're doing a partial replay, by definition only one command - // buffer will be partial at any one time. While replaying through - // the command buffer chunks, the partial command buffer will be - // created as a temporary new command buffer and when it comes to - // the queue that should submit it, it can submit this instead. - VkCommandPool resultPartialCmdPool; - VkCommandBuffer resultPartialCmdBuffer; - VkDevice partialDevice; // device for above cmd buffer - - // if we're replaying just a single draw or a particular command - // buffer subsection of command events, we don't go through the - // whole original command buffers to set up the partial replay, - // so we just set this command buffer - VkCommandBuffer outsideCmdBuffer; - - // this records where in the frame a command buffer was submitted, - // so that we know if our replay range ends in one of these ranges - // we need to construct a partial command buffer for future - // replaying. Note that we always have the complete command buffer - // around - it's the bakeID itself. - // Since we only ever record a bakeID once the key is unique - note - // that the same command buffer could be recorded multiple times - // a frame, so the parent command buffer ID (the one recorded in - // vkCmd chunks) is NOT unique. - // However, a single baked command list can be submitted multiple - // times - so we have to have a list of base events - // Note in the case of secondary command buffers we mark when these - // are rebased to 'absolute' event IDs, since they could be submitted - // multiple times in the frame and we don't want to rebase all of - // them each time. + // this records where in the frame a command buffer was submitted, so that we know if our replay + // range ends in one of these ranges we need to construct a partial command buffer for future + // replaying. Note that we always have the complete command buffer around - it's the bakeID + // itself. + // Since we only ever record a bakeID once the key is unique - note that the same command buffer + // could be recorded multiple times a frame, so the parent command buffer ID (the one recorded + // in vkCmd chunks) is NOT unique. + // However, a single baked command list can be submitted multiple times - so we have to have a + // list of base events + // Note in the case of secondary command buffers we mark when these are rebased to 'absolute' + // event IDs, since they could be submitted multiple times in the frame and we don't want to + // rebase all of them each time. // Map from bakeID -> vector - map > cmdBufferSubmits; + std::map > cmdBufferSubmits; - // This is just the ResourceId of the original parent command buffer - // and it's baked id. - // If we are in the middle of a partial replay - allows fast checking - // in all vkCmd chunks, with the iteration through the above list - // only in vkBegin. - // partialParent gets reset to ResourceId() in the vkEnd so that - // other baked command buffers from the same parent don't pick it up - // Also reset each overall replay + // identifies the baked ID of the command buffer that's actually partial at each level. ResourceId partialParent; - // If a partial replay is detected, this records the base of the - // range. This both allows easily and uniquely identifying it in the - // queuesubmit, but also allows the recording to 'rebase' the last - // event ID by subtracting this, to know how far to record + // the base even of the submission that's partial, as defined above in partialParent uint32_t baseEvent; - // If we're doing a partial record this bool tells us when we - // reach the vkEndCommandBuffer that we also need to end a render - // pass. + // whether a renderpass is currently active in the partial recording - as with baseEvent, only + // valid for the command buffer referred to by partialParent. bool renderPassActive; } m_Partial[ePartialNum]; - map m_RerecordCmds; + // if we're replaying just a single draw or a particular command + // buffer subsection of command events, we don't go through the + // whole original command buffers to set up the partial replay, + // so we just set this command buffer + VkCommandBuffer m_OutsideCmdBuffer = VK_NULL_HANDLE; + + // stores the currently re-recording command buffer for any original command buffer ID (not bake + // ID). This allows a quick check to see if an original command should be recorded, and also to + // fetch the command buffer to record into. + std::map m_RerecordCmds; + + // we store the list here, since we need to keep all command buffers until the whole replay is + // finished, but if a command buffer is re-recorded multiple times it would be overwritten in the + // above map + std::vector m_RerecordCmdList; // There is only a state while currently partially replaying, it's // undefined/empty otherwise. // All IDs are original IDs, not live. VulkanRenderState m_RenderState; - bool ShouldRerecordCmd(ResourceId cmdid); bool InRerecordRange(ResourceId cmdid); + bool HasRerecordCmdBuf(ResourceId cmdid); + bool IsPartialCmdBuf(ResourceId cmdid); VkCommandBuffer RerecordCmdBuf(ResourceId cmdid, PartialReplayIndex partialType = ePartialNum); // this info is stored in the record on capture, but we diff --git a/renderdoc/driver/vulkan/vk_counters.cpp b/renderdoc/driver/vulkan/vk_counters.cpp index 80fb67ed2..62a90afea 100644 --- a/renderdoc/driver/vulkan/vk_counters.cpp +++ b/renderdoc/driver/vulkan/vk_counters.cpp @@ -234,7 +234,6 @@ struct VulkanGPUTimerCallback : public VulkanDrawcallCallback void PreMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { PreDraw(eid, cmd); } bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { return PostDraw(eid, cmd); } void PostRemisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { PostRedraw(eid, cmd); } - bool RecordAllCmds() { return true; } void AliasEvent(uint32_t primary, uint32_t alias) { m_AliasEvents.push_back(std::make_pair(primary, alias)); diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 4406027b9..448c58a91 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -5026,7 +5026,6 @@ struct VulkanQuadOverdrawCallback : public VulkanDrawcallCallback void PreMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) {} bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { return false; } void PostRemisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) {} - bool RecordAllCmds() { return false; } void AliasEvent(uint32_t primary, uint32_t alias) { // don't care diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index b2275a92c..91aece1a2 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -4295,7 +4295,6 @@ struct VulkanInitPostVSCallback : public VulkanDrawcallCallback void PreMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) {} bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) { return false; } void PostRemisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd) {} - bool RecordAllCmds() { return false; } void AliasEvent(uint32_t primary, uint32_t alias) { if(std::find(m_Events.begin(), m_Events.end(), primary) != m_Events.end()) diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 55dd4ace2..c910a0648 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -28,7 +28,7 @@ std::vector WrappedVulkan::GetImplicitRenderPassBarriers(u { ResourceId rp, fb; - if(IsActiveReplaying(m_State)) + if(m_LastCmdBufferID == ResourceId()) { rp = m_RenderState.renderPass; fb = m_RenderState.framebuffer; @@ -62,7 +62,7 @@ std::vector WrappedVulkan::GetImplicitRenderPassBarriers(u } else { - if(IsActiveReplaying(m_State)) + if(m_LastCmdBufferID == ResourceId()) subpass = m_RenderState.subpass; else subpass = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass; @@ -585,6 +585,7 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman { const uint32_t length = m_BakedCmdBufferInfo[BakedCommandBuffer].eventCount; + bool rerecord = false; bool partial = false; int partialType = ePartialNum; @@ -606,23 +607,29 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman m_Partial[p].partialParent = BakedCommandBuffer; m_Partial[p].baseEvent = it->baseEvent; m_Partial[p].renderPassActive = false; - m_Partial[p].partialDevice = device; - m_Partial[p].resultPartialCmdPool = AllocateInfo.commandPool; + rerecord = true; partial = true; partialType = p; } + else if(it->baseEvent <= m_LastEventID) + { +#if ENABLED(VERBOSE_PARTIAL_REPLAY) + RDCDEBUG("vkBegin - full re-record detected %u < %u <= %u, %llu -> %llu", it->baseEvent, + it->baseEvent + length, m_LastEventID, m_LastCmdBufferID, BakedCommandBuffer); +#endif + + // this submission is completely within the range, so it should still be re-recorded + rerecord = true; + } } } - if(partial || (m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds())) + if(rerecord) { // pull all re-recorded commands from our own device and command pool for easier cleanup - if(!partial) - { - device = GetDev(); - AllocateInfo.commandPool = m_InternalCmds.cmdpool; - } + device = GetDev(); + AllocateInfo.commandPool = m_InternalCmds.cmdpool; VkCommandBuffer cmd = VK_NULL_HANDLE; VkCommandBufferAllocateInfo unwrappedInfo = AllocateInfo; @@ -639,24 +646,19 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman GetResourceManager()->WrapResource(Unwrap(device), cmd); } - if(partial) - { - m_Partial[partialType].resultPartialCmdBuffer = cmd; - } - else - { - // we store under both baked and non baked ID. - // The baked ID is the 'real' entry, the non baked is simply so it - // can be found in the subsequent serialised commands that ref the - // non-baked ID. The baked ID is referenced by the submit itself. - // - // In vkEndCommandBuffer we erase the non-baked reference, and since - // we know you can only be recording a command buffer once at a time - // (even if it's baked to several command buffers in the frame) - // there's no issue with clashes here. - m_RerecordCmds[BakedCommandBuffer] = cmd; - m_RerecordCmds[m_LastCmdBufferID] = cmd; - } + // we store under both baked and non baked ID. + // The baked ID is the 'real' entry, the non baked is simply so it + // can be found in the subsequent serialised commands that ref the + // non-baked ID. The baked ID is referenced by the submit itself. + // + // In vkEndCommandBuffer we erase the non-baked reference, and since + // we know you can only be recording a command buffer once at a time + // (even if it's baked to several command buffers in the frame) + // there's no issue with clashes here. + m_RerecordCmds[BakedCommandBuffer] = cmd; + m_RerecordCmds[m_LastCmdBufferID] = cmd; + + m_RerecordCmdList.push_back(cmd); m_BakedCmdBufferInfo[GetResID(cmd)].level = AllocateInfo.level; m_BakedCmdBufferInfo[GetResID(cmd)].beginFlags = BeginInfo.flags; @@ -834,17 +836,17 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(SerialiserType &ser, VkCommandB if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(BakedCommandBuffer)) + if(HasRerecordCmdBuf(BakedCommandBuffer)) { commandBuffer = RerecordCmdBuf(BakedCommandBuffer); + #if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Ending partial command buffer for %llu baked to %llu", m_LastCmdBufferID, + RDCDEBUG("Ending re-recorded command buffer for %llu baked to %llu", m_LastCmdBufferID, BakedCommandBuffer); #endif - bool recordAll = m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds(); - - if(!recordAll && m_Partial[Primary].partialParent == BakedCommandBuffer && + // finish any render pass that was still active in the primary partial parent + if(m_Partial[Primary].partialParent == BakedCommandBuffer && m_Partial[Primary].renderPassActive) { uint32_t numSubpasses = @@ -856,16 +858,13 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(SerialiserType &ser, VkCommandB ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer)); } + // also finish any nested markers we truncated and didn't finish if(ObjDisp(commandBuffer)->CmdDebugMarkerEndEXT) for(int i = 0; i < m_BakedCmdBufferInfo[BakedCommandBuffer].markerCount; i++) ObjDisp(commandBuffer)->CmdDebugMarkerEndEXT(Unwrap(commandBuffer)); ObjDisp(commandBuffer)->EndCommandBuffer(Unwrap(commandBuffer)); - // erase the non-baked reference to this command buffer so that we don't have - // duplicates when it comes time to clean up. See above in vkBeginCommandBuffer - m_RerecordCmds.erase(m_LastCmdBufferID); - if(m_Partial[Primary].partialParent == BakedCommandBuffer) m_Partial[Primary].partialParent = ResourceId(); } @@ -990,19 +989,31 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - m_Partial[Primary].renderPassActive = true; + // always track this, for WrappedVulkan::IsDrawInRenderPass() + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass = 0; + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = + GetResID(RenderPassBegin.renderPass); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer = + GetResID(RenderPassBegin.framebuffer); + + // only if we're partially recording do we update this state + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + m_Partial[Primary].renderPassActive = true; + + m_RenderState.subpass = 0; + + m_RenderState.renderPass = GetResID(RenderPassBegin.renderPass); + m_RenderState.framebuffer = GetResID(RenderPassBegin.framebuffer); + m_RenderState.renderArea = RenderPassBegin.renderArea; + } + ObjDisp(commandBuffer)->CmdBeginRenderPass(Unwrap(commandBuffer), &unwrappedInfo, contents); - m_RenderState.subpass = 0; - - m_RenderState.renderPass = GetResID(RenderPassBegin.renderPass); - m_RenderState.framebuffer = GetResID(RenderPassBegin.framebuffer); - m_RenderState.renderArea = RenderPassBegin.renderArea; - std::vector imgBarriers = GetImplicitRenderPassBarriers(); ResourceId cmd = GetResID(commandBuffer); @@ -1103,12 +1114,15 @@ bool WrappedVulkan::Serialise_vkCmdNextSubpass(SerialiserType &ser, VkCommandBuf { // don't do anything if we're executing a single draw, NextSubpass is meaningless (and invalid // on a partial render pass) - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID) && - m_FirstEventID != m_LastEventID) + if(InRerecordRange(m_LastCmdBufferID) && m_FirstEventID != m_LastEventID) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - m_RenderState.subpass++; + // always track this, for WrappedVulkan::IsDrawInRenderPass() + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass++; + + if(IsPartialCmdBuf(m_LastCmdBufferID)) + m_RenderState.subpass++; ObjDisp(commandBuffer)->CmdNextSubpass(Unwrap(commandBuffer), contents); @@ -1179,11 +1193,19 @@ bool WrappedVulkan::Serialise_vkCmdEndRenderPass(SerialiserType &ser, VkCommandB if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - m_Partial[Primary].renderPassActive = false; + // always track this, for WrappedVulkan::IsDrawInRenderPass() + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass = ResourceId(); + m_BakedCmdBufferInfo[m_LastCmdBufferID].state.framebuffer = ResourceId(); + + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + m_Partial[Primary].renderPassActive = false; + } + ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer)); std::vector imgBarriers = GetImplicitRenderPassBarriers(~0U); @@ -1277,62 +1299,65 @@ bool WrappedVulkan::Serialise_vkCmdBindPipeline(SerialiserType &ser, VkCommandBu if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); ResourceId liveid = GetResID(pipeline); - if(pipelineBindPoint == VK_PIPELINE_BIND_POINT_COMPUTE) + if(IsPartialCmdBuf(m_LastCmdBufferID)) { - m_RenderState.compute.pipeline = liveid; - } - else - { - m_RenderState.graphics.pipeline = liveid; + if(pipelineBindPoint == VK_PIPELINE_BIND_POINT_COMPUTE) + { + m_RenderState.compute.pipeline = liveid; + } + else + { + m_RenderState.graphics.pipeline = liveid; - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_VIEWPORT]) - { - m_RenderState.views = m_CreationInfo.m_Pipeline[liveid].viewports; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_SCISSOR]) - { - m_RenderState.scissors = m_CreationInfo.m_Pipeline[liveid].scissors; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_LINE_WIDTH]) - { - m_RenderState.lineWidth = m_CreationInfo.m_Pipeline[liveid].lineWidth; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BIAS]) - { - m_RenderState.bias.depth = m_CreationInfo.m_Pipeline[liveid].depthBiasConstantFactor; - m_RenderState.bias.biasclamp = m_CreationInfo.m_Pipeline[liveid].depthBiasClamp; - m_RenderState.bias.slope = m_CreationInfo.m_Pipeline[liveid].depthBiasSlopeFactor; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_BLEND_CONSTANTS]) - { - memcpy(m_RenderState.blendConst, m_CreationInfo.m_Pipeline[liveid].blendConst, - sizeof(float) * 4); - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BOUNDS]) - { - m_RenderState.mindepth = m_CreationInfo.m_Pipeline[liveid].minDepthBounds; - m_RenderState.maxdepth = m_CreationInfo.m_Pipeline[liveid].maxDepthBounds; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK]) - { - m_RenderState.front.compare = m_CreationInfo.m_Pipeline[liveid].front.compareMask; - m_RenderState.back.compare = m_CreationInfo.m_Pipeline[liveid].back.compareMask; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK]) - { - m_RenderState.front.write = m_CreationInfo.m_Pipeline[liveid].front.writeMask; - m_RenderState.back.write = m_CreationInfo.m_Pipeline[liveid].back.writeMask; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_REFERENCE]) - { - m_RenderState.front.ref = m_CreationInfo.m_Pipeline[liveid].front.reference; - m_RenderState.back.ref = m_CreationInfo.m_Pipeline[liveid].back.reference; + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_VIEWPORT]) + { + m_RenderState.views = m_CreationInfo.m_Pipeline[liveid].viewports; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_SCISSOR]) + { + m_RenderState.scissors = m_CreationInfo.m_Pipeline[liveid].scissors; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_LINE_WIDTH]) + { + m_RenderState.lineWidth = m_CreationInfo.m_Pipeline[liveid].lineWidth; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BIAS]) + { + m_RenderState.bias.depth = m_CreationInfo.m_Pipeline[liveid].depthBiasConstantFactor; + m_RenderState.bias.biasclamp = m_CreationInfo.m_Pipeline[liveid].depthBiasClamp; + m_RenderState.bias.slope = m_CreationInfo.m_Pipeline[liveid].depthBiasSlopeFactor; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_BLEND_CONSTANTS]) + { + memcpy(m_RenderState.blendConst, m_CreationInfo.m_Pipeline[liveid].blendConst, + sizeof(float) * 4); + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BOUNDS]) + { + m_RenderState.mindepth = m_CreationInfo.m_Pipeline[liveid].minDepthBounds; + m_RenderState.maxdepth = m_CreationInfo.m_Pipeline[liveid].maxDepthBounds; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK]) + { + m_RenderState.front.compare = m_CreationInfo.m_Pipeline[liveid].front.compareMask; + m_RenderState.back.compare = m_CreationInfo.m_Pipeline[liveid].back.compareMask; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK]) + { + m_RenderState.front.write = m_CreationInfo.m_Pipeline[liveid].front.writeMask; + m_RenderState.back.write = m_CreationInfo.m_Pipeline[liveid].back.writeMask; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_REFERENCE]) + { + m_RenderState.front.ref = m_CreationInfo.m_Pipeline[liveid].front.reference; + m_RenderState.back.ref = m_CreationInfo.m_Pipeline[liveid].back.reference; + } } } } @@ -1401,7 +1426,7 @@ bool WrappedVulkan::Serialise_vkCmdBindDescriptorSets( if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1410,64 +1435,68 @@ bool WrappedVulkan::Serialise_vkCmdBindDescriptorSets( firstSet, setCount, UnwrapArray(pDescriptorSets, setCount), dynamicOffsetCount, pDynamicOffsets); - std::vector &descsets = - (pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) ? m_RenderState.graphics.descSets - : m_RenderState.compute.descSets; - - // expand as necessary - if(descsets.size() < firstSet + setCount) - descsets.resize(firstSet + setCount); - - const std::vector &descSetLayouts = - m_CreationInfo.m_PipelineLayout[GetResID(layout)].descSetLayouts; - - const uint32_t *offsIter = pDynamicOffsets; - uint32_t dynConsumed = 0; - - // consume the offsets linearly along the descriptor set layouts - for(uint32_t i = 0; i < setCount; i++) + if(IsPartialCmdBuf(m_LastCmdBufferID)) { - descsets[firstSet + i].descSet = GetResID(pDescriptorSets[i]); - uint32_t dynCount = - m_CreationInfo.m_DescSetLayout[descSetLayouts[firstSet + i]].dynamicCount; - descsets[firstSet + i].offsets.assign(offsIter, offsIter + dynCount); - offsIter += dynCount; - dynConsumed += dynCount; - RDCASSERT(dynConsumed <= dynamicOffsetCount); - } + std::vector &descsets = + (pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) + ? m_RenderState.graphics.descSets + : m_RenderState.compute.descSets; - // if there are dynamic offsets, bake them into the current bindings by alias'ing - // the image layout member (which is never used for buffer views). - // This lets us look it up easily when we want to show the current pipeline state - RDCCOMPILE_ASSERT(sizeof(VkImageLayout) >= sizeof(uint32_t), - "Can't alias image layout for dynamic offset!"); - if(dynamicOffsetCount > 0) - { - uint32_t o = 0; + // expand as necessary + if(descsets.size() < firstSet + setCount) + descsets.resize(firstSet + setCount); - // spec states that dynamic offsets precisely match all the offsets needed for these - // sets, in order of set N before set N+1, binding X before binding X+1 within a set, - // and in array element order within a binding + const std::vector &descSetLayouts = + m_CreationInfo.m_PipelineLayout[GetResID(layout)].descSetLayouts; + + const uint32_t *offsIter = pDynamicOffsets; + uint32_t dynConsumed = 0; + + // consume the offsets linearly along the descriptor set layouts for(uint32_t i = 0; i < setCount; i++) { - ResourceId descId = GetResID(pDescriptorSets[i]); - const DescSetLayout &layoutinfo = - m_CreationInfo.m_DescSetLayout[descSetLayouts[firstSet + i]]; + descsets[firstSet + i].descSet = GetResID(pDescriptorSets[i]); + uint32_t dynCount = + m_CreationInfo.m_DescSetLayout[descSetLayouts[firstSet + i]].dynamicCount; + descsets[firstSet + i].offsets.assign(offsIter, offsIter + dynCount); + offsIter += dynCount; + dynConsumed += dynCount; + RDCASSERT(dynConsumed <= dynamicOffsetCount); + } - for(size_t b = 0; b < layoutinfo.bindings.size(); b++) + // if there are dynamic offsets, bake them into the current bindings by alias'ing + // the image layout member (which is never used for buffer views). + // This lets us look it up easily when we want to show the current pipeline state + RDCCOMPILE_ASSERT(sizeof(VkImageLayout) >= sizeof(uint32_t), + "Can't alias image layout for dynamic offset!"); + if(dynamicOffsetCount > 0) + { + uint32_t o = 0; + + // spec states that dynamic offsets precisely match all the offsets needed for these + // sets, in order of set N before set N+1, binding X before binding X+1 within a set, + // and in array element order within a binding + for(uint32_t i = 0; i < setCount; i++) { - // not dynamic, doesn't need an offset - if(layoutinfo.bindings[b].descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC && - layoutinfo.bindings[b].descriptorType != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) - continue; + ResourceId descId = GetResID(pDescriptorSets[i]); + const DescSetLayout &layoutinfo = + m_CreationInfo.m_DescSetLayout[descSetLayouts[firstSet + i]]; - // assign every array element an offset according to array size - for(uint32_t a = 0; a < layoutinfo.bindings[b].descriptorCount; a++) + for(size_t b = 0; b < layoutinfo.bindings.size(); b++) { - RDCASSERT(o < dynamicOffsetCount); - uint32_t *alias = - (uint32_t *)&m_DescriptorSetState[descId].currentBindings[b][a].imageInfo.imageLayout; - *alias = pDynamicOffsets[o++]; + // not dynamic, doesn't need an offset + if(layoutinfo.bindings[b].descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC && + layoutinfo.bindings[b].descriptorType != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) + continue; + + // assign every array element an offset according to array size + for(uint32_t a = 0; a < layoutinfo.bindings[b].descriptorCount; a++) + { + RDCASSERT(o < dynamicOffsetCount); + uint32_t *alias = + (uint32_t *)&m_DescriptorSetState[descId].currentBindings[b][a].imageInfo.imageLayout; + *alias = pDynamicOffsets[o++]; + } } } } @@ -1572,20 +1601,23 @@ bool WrappedVulkan::Serialise_vkCmdBindVertexBuffers(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); ObjDisp(commandBuffer) ->CmdBindVertexBuffers(Unwrap(commandBuffer), firstBinding, bindingCount, UnwrapArray(pBuffers, bindingCount), pOffsets); - if(m_RenderState.vbuffers.size() < firstBinding + bindingCount) - m_RenderState.vbuffers.resize(firstBinding + bindingCount); - - for(uint32_t i = 0; i < bindingCount; i++) + if(IsPartialCmdBuf(m_LastCmdBufferID)) { - m_RenderState.vbuffers[firstBinding + i].buf = GetResID(pBuffers[i]); - m_RenderState.vbuffers[firstBinding + i].offs = pOffsets[i]; + if(m_RenderState.vbuffers.size() < firstBinding + bindingCount) + m_RenderState.vbuffers.resize(firstBinding + bindingCount); + + for(uint32_t i = 0; i < bindingCount; i++) + { + m_RenderState.vbuffers[firstBinding + i].buf = GetResID(pBuffers[i]); + m_RenderState.vbuffers[firstBinding + i].offs = pOffsets[i]; + } } } } @@ -1659,15 +1691,18 @@ bool WrappedVulkan::Serialise_vkCmdBindIndexBuffer(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); ObjDisp(commandBuffer) ->CmdBindIndexBuffer(Unwrap(commandBuffer), Unwrap(buffer), offset, indexType); - m_RenderState.ibuffer.buf = GetResID(buffer); - m_RenderState.ibuffer.offs = offset; - m_RenderState.ibuffer.bytewidth = indexType == VK_INDEX_TYPE_UINT32 ? 4 : 2; + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + m_RenderState.ibuffer.buf = GetResID(buffer); + m_RenderState.ibuffer.offs = offset; + m_RenderState.ibuffer.bytewidth = indexType == VK_INDEX_TYPE_UINT32 ? 4 : 2; + } } } else @@ -1735,7 +1770,7 @@ bool WrappedVulkan::Serialise_vkCmdUpdateBuffer(SerialiserType &ser, VkCommandBu if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -1805,7 +1840,7 @@ bool WrappedVulkan::Serialise_vkCmdFillBuffer(SerialiserType &ser, VkCommandBuff if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -1876,16 +1911,19 @@ bool WrappedVulkan::Serialise_vkCmdPushConstants(SerialiserType &ser, VkCommandB if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); ObjDisp(commandBuffer) ->CmdPushConstants(Unwrap(commandBuffer), Unwrap(layout), stageFlags, start, length, values); - RDCASSERT(start + length < (uint32_t)ARRAY_COUNT(m_RenderState.pushconsts)); + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + RDCASSERT(start + length < (uint32_t)ARRAY_COUNT(m_RenderState.pushconsts)); - memcpy(m_RenderState.pushconsts + start, values, length); + memcpy(m_RenderState.pushconsts + start, values, length); + } } } else @@ -1989,7 +2027,7 @@ bool WrappedVulkan::Serialise_vkCmdPipelineBarrier( if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -2090,7 +2128,7 @@ bool WrappedVulkan::Serialise_vkCmdWriteTimestamp(SerialiserType &ser, VkCommand if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -2156,7 +2194,7 @@ bool WrappedVulkan::Serialise_vkCmdCopyQueryPoolResults( if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -2230,7 +2268,7 @@ bool WrappedVulkan::Serialise_vkCmdBeginQuery(SerialiserType &ser, VkCommandBuff if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -2283,7 +2321,7 @@ bool WrappedVulkan::Serialise_vkCmdEndQuery(SerialiserType &ser, VkCommandBuffer if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -2337,7 +2375,7 @@ bool WrappedVulkan::Serialise_vkCmdResetQueryPool(SerialiserType &ser, VkCommand if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -2480,7 +2518,7 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman } else { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -2526,43 +2564,15 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman RDCDEBUG("ExecuteCommands no replay %u == %u", m_LastEventID, startEID); #endif } - else if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) + else { #if ENABLED(VERBOSE_PARTIAL_REPLAY) RDCDEBUG("ExecuteCommands re-recording from %u", startEID); #endif - std::vector rerecordedCmds; - - for(uint32_t c = 0; c < commandBufferCount; c++) - { - ResourceId cmdid = GetResourceManager()->GetOriginalID(GetResID(pCommandBuffers[c])); - VkCommandBuffer cmd = RerecordCmdBuf(cmdid); - ResourceId rerecord = GetResID(cmd); -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("ExecuteCommands fully re-recorded replay of %llu, using %llu", cmdid, rerecord); -#endif - rerecordedCmds.push_back(Unwrap(cmd)); - - GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[rerecord].imgbarriers, - m_ImageLayouts); - } - - ObjDisp(commandBuffer) - ->CmdExecuteCommands(Unwrap(commandBuffer), commandBufferCount, &rerecordedCmds[0]); - } - else if(m_LastEventID > startEID && - m_LastEventID < parentCmdBufInfo.curEventID + m_Partial[Primary].baseEvent) - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("ExecuteCommands partial replay %u < %u", m_LastEventID, - parentCmdBufInfo.curEventID + m_Partial[Primary].baseEvent); -#endif - uint32_t eid = startEID; - std::vector trimmedCmdIds; - std::vector trimmedCmds; + std::vector rerecordedCmds; for(uint32_t c = 0; c < commandBufferCount; c++) { @@ -2572,26 +2582,22 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman // so it matches up to baseEvent eid++; +#if ENABLED(VERBOSE_PARTIAL_REPLAY) uint32_t end = eid + m_BakedCmdBufferInfo[cmdid].eventCount; +#endif - if(eid == m_Partial[Secondary].baseEvent) + if(eid <= m_LastEventID) { - ResourceId partial = GetResID(RerecordCmdBuf(cmdid, Secondary)); + VkCommandBuffer cmd = RerecordCmdBuf(cmdid); + ResourceId rerecord = GetResID(cmd); #if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("ExecuteCommands partial replay of %llu at %u, using %llu", cmdid, eid, - partial); + RDCDEBUG("ExecuteCommands re-recorded replay of %llu, using %llu (%u -> %u <= %u)", + cmdid, rerecord, eid, end, m_LastEventID); #endif - trimmedCmdIds.push_back(partial); - trimmedCmds.push_back(Unwrap(RerecordCmdBuf(cmdid, Secondary))); - } - else if(m_LastEventID >= end) - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("ExecuteCommands full replay %llu", cmdid); -#endif - trimmedCmdIds.push_back(cmdid); - trimmedCmds.push_back( - Unwrap(GetResourceManager()->GetLiveHandle(cmdid))); + rerecordedCmds.push_back(Unwrap(cmd)); + + GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[rerecord].imgbarriers, + m_ImageLayouts); } else { @@ -2605,35 +2611,10 @@ bool WrappedVulkan::Serialise_vkCmdExecuteCommands(SerialiserType &ser, VkComman eid += 1 + m_BakedCmdBufferInfo[cmdid].eventCount; } - if(trimmedCmds.size() > 0) + if(!rerecordedCmds.empty()) ObjDisp(commandBuffer) - ->CmdExecuteCommands(Unwrap(commandBuffer), (uint32_t)trimmedCmds.size(), - &trimmedCmds[0]); - - for(uint32_t i = 0; i < trimmedCmdIds.size(); i++) - { - ResourceId cmd = trimmedCmdIds[i]; - GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, - m_ImageLayouts); - } - } - else - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("ExecuteCommands full replay %u >= %u", m_LastEventID, - parentCmdBufInfo.curEventID + m_Partial[Primary].baseEvent); -#endif - - // execute the commands - ObjDisp(commandBuffer) - ->CmdExecuteCommands(Unwrap(commandBuffer), commandBufferCount, - UnwrapArray(pCommandBuffers, commandBufferCount)); - - for(uint32_t i = 0; i < commandBufferCount; i++) - { - GetResourceManager()->ApplyBarriers( - m_BakedCmdBufferInfo[GetResID(pCommandBuffers[i])].imgbarriers, m_ImageLayouts); - } + ->CmdExecuteCommands(Unwrap(commandBuffer), (uint32_t)rerecordedCmds.size(), + &rerecordedCmds[0]); } } } @@ -2697,7 +2678,7 @@ bool WrappedVulkan::Serialise_vkCmdDebugMarkerBeginEXT(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -2764,7 +2745,7 @@ bool WrappedVulkan::Serialise_vkCmdDebugMarkerEndEXT(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -2838,7 +2819,7 @@ bool WrappedVulkan::Serialise_vkCmdDebugMarkerInsertEXT(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp index 4cfc42725..202ff3e81 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp @@ -27,40 +27,25 @@ bool WrappedVulkan::IsDrawInRenderPass() { - ResourceId rp; + BakedCmdBufferInfo &cmd = m_BakedCmdBufferInfo[m_LastCmdBufferID]; - if(IsLoading(m_State)) - rp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass; - else - rp = m_RenderState.renderPass; - - ResourceId cmdid = m_LastCmdBufferID; - - bool rpActive = true; - - if(IsActiveReplaying(m_State)) - { - cmdid = GetResID(RerecordCmdBuf(cmdid)); - - rpActive = - m_Partial[m_BakedCmdBufferInfo[cmdid].level == VK_COMMAND_BUFFER_LEVEL_PRIMARY ? Primary : Secondary] - .renderPassActive; - } - - if(m_BakedCmdBufferInfo[cmdid].level == VK_COMMAND_BUFFER_LEVEL_PRIMARY && - (rp == ResourceId() || !rpActive)) + if(cmd.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY && cmd.state.renderPass == ResourceId()) { + // for primary command buffers, we just check the per-command buffer tracked state return false; } - else if(m_BakedCmdBufferInfo[cmdid].level == VK_COMMAND_BUFFER_LEVEL_SECONDARY && - (m_BakedCmdBufferInfo[cmdid].beginFlags & - VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) == 0 && - (rp == ResourceId() || !rpActive)) + else if(cmd.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY && + (cmd.beginFlags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) == 0) { + // secondary command buffers the VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT bit is + // one-to-one with being a render pass. i.e. you must specify the bit if the execute comes from + // inside a render pass, and you can't start a render pass in a secondary command buffer so + // that's the only way to be inside. return false; } - // assume a secondary buffer with RENDER_PASS_CONTINUE_BIT is in a render pass. + // assume a secondary buffer with RENDER_PASS_CONTINUE_BIT is in a render pass without checking + // where it was actually executed since we won't know that yet. return true; } @@ -86,8 +71,7 @@ bool WrappedVulkan::Serialise_vkCmdDraw(SerialiserType &ser, VkCommandBuffer com if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID) && - IsDrawInRenderPass()) + if(InRerecordRange(m_LastCmdBufferID) && IsDrawInRenderPass()) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -185,8 +169,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexed(SerialiserType &ser, VkCommandBuf if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID) && - IsDrawInRenderPass()) + if(InRerecordRange(m_LastCmdBufferID) && IsDrawInRenderPass()) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -293,8 +276,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(SerialiserType &ser, VkCommandBu { // for single draws, it's pretty simple - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID) && - IsDrawInRenderPass()) + if(InRerecordRange(m_LastCmdBufferID) && IsDrawInRenderPass()) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -313,7 +295,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(SerialiserType &ser, VkCommandBu } else { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -340,8 +322,8 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(SerialiserType &ser, VkCommandBu { uint32_t baseEventID = it->eventID; - // when re-recording all, submit every drawcall individually to the callback - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds() && IsDrawInRenderPass()) + // when we have a callback, submit every drawcall individually to the callback + if(m_DrawcallCallback && IsDrawInRenderPass()) { for(uint32_t i = 0; i < count; i++) { @@ -579,8 +561,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(SerialiserType &ser, { // for single draws, it's pretty simple - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID) && - IsDrawInRenderPass()) + if(InRerecordRange(m_LastCmdBufferID) && IsDrawInRenderPass()) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -600,7 +581,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(SerialiserType &ser, } else { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -627,8 +608,8 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(SerialiserType &ser, { uint32_t baseEventID = it->eventID; - // when re-recording all, submit every drawcall individually to the callback - if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds() && IsDrawInRenderPass()) + // when we have a callback, submit every drawcall individually to the callback + if(m_DrawcallCallback && IsDrawInRenderPass()) { for(uint32_t i = 0; i < count; i++) { @@ -861,7 +842,7 @@ bool WrappedVulkan::Serialise_vkCmdDispatch(SerialiserType &ser, VkCommandBuffer if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -938,7 +919,7 @@ bool WrappedVulkan::Serialise_vkCmdDispatchIndirect(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1046,7 +1027,7 @@ bool WrappedVulkan::Serialise_vkCmdBlitImage(SerialiserType &ser, VkCommandBuffe if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1169,7 +1150,7 @@ bool WrappedVulkan::Serialise_vkCmdResolveImage(SerialiserType &ser, VkCommandBu if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1292,7 +1273,7 @@ bool WrappedVulkan::Serialise_vkCmdCopyImage(SerialiserType &ser, VkCommandBuffe if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1411,7 +1392,7 @@ bool WrappedVulkan::Serialise_vkCmdCopyBufferToImage( if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1525,7 +1506,7 @@ bool WrappedVulkan::Serialise_vkCmdCopyImageToBuffer(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1640,7 +1621,7 @@ bool WrappedVulkan::Serialise_vkCmdCopyBuffer(SerialiserType &ser, VkCommandBuff if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1764,7 +1745,7 @@ bool WrappedVulkan::Serialise_vkCmdClearColorImage(SerialiserType &ser, VkComman if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1867,7 +1848,7 @@ bool WrappedVulkan::Serialise_vkCmdClearDepthStencilImage( if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); @@ -1972,7 +1953,7 @@ bool WrappedVulkan::Serialise_vkCmdClearAttachments(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); diff --git a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp index 062e8ab81..2036c838e 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp @@ -43,15 +43,18 @@ bool WrappedVulkan::Serialise_vkCmdSetViewport(SerialiserType &ser, VkCommandBuf if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - if(m_RenderState.views.size() < firstViewport + viewportCount) - m_RenderState.views.resize(firstViewport + viewportCount); + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + if(m_RenderState.views.size() < firstViewport + viewportCount) + m_RenderState.views.resize(firstViewport + viewportCount); - for(uint32_t i = 0; i < viewportCount; i++) - m_RenderState.views[firstViewport + i] = pViewports[i]; + for(uint32_t i = 0; i < viewportCount; i++) + m_RenderState.views[firstViewport + i] = pViewports[i]; + } } else { @@ -108,15 +111,18 @@ bool WrappedVulkan::Serialise_vkCmdSetScissor(SerialiserType &ser, VkCommandBuff if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - if(m_RenderState.scissors.size() < firstScissor + scissorCount) - m_RenderState.scissors.resize(firstScissor + scissorCount); + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + if(m_RenderState.scissors.size() < firstScissor + scissorCount) + m_RenderState.scissors.resize(firstScissor + scissorCount); - for(uint32_t i = 0; i < scissorCount; i++) - m_RenderState.scissors[firstScissor + i] = pScissors[i]; + for(uint32_t i = 0; i < scissorCount; i++) + m_RenderState.scissors[firstScissor + i] = pScissors[i]; + } } else { @@ -170,11 +176,12 @@ bool WrappedVulkan::Serialise_vkCmdSetLineWidth(SerialiserType &ser, VkCommandBu if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - m_RenderState.lineWidth = lineWidth; + if(IsPartialCmdBuf(m_LastCmdBufferID)) + m_RenderState.lineWidth = lineWidth; } else { @@ -228,13 +235,16 @@ bool WrappedVulkan::Serialise_vkCmdSetDepthBias(SerialiserType &ser, VkCommandBu if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - m_RenderState.bias.depth = depthBias; - m_RenderState.bias.biasclamp = depthBiasClamp; - m_RenderState.bias.slope = slopeScaledDepthBias; + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + m_RenderState.bias.depth = depthBias; + m_RenderState.bias.biasclamp = depthBiasClamp; + m_RenderState.bias.slope = slopeScaledDepthBias; + } } else { @@ -290,11 +300,12 @@ bool WrappedVulkan::Serialise_vkCmdSetBlendConstants(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - memcpy(m_RenderState.blendConst, blendConst, sizeof(m_RenderState.blendConst)); + if(IsPartialCmdBuf(m_LastCmdBufferID)) + memcpy(m_RenderState.blendConst, blendConst, sizeof(m_RenderState.blendConst)); } else { @@ -346,12 +357,15 @@ bool WrappedVulkan::Serialise_vkCmdSetDepthBounds(SerialiserType &ser, VkCommand if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - m_RenderState.mindepth = minDepthBounds; - m_RenderState.maxdepth = maxDepthBounds; + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + m_RenderState.mindepth = minDepthBounds; + m_RenderState.maxdepth = maxDepthBounds; + } } else { @@ -407,14 +421,17 @@ bool WrappedVulkan::Serialise_vkCmdSetStencilCompareMask(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - if(faceMask & VK_STENCIL_FACE_FRONT_BIT) - m_RenderState.front.compare = compareMask; - if(faceMask & VK_STENCIL_FACE_BACK_BIT) - m_RenderState.back.compare = compareMask; + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + if(faceMask & VK_STENCIL_FACE_FRONT_BIT) + m_RenderState.front.compare = compareMask; + if(faceMask & VK_STENCIL_FACE_BACK_BIT) + m_RenderState.back.compare = compareMask; + } } else { @@ -470,14 +487,17 @@ bool WrappedVulkan::Serialise_vkCmdSetStencilWriteMask(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - if(faceMask & VK_STENCIL_FACE_FRONT_BIT) - m_RenderState.front.write = writeMask; - if(faceMask & VK_STENCIL_FACE_BACK_BIT) - m_RenderState.back.write = writeMask; + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + if(faceMask & VK_STENCIL_FACE_FRONT_BIT) + m_RenderState.front.write = writeMask; + if(faceMask & VK_STENCIL_FACE_BACK_BIT) + m_RenderState.back.write = writeMask; + } } else { @@ -533,14 +553,17 @@ bool WrappedVulkan::Serialise_vkCmdSetStencilReference(SerialiserType &ser, if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) { commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); - if(faceMask & VK_STENCIL_FACE_FRONT_BIT) - m_RenderState.front.ref = reference; - if(faceMask & VK_STENCIL_FACE_BACK_BIT) - m_RenderState.back.ref = reference; + if(IsPartialCmdBuf(m_LastCmdBufferID)) + { + if(faceMask & VK_STENCIL_FACE_FRONT_BIT) + m_RenderState.front.ref = reference; + if(faceMask & VK_STENCIL_FACE_BACK_BIT) + m_RenderState.back.ref = reference; + } } else { diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index facf144a4..a15421bdb 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -267,12 +267,15 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(SerialiserType &ser, VkQueue queue, RDCDEBUG("Queue Submit no replay %u == %u", m_LastEventID, startEID); #endif } - else if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) + else { #if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit re-recording from %u", m_RootEventID); + RDCDEBUG("Queue Submit from re-recorded commands, root EID %u last EID", m_RootEventID, + m_LastEventID); #endif + uint32_t eid = startEID; + std::vector rerecordedCmds; for(uint32_t c = 0; c < submitInfo.commandBufferCount; c++) @@ -280,15 +283,37 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(SerialiserType &ser, VkQueue queue, ResourceId cmdId = GetResourceManager()->GetOriginalID(GetResID(submitInfo.pCommandBuffers[c])); - VkCommandBuffer cmd = RerecordCmdBuf(cmdId); - ResourceId rerecord = GetResID(cmd); -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit fully re-recorded replay of %llu, using %llu", cmdId, rerecord); -#endif - rerecordedCmds.push_back(Unwrap(cmd)); + // account for the virtual vkBeginCommandBuffer label at the start of the events here + // so it matches up to baseEvent + eid++; - GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[rerecord].imgbarriers, - m_ImageLayouts); +#if ENABLED(VERBOSE_PARTIAL_REPLAY) + uint32_t end = eid + m_BakedCmdBufferInfo[cmdId].eventCount; +#endif + + if(eid <= m_LastEventID) + { + VkCommandBuffer cmd = RerecordCmdBuf(cmdId); + ResourceId rerecord = GetResID(cmd); +#if ENABLED(VERBOSE_PARTIAL_REPLAY) + RDCDEBUG("Queue Submit re-recorded replay of %llu, using %llu (%u -> %u <= %u)", + cmdId, rerecord, eid, end, m_LastEventID); +#endif + rerecordedCmds.push_back(Unwrap(cmd)); + + GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[rerecord].imgbarriers, + m_ImageLayouts); + } + else + { +#if ENABLED(VERBOSE_PARTIAL_REPLAY) + RDCDEBUG("Queue not submitting %llu", cmdId); +#endif + } + + // 1 extra to account for the virtual end command buffer label (begin is accounted for + // above) + eid += 1 + m_BakedCmdBufferInfo[cmdId].eventCount; } VkSubmitInfo rerecordedSubmit = submitInfo; @@ -309,118 +334,6 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(SerialiserType &ser, VkQueue queue, // don't submit the fence, since we have nothing to wait on it being signalled, and we // might not have it correctly in the unsignalled state. ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &rerecordedSubmit, VK_NULL_HANDLE); -#endif - } - else if(m_LastEventID > startEID && m_LastEventID < m_RootEventID) - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit partial replay %u < %u", m_LastEventID, m_RootEventID); -#endif - - uint32_t eid = startEID; - - std::vector trimmedCmdIds; - std::vector trimmedCmds; - - for(uint32_t c = 0; c < submitInfo.commandBufferCount; c++) - { - ResourceId cmdId = - GetResourceManager()->GetOriginalID(GetResID(submitInfo.pCommandBuffers[c])); - - // account for the virtual vkBeginCommandBuffer label at the start of the events here - // so it matches up to baseEvent - eid++; - - uint32_t end = eid + m_BakedCmdBufferInfo[cmdId].eventCount; - - if(eid == m_Partial[Primary].baseEvent) - { - ResourceId partial = GetResID(RerecordCmdBuf(cmdId, Primary)); -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit partial replay of %llu at %u, using %llu", cmdId, eid, partial); -#endif - trimmedCmdIds.push_back(partial); - trimmedCmds.push_back(Unwrap(RerecordCmdBuf(cmdId, Primary))); - } - else if(m_LastEventID >= end) - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit full replay %llu", cmdId); -#endif - trimmedCmdIds.push_back(cmdId); - trimmedCmds.push_back( - Unwrap(GetResourceManager()->GetLiveHandle(cmdId))); - } - else - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue not submitting %llu", cmdId); -#endif - } - - // 1 extra to account for the virtual end command buffer label (begin is accounted for - // above) - eid += 1 + m_BakedCmdBufferInfo[cmdId].eventCount; - } - - RDCASSERT(trimmedCmds.size() > 0); - - VkSubmitInfo trimmedSubmit = submitInfo; - - trimmedSubmit.commandBufferCount = (uint32_t)trimmedCmds.size(); - trimmedSubmit.pCommandBuffers = &trimmedCmds[0]; - -#if ENABLED(SINGLE_FLUSH_VALIDATE) - trimmedSubmit.commandBufferCount = 1; - for(uint32_t i = 0; i < trimmedSubmit.commandBufferCount; i++) - { - ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &trimmedSubmit, VK_NULL_HANDLE); - trimmedSubmit.pCommandBuffers++; - - FlushQ(); - } -#else - // don't submit the fence, since we have nothing to wait on it being signalled, and we - // might not have it correctly in the unsignalled state. - ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &trimmedSubmit, VK_NULL_HANDLE); -#endif - - for(uint32_t i = 0; i < trimmedCmdIds.size(); i++) - { - ResourceId cmd = trimmedCmdIds[i]; - GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, - m_ImageLayouts); - } - } - else - { -#if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("Queue Submit full replay %u >= %u", m_LastEventID, m_RootEventID); -#endif - - VkCommandBuffer *cmds = (VkCommandBuffer *)submitInfo.pCommandBuffers; - for(uint32_t i = 0; i < submitInfo.commandBufferCount; i++) - { - ResourceId cmd = GetResID(submitInfo.pCommandBuffers[i]); - GetResourceManager()->ApplyBarriers(m_BakedCmdBufferInfo[cmd].imgbarriers, - m_ImageLayouts); - - cmds[i] = Unwrap(cmds[i]); - } - -#if ENABLED(SINGLE_FLUSH_VALIDATE) - submitInfo.commandBufferCount = 1; - for(uint32_t i = 0; i < submitInfo.commandBufferCount; i++) - { - ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &submitInfo, VK_NULL_HANDLE); - submitInfo.pCommandBuffers++; - - FlushQ(); - } -#else - // don't submit the fence, since we have nothing to wait on it being signalled, and we - // might not have it correctly in the unsignalled state. - ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &submitInfo, VK_NULL_HANDLE); #endif } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp index 4abec9b24..89721f7ca 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp @@ -571,7 +571,7 @@ bool WrappedVulkan::Serialise_vkCmdSetEvent(SerialiserType &ser, VkCommandBuffer if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -626,7 +626,7 @@ bool WrappedVulkan::Serialise_vkCmdResetEvent(SerialiserType &ser, VkCommandBuff if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE; @@ -733,7 +733,7 @@ bool WrappedVulkan::Serialise_vkCmdWaitEvents( if(IsActiveReplaying(m_State)) { - if(ShouldRerecordCmd(m_LastCmdBufferID) && InRerecordRange(m_LastCmdBufferID)) + if(InRerecordRange(m_LastCmdBufferID)) commandBuffer = RerecordCmdBuf(m_LastCmdBufferID); else commandBuffer = VK_NULL_HANDLE;