mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Pass through child processes via remote access to UI. Refs #78
This commit is contained in:
@@ -187,4 +187,10 @@ struct RemoteMessage
|
||||
{
|
||||
rdctype::wstr ClientName;
|
||||
} Busy;
|
||||
|
||||
struct NewChildData
|
||||
{
|
||||
uint32_t PID;
|
||||
uint32_t ident;
|
||||
} NewChild;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -379,4 +379,5 @@ enum RemoteMessageType
|
||||
eRemoteMsg_NewCapture,
|
||||
eRemoteMsg_CaptureCopied,
|
||||
eRemoteMsg_RegisterAPI,
|
||||
eRemoteMsg_NewChild,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -384,6 +384,7 @@ namespace renderdoc
|
||||
NewCapture,
|
||||
CaptureCopied,
|
||||
RegisterAPI,
|
||||
NewChild,
|
||||
};
|
||||
|
||||
public static class EnumString
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user