diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index d28da9186..061169afe 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -34,6 +34,12 @@ struct FloatVector float x, y, z, w; }; +struct DirectoryFile +{ + rdctype::str filename; + uint32_t flags; +}; + struct ResourceFormat { ResourceFormat() diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index f137fc83e..4400506cd 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -483,6 +483,9 @@ struct IRemoteServer virtual bool LocalProxies(rdctype::array *out) = 0; virtual bool RemoteSupportedReplays(rdctype::array *out) = 0; + virtual rdctype::str GetHomeFolder() = 0; + virtual rdctype::array ListFolder(const char *path) = 0; + virtual uint32_t ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine, const CaptureOptions *opts) = 0; @@ -519,6 +522,11 @@ RemoteServer_LocalProxies(RemoteServer *remote, rdctype::array *ou extern "C" RENDERDOC_API bool32 RENDERDOC_CC RemoteServer_RemoteSupportedReplays(RemoteServer *remote, rdctype::array *out); +extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_GetHomeFolder(RemoteServer *remote, + rdctype::str *home); +extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_ListFolder( + RemoteServer *remote, const char *path, rdctype::array *dirlist); + extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RemoteServer_ExecuteAndInject(RemoteServer *remote, const char *app, const char *workingDir, const char *cmdLine, const CaptureOptions *opts); diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 90307b656..29c0cd062 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -25,6 +25,17 @@ #pragma once +enum DirectoryFileProperty +{ + eFileProp_Directory = 0x1, + eFileProp_Hidden = 0x2, + eFileProp_Executable = 0x4, + + eFileProp_ErrorUnknown = 0x2000, + eFileProp_ErrorAccessDenied = 0x4000, + eFileProp_ErrorInvalidPath = 0x8000, +}; + // replay_shader.h enum VarType diff --git a/renderdoc/core/remote_server.cpp b/renderdoc/core/remote_server.cpp index 2396a44c8..5bff644cb 100644 --- a/renderdoc/core/remote_server.cpp +++ b/renderdoc/core/remote_server.cpp @@ -41,6 +41,15 @@ string ToStrHelper::Get(const CaptureOptions &el) return "<...>"; } +template <> +void Serialiser::Serialise(const char *name, DirectoryFile &el) +{ + ScopedContext scope(this, name, "DirectoryFile", 0, true); + + Serialise("filename", el.filename); + Serialise("flags", el.flags); +} + enum RemoteServerPacket { eRemoteServer_Noop, @@ -54,6 +63,8 @@ enum RemoteServerPacket eRemoteServer_LogOpenProgress, eRemoteServer_LogOpened, eRemoteServer_CloseLog, + eRemoteServer_HomeDir, + eRemoteServer_ListDir, eRemoteServer_ExecuteAndInject, eRemoteServer_ShutdownServer, eRemoteServer_RemoteServerCount, @@ -197,6 +208,33 @@ static void ActiveRemoteClientThread(void *data) sendSer.Serialise("", (*it).second); } } + else if(type == eRemoteServer_HomeDir) + { + sendType = eRemoteServer_HomeDir; + + string home = FileIO::GetHomeFolderFilename(); + sendSer.Serialise("", home); + } + else if(type == eRemoteServer_ListDir) + { + string path; + recvser->Serialise("path", path); + + sendType = eRemoteServer_ListDir; + + vector files = FileIO::GetFilesInDirectory(path.c_str()); + + uint32_t count = (uint32_t)files.size(); + sendSer.Serialise("", count); + + for(uint32_t i = 0; i < count; i++) + { + DirectoryFile df; + df.filename = files[i].filename; + df.flags = files[i].flags; + sendSer.Serialise("", df); + } + } else if(type == eRemoteServer_CopyCaptureFromRemote) { string path; @@ -670,6 +708,67 @@ public: return true; } + rdctype::str GetHomeFolder() + { + rdctype::str ret; + + Serialiser sendData("", Serialiser::WRITING, false); + Send(eRemoteServer_HomeDir, sendData); + + RemoteServerPacket type = eRemoteServer_HomeDir; + + Serialiser *ser = NULL; + Get(type, &ser); + + if(ser) + { + string home; + ser->Serialise("", home); + + ret = home; + + delete ser; + } + + return ret; + } + + rdctype::array ListFolder(const char *path) + { + rdctype::array ret; + + string folderPath = path; + + Serialiser sendData("", Serialiser::WRITING, false); + sendData.Serialise("", folderPath); + Send(eRemoteServer_ListDir, sendData); + + RemoteServerPacket type = eRemoteServer_ListDir; + + Serialiser *ser = NULL; + Get(type, &ser); + + if(ser) + { + uint32_t count = 0; + ser->Serialise("", count); + + create_array_uninit(ret, count); + for(uint32_t i = 0; i < count; i++) + ser->Serialise("", ret[i]); + + delete ser; + } + else + { + create_array_uninit(ret, 1); + ret.elems[0].filename = path; + ret.elems[0].flags = eFileProp_ErrorUnknown; + } + + return ret; + } + uint32_t ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine, const CaptureOptions *opts) { @@ -896,6 +995,22 @@ RemoteServer_LocalProxies(RemoteServer *remote, rdctype::array *ou return remote->LocalProxies(out); } +extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_GetHomeFolder(RemoteServer *remote, + rdctype::str *home) +{ + rdctype::str path = remote->GetHomeFolder(); + if(home) + *home = path; +} + +extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_ListFolder( + RemoteServer *remote, const char *path, rdctype::array *dirlist) +{ + rdctype::array files = remote->ListFolder(path); + if(dirlist) + *dirlist = files; +} + extern "C" RENDERDOC_API bool32 RENDERDOC_CC RemoteServer_RemoteSupportedReplays(RemoteServer *remote, rdctype::array *out) { diff --git a/renderdocui/Interop/Enums.cs b/renderdocui/Interop/Enums.cs index c99beedd9..455f8734a 100644 --- a/renderdocui/Interop/Enums.cs +++ b/renderdocui/Interop/Enums.cs @@ -30,6 +30,18 @@ using System.Runtime.InteropServices; namespace renderdoc { + [Flags] + public enum DirectoryFileProperty + { + Directory = 0x1, + Hidden = 0x2, + Executable = 0x4, + + ErrorUnknown = 0x2000, + ErrorAccessDenied = 0x4000, + ErrorInvalidPath = 0x8000, + }; + public enum VarType { Float = 0, diff --git a/renderdocui/Interop/FetchInfo.cs b/renderdocui/Interop/FetchInfo.cs index ce17a5291..2b2416953 100644 --- a/renderdocui/Interop/FetchInfo.cs +++ b/renderdocui/Interop/FetchInfo.cs @@ -74,6 +74,34 @@ namespace renderdoc public float x, y, z, w; }; + [StructLayout(LayoutKind.Sequential)] + public struct DirectoryFile : IComparable + { + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string filename; + public DirectoryFileProperty flags; + + public override string ToString() + { + return String.Format("{0} ({1})", filename, flags); + } + + public int CompareTo(DirectoryFile o) + { + // sort directories first + bool thisdir = flags.HasFlag(DirectoryFileProperty.Directory); + bool odir = o.flags.HasFlag(DirectoryFileProperty.Directory); + + if (thisdir && !odir) + return -1; + if (!thisdir && odir) + return 1; + + // can't have duplicates with same filename, so just compare filenames + return filename.CompareTo(o.filename); + } + }; + [StructLayout(LayoutKind.Sequential)] public class ResourceFormat { diff --git a/renderdocui/Interop/ReplayRenderer.cs b/renderdocui/Interop/ReplayRenderer.cs index f3a0d18f1..727683cf1 100644 --- a/renderdocui/Interop/ReplayRenderer.cs +++ b/renderdocui/Interop/ReplayRenderer.cs @@ -858,6 +858,11 @@ namespace renderdoc [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern bool RemoteServer_RemoteSupportedReplays(IntPtr real, IntPtr outlist); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void RemoteServer_GetHomeFolder(IntPtr real, IntPtr outfolder); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern void RemoteServer_ListFolder(IntPtr real, IntPtr path, IntPtr outlist); + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern UInt32 RemoteServer_ExecuteAndInject(IntPtr real, IntPtr app, IntPtr workingDir, IntPtr cmdLine, CaptureOptions opts); @@ -896,6 +901,41 @@ namespace renderdoc } } + public string GetHomeFolder() + { + IntPtr homepath_mem = CustomMarshal.Alloc(typeof(templated_array)); + + RemoteServer_GetHomeFolder(m_Real, homepath_mem); + + string home = CustomMarshal.TemplatedArrayToString(homepath_mem, true); + + CustomMarshal.Free(homepath_mem); + + // normalise to /s and with no trailing /s + home.Replace('\\', '/'); + if (home[home.Length - 1] == '/') + home = home.Remove(0, home.Length - 1); + + return home; + } + + public DirectoryFile[] ListFolder(string path) + { + IntPtr path_mem = CustomMarshal.MakeUTF8String(path); + IntPtr out_mem = CustomMarshal.Alloc(typeof(templated_array)); + + RemoteServer_ListFolder(m_Real, path_mem, out_mem); + + DirectoryFile[] ret = (DirectoryFile[])CustomMarshal.GetTemplatedArray(out_mem, typeof(DirectoryFile), true); + + CustomMarshal.Free(out_mem); + CustomMarshal.Free(path_mem); + + Array.Sort(ret); + + return ret; + } + public string[] LocalProxies() { IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));