From ced8a62af63cd955eb14d43b515e470bdac4229f Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 12 Jul 2016 16:48:57 +0200 Subject: [PATCH] Add replay command (with optional remote replay) --- renderdoc/api/replay/renderdoc_replay.h | 2 +- renderdoc/core/remote_replay.cpp | 2 +- renderdoc/replay/entry_points.cpp | 4 +- renderdoccmd/renderdoccmd.cpp | 90 +++++++++++++++++++++++-- renderdoccmd/renderdoccmd.h | 3 +- renderdoccmd/renderdoccmd_android.cpp | 3 +- renderdoccmd/renderdoccmd_apple.cpp | 3 +- renderdoccmd/renderdoccmd_linux.cpp | 5 +- renderdoccmd/renderdoccmd_win32.cpp | 9 ++- 9 files changed, 104 insertions(+), 17 deletions(-) diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 618725292..07173d7ef 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -513,7 +513,7 @@ extern "C" RENDERDOC_API RemoteAccess *RENDERDOC_CC RENDERDOC_CreateRemoteAccess extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_EnumerateRemoteConnections(const char *host, uint32_t nextIdent); -extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_DefaultReplayHostPort(); +extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_GetDefaultReplayHostPort(); extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC RENDERDOC_CreateRemoteReplayConnection(const char *host, uint32_t port, RemoteRenderer **rend); extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SpawnReplayHost(const char *listenhost, diff --git a/renderdoc/core/remote_replay.cpp b/renderdoc/core/remote_replay.cpp index 0c6ed302f..20a110f27 100644 --- a/renderdoc/core/remote_replay.cpp +++ b/renderdoc/core/remote_replay.cpp @@ -439,7 +439,7 @@ RENDERDOC_CreateRemoteReplayConnection(const char *host, uint32_t port, RemoteRe s = host; if(port == 0) - port = RENDERDOC_DefaultReplayHostPort(); + port = RENDERDOC_GetDefaultReplayHostPort(); Network::Socket *sock = NULL; diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index 35f3d4b03..d6e52198d 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -454,7 +454,7 @@ extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_EnumerateRemoteConnecti return ~0U; } -extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_DefaultReplayHostPort() +extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_GetDefaultReplayHostPort() { return RenderDoc_ReplayNetworkPort; } @@ -472,7 +472,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SpawnReplayHost(const char listenhost = "0.0.0.0"; if(port == 0) - port = RENDERDOC_DefaultReplayHostPort(); + port = RENDERDOC_GetDefaultReplayHostPort(); RenderDoc::Inst().BecomeReplayHost(listenhost, (uint16_t)port, *killReplay); } diff --git a/renderdoccmd/renderdoccmd.cpp b/renderdoccmd/renderdoccmd.cpp index 049a6d718..4b52207a7 100644 --- a/renderdoccmd/renderdoccmd.cpp +++ b/renderdoccmd/renderdoccmd.cpp @@ -42,7 +42,7 @@ void readCapOpts(const std::string &str, CaptureOptions *opts) *(b++) = (byte(str[i * 2 + 0] - 'a') << 4) | byte(str[i * 2 + 1] - 'a'); } -void DisplayRendererPreview(ReplayRenderer *renderer) +void DisplayRendererPreview(ReplayRenderer *renderer, uint32_t width, uint32_t height) { if(renderer == NULL) return; @@ -66,7 +66,8 @@ void DisplayRendererPreview(ReplayRenderer *renderer) d.offy = 0.0f; d.sliceFace = 0; d.rawoutput = false; - d.lightBackgroundColour = d.darkBackgroundColour = FloatVector(0.0f, 0.0f, 0.0f, 0.0f); + d.lightBackgroundColour = FloatVector(0.81f, 0.81f, 0.81f, 1.0f); + d.darkBackgroundColour = FloatVector(0.57f, 0.57f, 0.57f, 1.0f); d.Red = d.Green = d.Blue = true; d.Alpha = false; @@ -89,7 +90,7 @@ void DisplayRendererPreview(ReplayRenderer *renderer) d.texid = id; } - DisplayRendererPreview(renderer, d); + DisplayRendererPreview(renderer, d, width, height); } std::map commands; @@ -389,7 +390,7 @@ struct ReplayHostCommand : public Command parser.add( "host", 'h', "The interface to listen on. By default listens on all interfaces", false, ""); parser.add("port", 'p', "The port to listen on.", false, - RENDERDOC_DefaultReplayHostPort()); + RENDERDOC_GetDefaultReplayHostPort()); } virtual const char *Description() { @@ -412,6 +413,84 @@ struct ReplayHostCommand : public Command } }; +struct ReplayCommand : public Command +{ + virtual void AddOptions(cmdline::parser &parser) + { + parser.set_footer(""); + parser.add("width", 'w', "The preview window width.", false, 1280); + parser.add("height", 'h', "The preview window height.", false, 720); + parser.add("remote-host", 0, + "Instead of replaying locally, replay on this host over the network.", false); + parser.add("remote-port", 0, "If --remote-host is set, use this port.", false, + RENDERDOC_GetDefaultReplayHostPort()); + } + virtual const char *Description() + { + return "Replay the log file and show the backbuffer on a preview window."; + } + virtual bool IsInternalOnly() { return false; } + virtual bool IsCaptureCommand() { return false; } + virtual int Execute(cmdline::parser &parser, const CaptureOptions &) + { + if(parser.rest().empty()) + { + std::cerr << "Error: capture command requires a filename to load." << std::endl + << std::endl + << parser.usage(); + return 0; + } + + string filename = parser.rest()[0]; + + float progress = 0.0f; + RemoteRenderer *remote = NULL; + ReplayRenderer *renderer = NULL; + + if(parser.exist("remote-host")) + { + ReplayCreateStatus status = RENDERDOC_CreateRemoteReplayConnection( + parser.get("remote-host").c_str(), parser.get("remote-port"), &remote); + + if(remote == NULL || status != eReplayCreate_Success) + { + std::cerr << "Error: Couldn't connect to " << parser.get("remote-host") << ":" + << parser.get("remote-port") << "." << std::endl; + std::cerr << " Have you run renderdoccmd replayhost ?" << std::endl; + return 1; + } + + float progress = 0.0f; + + ReplayRenderer *renderer = NULL; + status = RemoteRenderer_CreateProxyRenderer(remote, 0, filename.c_str(), &progress, &renderer); + + if(status == eReplayCreate_Success) + DisplayRendererPreview(renderer, parser.get("width"), + parser.get("height")); + else + std::cerr << "Couldn't load and replay '" << filename << "'." << std::endl; + + ReplayRenderer_Shutdown(renderer); + remote->Shutdown(); + } + else + { + ReplayCreateStatus status = + RENDERDOC_CreateReplayRenderer(filename.c_str(), &progress, &renderer); + + if(status == eReplayCreate_Success) + DisplayRendererPreview(renderer, parser.get("width"), + parser.get("height")); + else + std::cerr << "Couldn't load and replay '" << filename << "'." << std::endl; + + ReplayRenderer_Shutdown(renderer); + } + return 0; + } +}; + int renderdoccmd(std::vector &argv) { // add basic commands, and common aliases @@ -427,9 +506,8 @@ int renderdoccmd(std::vector &argv) add_command("capture", new CaptureCommand()); add_command("inject", new InjectCommand()); add_command("replayhost", new ReplayHostCommand()); - // add_command("replay", new ReplayCommand()); + add_command("replay", new ReplayCommand()); // add_command("cap32for64", new Cap32For64Command()); - // add_command("remotereplay", new RemoteReplayCommand()); if(argv.size() <= 1) { diff --git a/renderdoccmd/renderdoccmd.h b/renderdoccmd/renderdoccmd.h index a58613bfa..065c562af 100644 --- a/renderdoccmd/renderdoccmd.h +++ b/renderdoccmd/renderdoccmd.h @@ -56,5 +56,6 @@ int renderdoccmd(std::vector &argv); void readCapOpts(const std::string &str, CaptureOptions *opts); // these must be defined in platform .cpps -void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg); +void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg, uint32_t width, + uint32_t height); std::wstring GetUsername(); diff --git a/renderdoccmd/renderdoccmd_android.cpp b/renderdoccmd/renderdoccmd_android.cpp index 185f69eaa..7f4cc0027 100644 --- a/renderdoccmd/renderdoccmd_android.cpp +++ b/renderdoccmd/renderdoccmd_android.cpp @@ -47,7 +47,8 @@ string GetUsername() return string("Username"); } -void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg) +void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg, uint32_t width, + uint32_t height) { ANativeWindow *connectionScreenWindow = android_state->window; diff --git a/renderdoccmd/renderdoccmd_apple.cpp b/renderdoccmd/renderdoccmd_apple.cpp index dbaf1c41b..c338fc50e 100644 --- a/renderdoccmd/renderdoccmd_apple.cpp +++ b/renderdoccmd/renderdoccmd_apple.cpp @@ -39,7 +39,8 @@ string GetUsername() return string(buf, buf + strlen(buf)); } -void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg) +void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg, uint32_t width, + uint32_t height) { } diff --git a/renderdoccmd/renderdoccmd_linux.cpp b/renderdoccmd/renderdoccmd_linux.cpp index eaaef9ebb..ebedc18b9 100644 --- a/renderdoccmd/renderdoccmd_linux.cpp +++ b/renderdoccmd/renderdoccmd_linux.cpp @@ -42,7 +42,8 @@ string GetUsername() return string(buf, buf + strlen(buf)); } -void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg) +void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg, uint32_t width, + uint32_t height) { int scr; @@ -63,7 +64,7 @@ void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg value_list[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY; - xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, 1280, 720, 0, + xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list); /* Magic code that will send notification when window is destroyed */ diff --git a/renderdoccmd/renderdoccmd_win32.cpp b/renderdoccmd/renderdoccmd_win32.cpp index ec77a15bd..a6a05829a 100644 --- a/renderdoccmd/renderdoccmd_win32.cpp +++ b/renderdoccmd/renderdoccmd_win32.cpp @@ -225,10 +225,15 @@ wstring GetUsername() return username; } -void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg) +void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg, uint32_t width, + uint32_t height) { + RECT wr = {0, 0, width, height}; + AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); + HWND wnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"renderdoccmd", L"renderdoccmd", WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, 1280, 720, NULL, NULL, hInstance, NULL); + CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top, + NULL, NULL, hInstance, NULL); if(wnd == NULL) return;