From d2faf763567456f38fa91b8fa13b9d44cbf46f0a Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 19 Aug 2016 12:44:20 +0200 Subject: [PATCH] Save machine ident in captures and compare to machine ident on open * If the machine idents differ in significant ways that we'd consider it to be a different platform (currently just OS), and if so mark it as supported but suggested to be replayed remotely. --- renderdoc/api/replay/renderdoc_replay.h | 4 +-- renderdoc/api/replay/replay_enums.h | 7 +++++ renderdoc/core/core.cpp | 6 +++- renderdoc/core/core.h | 2 +- renderdoc/core/remote_server.cpp | 5 +-- renderdoc/driver/d3d11/d3d11_replay.cpp | 3 +- renderdoc/driver/d3d12/d3d12_replay.cpp | 3 +- renderdoc/driver/gl/gl_replay_linux.cpp | 3 +- renderdoc/driver/gl/gl_replay_win32.cpp | 3 +- renderdoc/driver/vulkan/vk_replay.cpp | 4 ++- renderdoc/os/os_specific.cpp | 41 +++++++++++++++++++++++++ renderdoc/os/os_specific.h | 1 + renderdoc/replay/entry_points.cpp | 28 ++++++++++++++--- renderdoc/replay/replay_renderer.cpp | 4 ++- renderdoc/serialise/serialiser.cpp | 18 +++++++++++ renderdoc/serialise/serialiser.h | 17 ++++++++++ renderdocui/Interop/Enums.cs | 7 +++++ renderdocui/Interop/StaticExports.cs | 16 ++++++---- renderdocui/Windows/MainWindow.cs | 11 ++++--- 19 files changed, 155 insertions(+), 28 deletions(-) diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 58d396563..e679388e4 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -594,8 +594,8 @@ extern "C" RENDERDOC_API uint32_t RENDERDOC_CC Topology_VertexOffset(PrimitiveTo // Takes the filename of the log. Returns NULL in the case of any error. ////////////////////////////////////////////////////////////////////////// -extern "C" RENDERDOC_API bool32 RENDERDOC_CC RENDERDOC_SupportLocalReplay(const char *logfile, - rdctype::str *driverName); +extern "C" RENDERDOC_API ReplaySupport RENDERDOC_CC RENDERDOC_SupportLocalReplay( + const char *logfile, rdctype::str *driverName, rdctype::str *recordMachineIdent); extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC RENDERDOC_CreateReplayRenderer(const char *logfile, float *progress, ReplayRenderer **rend); diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 706879729..0909b5f51 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -492,6 +492,13 @@ enum CounterUnits eUnits_Percentage, }; +enum ReplaySupport +{ + eReplaySupport_Unsupported, + eReplaySupport_Supported, + eReplaySupport_SuggestRemote, +}; + enum ReplayCreateStatus { eReplayCreate_Success = 0, diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index 1a13cda6f..1f72be7f9 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -633,7 +633,8 @@ Serialiser *RenderDoc::OpenWriteSerialiser(uint32_t frameNum, RDCInitParams *par } ReplayCreateStatus RenderDoc::FillInitParams(const char *logFile, RDCDriver &driverType, - string &driverName, RDCInitParams *params) + string &driverName, uint64_t &fileMachineIdent, + RDCInitParams *params) { Serialiser ser(logFile, Serialiser::READING, true); @@ -659,6 +660,7 @@ ReplayCreateStatus RenderDoc::FillInitParams(const char *logFile, RDCDriver &dri { driverType = RDC_Image; driverName = "Image"; + fileMachineIdent = 0; return eReplayCreate_Success; } } @@ -678,6 +680,8 @@ ReplayCreateStatus RenderDoc::FillInitParams(const char *logFile, RDCDriver &dri ser.Rewind(); + fileMachineIdent = ser.GetSavedMachineIdent(); + { int chunkType = ser.PushContext(NULL, NULL, 1, false); diff --git a/renderdoc/core/core.h b/renderdoc/core/core.h index ab9bbe7a6..17230d032 100644 --- a/renderdoc/core/core.h +++ b/renderdoc/core/core.h @@ -229,7 +229,7 @@ public: } ReplayCreateStatus FillInitParams(const char *logfile, RDCDriver &driverType, string &driverName, - RDCInitParams *params); + uint64_t &fileMachineIdent, RDCInitParams *params); void RegisterReplayProvider(RDCDriver driver, const char *name, ReplayDriverProvider provider); void RegisterRemoteProvider(RDCDriver driver, const char *name, RemoteDriverProvider provider); diff --git a/renderdoc/core/remote_server.cpp b/renderdoc/core/remote_server.cpp index 29d2cc4ff..34adb14f2 100644 --- a/renderdoc/core/remote_server.cpp +++ b/renderdoc/core/remote_server.cpp @@ -322,8 +322,9 @@ static void ActiveRemoteClientThread(void *data) RDCDriver driverType = RDC_Unknown; string driverName = ""; - ReplayCreateStatus status = - RenderDoc::Inst().FillInitParams(cap_file.c_str(), driverType, driverName, NULL); + uint64_t fileMachineIdent = 0; + ReplayCreateStatus status = RenderDoc::Inst().FillInitParams( + cap_file.c_str(), driverType, driverName, fileMachineIdent, NULL); if(status != eReplayCreate_Success) { diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 084e7f1bc..33acdb0e0 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -1978,10 +1978,11 @@ ReplayCreateStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver * D3D11InitParams initParams; RDCDriver driverFileType = RDC_D3D11; string driverName = "D3D11"; + uint64_t machineIdent = 0; if(logfile) { auto status = RenderDoc::Inst().FillInitParams(logfile, driverFileType, driverName, - (RDCInitParams *)&initParams); + machineIdent, (RDCInitParams *)&initParams); if(status != eReplayCreate_Success) return status; } diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index f0450d2cf..b6c7bb7f5 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -547,10 +547,11 @@ ReplayCreateStatus D3D12_CreateReplayDevice(const char *logfile, IReplayDriver * D3D12InitParams initParams; RDCDriver driverFileType = RDC_D3D12; string driverName = "D3D12"; + uint64_t machineIdent = 0; if(logfile) { auto status = RenderDoc::Inst().FillInitParams(logfile, driverFileType, driverName, - (RDCInitParams *)&initParams); + machineIdent, (RDCInitParams *)&initParams); if(status != eReplayCreate_Success) return status; } diff --git a/renderdoc/driver/gl/gl_replay_linux.cpp b/renderdoc/driver/gl/gl_replay_linux.cpp index 52c6fda8a..ff1658278 100644 --- a/renderdoc/driver/gl/gl_replay_linux.cpp +++ b/renderdoc/driver/gl/gl_replay_linux.cpp @@ -265,9 +265,10 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr GLInitParams initParams; RDCDriver driverType = RDC_OpenGL; string driverName = "OpenGL"; + uint64_t machineIdent = 0; if(logfile) { - auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, + auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, machineIdent, (RDCInitParams *)&initParams); if(status != eReplayCreate_Success) return status; diff --git a/renderdoc/driver/gl/gl_replay_win32.cpp b/renderdoc/driver/gl/gl_replay_win32.cpp index 218126cb8..75820c27b 100644 --- a/renderdoc/driver/gl/gl_replay_win32.cpp +++ b/renderdoc/driver/gl/gl_replay_win32.cpp @@ -261,9 +261,10 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr GLInitParams initParams; RDCDriver driverType = RDC_OpenGL; string driverName = "OpenGL"; + uint64_t machineIdent = 0; if(logfile) { - auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, + auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, machineIdent, (RDCInitParams *)&initParams); if(status != eReplayCreate_Success) return status; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index d9651df2b..c5d7716aa 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -5557,8 +5557,10 @@ ReplayCreateStatus Vulkan_CreateReplayDevice(const char *logfile, IReplayDriver VkInitParams initParams; RDCDriver driverType = RDC_Vulkan; string driverName = "VulkanReplay"; + uint64_t machineIdent = 0; if(logfile) - RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, (RDCInitParams *)&initParams); + RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, machineIdent, + (RDCInitParams *)&initParams); if(initParams.SerialiseVersion != VkInitParams::VK_SERIALISE_VERSION) { diff --git a/renderdoc/os/os_specific.cpp b/renderdoc/os/os_specific.cpp index 3eae1a250..63f31b8e8 100644 --- a/renderdoc/os/os_specific.cpp +++ b/renderdoc/os/os_specific.cpp @@ -127,3 +127,44 @@ string Callstack::AddressDetails::formattedString(const char *commonPath) return fmt; } + +string OSUtility::MakeMachineIdentString(uint64_t ident) +{ + string ret = ""; + + if(ident & MachineIdent_Windows) + ret += "Windows "; + else if(ident & MachineIdent_Linux) + ret += "Linux "; + else if(ident & MachineIdent_macOS) + ret += "macOS "; + else if(ident & MachineIdent_Android) + ret += "Android "; + else if(ident & MachineIdent_iOS) + ret += "iOS "; + + if(ident & MachineIdent_Arch_x86) + ret += "x86 "; + else if(ident & MachineIdent_Arch_ARM) + ret += "ARM "; + + if(ident & MachineIdent_32bit) + ret += "32-bit "; + else if(ident & MachineIdent_64bit) + ret += "64-bit "; + + switch(ident & MachineIdent_GPU_Mask) + { + case MachineIdent_GPU_ARM: ret += "ARM GPU "; break; + case MachineIdent_GPU_AMD: ret += "AMD GPU "; break; + case MachineIdent_GPU_IMG: ret += "Imagination GPU "; break; + case MachineIdent_GPU_Intel: ret += "Intel GPU "; break; + case MachineIdent_GPU_NV: ret += "nVidia GPU "; break; + case MachineIdent_GPU_QUALCOMM: ret += "QUALCOMM GPU "; break; + case MachineIdent_GPU_Samsung: ret += "Samsung GPU "; break; + case MachineIdent_GPU_Verisilicon: ret += "Verisilicon GPU "; break; + default: break; + } + + return ret; +} diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index e99c29014..ce4796980 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -411,6 +411,7 @@ enum MachineIdentBits }; uint64_t GetMachineIdent(); +string MakeMachineIdentString(uint64_t ident); }; namespace Bits diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index e11551c25..89befa69a 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -315,20 +315,38 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_TriggerExceptionHandler(voi } } -extern "C" RENDERDOC_API bool32 RENDERDOC_CC RENDERDOC_SupportLocalReplay(const char *logfile, - rdctype::str *driver) +extern "C" RENDERDOC_API ReplaySupport RENDERDOC_CC RENDERDOC_SupportLocalReplay( + const char *logfile, rdctype::str *driver, rdctype::str *recordMachineIdent) { if(logfile == NULL) - return false; + return eReplaySupport_Unsupported; RDCDriver driverType = RDC_Unknown; string driverName = ""; - RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, NULL); + uint64_t fileMachineIdent = 0; + RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, fileMachineIdent, NULL); if(driver) *driver = driverName; - return RenderDoc::Inst().HasReplayDriver(driverType); + bool supported = RenderDoc::Inst().HasReplayDriver(driverType); + + if(!supported) + return eReplaySupport_Unsupported; + + if(fileMachineIdent != 0) + { + uint64_t machineIdent = OSUtility::GetMachineIdent(); + + if(recordMachineIdent) + *recordMachineIdent = OSUtility::MakeMachineIdentString(fileMachineIdent); + + if((machineIdent & OSUtility::MachineIdent_OS_Mask) != + (fileMachineIdent & OSUtility::MachineIdent_OS_Mask)) + return eReplaySupport_SuggestRemote; + } + + return eReplaySupport_Supported; } extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC diff --git a/renderdoc/replay/replay_renderer.cpp b/renderdoc/replay/replay_renderer.cpp index becac8ad1..0fd403b65 100644 --- a/renderdoc/replay/replay_renderer.cpp +++ b/renderdoc/replay/replay_renderer.cpp @@ -1552,7 +1552,9 @@ ReplayCreateStatus ReplayRenderer::CreateDevice(const char *logfile) RDCDriver driverType = RDC_Unknown; string driverName = ""; - auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, NULL); + uint64_t fileMachineIdent = 0; + auto status = + RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, fileMachineIdent, NULL); if(driverType == RDC_Unknown || driverName == "" || status != eReplayCreate_Success) { diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index 311cb94ce..23f1cb451 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -1450,6 +1450,24 @@ void Serialiser::FlushToDisk() SAFE_DELETE_ARRAY(symbolDB); } + // write the machine identifier as an ASCII section + { + const char sectionName[] = "renderdoc/internal/machineid"; + + uint64_t machineID = OSUtility::GetMachineIdent(); + + BinarySectionHeader section = {0}; + section.isASCII = 0; // redundant but explicit + section.sectionNameLength = sizeof(sectionName); // includes null terminator + section.sectionType = eSectionType_MachineID; + section.sectionFlags = eSectionFlag_None; + section.sectionLength = sizeof(machineID); + + FileIO::fwrite(§ion, 1, offsetof(BinarySectionHeader, name), binFile); + FileIO::fwrite(sectionName, 1, sizeof(sectionName), binFile); + FileIO::fwrite(&machineID, 1, sizeof(machineID), binFile); + } + FileIO::fclose(binFile); } } diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index cb1c4e0e3..4bad0bc29 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -180,6 +180,7 @@ public: eSectionType_Unknown = 0, eSectionType_FrameCapture, // renderdoc/internal/framecapture eSectionType_ResolveDatabase, // renderdoc/internal/resolvedb + eSectionType_MachineID, // renderdoc/internal/machineid eSectionType_FrameBookmarks, // renderdoc/ui/bookmarks eSectionType_Notes, // renderdoc/ui/notes eSectionType_Num, @@ -281,6 +282,22 @@ public: Callstack::StackResolver *GetCallstackResolver() { return m_pResolver; } void SetCallstack(uint64_t *levels, size_t numLevels); + uint64_t GetSavedMachineIdent() + { + Section *id = m_KnownSections[eSectionType_MachineID]; + + // section might not be present on older captures (or if it was stripped out + // by someone over-eager to remove information) + if(id != NULL && id->data.size() >= sizeof(uint64_t)) + { + uint64_t ident = 0; + memcpy(&ident, &id->data[0], sizeof(ident)); + return ident; + } + + return 0; + } + // get the callstack associated with the last scope Callstack::Stackwalk *GetLastCallstack() { diff --git a/renderdocui/Interop/Enums.cs b/renderdocui/Interop/Enums.cs index 75ac00e9d..8514fb365 100644 --- a/renderdocui/Interop/Enums.cs +++ b/renderdocui/Interop/Enums.cs @@ -504,6 +504,13 @@ namespace renderdoc Percentage, }; + public enum ReplaySupport + { + Unsupported, + Supported, + SuggestRemote, + }; + public enum ReplayCreateStatus { Success = 0, diff --git a/renderdocui/Interop/StaticExports.cs b/renderdocui/Interop/StaticExports.cs index 5052c979a..7f0a262b3 100644 --- a/renderdocui/Interop/StaticExports.cs +++ b/renderdocui/Interop/StaticExports.cs @@ -49,7 +49,7 @@ namespace renderdoc class StaticExports { [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] - private static extern bool RENDERDOC_SupportLocalReplay(IntPtr logfile, IntPtr outdriver); + private static extern ReplaySupport RENDERDOC_SupportLocalReplay(IntPtr logfile, IntPtr outdriver, IntPtr outident); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern ReplayCreateStatus RENDERDOC_CreateReplayRenderer(IntPtr logfile, ref float progress, ref IntPtr rendPtr); @@ -110,19 +110,23 @@ namespace renderdoc [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern void RENDERDOC_FreeEnvironmentModificationList(IntPtr mem); - public static bool SupportLocalReplay(string logfile, out string driverName) + public static ReplaySupport SupportLocalReplay(string logfile, out string driverName, out string recordMachineIdent) { - IntPtr mem = CustomMarshal.Alloc(typeof(templated_array)); + IntPtr name_mem = CustomMarshal.Alloc(typeof(templated_array)); + IntPtr ident_mem = CustomMarshal.Alloc(typeof(templated_array)); IntPtr logfile_mem = CustomMarshal.MakeUTF8String(logfile); - bool ret = RENDERDOC_SupportLocalReplay(logfile_mem, mem); + ReplaySupport ret = RENDERDOC_SupportLocalReplay(logfile_mem, name_mem, ident_mem); CustomMarshal.Free(logfile_mem); - driverName = CustomMarshal.TemplatedArrayToString(mem, true); + driverName = CustomMarshal.TemplatedArrayToString(name_mem, true); + recordMachineIdent = CustomMarshal.TemplatedArrayToString(ident_mem, true); + + CustomMarshal.Free(name_mem); + CustomMarshal.Free(ident_mem); - CustomMarshal.Free(mem); return ret; } diff --git a/renderdocui/Windows/MainWindow.cs b/renderdocui/Windows/MainWindow.cs index 8c0ec8e59..fb8bdb38b 100644 --- a/renderdocui/Windows/MainWindow.cs +++ b/renderdocui/Windows/MainWindow.cs @@ -625,24 +625,25 @@ namespace renderdocui.Windows if (m_Core.LogLoading) return; string driver = ""; - bool support = false; + string machineIdent = ""; + ReplaySupport support = ReplaySupport.Unsupported; bool remoteReplay = !local || (m_Core.Renderer.Remote != null && m_Core.Renderer.Remote.Connected); if (local) { - support = StaticExports.SupportLocalReplay(filename, out driver); + support = StaticExports.SupportLocalReplay(filename, out driver, out machineIdent); if (remoteReplay) { - support = false; + support = ReplaySupport.Unsupported; string[] remoteDrivers = m_Core.Renderer.GetRemoteSupport(); for (int i = 0; i < remoteDrivers.Length; i++) { if (driver == remoteDrivers[i]) - support = true; + support = ReplaySupport.Supported; } } } @@ -651,7 +652,7 @@ namespace renderdocui.Windows // if driver is empty something went wrong loading the log, let it be handled as usual // below. Otherwise indicate that support is missing. - if (driver.Length > 0 && !support) + if (driver.Length > 0 && support == ReplaySupport.Unsupported) { if (remoteReplay) {