diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 8d6d66eda..aa3529ae4 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -435,6 +435,7 @@ struct ITargetControl virtual void TriggerCapture(uint32_t numFrames) = 0; virtual void QueueCapture(uint32_t frameNumber) = 0; virtual void CopyCapture(uint32_t remoteID, const char *localpath) = 0; + virtual void DeleteCapture(uint32_t remoteID) = 0; virtual void ReceiveMessage(TargetControlMessage *msg) = 0; }; @@ -467,6 +468,8 @@ extern "C" RENDERDOC_API void RENDERDOC_CC TargetControl_QueueCapture(TargetCont extern "C" RENDERDOC_API void RENDERDOC_CC TargetControl_CopyCapture(TargetControl *control, uint32_t remoteID, const char *localpath); +extern "C" RENDERDOC_API void RENDERDOC_CC TargetControl_DeleteCapture(TargetControl *control, + uint32_t remoteID); extern "C" RENDERDOC_API void RENDERDOC_CC TargetControl_ReceiveMessage(TargetControl *control, TargetControlMessage *msg); diff --git a/renderdoc/core/target_control.cpp b/renderdoc/core/target_control.cpp index c71845ddd..0eb7c9467 100644 --- a/renderdoc/core/target_control.cpp +++ b/renderdoc/core/target_control.cpp @@ -39,6 +39,7 @@ enum PacketType ePacket_RegisterAPI, ePacket_TriggerCapture, ePacket_CopyCapture, + ePacket_DeleteCapture, ePacket_QueueCapture, ePacket_NewChild, }; @@ -177,6 +178,14 @@ void RenderDoc::TargetControlClientThread(void *s) RenderDoc::Inst().QueueCapture(frameNum); } + else if(type == ePacket_DeleteCapture) + { + uint32_t id = 0; + recvser->Serialise("", id); + + // this means it will be deleted on shutdown + RenderDoc::Inst().MarkCaptureRetrieved(id); + } else if(type == ePacket_CopyCapture) { caps = RenderDoc::Inst().GetCaptures(); @@ -465,6 +474,19 @@ public: m_CaptureCopies[remoteID] = localpath; } + void DeleteCapture(uint32_t remoteID) + { + Serialiser ser("", Serialiser::WRITING, false); + + ser.Serialise("", remoteID); + + if(!SendPacket(m_Socket, ePacket_DeleteCapture, ser)) + { + SAFE_DELETE(m_Socket); + return; + } + } + void ReceiveMessage(TargetControlMessage *msg) { if(m_Socket == NULL) @@ -664,6 +686,12 @@ extern "C" RENDERDOC_API void RENDERDOC_CC TargetControl_CopyCapture(TargetContr control->CopyCapture(remoteID, localpath); } +extern "C" RENDERDOC_API void RENDERDOC_CC TargetControl_DeleteCapture(TargetControl *control, + uint32_t remoteID) +{ + control->DeleteCapture(remoteID); +} + extern "C" RENDERDOC_API void RENDERDOC_CC TargetControl_ReceiveMessage(TargetControl *control, TargetControlMessage *msg) { diff --git a/renderdocui/Interop/ReplayRenderer.cs b/renderdocui/Interop/ReplayRenderer.cs index 4ae68f1d0..0b0ea71b5 100644 --- a/renderdocui/Interop/ReplayRenderer.cs +++ b/renderdocui/Interop/ReplayRenderer.cs @@ -1135,6 +1135,8 @@ namespace renderdoc private static extern void TargetControl_QueueCapture(IntPtr real, UInt32 frameNumber); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern void TargetControl_CopyCapture(IntPtr real, UInt32 remoteID, IntPtr localpath); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void TargetControl_DeleteCapture(IntPtr real, UInt32 remoteID); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern void TargetControl_ReceiveMessage(IntPtr real, IntPtr outmsg); @@ -1213,6 +1215,11 @@ namespace renderdoc CustomMarshal.Free(localpath_mem); } + public void DeleteCapture(UInt32 id) + { + TargetControl_DeleteCapture(m_Real, id); + } + public void ReceiveMessage() { if (m_Real != IntPtr.Zero) diff --git a/renderdocui/Windows/Dialogs/LiveCapture.cs b/renderdocui/Windows/Dialogs/LiveCapture.cs index f1c585b4d..4cc726d25 100644 --- a/renderdocui/Windows/Dialogs/LiveCapture.cs +++ b/renderdocui/Windows/Dialogs/LiveCapture.cs @@ -60,6 +60,10 @@ namespace renderdocui.Windows bool m_Disconnect = false; TargetControl m_Connection = null; + uint m_CopyLogID = uint.MaxValue; + string m_CopyLogLocalPath = ""; + List m_DeleteLogs = new List(); + bool m_IgnoreThreadClosed = false; string m_Host; @@ -197,6 +201,23 @@ namespace renderdocui.Windows m_CaptureFrameNum = 0; } + if (m_CopyLogLocalPath != "") + { + m_Connection.CopyCapture(m_CopyLogID, m_CopyLogLocalPath); + m_CopyLogLocalPath = ""; + m_CopyLogID = uint.MaxValue; + } + + List dels = new List(); + lock (m_DeleteLogs) + { + dels.AddRange(m_DeleteLogs); + m_DeleteLogs.Clear(); + } + + foreach(var del in dels) + m_Connection.DeleteCapture(del); + if (m_Disconnect) { m_Connection.Shutdown(); @@ -236,6 +257,13 @@ namespace renderdocui.Windows { uint capID = m_Connection.CaptureFile.ID; string path = m_Connection.CaptureFile.path; + + this.BeginInvoke((MethodInvoker)delegate + { + CaptureCopied(capID, path); + }); + + m_Connection.CaptureCopied = false; } if (m_Connection.ChildAdded) @@ -363,8 +391,22 @@ namespace renderdocui.Windows private void OpenCapture(CaptureLog log) { - m_Main.LoadLogfile(log.path, !log.saved, log.local); log.opened = true; + + if (!log.local && + (m_Core.Renderer.Remote == null || + m_Core.Renderer.Remote.Hostname != m_Host || + !m_Core.Renderer.Remote.Connected) + ) + { + MessageBox.Show( + String.Format("This capture is on remote host {0} and there is no active replay context on that host.\n" + + "You can either save the log locally, or switch to a replay context on {0}.\n\n", m_Host), + "No active replay context", MessageBoxButtons.OK); + return; + } + + m_Main.LoadLogfile(log.path, !log.saved, log.local); } private bool SaveCapture(CaptureLog log) @@ -381,8 +423,25 @@ namespace renderdocui.Windows { File.Copy(log.path, path, true); } + else if (m_Connection.Connected) + { + // if we have a current live connection, prefer using it + m_CopyLogLocalPath = path; + m_CopyLogID = log.remoteID; + } else { + if (m_Core.Renderer.Remote == null || + m_Core.Renderer.Remote.Hostname != m_Host || + !m_Core.Renderer.Remote.Connected) + { + MessageBox.Show( + String.Format("This capture is on remote host {0} and there is no active replay context on that host.\n" + + "Without an active replay context the capture cannot be saved, try switching to a replay context on {0}.\n\n", m_Host), + "No active replay context", MessageBoxButtons.OK); + return false; + } + m_Core.Renderer.CopyCaptureFromRemote(log.path, path, this); m_Core.Renderer.DeleteCapture(log.path, false); } @@ -435,15 +494,15 @@ namespace renderdocui.Windows } // we either have to save or delete the log. Make sure that if it's remote that we are able - // to by having an active replay context on that host. - if (suppressRemoteWarning == false && + // to by having an active connection or replay context on that host. + if (suppressRemoteWarning == false && !m_Connection.Connected && (m_Core.Renderer.Remote == null || m_Core.Renderer.Remote.Hostname != m_Host || !m_Core.Renderer.Remote.Connected) ) { DialogResult res2 = MessageBox.Show( - String.Format("This connection is to a remote host {0} and there is no active replay context on that host.\n", m_Host) + + String.Format("This capture is on remote host {0} and there is no active replay context on that host.\n", m_Host) + "Without an active replay context the capture cannot be " + (res == DialogResult.Yes ? "saved.\n\n" : "deleted.\n\n") + "Would you like to continue and discard this capture and any others, to be left in the temporary folder on the remote machine?", "No active replay context", MessageBoxButtons.YesNoCancel); @@ -492,7 +551,18 @@ namespace renderdocui.Windows } else { - m_Core.Renderer.DeleteCapture(log.path, log.local); + // if connected, prefer using the live connection + if (m_Connection.Connected && !log.local) + { + lock (m_DeleteLogs) + { + m_DeleteLogs.Add(log.remoteID); + } + } + else + { + m_Core.Renderer.DeleteCapture(log.path, log.local); + } } } catch (System.Exception) @@ -512,6 +582,7 @@ namespace renderdocui.Windows return; } + CleanItems(); KillThread(); } @@ -532,8 +603,8 @@ namespace renderdocui.Windows captures.LargeImageList.Images.Clear(); thumbs.Dispose(); - KillThread(); CleanItems(); + KillThread(); } private bool CheckAllowDelete() @@ -577,7 +648,18 @@ namespace renderdocui.Windows try { - m_Core.Renderer.DeleteCapture(log.path, log.local); + // if connected, prefer using the live connection + if (m_Connection.Connected && !log.local) + { + lock (m_DeleteLogs) + { + m_DeleteLogs.Add(log.remoteID); + } + } + else + { + m_Core.Renderer.DeleteCapture(log.path, log.local); + } } catch (System.Exception) { @@ -650,6 +732,22 @@ namespace renderdocui.Windows } } + private void CaptureCopied(uint ID, string localPath) + { + foreach (ListViewItem item in captures.Items) + { + var log = item.Tag as CaptureLog; + + if (log != null && log.remoteID == ID) + { + log.local = true; + log.path = localPath; + item.SubItems[0].Text = log.exe; + item.SubItems[0].Font = new Font(item.SubItems[0].Font, FontStyle.Regular); + } + } + } + private void CaptureAdded(uint ID, string executable, string api, byte[] thumbnail, DateTime timestamp, string path, bool local) { if (thumbnail == null || thumbnail.Length == 0)