Pass through child processes via remote access to UI. Refs #78

This commit is contained in:
baldurk
2014-09-28 13:58:18 +01:00
parent 67645f1d63
commit a0d6d771f2
9 changed files with 127 additions and 34 deletions
+6
View File
@@ -187,4 +187,10 @@ struct RemoteMessage
{
rdctype::wstr ClientName;
} Busy;
struct NewChildData
{
uint32_t PID;
uint32_t ident;
} NewChild;
};
+1
View File
@@ -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);
+1
View File
@@ -379,4 +379,5 @@ enum RemoteMessageType
eRemoteMsg_NewCapture,
eRemoteMsg_CaptureCopied,
eRemoteMsg_RegisterAPI,
eRemoteMsg_NewChild,
};
+16
View File
@@ -31,9 +31,11 @@
#include <vector>
#include <map>
#include <set>
#include <utility>
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<uint32_t, uint32_t> > GetChildProcesses()
{
SCOPED_LOCK(m_ChildLock);
return m_Children;
}
vector<CaptureData> GetCaptures()
{
SCOPED_LOCK(m_CaptureLock);
@@ -284,6 +297,9 @@ class RenderDoc
Threading::CriticalSection m_CaptureLock;
vector<CaptureData> m_Captures;
Threading::CriticalSection m_ChildLock;
vector< pair<uint32_t, uint32_t> > m_Children;
map<RDCDriver, wstring> m_DriverNames;
map<RDCDriver, ReplayDriverProvider> m_ReplayDriverProviders;
+54 -19
View File
@@ -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<CaptureData> captures;
vector< pair<uint32_t, uint32_t> > children;
while(client)
{
@@ -97,6 +101,9 @@ void RenderDoc::RemoteAccessClientThread(void *s)
wstring curapi;
RenderDoc::Inst().GetCurrentDriver(driver, curapi);
vector<CaptureData> caps = RenderDoc::Inst().GetCaptures();
vector< pair<uint32_t, uint32_t> > 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<CaptureData> 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<uint32_t, wstring> 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(); }
+6 -2
View File
@@ -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);
+1
View File
@@ -384,6 +384,7 @@ namespace renderdoc
NewCapture,
CaptureCopied,
RegisterAPI,
NewChild,
};
public static class EnumString
+23 -13
View File
@@ -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();
};
};
@@ -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