diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index 70aa46a16..0caa4933a 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -2209,8 +2209,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DrawInstanced(UINT VertexCountP if(m_State < WRITING) m_Cmd->m_LastCmdListID = CommandList; - D3D12NOTIMP("Serialise_DebugMessages"); - if(m_State == EXECUTING) { if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList)) @@ -2286,8 +2284,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_DrawIndexedInstanced(UINT Index if(m_State < WRITING) m_Cmd->m_LastCmdListID = CommandList; - D3D12NOTIMP("Serialise_DebugMessages"); - if(m_State == EXECUTING) { if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList)) @@ -2362,8 +2358,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Dispatch(UINT ThreadGroupCountX if(m_State < WRITING) m_Cmd->m_LastCmdListID = CommandList; - D3D12NOTIMP("Serialise_DebugMessages"); - if(m_State == EXECUTING) { if(m_Cmd->ShouldRerecordCmd(CommandList) && m_Cmd->InRerecordRange(CommandList)) @@ -2439,8 +2433,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ExecuteIndirect( if(m_State < WRITING) m_Cmd->m_LastCmdListID = CommandList; - D3D12NOTIMP("Serialise_DebugMessages"); - if(m_State == EXECUTING) { pCommandSignature = GetResourceManager()->GetLiveAs(sig); diff --git a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp index 17139fa3c..6d2c8f2ff 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp @@ -80,7 +80,41 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis const string desc = m_pSerialiser->GetDebugStr(); - D3D12NOTIMP("Serialise_DebugMessages"); + // debug messages + { + vector debugMessages; + + if(m_State == WRITING_CAPFRAME) + debugMessages = m_pDevice->GetDebugMessages(); + + SERIALISE_ELEMENT(uint32_t, NumMessages, (uint32_t)debugMessages.size()); + + for(uint32_t i = 0; i < NumMessages; i++) + { + ScopedContext msgscope(m_pSerialiser, "DebugMessage", "DebugMessage", 0, false); + + string desc; + if(m_State >= WRITING) + desc = debugMessages[i].description.elems; + + SERIALISE_ELEMENT(uint32_t, Category, debugMessages[i].category); + SERIALISE_ELEMENT(uint32_t, Severity, debugMessages[i].severity); + SERIALISE_ELEMENT(uint32_t, ID, debugMessages[i].messageID); + SERIALISE_ELEMENT(string, Description, desc); + + if(m_State == READING) + { + DebugMessage msg; + msg.source = eDbgSource_API; + msg.category = (DebugMessageCategory)Category; + msg.severity = (DebugMessageSeverity)Severity; + msg.messageID = ID; + msg.description = Description; + + m_Cmd.m_EventMessages.push_back(msg); + } + } + } if(m_State == READING) { @@ -127,14 +161,12 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis submits[s] += m_Cmd.m_RootEventID; } - D3D12NOTIMP("Debug Messages"); - /* for(size_t i = 0; i < cmdBufInfo.debugMessages.size(); i++) { - m_DebugMessages.push_back(cmdBufInfo.debugMessages[i]); - m_DebugMessages.back().eventID += m_RootEventID; + DebugMessage msg = cmdBufInfo.debugMessages[i]; + msg.eventID += m_Cmd.m_RootEventID; + m_pDevice->AddDebugMessage(msg); } - */ // only primary command lists can be submitted m_Cmd.m_Partial[D3D12CommandData::Primary].cmdListExecs[cmdIds[c]].push_back( diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index 41e37bad9..0d3fc65f7 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -795,9 +795,6 @@ void D3D12CommandData::AddEvent(D3D12ChunkType type, string description) memcpy(apievent.callstack.elems, stack->GetAddrs(), sizeof(uint64_t) * stack->NumLevels()); } - D3D12NOTIMP("debug messages"); - vector m_EventMessages; - for(size_t i = 0; i < m_EventMessages.size(); i++) m_EventMessages[i].eventID = apievent.eventID; @@ -814,9 +811,8 @@ void D3D12CommandData::AddEvent(D3D12ChunkType type, string description) m_RootEvents.push_back(apievent); m_Events.push_back(apievent); - D3D12NOTIMP("debug messages"); - // m_DebugMessages.insert(m_DebugMessages.end(), m_EventMessages.begin(), - // m_EventMessages.end()); + for(auto it = m_EventMessages.begin(); it != m_EventMessages.end(); ++it) + m_pDevice->AddDebugMessage(*it); } m_EventMessages.clear(); diff --git a/renderdoc/driver/d3d12/d3d12_commands.h b/renderdoc/driver/d3d12/d3d12_commands.h index 3332d2436..49de5935d 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.h +++ b/renderdoc/driver/d3d12/d3d12_commands.h @@ -265,6 +265,8 @@ struct D3D12CommandData }; vector m_DrawcallUses; + vector m_EventMessages; + map m_RerecordCmds; bool m_AddedDrawcall; diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 9374fbec9..246b1fab5 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -890,6 +890,8 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd) RDCEraseEl(frame.stats); m_CapturedFrames.push_back(frame); + m_DebugMessages.clear(); + GetResourceManager()->ClearReferencedResources(); GetResourceManager()->MarkResourceFrameReferenced(m_ResourceID, eFrameRef_Read); @@ -1301,6 +1303,91 @@ void WrappedID3D12Device::ReleaseResource(ID3D12DeviceChild *res) } } +vector WrappedID3D12Device::GetDebugMessages() +{ + vector ret; + + // if reading, m_DebugMessages will contain all the messages (we + // don't try and fetch anything from the API). If writing, + // m_DebugMessages will contain any manually-added messages. + ret.swap(m_DebugMessages); + + if(m_State < WRITING) + return ret; + + if(!m_pInfoQueue) + return ret; + + UINT64 numMessages = m_pInfoQueue->GetNumStoredMessagesAllowedByRetrievalFilter(); + + for(UINT64 i = 0; i < m_pInfoQueue->GetNumStoredMessagesAllowedByRetrievalFilter(); i++) + { + SIZE_T len = 0; + m_pInfoQueue->GetMessage(i, NULL, &len); + + char *msgbuf = new char[len]; + D3D12_MESSAGE *message = (D3D12_MESSAGE *)msgbuf; + + m_pInfoQueue->GetMessage(i, message, &len); + + DebugMessage msg; + msg.eventID = 0; + msg.source = eDbgSource_API; + msg.category = eDbgCategory_Miscellaneous; + msg.severity = eDbgSeverity_Medium; + + switch(message->Category) + { + case D3D12_MESSAGE_CATEGORY_APPLICATION_DEFINED: + msg.category = eDbgCategory_Application_Defined; + break; + case D3D12_MESSAGE_CATEGORY_MISCELLANEOUS: msg.category = eDbgCategory_Miscellaneous; break; + case D3D12_MESSAGE_CATEGORY_INITIALIZATION: msg.category = eDbgCategory_Initialization; break; + case D3D12_MESSAGE_CATEGORY_CLEANUP: msg.category = eDbgCategory_Cleanup; break; + case D3D12_MESSAGE_CATEGORY_COMPILATION: msg.category = eDbgCategory_Compilation; break; + case D3D12_MESSAGE_CATEGORY_STATE_CREATION: msg.category = eDbgCategory_State_Creation; break; + case D3D12_MESSAGE_CATEGORY_STATE_SETTING: msg.category = eDbgCategory_State_Setting; break; + case D3D12_MESSAGE_CATEGORY_STATE_GETTING: msg.category = eDbgCategory_State_Getting; break; + case D3D12_MESSAGE_CATEGORY_RESOURCE_MANIPULATION: + msg.category = eDbgCategory_Resource_Manipulation; + break; + case D3D12_MESSAGE_CATEGORY_EXECUTION: msg.category = eDbgCategory_Execution; break; + case D3D12_MESSAGE_CATEGORY_SHADER: msg.category = eDbgCategory_Shaders; break; + default: RDCWARN("Unexpected message category: %d", message->Category); break; + } + + switch(message->Severity) + { + case D3D12_MESSAGE_SEVERITY_CORRUPTION: msg.severity = eDbgSeverity_High; break; + case D3D12_MESSAGE_SEVERITY_ERROR: msg.severity = eDbgSeverity_Medium; break; + case D3D12_MESSAGE_SEVERITY_WARNING: msg.severity = eDbgSeverity_Low; break; + case D3D12_MESSAGE_SEVERITY_INFO: msg.severity = eDbgSeverity_Info; break; + case D3D12_MESSAGE_SEVERITY_MESSAGE: msg.severity = eDbgSeverity_Info; break; + default: RDCWARN("Unexpected message severity: %d", message->Severity); break; + } + + msg.messageID = (uint32_t)message->ID; + msg.description = string(message->pDescription); + + ret.push_back(msg); + + SAFE_DELETE_ARRAY(msgbuf); + } + + // Docs are fuzzy on the thread safety of the info queue, but I'm going to assume it should only + // ever be accessed on one thread since it's tied to the device & immediate context. + // There doesn't seem to be a way to lock it for access and without that there's no way to know + // that a new message won't be added between the time you retrieve the last one and clearing the + // queue. There is also no way to pop a message that I can see, which would presumably be the + // best way if its member functions are thread safe themselves (if the queue is protected + // internally). + RDCASSERT(numMessages == m_pInfoQueue->GetNumStoredMessagesAllowedByRetrievalFilter()); + + m_pInfoQueue->ClearStoredMessages(); + + return ret; +} + void WrappedID3D12Device::FlushPendingDescriptorWrites() { std::vector writes; diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index 4f496d3dc..cbc6cbf02 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -266,6 +266,8 @@ private: Serialiser *GetThreadSerialiser(); + vector m_DebugMessages; + uint32_t m_FrameCounter; vector m_CapturedFrames; FetchFrameRecord m_FrameRecord; @@ -343,6 +345,9 @@ public: FetchFrameRecord &GetFrameRecord() { return m_FrameRecord; } const FetchDrawcall *GetDrawcall(uint32_t eventID); + void AddDebugMessage(const DebugMessage &msg) { m_DebugMessages.push_back(msg); } + vector GetDebugMessages(); + const string &GetResourceName(ResourceId id) { return m_ResourceNames[id]; } vector &GetSubresourceStates(ResourceId id) { diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index d6590153a..cd357dff5 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -1324,13 +1324,13 @@ Callstack::StackResolver *D3D12Replay::GetCallstackResolver() return m_pDevice->GetMainSerialiser()->GetCallstackResolver(); } -#pragma region not yet implemented - vector D3D12Replay::GetDebugMessages() { - return vector(); + return m_pDevice->GetDebugMessages(); } +#pragma region not yet implemented + vector D3D12Replay::GetPassEvents(uint32_t eventID) { vector passEvents;