diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index 35ba8c26f..19298a0a5 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -174,11 +174,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p } } - D3D12NOTIMP("m_DrawcallCallback"); - // const bool recordAllCmds = false; // m_DrawcallCallback && - // m_DrawcallCallback->RecordAllCmds() - - if(partial) // || recordAllCmds + if(partial || (m_Cmd->m_DrawcallCallback && m_Cmd->m_DrawcallCallback->RecordAllCmds())) { pAllocator = GetResourceManager()->GetLiveAs(Allocator); pInitialState = @@ -338,23 +334,15 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DrawIndexedInstanced(UINT Index { ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList); + uint32_t eventID = m_Cmd->HandlePreCallback(list); + Unwrap(list)->DrawIndexedInstanced(idxCount, instCount, startIdx, startVtx, startInst); - D3D12NOTIMP("Drawcall callbacks"); - /* - uint32_t eventID = HandlePreCallback(commandBuffer); - - ObjDisp(commandBuffer) - ->CmdDrawIndexed(Unwrap(commandBuffer), idxCount, instCount, firstIdx, vtxOffs, - firstInst); - - if(eventID && m_DrawcallCallback->PostDraw(eventID, commandBuffer)) + if(eventID && m_Cmd->m_DrawcallCallback->PostDraw(eventID, list)) { - ObjDisp(commandBuffer) - ->CmdDrawIndexed(Unwrap(commandBuffer), idxCount, instCount, firstIdx, vtxOffs, - firstInst); - m_DrawcallCallback->PostRedraw(eventID, commandBuffer); - }*/ + Unwrap(list)->DrawIndexedInstanced(idxCount, instCount, startIdx, startVtx, startInst); + m_Cmd->m_DrawcallCallback->PostRedraw(eventID, list); + } } } else if(m_State == READING) diff --git a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp index e64bf4a23..5ca26fb28 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp @@ -173,8 +173,6 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis // same accounting for the outer loop as above m_Cmd.m_RootEventID--; - D3D12NOTIMP("m_DrawcallCallback"); - if(numCmds == 0) { // do nothing, don't bother with the logic below @@ -185,30 +183,28 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis RDCDEBUG("Queue Submit no replay %u == %u", m_Cmd.m_LastEventID, startEID); #endif } - /* - else if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) + else if(m_Cmd.m_DrawcallCallback && m_Cmd.m_DrawcallCallback->RecordAllCmds()) { #ifdef VERBOSE_PARTIAL_REPLAY - RDCDEBUG("Queue Submit re-recording from %u", m_RootEventID); + RDCDEBUG("Queue Submit re-recording from %u", m_Cmd.m_RootEventID); #endif vector rerecordedCmds; for(uint32_t c = 0; c < numCmds; c++) { - ID3D12CommandList *cmd = RerecordCmdBuf(cmdIds[c]); + ID3D12CommandList *cmd = m_Cmd.RerecordCmdList(cmdIds[c]); ResourceId rerecord = GetResID(cmd); #ifdef VERBOSE_PARTIAL_REPLAY RDCDEBUG("Queue Submit fully re-recorded replay of %llu, using %llu", cmdIds[c], rerecord); #endif rerecordedCmds.push_back(Unwrap(cmd)); - m_pDevice->ApplyBarriers(m_BakedCmdBufferInfo[rerecord].imgbarriers); + m_pDevice->ApplyBarriers(m_Cmd.m_BakedCmdListInfo[rerecord].barriers); } m_pReal->ExecuteCommandLists((UINT)rerecordedCmds.size(), &rerecordedCmds[0]); } - */ else if(m_Cmd.m_LastEventID > startEID && m_Cmd.m_LastEventID < m_Cmd.m_RootEventID) { #ifdef VERBOSE_PARTIAL_REPLAY diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index 5eb4d5396..3c0efc160 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -169,6 +169,7 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real, m_QueueRecord = NULL; m_Cmd.m_pSerialiser = m_pSerialiser; + m_Cmd.m_pDevice = m_pDevice; if(!RenderDoc::Inst().IsReplayApp()) { @@ -585,16 +586,51 @@ D3D12CommandData::D3D12CommandData() m_RootDrawcallStack.push_back(&m_ParentDrawcall); } +uint32_t D3D12CommandData::HandlePreCallback(ID3D12GraphicsCommandList *list, bool dispatch, + uint32_t multiDrawOffset) +{ + if(!m_DrawcallCallback) + return 0; + + // look up the EID this drawcall came from + DrawcallUse use(m_CurChunkOffset, 0); + auto it = std::lower_bound(m_DrawcallUses.begin(), m_DrawcallUses.end(), use); + RDCASSERT(it != m_DrawcallUses.end()); + + uint32_t eventID = it->eventID; + + RDCASSERT(eventID != 0); + + // handle all aliases of this drawcall as long as it's not a multidraw + const FetchDrawcall *draw = m_pDevice->GetDrawcall(eventID); + + if(draw == NULL || (draw->flags & eDraw_MultiDraw) == 0) + { + ++it; + while(it != m_DrawcallUses.end() && it->fileOffset == m_CurChunkOffset) + { + m_DrawcallCallback->AliasEvent(eventID, it->eventID); + ++it; + } + } + + eventID += multiDrawOffset; + + if(dispatch) + m_DrawcallCallback->PreDispatch(eventID, list); + else + m_DrawcallCallback->PreDraw(eventID, list); + + return eventID; +} + bool D3D12CommandData::ShouldRerecordCmd(ResourceId cmdid) { if(m_Partial[Primary].outsideCmdList != NULL) return true; - D3D12NOTIMP("m_DrawcallCallback"); - /* if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) return true; - */ return cmdid == m_Partial[Primary].partialParent || cmdid == m_Partial[Secondary].partialParent; } @@ -604,11 +640,8 @@ bool D3D12CommandData::InRerecordRange(ResourceId cmdid) if(m_Partial[Primary].outsideCmdList != NULL) return true; - D3D12NOTIMP("m_DrawcallCallback"); - /* if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) return true; - */ for(int p = 0; p < ePartialNum; p++) { @@ -628,8 +661,6 @@ ID3D12GraphicsCommandList *D3D12CommandData::RerecordCmdList(ResourceId cmdid, if(m_Partial[Primary].outsideCmdList != NULL) return m_Partial[Primary].outsideCmdList; - D3D12NOTIMP("m_DrawcallCallback"); - /* if(m_DrawcallCallback && m_DrawcallCallback->RecordAllCmds()) { auto it = m_RerecordCmds.find(cmdid); @@ -638,7 +669,6 @@ ID3D12GraphicsCommandList *D3D12CommandData::RerecordCmdList(ResourceId cmdid, return it->second; } - */ if(partialType != ePartialNum) return m_Partial[partialType].resultPartialCmdList; diff --git a/renderdoc/driver/d3d12/d3d12_commands.h b/renderdoc/driver/d3d12/d3d12_commands.h index 46f89f665..3332d2436 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.h +++ b/renderdoc/driver/d3d12/d3d12_commands.h @@ -83,6 +83,44 @@ struct D3D12DrawcallTreeNode } }; +struct D3D12DrawcallCallback +{ + // the three callbacks are used to allow the callback implementor to either + // do a modified draw before or after the real thing. + // + // PreDraw() + // do draw call as specified by the log + // PostDraw() + // if PostDraw() returns true: + // do draw call again + // PostRedraw() + // + // So either the modification happens in PreDraw, the modified draw happens, + // then in PostDraw() the implementation can elect to undo the modifications + // and do the real draw by returning true. OR they can do nothing in PreDraw, + // do the real draw, then in PostDraw return true to apply the modifications + // which are then undone in PostRedraw. + virtual void PreDraw(uint32_t eid, ID3D12GraphicsCommandList *cmd) = 0; + virtual bool PostDraw(uint32_t eid, ID3D12GraphicsCommandList *cmd) = 0; + virtual void PostRedraw(uint32_t eid, ID3D12GraphicsCommandList *cmd) = 0; + + // same principle as above, but for dispatch calls + virtual void PreDispatch(uint32_t eid, ID3D12GraphicsCommandList *cmd) = 0; + 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 + // to indicate that they are the same. + virtual void AliasEvent(uint32_t primary, uint32_t alias) = 0; +}; + struct BakedCmdListInfo { void BakeFrom(BakedCmdListInfo &parent) @@ -127,12 +165,17 @@ struct BakedCmdListInfo uint32_t drawCount; // similar to above }; +class WrappedID3D12Device; + struct D3D12CommandData { D3D12CommandData(); + WrappedID3D12Device *m_pDevice; Serialiser *m_pSerialiser; + D3D12DrawcallCallback *m_DrawcallCallback; + ResourceId m_LastCmdListID; map m_BakedCmdListInfo; @@ -247,6 +290,11 @@ struct D3D12CommandData return m_RootDrawcallStack; } + // util function to handle fetching the right eventID, calling any + // aliases then calling PreDraw/PreDispatch. + uint32_t HandlePreCallback(ID3D12GraphicsCommandList *list, bool dispatch = false, + uint32_t multiDrawOffset = 0); + bool ShouldRerecordCmd(ResourceId cmdid); bool InRerecordRange(ResourceId cmdid); ID3D12GraphicsCommandList *RerecordCmdList(ResourceId cmdid, diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 9aafd204a..5a2b8c046 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -122,7 +122,7 @@ struct VulkanDrawcallTreeNode #undef SERIALISED_PARAMETER #define SERIALISED_PARAMETER Serialiser *localSerialiser, -struct DrawcallCallback +struct VulkanDrawcallCallback { // the three callbacks are used to allow the callback implementor to either // do a modified draw before or after the real thing. @@ -239,7 +239,7 @@ private: Threading::CriticalSection m_CapTransitionLock; - DrawcallCallback *m_DrawcallCallback; + VulkanDrawcallCallback *m_DrawcallCallback; // util function to handle fetching the right eventID, calling any // aliases then calling PreDraw/PreDispatch. @@ -700,7 +700,7 @@ public: void FlushQ(); VulkanRenderState &GetRenderState() { return m_RenderState; } - void SetDrawcallCB(DrawcallCallback *cb) { m_DrawcallCallback = cb; } + void SetDrawcallCB(VulkanDrawcallCallback *cb) { m_DrawcallCallback = cb; } VkResult FilterDeviceExtensionProperties(VkPhysicalDevice physDev, uint32_t *pPropertyCount, VkExtensionProperties *pProperties); static VkResult GetProvidedExtensionProperties(uint32_t *pPropertyCount, diff --git a/renderdoc/driver/vulkan/vk_counters.cpp b/renderdoc/driver/vulkan/vk_counters.cpp index b1214edfd..782133ccf 100644 --- a/renderdoc/driver/vulkan/vk_counters.cpp +++ b/renderdoc/driver/vulkan/vk_counters.cpp @@ -74,7 +74,7 @@ void VulkanReplay::DescribeCounter(uint32_t counterID, CounterDescription &desc) desc.units = eUnits_Absolute; } } -struct GPUTimerCallback : public DrawcallCallback +struct GPUTimerCallback : public VulkanDrawcallCallback { GPUTimerCallback(WrappedVulkan *vk, VulkanReplay *rp, VkQueryPool qp) : m_pDriver(vk), m_pReplay(rp), m_QueryPool(qp) diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 38c71f5fb..1b30668d5 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -3697,7 +3697,7 @@ void VulkanDebugManager::PatchFixedColShader(VkShaderModule &mod, float col[4]) RDCASSERTEQUAL(vkr, VK_SUCCESS); } -struct QuadOverdrawCallback : public DrawcallCallback +struct QuadOverdrawCallback : public VulkanDrawcallCallback { QuadOverdrawCallback(WrappedVulkan *vk, const vector &events) : m_pDriver(vk), m_pDebug(vk->GetDebugManager()), m_Events(events), m_PrevState(NULL) diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 959c033cf..b4e6593ef 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -4502,7 +4502,7 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventID) GetDebugManager()->InitPostVSBuffers(eventID); } -struct InitPostVSCallback : public DrawcallCallback +struct InitPostVSCallback : public VulkanDrawcallCallback { InitPostVSCallback(WrappedVulkan *vk, const vector &events) : m_pDriver(vk), m_Events(events)