diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index f142d5e90..b9c6795c2 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -34,13 +34,12 @@ WrappedID3D11Device *D3D11MarkerRegion::device; D3D11MarkerRegion::D3D11MarkerRegion(const std::string &marker) { - if(device == NULL) - return; + D3D11MarkerRegion::Begin(marker); +} - ID3DUserDefinedAnnotation *annot = device->GetAnnotations(); - - if(annot) - annot->BeginEvent(StringFormat::UTF82Wide(marker).c_str()); +D3D11MarkerRegion::~D3D11MarkerRegion() +{ + D3D11MarkerRegion::End(); } void D3D11MarkerRegion::Set(const std::string &marker) @@ -54,7 +53,18 @@ void D3D11MarkerRegion::Set(const std::string &marker) annot->SetMarker(StringFormat::UTF82Wide(marker).c_str()); } -D3D11MarkerRegion::~D3D11MarkerRegion() +void D3D11MarkerRegion::Begin(const std::string &marker) +{ + if(device == NULL) + return; + + ID3DUserDefinedAnnotation *annot = device->GetAnnotations(); + + if(annot) + annot->BeginEvent(StringFormat::UTF82Wide(marker).c_str()); +} + +void D3D11MarkerRegion::End() { if(device == NULL) return; diff --git a/renderdoc/driver/d3d11/d3d11_common.h b/renderdoc/driver/d3d11/d3d11_common.h index 7fe6b4c5d..e101591f1 100644 --- a/renderdoc/driver/d3d11/d3d11_common.h +++ b/renderdoc/driver/d3d11/d3d11_common.h @@ -43,6 +43,8 @@ struct D3D11MarkerRegion D3D11MarkerRegion(const std::string &marker); ~D3D11MarkerRegion(); static void Set(const std::string &marker); + static void Begin(const std::string &marker); + static void End(); static WrappedID3D11Device *device; }; diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index 6f8c4375b..ab4b65b44 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -53,6 +53,9 @@ bool WrappedID3D11DeviceContext::Serialise_SetMarker(uint32_t col, const wchar_t m_pSerialiser->Serialise("Name", name); + if(m_State <= EXECUTING) + D3D11MarkerRegion::Set(name); + if(m_State == READING) { DrawcallDescription draw; @@ -89,6 +92,12 @@ bool WrappedID3D11DeviceContext::Serialise_PushEvent(uint32_t col, const wchar_t m_pSerialiser->Serialise("Name", name); + if(m_State <= EXECUTING) + { + D3D11MarkerRegion::Begin(name); + m_pDevice->ReplayPushEvent(); + } + if(m_State == READING) { DrawcallDescription draw; @@ -113,6 +122,12 @@ bool WrappedID3D11DeviceContext::Serialise_PushEvent(uint32_t col, const wchar_t bool WrappedID3D11DeviceContext::Serialise_PopEvent() { + if(m_State <= EXECUTING) + { + D3D11MarkerRegion::End(); + m_pDevice->ReplayPopEvent(); + } + if(m_State == READING && !m_CurEvents.empty()) { DrawcallDescription draw; diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 6388f21fa..b7236f93d 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -2469,35 +2469,32 @@ void WrappedID3D11Device::ReplayLog(uint32_t startEventID, uint32_t endEventID, if(!partial) { - D3D11MarkerRegion apply("ApplyInitialContents"); + D3D11MarkerRegion apply("!!!!RenderDoc Internal: ApplyInitialContents"); GetResourceManager()->ApplyInitialContents(); GetResourceManager()->ReleaseInFrameResources(); } m_State = EXECUTING; + D3D11MarkerRegion::Set(StringFormat::Fmt("!!!!RenderDoc Internal: Replay %d (%d): %u->%u", + (int)replayType, (int)partial, startEventID, endEventID)); + + m_ReplayEventCount = 0; + if(replayType == eReplay_Full) - { - D3D11MarkerRegion exec( - StringFormat::Fmt("Replay: Full %u->%u (partial %u)", startEventID, endEventID, partial)); m_pImmediateContext->ReplayLog(EXECUTING, startEventID, endEventID, partial); - } else if(replayType == eReplay_WithoutDraw) - { - D3D11MarkerRegion exec(StringFormat::Fmt("Replay: W/O Draw %u->%u (partial %u)", startEventID, - endEventID, partial)); m_pImmediateContext->ReplayLog(EXECUTING, startEventID, RDCMAX(1U, endEventID) - 1, partial); - } else if(replayType == eReplay_OnlyDraw) - { - D3D11MarkerRegion exec(StringFormat::Fmt("Replay: Draw Only %u->%u (partial %u)", endEventID, - endEventID, partial)); m_pImmediateContext->ReplayLog(EXECUTING, endEventID, endEventID, partial); - } else - { RDCFATAL("Unexpected replay type"); - } + + // make sure to end any unbalanced replay events if we stopped in the middle of a frame + for(int i = 0; i < m_ReplayEventCount; i++) + D3D11MarkerRegion::End(); + + D3D11MarkerRegion::Set("!!!!RenderDoc Internal: Done replay"); } void WrappedID3D11Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap, UINT QueueCount, diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index bf623c568..14d3a402d 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -327,6 +327,7 @@ private: WrappedID3D11Debug m_WrappedDebug; ID3DUserDefinedAnnotation *m_RealAnnotations; + int m_ReplayEventCount; unsigned int m_InternalRefcount; RefCounter m_RefCounter; @@ -434,6 +435,8 @@ public: FrameStatistics &GetFrameStats() { return m_FrameRecord.frameInfo.stats; } const DrawcallDescription *GetDrawcall(uint32_t eventID); + void ReplayPushEvent() { m_ReplayEventCount++; } + void ReplayPopEvent() { m_ReplayEventCount = RDCMAX(0, m_ReplayEventCount - 1); } void LockForChunkFlushing(); void UnlockForChunkFlushing(); void LockForChunkRemoval(); diff --git a/renderdoc/driver/d3d12/d3d12_command_list.h b/renderdoc/driver/d3d12/d3d12_command_list.h index 0b981fd48..301cf5a31 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list.h +++ b/renderdoc/driver/d3d12/d3d12_command_list.h @@ -123,7 +123,9 @@ public: WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; } D3D12ResourceRecord *GetResourceRecord() { return m_ListRecord; } ID3D12GraphicsCommandList *GetList(ResourceId id); + ID3D12GraphicsCommandList *GetWrappedList(ResourceId id); ID3D12GraphicsCommandList *GetCrackedList(ResourceId id); + ID3D12GraphicsCommandList *GetWrappedCrackedList(ResourceId id); void SetCommandData(D3D12CommandData *cmd) { m_Cmd = cmd; } void SetInitParams(REFIID riid, UINT nodeMask, D3D12_COMMAND_LIST_TYPE type) diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index a7b167d3b..1134a5bbc 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -30,11 +30,21 @@ ID3D12GraphicsCommandList *WrappedID3D12GraphicsCommandList::GetList(ResourceId return GetResourceManager()->GetLiveAs(id)->GetReal(); } +ID3D12GraphicsCommandList *WrappedID3D12GraphicsCommandList::GetWrappedList(ResourceId id) +{ + return GetResourceManager()->GetLiveAs(id); +} + ID3D12GraphicsCommandList *WrappedID3D12GraphicsCommandList::GetCrackedList(ResourceId id) { return Unwrap(m_Cmd->m_BakedCmdListInfo[id].crackedLists.back()); } +ID3D12GraphicsCommandList *WrappedID3D12GraphicsCommandList::GetWrappedCrackedList(ResourceId id) +{ + return m_Cmd->m_BakedCmdListInfo[id].crackedLists.back(); +} + bool WrappedID3D12GraphicsCommandList::Serialise_Close() { SERIALISE_ELEMENT(ResourceId, CommandList, GetResourceID()); @@ -63,6 +73,11 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close() RDCDEBUG("Ending partial command list for %llu baked to %llu", CommandList, bakeId); #endif + int &markerCount = m_Cmd->m_BakedCmdListInfo[CommandList].markerCount; + + for(int i = 0; i < markerCount; i++) + D3D12MarkerRegion::End(list); + list->Close(); // erase the non-baked reference to this command list so that we don't have @@ -219,6 +234,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p m_Cmd->m_RenderState.pipe = GetResID(pInitialState); } + m_Cmd->m_BakedCmdListInfo[CommandList].markerCount = 0; m_Cmd->m_BakedCmdListInfo[CommandList].curEventID = 0; m_Cmd->m_BakedCmdListInfo[CommandList].executeEvents = m_Cmd->m_BakedCmdListInfo[bakeId].executeEvents; @@ -2653,8 +2669,20 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetMarker(UINT Metadata, const if(m_State < WRITING) m_Cmd->m_LastCmdListID = CommandList; - if(m_State == READING) + if(m_State == EXECUTING) { + if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList)) + { + ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList); + + D3D12MarkerRegion::Set(list, markerText); + } + } + else if(m_State == READING) + { + D3D12MarkerRegion::Set(GetWrappedList(CommandList), markerText); + D3D12MarkerRegion::Set(GetWrappedCrackedList(CommandList), markerText); + DrawcallDescription draw; draw.name = markerText; draw.flags |= DrawFlags::SetMarker; @@ -2711,8 +2739,22 @@ bool WrappedID3D12GraphicsCommandList::Serialise_BeginEvent(UINT Metadata, const if(m_State < WRITING) m_Cmd->m_LastCmdListID = CommandList; - if(m_State == READING) + if(m_State == EXECUTING) { + if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList)) + { + ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList); + + m_Cmd->m_BakedCmdListInfo[CommandList].markerCount++; + + D3D12MarkerRegion::Begin(list, markerText); + } + } + else if(m_State == READING) + { + D3D12MarkerRegion::Begin(GetWrappedList(CommandList), markerText); + D3D12MarkerRegion::Begin(GetWrappedCrackedList(CommandList), markerText); + DrawcallDescription draw; draw.name = markerText; draw.flags |= DrawFlags::PushMarker; @@ -2752,8 +2794,23 @@ bool WrappedID3D12GraphicsCommandList::Serialise_EndEvent() m_Cmd->AddDrawcall(draw, true); } - if(m_State == READING) + if(m_State == EXECUTING) { + if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList)) + { + ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList); + + int &markerCount = m_Cmd->m_BakedCmdListInfo[CommandList].markerCount; + markerCount = RDCMAX(0, markerCount - 1); + + D3D12MarkerRegion::End(list); + } + } + else if(m_State == READING) + { + D3D12MarkerRegion::End(GetWrappedList(CommandList)); + D3D12MarkerRegion::End(GetWrappedCrackedList(CommandList)); + // dummy draw that is consumed when this command buffer // is being in-lined into the call stream DrawcallDescription draw; diff --git a/renderdoc/driver/d3d12/d3d12_commands.h b/renderdoc/driver/d3d12/d3d12_commands.h index 8b436edfe..b8ae20779 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.h +++ b/renderdoc/driver/d3d12/d3d12_commands.h @@ -192,6 +192,10 @@ struct BakedCmdListInfo ResourceId parentList; + // modified during recording to ensure we end any markers that should be ended but weren't due to + // a partial replay + int markerCount; + D3D12DrawcallTreeNode *draw; // the root draw to copy from when submitting uint32_t eventCount; // how many events are in this cmd list, for quick skipping uint32_t curEventID; // current event ID while reading or executing diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index a1f724d4d..fb4ffccd5 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -31,7 +31,29 @@ D3D12MarkerRegion::D3D12MarkerRegion(ID3D12GraphicsCommandList *l, const std::string &marker) { list = l; + queue = NULL; + D3D12MarkerRegion::Begin(list, marker); +} + +D3D12MarkerRegion::D3D12MarkerRegion(ID3D12CommandQueue *q, const std::string &marker) +{ + list = NULL; + queue = q; + + D3D12MarkerRegion::Begin(queue, marker); +} + +D3D12MarkerRegion::~D3D12MarkerRegion() +{ + if(list) + D3D12MarkerRegion::End(list); + if(queue) + D3D12MarkerRegion::End(queue); +} + +void D3D12MarkerRegion::Begin(ID3D12GraphicsCommandList *list, const std::string &marker) +{ if(list) { std::wstring text = StringFormat::UTF82Wide(marker); @@ -39,6 +61,15 @@ D3D12MarkerRegion::D3D12MarkerRegion(ID3D12GraphicsCommandList *l, const std::st } } +void D3D12MarkerRegion::Begin(ID3D12CommandQueue *queue, const std::string &marker) +{ + if(queue) + { + std::wstring text = StringFormat::UTF82Wide(marker); + queue->BeginEvent(0, text.c_str(), (UINT)text.size()); + } +} + void D3D12MarkerRegion::Set(ID3D12GraphicsCommandList *list, const std::string &marker) { if(list) @@ -48,10 +79,23 @@ void D3D12MarkerRegion::Set(ID3D12GraphicsCommandList *list, const std::string & } } -D3D12MarkerRegion::~D3D12MarkerRegion() +void D3D12MarkerRegion::Set(ID3D12CommandQueue *queue, const std::string &marker) { - if(list) - list->EndEvent(); + if(queue) + { + std::wstring text = StringFormat::UTF82Wide(marker); + queue->SetMarker(0, text.c_str(), (UINT)text.size()); + } +} + +void D3D12MarkerRegion::End(ID3D12GraphicsCommandList *list) +{ + list->EndEvent(); +} + +void D3D12MarkerRegion::End(ID3D12CommandQueue *queue) +{ + queue->EndEvent(); } TextureDim MakeTextureDim(D3D12_SRV_DIMENSION dim) diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index 2d5fe776f..ac3833bbe 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -37,10 +37,19 @@ struct D3D12MarkerRegion { D3D12MarkerRegion(ID3D12GraphicsCommandList *list, const std::string &marker); + D3D12MarkerRegion(ID3D12CommandQueue *queue, const std::string &marker); ~D3D12MarkerRegion(); - static void Set(ID3D12GraphicsCommandList *list, const std::string &marker); - ID3D12GraphicsCommandList *list; + static void Set(ID3D12GraphicsCommandList *list, const std::string &marker); + static void Set(ID3D12CommandQueue *queue, const std::string &marker); + + static void Begin(ID3D12GraphicsCommandList *list, const std::string &marker); + static void End(ID3D12GraphicsCommandList *list); + static void Begin(ID3D12CommandQueue *queue, const std::string &marker); + static void End(ID3D12CommandQueue *queue); + + ID3D12GraphicsCommandList *list = NULL; + ID3D12CommandQueue *queue = NULL; }; inline void SetObjName(ID3D12Object *obj, const std::string &utf8name) diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 515570b2f..9ea771e6b 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -589,7 +589,10 @@ void WrappedID3D12Device::ApplyInitialContents() // close the final list if(initStateCurList) + { + D3D12MarkerRegion::End(initStateCurList); initStateCurList->Close(); + } initStateCurBatch = 0; initStateCurList = NULL; @@ -2159,13 +2162,22 @@ ID3D12GraphicsCommandList *WrappedID3D12Device::GetInitialStateList() } if(initStateCurList == NULL) + { initStateCurList = GetNewList(); + if(m_State < WRITING) + { + D3D12MarkerRegion::Begin(initStateCurList, + "!!!!RenderDoc Internal: ApplyInitialContents batched list"); + } + } + return initStateCurList; } void WrappedID3D12Device::CloseInitialStateList() { + D3D12MarkerRegion::End(initStateCurList); initStateCurList->Close(); initStateCurList = NULL; initStateCurBatch = 0; @@ -2467,8 +2479,11 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID, if(!partial) { - ApplyInitialContents(); - GetResourceManager()->ReleaseInFrameResources(); + { + D3D12MarkerRegion apply(GetQueue(), "!!!!RenderDoc Internal: ApplyInitialContents"); + ApplyInitialContents(); + GetResourceManager()->ReleaseInFrameResources(); + } ExecuteLists(); FlushLists(true); @@ -2476,6 +2491,10 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID, m_State = EXECUTING; + D3D12MarkerRegion::Set( + GetQueue(), StringFormat::Fmt("!!!!RenderDoc Internal: RenderDoc Replay %d (%d): %u->%u", + (int)replayType, (int)partial, startEventID, endEventID)); + { D3D12CommandData &cmd = *m_Queue->GetCommandData(); @@ -2526,6 +2545,8 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID, #endif } + D3D12MarkerRegion::Set(GetQueue(), "!!!!RenderDoc Internal: Done replay"); + // ensure all UAV writes have finished before subsequent work ID3D12GraphicsCommandList *list = GetNewList(); diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index 439f19fcb..9082c4ad0 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -738,6 +738,16 @@ void DoVendorChecks(const GLHookSet &gl, GLPlatform &platform, GLWindowingData c const GLHookSet *GLMarkerRegion::gl; GLMarkerRegion::GLMarkerRegion(const std::string &marker) +{ + Begin(marker); +} + +GLMarkerRegion::~GLMarkerRegion() +{ + End(); +} + +void GLMarkerRegion::Begin(const std::string &marker) { if(gl == NULL || !HasExt[KHR_debug] || !gl->glPushDebugGroup) return; @@ -754,7 +764,7 @@ void GLMarkerRegion::Set(const std::string &marker) eGL_DEBUG_SEVERITY_NOTIFICATION, -1, marker.c_str()); } -GLMarkerRegion::~GLMarkerRegion() +void GLMarkerRegion::End() { if(gl == NULL || !HasExt[KHR_debug] || !gl->glPopDebugGroup) return; diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 48da01959..5034dabca 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -250,7 +250,10 @@ struct GLMarkerRegion { GLMarkerRegion(const std::string &marker); ~GLMarkerRegion(); + + static void Begin(const std::string &marker); static void Set(const std::string &marker); + static void End(); static const GLHookSet *gl; }; diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index ff3519c51..3d2c5de0b 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -3312,7 +3312,8 @@ bool WrappedOpenGL::RecordUpdateCheck(GLResourceRecord *record) void WrappedOpenGL::DebugSnoop(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message) { - if(type != eGL_DEBUG_TYPE_PUSH_GROUP && type != eGL_DEBUG_TYPE_POP_GROUP) + if(type != eGL_DEBUG_TYPE_PUSH_GROUP && type != eGL_DEBUG_TYPE_POP_GROUP && + type != eGL_DEBUG_TYPE_MARKER) { if(type != eGL_DEBUG_TYPE_PERFORMANCE && type != eGL_DEBUG_TYPE_OTHER) { @@ -4503,31 +4504,28 @@ void WrappedOpenGL::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay if(!partial) { - GLMarkerRegion apply("ApplyInitialContents"); + GLMarkerRegion apply("!!!!RenderDoc Internal: ApplyInitialContents"); GetResourceManager()->ApplyInitialContents(); GetResourceManager()->ReleaseInFrameResources(); } + GLMarkerRegion::Set(StringFormat::Fmt("!!!!RenderDoc Internal: Replay %d (%d): %u->%u", + (int)replayType, (int)partial, startEventID, endEventID)); + + m_ReplayEventCount = 0; + if(replayType == eReplay_Full) - { - GLMarkerRegion exec( - StringFormat::Fmt("Replay: Full %u->%u (partial %u)", startEventID, endEventID, partial)); ContextReplayLog(EXECUTING, startEventID, endEventID, partial); - } else if(replayType == eReplay_WithoutDraw) - { - GLMarkerRegion exec(StringFormat::Fmt("Replay: W/O Draw %u->%u (partial %u)", startEventID, - endEventID, partial)); ContextReplayLog(EXECUTING, startEventID, RDCMAX(1U, endEventID) - 1, partial); - } else if(replayType == eReplay_OnlyDraw) - { - GLMarkerRegion exec(StringFormat::Fmt("Replay: Draw Only %u->%u (partial %u)", endEventID, - endEventID, partial)); ContextReplayLog(EXECUTING, endEventID, endEventID, partial); - } else - { RDCFATAL("Unexpected replay type"); - } + + // make sure to end any unbalanced replay events if we stopped in the middle of a frame + for(int i = 0; i < m_ReplayEventCount; i++) + GLMarkerRegion::End(); + + GLMarkerRegion::Set("!!!!RenderDoc Internal: Done replay"); } diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 986d8bf7a..4ac92f760 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -192,6 +192,8 @@ private: set m_HighTrafficResources; + int m_ReplayEventCount; + // we store two separate sets of maps, since for an explicit glMemoryBarrier // we need to flush both types of maps, but for implicit sync points we only // want to consider coherent maps, and since that happens often we want it to diff --git a/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp index de8c491d6..d1d1194c1 100644 --- a/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp @@ -158,7 +158,11 @@ bool WrappedOpenGL::Serialise_glDebugMessageInsert(GLenum source, GLenum type, G m_pSerialiser->Serialise("Name", name); - if(m_State == READING) + if(m_State == EXECUTING) + { + GLMarkerRegion::Set(name); + } + else if(m_State == READING) { DrawcallDescription draw; draw.name = name; @@ -240,7 +244,12 @@ bool WrappedOpenGL::Serialise_glPushDebugGroup(GLenum source, GLuint id, GLsizei m_pSerialiser->Serialise("Name", name); - if(m_State == READING) + if(m_State == EXECUTING) + { + GLMarkerRegion::Begin(name); + m_ReplayEventCount++; + } + else if(m_State == READING) { DrawcallDescription draw; draw.name = name; @@ -267,7 +276,12 @@ void WrappedOpenGL::glPushDebugGroup(GLenum source, GLuint id, GLsizei length, c bool WrappedOpenGL::Serialise_glPopDebugGroup() { - if(m_State == READING && !m_CurEvents.empty()) + if(m_State == EXECUTING) + { + GLMarkerRegion::End(); + m_ReplayEventCount = RDCMAX(0, m_ReplayEventCount - 1); + } + else if(m_State == READING && !m_CurEvents.empty()) { DrawcallDescription draw; draw.name = "API Calls"; diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index b69fd110d..fda9cf395 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -23,12 +23,108 @@ ******************************************************************************/ #include "vk_common.h" +#include "vk_core.h" #include "vk_manager.h" #include "vk_resources.h" const uint32_t AMD_PCI_ID = 0x1002; const uint32_t NV_PCI_ID = 0x10DE; +// utility struct for firing one-shot command buffers to begin/end markers +struct ScopedCommandBuffer +{ + ScopedCommandBuffer(VkCommandBuffer cmdbuf, WrappedVulkan *vk) + { + core = vk; + cmd = cmdbuf; + local = (cmd == VK_NULL_HANDLE); + + if(local) + { + VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT}; + + cmd = vk->GetNextCmd(); + + VkResult vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + } + } + ~ScopedCommandBuffer() + { + VkResult vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + core->SubmitCmds(); + } + + WrappedVulkan *core; + VkCommandBuffer cmd; + bool local; +}; + +WrappedVulkan *VkMarkerRegion::vk = NULL; + +VkMarkerRegion::VkMarkerRegion(const std::string &marker, VkCommandBuffer cmd) +{ + if(cmd == VK_NULL_HANDLE) + { + RDCERR("Cannot auto-allocate a command buffer for a scoped VkMarkerRegion"); + return; + } + + cmdbuf = cmd; + Begin(marker, cmd); +} + +VkMarkerRegion::~VkMarkerRegion() +{ + if(cmdbuf) + End(cmdbuf); +} + +void VkMarkerRegion::Begin(const std::string &marker, VkCommandBuffer cmd) +{ + if(!vk) + return; + + // check for presence of the marker extension + if(!ObjDisp(vk->GetDev())->CmdDebugMarkerBeginEXT) + return; + + ScopedCommandBuffer scope(cmd, vk); + + VkDebugMarkerMarkerInfoEXT markerInfo = {}; + markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + markerInfo.pMarkerName = marker.c_str(); + ObjDisp(scope.cmd)->CmdDebugMarkerBeginEXT(Unwrap(scope.cmd), &markerInfo); +} + +void VkMarkerRegion::Set(const std::string &marker, VkCommandBuffer cmd) +{ + // check for presence of the marker extension + if(!ObjDisp(vk->GetDev())->CmdDebugMarkerBeginEXT) + return; + + ScopedCommandBuffer scope(cmd, vk); + + VkDebugMarkerMarkerInfoEXT markerInfo = {}; + markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + markerInfo.pMarkerName = marker.c_str(); + ObjDisp(scope.cmd)->CmdDebugMarkerInsertEXT(Unwrap(scope.cmd), &markerInfo); +} + +void VkMarkerRegion::End(VkCommandBuffer cmd) +{ + // check for presence of the marker extension + if(!ObjDisp(vk->GetDev())->CmdDebugMarkerBeginEXT) + return; + + ScopedCommandBuffer scope(cmd, vk); + + ObjDisp(scope.cmd)->CmdDebugMarkerEndEXT(Unwrap(scope.cmd)); +} + VkAccessFlags MakeAccessMask(VkImageLayout layout) { switch(layout) diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 410596d90..82a428560 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -104,6 +104,29 @@ int SampleCount(VkSampleCountFlagBits countFlag); int SampleIndex(VkSampleCountFlagBits countFlag); int StageIndex(VkShaderStageFlagBits stageFlag); +class WrappedVulkan; + +// replay only class for handling marker regions. +// +// The cmd allows you to pass in an existing command buffer to insert/add the marker to. +// If cmd is NULL, then a new command buffer is fetched, begun, the marker is applied to, then +// closed again. Note that when constructing a scoped marker, cmd cannot be NULL +// +// If VK_EXT_debug_marker isn't supported, will silently do nothing +struct VkMarkerRegion +{ + VkMarkerRegion(const std::string &marker, VkCommandBuffer cmd); + ~VkMarkerRegion(); + + static void Begin(const std::string &marker, VkCommandBuffer cmd = VK_NULL_HANDLE); + static void Set(const std::string &marker, VkCommandBuffer cmd = VK_NULL_HANDLE); + static void End(VkCommandBuffer cmd = VK_NULL_HANDLE); + + VkCommandBuffer cmdbuf = VK_NULL_HANDLE; + + static WrappedVulkan *vk; +}; + // in vk_.cpp extern const char *VulkanLibraryName; diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 367ffe525..52d3563e5 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -266,6 +266,8 @@ WrappedVulkan::WrappedVulkan(const char *logFilename) : m_RenderState(this, &m_C if(RenderDoc::Inst().IsReplayApp()) { + VkMarkerRegion::vk = this; + m_State = READING; if(logFilename) { @@ -2352,7 +2354,9 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay if(!partial) { + VkMarkerRegion::Begin("!!!!RenderDoc Internal: ApplyInitialContents"); ApplyInitialContents(); + VkMarkerRegion::End(); SubmitCmds(); FlushQ(); @@ -2360,6 +2364,9 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay GetResourceManager()->ReleaseInFrameResources(); } + VkMarkerRegion::Set(StringFormat::Fmt("!!!!RenderDoc Internal: RenderDoc Replay %d (%d): %u->%u", + (int)replayType, (int)partial, startEventID, endEventID)); + { if(!partial) { @@ -2488,6 +2495,8 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay SubmitCmds(); #endif } + + VkMarkerRegion::Set("!!!!RenderDoc Internal: Done replay"); } void WrappedVulkan::Serialise_DebugMessages(Serialiser *localSerialiser, bool isDrawcall) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 7497aa818..4e126092d 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -409,6 +409,8 @@ private: VkCommandBufferLevel level; VkCommandBufferUsageFlags beginFlags; + int markerCount; + vector > resourceUsage; struct CmdBufferState diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index e49903dd8..2a1135c94 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -500,6 +500,7 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(Serialiser *localSerialiser, m_BakedCmdBufferInfo[cmdId].level = m_BakedCmdBufferInfo[bakeId].level = allocInfo.level; m_BakedCmdBufferInfo[cmdId].beginFlags = m_BakedCmdBufferInfo[bakeId].beginFlags = info.flags; + m_BakedCmdBufferInfo[cmdId].markerCount = 0; } if(m_State == EXECUTING) @@ -737,6 +738,10 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(Serialiser *localSerialiser, ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer)); } + if(ObjDisp(commandBuffer)->CmdDebugMarkerEndEXT) + for(int i = 0; i < m_BakedCmdBufferInfo[cmdid].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 @@ -2654,8 +2659,37 @@ bool WrappedVulkan::Serialise_vkCmdDebugMarkerBeginEXT(Serialiser *localSerialis if(m_State < WRITING) m_LastCmdBufferID = cmdid; - if(m_State == READING) + if(m_State == EXECUTING) { + if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid)) + { + commandBuffer = RerecordCmdBuf(cmdid); + + m_BakedCmdBufferInfo[m_LastCmdBufferID].markerCount++; + + if(ObjDisp(commandBuffer)->CmdDebugMarkerBeginEXT) + { + VkDebugMarkerMarkerInfoEXT marker = {}; + marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + memcpy(marker.color, color, sizeof(color)); + marker.pMarkerName = name.c_str(); + ObjDisp(commandBuffer)->CmdDebugMarkerBeginEXT(Unwrap(commandBuffer), &marker); + } + } + } + else if(m_State == READING) + { + commandBuffer = GetResourceManager()->GetLiveHandle(cmdid); + + if(ObjDisp(commandBuffer)->CmdDebugMarkerBeginEXT) + { + VkDebugMarkerMarkerInfoEXT marker = {}; + marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + memcpy(marker.color, color, sizeof(color)); + marker.pMarkerName = name.c_str(); + ObjDisp(commandBuffer)->CmdDebugMarkerBeginEXT(Unwrap(commandBuffer), &marker); + } + DrawcallDescription draw; draw.name = name; draw.flags |= DrawFlags::PushMarker; @@ -2707,8 +2741,26 @@ bool WrappedVulkan::Serialise_vkCmdDebugMarkerEndEXT(Serialiser *localSerialiser AddDrawcall(draw, true); } - if(m_State == READING) + if(m_State == EXECUTING) { + if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid)) + { + commandBuffer = RerecordCmdBuf(cmdid); + + int &markerCount = m_BakedCmdBufferInfo[m_LastCmdBufferID].markerCount; + markerCount = RDCMAX(0, markerCount - 1); + + if(ObjDisp(commandBuffer)->CmdDebugMarkerEndEXT) + ObjDisp(commandBuffer)->CmdDebugMarkerEndEXT(Unwrap(commandBuffer)); + } + } + else if(m_State == READING) + { + commandBuffer = GetResourceManager()->GetLiveHandle(cmdid); + + if(ObjDisp(commandBuffer)->CmdDebugMarkerEndEXT) + ObjDisp(commandBuffer)->CmdDebugMarkerEndEXT(Unwrap(commandBuffer)); + // dummy draw that is consumed when this command buffer // is being in-lined into the call stream DrawcallDescription draw; @@ -2756,8 +2808,35 @@ bool WrappedVulkan::Serialise_vkCmdDebugMarkerInsertEXT(Serialiser *localSeriali if(m_State < WRITING) m_LastCmdBufferID = cmdid; - if(m_State == READING) + if(m_State == EXECUTING) { + if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid)) + { + commandBuffer = RerecordCmdBuf(cmdid); + + if(ObjDisp(commandBuffer)->CmdDebugMarkerInsertEXT) + { + VkDebugMarkerMarkerInfoEXT marker = {}; + marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + memcpy(marker.color, color, sizeof(color)); + marker.pMarkerName = name.c_str(); + ObjDisp(commandBuffer)->CmdDebugMarkerInsertEXT(Unwrap(commandBuffer), &marker); + } + } + } + else if(m_State == READING) + { + commandBuffer = GetResourceManager()->GetLiveHandle(cmdid); + + if(ObjDisp(commandBuffer)->CmdDebugMarkerInsertEXT) + { + VkDebugMarkerMarkerInfoEXT marker = {}; + marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + memcpy(marker.color, color, sizeof(color)); + marker.pMarkerName = name.c_str(); + ObjDisp(commandBuffer)->CmdDebugMarkerInsertEXT(Unwrap(commandBuffer), &marker); + } + DrawcallDescription draw; draw.name = name; draw.flags |= DrawFlags::SetMarker; diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 04b9570be..7af5aadc9 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -934,6 +934,14 @@ bool WrappedVulkan::Serialise_vkCreateDevice(Serialiser *localSerialiser, AddRequiredExtensions(false, Extensions, supportedExtensions); + // enable VK_EXT_debug_marker if it's available, to replay markers to the driver/any other + // layers that might be listening + if(supportedExtensions.find(VK_EXT_DEBUG_MARKER_EXTENSION_NAME) != supportedExtensions.end()) + { + Extensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); + RDCLOG("Enabling VK_EXT_debug_marker"); + } + #if ENABLED(FORCE_VALIDATION_LAYERS) Layers.push_back("VK_LAYER_LUNARG_standard_validation"); #endif