From a0d6d771f21d9b0b9af97e825bbcfd7d6591db05 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 28 Sep 2014 13:58:18 +0100 Subject: [PATCH] Pass through child processes via remote access to UI. Refs #78 --- renderdoc/api/replay/control_types.h | 6 ++ renderdoc/api/replay/renderdoc_replay.h | 1 + renderdoc/api/replay/replay_enums.h | 1 + renderdoc/core/core.h | 16 +++++ renderdoc/core/remote_access.cpp | 73 ++++++++++++++++------ renderdoc/hooks/sys_win32_hooks.cpp | 8 ++- renderdocui/Interop/Enums.cs | 1 + renderdocui/Interop/ReplayRenderer.cs | 36 +++++++---- renderdocui/Windows/Dialogs/LiveCapture.cs | 19 ++++++ 9 files changed, 127 insertions(+), 34 deletions(-) diff --git a/renderdoc/api/replay/control_types.h b/renderdoc/api/replay/control_types.h index b7fca6ec6..fc423fef6 100644 --- a/renderdoc/api/replay/control_types.h +++ b/renderdoc/api/replay/control_types.h @@ -187,4 +187,10 @@ struct RemoteMessage { rdctype::wstr ClientName; } Busy; + + struct NewChildData + { + uint32_t PID; + uint32_t ident; + } NewChild; }; diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index a66c844e5..55a4c8fdd 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -180,6 +180,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RemoteAccess_Shutdown(RemoteAccess *a extern "C" RENDERDOC_API const wchar_t* RENDERDOC_CC RemoteAccess_GetTarget(RemoteAccess *access); extern "C" RENDERDOC_API const wchar_t* RENDERDOC_CC RemoteAccess_GetAPI(RemoteAccess *access); +extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RemoteAccess_GetPID(RemoteAccess *access); extern "C" RENDERDOC_API const wchar_t* RENDERDOC_CC RemoteAccess_GetBusyClient(RemoteAccess *access); extern "C" RENDERDOC_API void RENDERDOC_CC RemoteAccess_TriggerCapture(RemoteAccess *access); diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 3adb6f601..5d00902fd 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -379,4 +379,5 @@ enum RemoteMessageType eRemoteMsg_NewCapture, eRemoteMsg_CaptureCopied, eRemoteMsg_RegisterAPI, + eRemoteMsg_NewChild, }; diff --git a/renderdoc/core/core.h b/renderdoc/core/core.h index 1c05379d3..c4974b5e4 100644 --- a/renderdoc/core/core.h +++ b/renderdoc/core/core.h @@ -31,9 +31,11 @@ #include #include #include +#include using std::wstring; using std::vector; using std::map; +using std::pair; using std::set; class Serialiser; @@ -182,6 +184,17 @@ class RenderDoc Serialiser *OpenWriteSerialiser(uint32_t frameNum, RDCInitParams *params, void *thpixels, size_t thlen, uint32_t thwidth, uint32_t thheight); void SuccessfullyWrittenLog(); + void AddChildProcess(uint32_t pid, uint32_t ident) + { + SCOPED_LOCK(m_ChildLock); + m_Children.push_back( std::make_pair(pid, ident) ); + } + vector< pair > GetChildProcesses() + { + SCOPED_LOCK(m_ChildLock); + return m_Children; + } + vector GetCaptures() { SCOPED_LOCK(m_CaptureLock); @@ -284,6 +297,9 @@ class RenderDoc Threading::CriticalSection m_CaptureLock; vector m_Captures; + + Threading::CriticalSection m_ChildLock; + vector< pair > m_Children; map m_DriverNames; map m_ReplayDriverProviders; diff --git a/renderdoc/core/remote_access.cpp b/renderdoc/core/remote_access.cpp index 86a3fa5f1..14377b1a2 100644 --- a/renderdoc/core/remote_access.cpp +++ b/renderdoc/core/remote_access.cpp @@ -40,6 +40,7 @@ enum PacketType ePacket_TriggerCapture, ePacket_CopyCapture, ePacket_QueueCapture, + ePacket_NewChild, }; void RenderDoc::RemoteAccessClientThread(void *s) @@ -59,6 +60,8 @@ void RenderDoc::RemoteAccessClientThread(void *s) wstring target = RenderDoc::Inst().GetCurrentTarget(); ser.Serialise("", target); ser.Serialise("", api); + uint32_t mypid = Process::GetCurrentPID(); + ser.Serialise("", mypid); if(!SendPacket(client, ePacket_Handshake, ser)) { @@ -78,6 +81,7 @@ void RenderDoc::RemoteAccessClientThread(void *s) int curtime = 0; vector captures; + vector< pair > children; while(client) { @@ -97,6 +101,9 @@ void RenderDoc::RemoteAccessClientThread(void *s) wstring curapi; RenderDoc::Inst().GetCurrentDriver(driver, curapi); + vector caps = RenderDoc::Inst().GetCaptures(); + vector< pair > childprocs = RenderDoc::Inst().GetChildProcesses(); + if(curapi != api) { api = curapi; @@ -105,31 +112,37 @@ void RenderDoc::RemoteAccessClientThread(void *s) packetType = ePacket_RegisterAPI; } - else + else if(caps.size() != captures.size()) { - vector caps = RenderDoc::Inst().GetCaptures(); + uint32_t idx = (uint32_t)captures.size(); - if(caps.size() != captures.size()) - { - uint32_t idx = (uint32_t)captures.size(); + captures.push_back(caps[idx]); - captures.push_back(caps[idx]); + packetType = ePacket_NewCapture; - packetType = ePacket_NewCapture; + ser.Serialise("", idx); + ser.Serialise("", captures.back().timestamp); + ser.Serialise("", captures.back().path); - ser.Serialise("", idx); - ser.Serialise("", captures.back().timestamp); - ser.Serialise("", captures.back().path); + uint32_t len = 128*1024; + byte *thumb = new byte[len]; + RENDERDOC_GetThumbnail(captures.back().path.c_str(), thumb, len); - uint32_t len = 128*1024; - byte *thumb = new byte[len]; - RENDERDOC_GetThumbnail(captures.back().path.c_str(), thumb, len); + size_t l = len; + ser.Serialise("", len); + ser.SerialiseBuffer("", thumb, l); + delete[] thumb; + } + else if(childprocs.size() != children.size()) + { + uint32_t idx = (uint32_t)children.size(); - size_t l = len; - ser.Serialise("", len); - ser.SerialiseBuffer("", thumb, l); - delete[] thumb; - } + children.push_back(childprocs[idx]); + + packetType = ePacket_NewChild; + + ser.Serialise("", children.back().first); + ser.Serialise("", children.back().second); } if(curtime < pingtime && packetType == ePacket_Noop) @@ -368,8 +381,9 @@ struct RemoteAccess { ser->Serialise("", m_Target); ser->Serialise("", m_API); + ser->Serialise("", m_PID); - RDCLOG("Got remote handshake: %ls (%ls)", m_Target.c_str(), m_API.c_str()); + RDCLOG("Got remote handshake: %ls (%ls) [%u]", m_Target.c_str(), m_API.c_str(), m_PID); } else if(type == ePacket_Busy) { @@ -401,6 +415,11 @@ struct RemoteAccess return m_API.c_str(); } + uint32_t GetPID() + { + return m_PID; + } + const wchar_t *GetBusyClient() { return m_BusyClient.c_str(); @@ -525,6 +544,19 @@ struct RemoteAccess return; } + else if(type == ePacket_NewChild) + { + msg->Type = eRemoteMsg_NewChild; + + ser->Serialise("", msg->NewChild.PID); + ser->Serialise("", msg->NewChild.ident); + + RDCLOG("Got a new child process: %u %u", msg->NewChild.PID, msg->NewChild.ident); + + SAFE_DELETE(ser); + + return; + } else if(type == ePacket_NewCapture) { msg->Type = eRemoteMsg_NewCapture; @@ -578,6 +610,7 @@ struct RemoteAccess Network::Socket *m_Socket; bool m_Local; wstring m_Target, m_API, m_BusyClient; + uint32_t m_PID; map m_CaptureCopies; @@ -595,6 +628,8 @@ extern "C" RENDERDOC_API const wchar_t* RENDERDOC_CC RemoteAccess_GetTarget(Remo { return access->GetTarget(); } extern "C" RENDERDOC_API const wchar_t* RENDERDOC_CC RemoteAccess_GetAPI(RemoteAccess *access) { return access->GetAPI(); } +extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RemoteAccess_GetPID(RemoteAccess *access) +{ return access->GetPID(); } extern "C" RENDERDOC_API const wchar_t* RENDERDOC_CC RemoteAccess_GetBusyClient(RemoteAccess *access) { return access->GetBusyClient(); } diff --git a/renderdoc/hooks/sys_win32_hooks.cpp b/renderdoc/hooks/sys_win32_hooks.cpp index d49954d67..da388e709 100644 --- a/renderdoc/hooks/sys_win32_hooks.cpp +++ b/renderdoc/hooks/sys_win32_hooks.cpp @@ -126,8 +126,10 @@ class SysHook : LibraryHook RDCDEBUG("Intercepting CreateProcessA"); // inherit logfile and capture options - RENDERDOC_InjectIntoProcess(lpProcessInformation->dwProcessId, + uint32_t ident = RENDERDOC_InjectIntoProcess(lpProcessInformation->dwProcessId, RenderDoc::Inst().GetLogFile(), &RenderDoc::Inst().GetCaptureOptions(), false); + + RenderDoc::Inst().AddChildProcess((uint32_t)lpProcessInformation->dwProcessId, ident); } ResumeThread(lpProcessInformation->hThread); @@ -176,8 +178,10 @@ class SysHook : LibraryHook RDCDEBUG("Intercepting CreateProcessW"); // inherit logfile and capture options - RENDERDOC_InjectIntoProcess(lpProcessInformation->dwProcessId, + uint32_t ident = RENDERDOC_InjectIntoProcess(lpProcessInformation->dwProcessId, RenderDoc::Inst().GetLogFile(), &RenderDoc::Inst().GetCaptureOptions(), false); + + RenderDoc::Inst().AddChildProcess((uint32_t)lpProcessInformation->dwProcessId, ident); } ResumeThread(lpProcessInformation->hThread); diff --git a/renderdocui/Interop/Enums.cs b/renderdocui/Interop/Enums.cs index 72728d924..fc9febf65 100644 --- a/renderdocui/Interop/Enums.cs +++ b/renderdocui/Interop/Enums.cs @@ -384,6 +384,7 @@ namespace renderdoc NewCapture, CaptureCopied, RegisterAPI, + NewChild, }; public static class EnumString diff --git a/renderdocui/Interop/ReplayRenderer.cs b/renderdocui/Interop/ReplayRenderer.cs index e9260c269..d65d59ba9 100644 --- a/renderdocui/Interop/ReplayRenderer.cs +++ b/renderdocui/Interop/ReplayRenderer.cs @@ -64,6 +64,15 @@ namespace renderdoc }; [CustomMarshalAs(CustomUnmanagedType.CustomClass)] public BusyData Busy; + + [StructLayout(LayoutKind.Sequential)] + public struct NewChildData + { + public UInt32 PID; + public UInt32 ident; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public NewChildData NewChild; }; public class ReplayOutput @@ -749,6 +758,8 @@ namespace renderdoc [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr RemoteAccess_GetAPI(IntPtr real); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern UInt32 RemoteAccess_GetPID(IntPtr real); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr RemoteAccess_GetBusyClient(IntPtr real); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] @@ -783,6 +794,7 @@ namespace renderdoc m_Connected = true; Target = Marshal.PtrToStringUni(RemoteAccess_GetTarget(m_Real)); API = Marshal.PtrToStringUni(RemoteAccess_GetAPI(m_Real)); + PID = RemoteAccess_GetPID(m_Real); BusyClient = Marshal.PtrToStringUni(RemoteAccess_GetBusyClient(m_Real)); } @@ -851,11 +863,7 @@ namespace renderdoc } else if (msg.Type == RemoteMessageType.NewCapture) { - CaptureFile.ID = msg.NewCapture.ID; - CaptureFile.timestamp = msg.NewCapture.timestamp; - CaptureFile.localpath = msg.NewCapture.localpath; - CaptureFile.thumbnail = msg.NewCapture.thumbnail; - + CaptureFile = msg.NewCapture; CaptureExists = true; } else if (msg.Type == RemoteMessageType.CaptureCopied) @@ -869,24 +877,26 @@ namespace renderdoc API = msg.RegisterAPI.APIName; InfoUpdated = true; } + else if (msg.Type == RemoteMessageType.NewChild) + { + NewChild = msg.NewChild; + ChildAdded = true; + } } } public string BusyClient; public string Target; public string API; + public UInt32 PID; public bool CaptureExists; + public bool ChildAdded; public bool CaptureCopied; public bool InfoUpdated; - public struct CaptureInfo - { - public UInt32 ID; - public UInt64 timestamp; - public byte[] thumbnail; - public string localpath; - }; - public CaptureInfo CaptureFile = new CaptureInfo(); + public RemoteMessage.NewCaptureData CaptureFile = new RemoteMessage.NewCaptureData(); + + public RemoteMessage.NewChildData NewChild = new RemoteMessage.NewChildData(); }; }; diff --git a/renderdocui/Windows/Dialogs/LiveCapture.cs b/renderdocui/Windows/Dialogs/LiveCapture.cs index a8b68d3e4..0691cecaa 100644 --- a/renderdocui/Windows/Dialogs/LiveCapture.cs +++ b/renderdocui/Windows/Dialogs/LiveCapture.cs @@ -39,6 +39,8 @@ using System.IO; using System.Drawing.Imaging; using System.Drawing.Drawing2D; +using Process = System.Diagnostics.Process; + namespace renderdocui.Windows { public partial class LiveCapture : DockContent @@ -213,6 +215,23 @@ namespace renderdocui.Windows }); m_Connection.CaptureCopied = false; } + + if (m_Connection.ChildAdded) + { + try + { + var p = Process.GetProcessById((int)m_Connection.NewChild.PID); + + System.Diagnostics.Trace.WriteLine(String.Format("Add new child PID {0} name {1} ident {2} to UI", + m_Connection.NewChild.PID, p.ProcessName, m_Connection.NewChild.ident)); + } + catch (Exception) + { + // process expired/doesn't exist anymore + } + + m_Connection.ChildAdded = false; + } } this.BeginInvoke((MethodInvoker)delegate