Change remote server from being a one-shot remote replay to proper loop

* The remote server is intended to be long-lived and do many things, so
  we keep it around and mix proxy commands with normal commands.
This commit is contained in:
baldurk
2016-08-02 23:28:09 +02:00
parent 30dcc72a68
commit aa69c2d6d2
3 changed files with 274 additions and 180 deletions
+7 -4
View File
@@ -481,8 +481,11 @@ struct IRemoteServer
virtual bool LocalProxies(rdctype::array<rdctype::str> *out) = 0;
virtual bool RemoteSupportedReplays(rdctype::array<rdctype::str> *out) = 0;
virtual ReplayCreateStatus CreateProxyRenderer(uint32_t proxyid, const char *logfile,
float *progress, ReplayRenderer **rend) = 0;
virtual void CopyCapture(const char *filename, float *progress) = 0;
virtual ReplayCreateStatus OpenCapture(uint32_t proxyid, const char *logfile, float *progress,
ReplayRenderer **rend) = 0;
virtual void CloseCapture(ReplayRenderer *rend) = 0;
};
#endif
@@ -507,8 +510,8 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC
RemoteServer_RemoteSupportedReplays(RemoteServer *remote, rdctype::array<rdctype::str> *out);
extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC
RemoteServer_CreateProxyRenderer(RemoteServer *remote, uint32_t proxyid, const char *logfile,
float *progress, ReplayRenderer **rend);
RemoteServer_OpenCapture(RemoteServer *remote, uint32_t proxyid, const char *logfile,
float *progress, ReplayRenderer **rend);
//////////////////////////////////////////////////////////////////////////
// camera
+25
View File
@@ -92,6 +92,31 @@ string ToStrHelper<false, WindowingSystem>::Get(const WindowingSystem &el)
return tostrBuf;
}
template <>
string ToStrHelper<false, ReplayCreateStatus>::Get(const ReplayCreateStatus &el)
{
switch(el)
{
case eReplayCreate_Success: return "Success";
case eReplayCreate_UnknownError: return "Unknown error";
case eReplayCreate_InternalError: return "Internal error";
case eReplayCreate_NetworkIOFailed: return "Network I/O failed";
case eReplayCreate_FileIOFailed: return "File I/O failed";
case eReplayCreate_FileIncompatibleVersion: return "File of incompatible version";
case eReplayCreate_FileCorrupted: return "File corrupted";
case eReplayCreate_APIUnsupported: return "API unsupported";
case eReplayCreate_APIInitFailed: return "API initialisation failed";
case eReplayCreate_APIIncompatibleVersion: return "API incompatible version";
case eReplayCreate_APIHardwareUnsupported: return "API hardware unsupported";
default: break;
}
char tostrBuf[256] = {0};
StringFormat::snprintf(tostrBuf, 255, "ReplayCreateStatus<%d>", el);
return tostrBuf;
}
template <>
string ToStrHelper<false, RENDERDOC_InputButton>::Get(const RENDERDOC_InputButton &el)
{
+242 -176
View File
@@ -40,8 +40,10 @@ enum RemoteServerPacket
eRemoteServer_Noop,
eRemoteServer_RemoteDriverList,
eRemoteServer_CopyCapture,
eRemoteServer_OpenCapture,
eRemoteServer_LogOpenProgress,
eRemoteServer_LogReady,
eRemoteServer_LogOpened,
eRemoteServer_CloseCapture,
eRemoteServer_RemoteServerCount,
};
@@ -82,8 +84,6 @@ void RenderDoc::BecomeRemoteServer(const char *listenhost, uint16_t port, volati
if(sock == NULL)
return;
bool newlyReady = true;
std::vector<std::pair<uint32_t, uint32_t> > listenRanges;
bool allowExecution = true;
@@ -161,14 +161,10 @@ void RenderDoc::BecomeRemoteServer(const char *listenhost, uint16_t port, volati
else
RDCLOG("Blocking execution commands");
RDCLOG("Replay host ready for requests...");
while(!killReplay)
{
if(newlyReady)
{
RDCLOG("Replay host ready for requests.");
newlyReady = false;
}
Network::Socket *client = sock->AcceptClient(false);
if(client == NULL)
@@ -212,137 +208,183 @@ void RenderDoc::BecomeRemoteServer(const char *listenhost, uint16_t port, volati
continue;
}
Serialiser ser("", Serialiser::WRITING, false);
vector<string> tempFiles;
IRemoteDriver *driver = NULL;
ProxySerialiser *proxy = NULL;
newlyReady = true;
Serialiser sendSer("", Serialiser::WRITING, false);
map<RDCDriver, string> drivers = RenderDoc::Inst().GetRemoteDrivers();
uint32_t count = (uint32_t)drivers.size();
ser.Serialise("", count);
for(auto it = drivers.begin(); it != drivers.end(); ++it)
while(client)
{
RDCDriver driver = it->first;
ser.Serialise("", driver);
ser.Serialise("", (*it).second);
}
if(client && !client->Connected())
break;
if(!SendPacket(client, eRemoteServer_RemoteDriverList, ser))
{
RDCERR("Network error sending supported driver list");
SAFE_DELETE(client);
continue;
}
if(killReplay)
break;
Threading::Sleep(4);
sendSer.Rewind();
// don't care about the result, just want to check that the socket hasn't been gracefully shut
// down
client->IsRecvDataWaiting();
if(!client->Connected())
{
RDCLOG("Connection closed after sending remote driver list");
SAFE_DELETE(client);
continue;
}
Threading::Sleep(4);
string cap_file;
string dummy, dummy2;
FileIO::GetDefaultFiles("remotecopy", cap_file, dummy, dummy2);
Serialiser *fileRecv = NULL;
if(!RecvChunkedFile(client, eRemoteServer_CopyCapture, cap_file.c_str(), fileRecv, NULL))
{
FileIO::Delete(cap_file.c_str());
RDCERR("Network error receiving file");
SAFE_DELETE(fileRecv);
SAFE_DELETE(client);
continue;
}
RDCLOG("File received.");
SAFE_DELETE(fileRecv);
RDCDriver driverType = RDC_Unknown;
string driverName = "";
RenderDoc::Inst().FillInitParams(cap_file.c_str(), driverType, driverName, NULL);
if(RenderDoc::Inst().HasRemoteDriver(driverType))
{
ProgressLoopData data;
data.sock = client;
data.killsignal = false;
data.progress = 0.0f;
RenderDoc::Inst().SetProgressPtr(&data.progress);
Threading::ThreadHandle ticker = Threading::CreateThread(ProgressTicker, &data);
IRemoteDriver *driver = NULL;
auto status = RenderDoc::Inst().CreateRemoteDriver(driverType, cap_file.c_str(), &driver);
if(status != eReplayCreate_Success || driver == NULL)
if(client->IsRecvDataWaiting())
{
RDCERR("Failed to create remote driver for driver type %d name %s", driverType,
driverName.c_str());
SAFE_DELETE(client);
continue;
}
RemoteServerPacket type;
Serialiser *recvser = NULL;
driver->ReadLogInitialisation();
if(!RecvPacket(client, type, &recvser))
break;
RenderDoc::Inst().SetProgressPtr(NULL);
data.killsignal = true;
Threading::JoinThread(ticker);
Threading::CloseThread(ticker);
FileIO::Delete(cap_file.c_str());
SendPacket(client, eRemoteServer_LogReady);
ProxySerialiser *proxy = new ProxySerialiser(client, driver);
while(client)
{
int packet;
Serialiser *data = NULL;
if(!RecvPacket(client, packet, &data))
if(client == NULL)
{
SAFE_DELETE(data);
SAFE_DELETE(client);
SAFE_DELETE(recvser);
continue;
}
else if(type == eRemoteServer_RemoteDriverList)
{
map<RDCDriver, string> drivers = RenderDoc::Inst().GetRemoteDrivers();
uint32_t count = (uint32_t)drivers.size();
sendSer.Serialise("", count);
for(auto it = drivers.begin(); it != drivers.end(); ++it)
{
RDCDriver driver = it->first;
sendSer.Serialise("", driver);
sendSer.Serialise("", (*it).second);
}
type = eRemoteServer_RemoteDriverList;
}
else if(type == eRemoteServer_CopyCapture)
{
string cap_file;
string dummy, dummy2;
FileIO::GetDefaultFiles("remotecopy", cap_file, dummy, dummy2);
Serialiser *fileRecv = NULL;
RDCLOG("Copying file to local path '%s'.", cap_file.c_str());
if(!RecvChunkedFile(client, type, cap_file.c_str(), fileRecv, NULL))
{
FileIO::Delete(cap_file.c_str());
RDCERR("Network error receiving file");
SAFE_DELETE(fileRecv);
break;
}
RDCLOG("File received.");
tempFiles.push_back(cap_file);
SAFE_DELETE(fileRecv);
}
else if(type == eRemoteServer_OpenCapture)
{
string cap_file;
recvser->Serialise("filename", cap_file);
RDCASSERT(driver == NULL && proxy == NULL);
RDCDriver driverType = RDC_Unknown;
string driverName = "";
RenderDoc::Inst().FillInitParams(cap_file.c_str(), driverType, driverName, NULL);
if(RenderDoc::Inst().HasRemoteDriver(driverType))
{
ProgressLoopData data;
data.sock = client;
data.killsignal = false;
data.progress = 0.0f;
RenderDoc::Inst().SetProgressPtr(&data.progress);
Threading::ThreadHandle ticker = Threading::CreateThread(ProgressTicker, &data);
ReplayCreateStatus status =
RenderDoc::Inst().CreateRemoteDriver(driverType, cap_file.c_str(), &driver);
sendSer.Serialise("status", status);
if(status != eReplayCreate_Success || driver == NULL)
{
RDCERR("Failed to create remote driver for driver type %d name %s", driverType,
driverName.c_str());
continue;
}
driver->ReadLogInitialisation();
RenderDoc::Inst().SetProgressPtr(NULL);
data.killsignal = true;
Threading::JoinThread(ticker);
Threading::CloseThread(ticker);
type = eRemoteServer_LogOpened;
proxy = new ProxySerialiser(client, driver);
}
else
{
RDCERR("File needs driver for %s which isn't supported!", driverName.c_str());
ReplayCreateStatus status = eReplayCreate_APIUnsupported;
sendSer.Serialise("status", status);
type = eRemoteServer_LogOpened;
}
}
else if(type == eRemoteServer_CloseCapture)
{
if(driver)
driver->Shutdown();
driver = NULL;
SAFE_DELETE(proxy);
type = eRemoteServer_Noop;
}
else if((int)type >= eReplayProxy_First && proxy)
{
bool ok = proxy->Tick(type, recvser);
if(!ok)
break;
continue;
}
SAFE_DELETE(recvser);
if(type != eRemoteServer_Noop && !SendPacket(client, type, sendSer))
{
RDCERR("Network error sending supported driver list");
break;
}
if(!proxy->Tick(packet, data) || killReplay)
{
SAFE_DELETE(data);
SAFE_DELETE(client);
}
continue;
}
driver->Shutdown();
RDCLOG("Closing replay connection");
SAFE_DELETE(proxy);
SAFE_DELETE(client);
}
else
{
RDCERR("File needs driver for %s which isn't supported!", driverName.c_str());
FileIO::Delete(cap_file.c_str());
}
SAFE_DELETE(client);
if(driver)
driver->Shutdown();
SAFE_DELETE(proxy);
for(size_t i = 0; i < tempFiles.size(); i++)
{
FileIO::Delete(tempFiles[i].c_str());
}
RDCLOG("Closing replay connection from %u.%u.%u.%u.", Network::GetIPOctet(ip, 0),
Network::GetIPOctet(ip, 1), Network::GetIPOctet(ip, 2), Network::GetIPOctet(ip, 3));
RDCLOG("Ready for new connection...");
}
SAFE_DELETE(sock);
@@ -358,36 +400,6 @@ public:
m_Proxies.reserve(m.size());
for(auto it = m.begin(); it != m.end(); ++it)
m_Proxies.push_back(*it);
{
RemoteServerPacket type;
Serialiser *ser = NULL;
GetPacket(type, &ser);
m.clear();
if(ser)
{
uint32_t count = 0;
ser->Serialise("", count);
for(uint32_t i = 0; i < count; i++)
{
RDCDriver driver = RDC_Unknown;
string name = "";
ser->Serialise("", driver);
ser->Serialise("", name);
m[driver] = name;
}
delete ser;
}
}
m_RemoteDrivers.reserve(m.size());
for(auto it = m.begin(); it != m.end(); ++it)
m_RemoteDrivers.push_back(*it);
}
virtual ~RemoteServer() { SAFE_DELETE(m_Socket); }
void Shutdown() { delete this; }
@@ -411,21 +423,65 @@ public:
if(out == NULL)
return false;
create_array_uninit(*out, m_RemoteDrivers.size());
{
Serialiser sendData("", Serialiser::WRITING, false);
Send(eRemoteServer_RemoteDriverList, sendData);
size_t i = 0;
for(auto it = m_RemoteDrivers.begin(); it != m_RemoteDrivers.end(); ++it, ++i)
out->elems[i] = it->second;
RemoteServerPacket type = eRemoteServer_RemoteDriverList;
Serialiser *ser = NULL;
Get(type, &ser);
if(ser)
{
uint32_t count = 0;
ser->Serialise("", count);
create_array_uninit(*out, count);
for(uint32_t i = 0; i < count; i++)
{
RDCDriver driver = RDC_Unknown;
string name = "";
ser->Serialise("", driver);
ser->Serialise("", name);
out->elems[i] = name;
}
delete ser;
}
}
return true;
}
ReplayCreateStatus CreateProxyRenderer(uint32_t proxyid, const char *logfile, float *progress,
ReplayRenderer **rend)
void CopyCapture(const char *filename, float *progress)
{
Serialiser sendData("", Serialiser::WRITING, false);
Send(eRemoteServer_CopyCapture, sendData);
float dummy = 0.0f;
if(progress == NULL)
progress = &dummy;
sendData.Rewind();
if(!SendChunkedFile(m_Socket, eRemoteServer_CopyCapture, filename, sendData, progress))
{
SAFE_DELETE(m_Socket);
return;
}
}
ReplayCreateStatus OpenCapture(uint32_t proxyid, const char *filename, float *progress,
ReplayRenderer **rend)
{
if(rend == NULL)
return eReplayCreate_InternalError;
string logfile = filename;
if(proxyid >= m_Proxies.size())
{
RDCERR("Invalid proxy driver id %d specified for remote renderer", proxyid);
@@ -438,21 +494,15 @@ public:
RDCDriver proxydrivertype = m_Proxies[proxyid].first;
Serialiser ser("", Serialiser::WRITING, false);
if(!SendChunkedFile(m_Socket, eRemoteServer_CopyCapture, logfile, ser, progress))
{
SAFE_DELETE(m_Socket);
return eReplayCreate_NetworkIOFailed;
}
RDCLOG("Sent file to replay host. Loading...");
Serialiser sendData("", Serialiser::WRITING, false);
sendData.Serialise("logfile", logfile);
Send(eRemoteServer_OpenCapture, sendData);
Serialiser *progressSer = NULL;
RemoteServerPacket type = eRemoteServer_Noop;
while(m_Socket)
{
Serialiser *progressSer;
GetPacket(type, &progressSer);
Get(type, &progressSer);
if(!m_Socket || type != eRemoteServer_LogOpenProgress)
break;
@@ -460,17 +510,25 @@ public:
progressSer->Serialise("", *progress);
RDCLOG("% 3.0f%%...", (*progress) * 100.0f);
SAFE_DELETE(progressSer);
}
if(!m_Socket || type != eRemoteServer_LogReady)
if(!m_Socket || type != eRemoteServer_LogOpened)
return eReplayCreate_NetworkIOFailed;
ReplayCreateStatus status = eReplayCreate_Success;
progressSer->Serialise("status", status);
*progress = 1.0f;
if(status != eReplayCreate_Success)
return status;
RDCLOG("Log ready on replay host");
IReplayDriver *proxyDriver = NULL;
auto status = RenderDoc::Inst().CreateReplayDriver(proxydrivertype, NULL, &proxyDriver);
status = RenderDoc::Inst().CreateReplayDriver(proxydrivertype, NULL, &proxyDriver);
if(status != eReplayCreate_Success || !proxyDriver)
{
@@ -498,10 +556,19 @@ public:
return eReplayCreate_Success;
}
void CloseCapture(ReplayRenderer *rend)
{
Serialiser sendData("", Serialiser::WRITING, false);
Send(eRemoteServer_CloseCapture, sendData);
rend->Shutdown();
}
private:
Network::Socket *m_Socket;
void GetPacket(RemoteServerPacket &type, Serialiser **ser)
void Send(RemoteServerPacket type, const Serialiser &ser) { SendPacket(m_Socket, type, ser); }
void Get(RemoteServerPacket &type, Serialiser **ser)
{
vector<byte> payload;
@@ -518,7 +585,6 @@ private:
}
vector<pair<RDCDriver, string> > m_Proxies;
vector<pair<RDCDriver, string> > m_RemoteDrivers;
};
extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_Shutdown(RemoteServer *remote)
@@ -539,10 +605,10 @@ RemoteServer_RemoteSupportedReplays(RemoteServer *remote, rdctype::array<rdctype
}
extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC
RemoteServer_CreateProxyRenderer(RemoteServer *remote, uint32_t proxyid, const char *logfile,
float *progress, ReplayRenderer **rend)
RemoteServer_OpenCapture(RemoteServer *remote, uint32_t proxyid, const char *logfile,
float *progress, ReplayRenderer **rend)
{
return remote->CreateProxyRenderer(proxyid, logfile, progress, rend);
return remote->OpenCapture(proxyid, logfile, progress, rend);
}
extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC