From 0f4acb395642bb5a30744314f1d0d12c60288102 Mon Sep 17 00:00:00 2001 From: Aliya Pazylbekova Date: Fri, 15 Feb 2019 14:32:19 -0500 Subject: [PATCH] Add support for GGP in "renderdoccmd replay" --- renderdoccmd/renderdoccmd_ggp.cpp | 199 +++++++++++++++++++++++++++++- 1 file changed, 198 insertions(+), 1 deletion(-) diff --git a/renderdoccmd/renderdoccmd_ggp.cpp b/renderdoccmd/renderdoccmd_ggp.cpp index 486a344d7..06d89e980 100644 --- a/renderdoccmd/renderdoccmd_ggp.cpp +++ b/renderdoccmd/renderdoccmd_ggp.cpp @@ -23,8 +23,205 @@ ******************************************************************************/ #include "renderdoccmd.h" +#include +#include +#include + +#include +#include + +const uint64_t kMicrosecondsPerFrame = 16666L; + +// struct appData: Global application data +static struct +{ + // GGP + GgpEventQueue event_queue; + uint32_t stream_started_handler_id; + uint32_t stream_stopped_handler_id; + // General + bool quit; +} app_data = {0}; + +void Daemonise() +{ + // don't change dir, but close stdin/stdout + daemon(1, 0); +} + +WindowingData DisplayRemoteServerPreview(bool active, const rdcarray &systems) +{ + static WindowingData remoteServerPreview = {WindowingSystem::Unknown}; + // No preview implemented. + return remoteServerPreview; +} + +// ClockNowMicroSeconds(): Return current time in microseconds +static inline uint64_t ClockNowMicroSeconds() +{ + struct timespec now = {}; + clock_gettime(CLOCK_MONOTONIC_RAW, &now); + uint64_t nanoseconds = (now.tv_sec * 1000000000LL) + now.tv_nsec; + uint64_t microseconds = nanoseconds / 1000LL; + return microseconds; +} + +// HandleStreamStarted(): Client connected handler +static void HandleStreamStarted(void *user_data) +{ + std::cout << "GGP client connected" << std::endl; +} + +// HandleStreamStopped(): Client disconnected handler +static void HandleStreamStopped(const GgpStreamStoppedEvent *event, void *user_data) +{ + std::cout << "GGP client disconnected" << std::endl; + // Exit the application if the client disconnects to exit. + if(event->stream_stopped_reason == kGgpStreamStopped_Exited) + { + app_data.quit = true; + } + else if(event->stream_stopped_reason == kGgpStreamStopped_Unexpected) + { + GgpSuspended(); + } +} + +// UnregisterCallback(): Handler unregistered +static void UnregisterCallback(void *user_data) +{ + std::cout << "Unregistered callback" << std::endl; +} + +// Initialize(): Initialize application +static void Initialize() +{ + // Initialize event queue + app_data.event_queue = GgpEventQueueCreate(); + std::cout << "GGP event queue created" << std::endl; + // Add client connection handlers + app_data.stream_started_handler_id = GgpAddStreamStartedHandler( + app_data.event_queue, HandleStreamStarted, NULL, UnregisterCallback); + app_data.stream_stopped_handler_id = GgpAddStreamStoppedHandler( + app_data.event_queue, HandleStreamStopped, NULL, UnregisterCallback); + // Signal that the session is ready to receive events. + GgpHandlersRegistered(); + + GgpReadyToStream(); + std::cout << "GGP ready to stream" << std::endl; +} + +// Finalize(): Clean up application resources +static void Finalize() +{ + // Destroy the event queue + GgpEventQueueDestroy(app_data.event_queue); + std::cout << "GGP event queue destroyed" << std::endl; + // Remove client connection handlers. + GgpRemoveStreamStartedHandler(app_data.stream_started_handler_id); + GgpRemoveStreamStoppedHandler(app_data.stream_stopped_handler_id); + // Indicate that GGP should shutdown. + GgpShutDown(); +} + +void DisplayRendererPreview(IReplayController *renderer, TextureDisplay &displayCfg, uint32_t width, + uint32_t height, uint32_t numLoops) +{ + Initialize(); + + IReplayOutput *out = renderer->CreateOutput(CreateGgpWindowingData(), ReplayOutputType::Texture); + out->SetTextureDisplay(displayCfg); + + // Wait until user closes the window, then exit + while(!app_data.quit) + { + uint64_t whenToResume = ClockNowMicroSeconds() + kMicrosecondsPerFrame; + while(GgpEventQueueProcessEvent(app_data.event_queue, 0)) + { + } + renderer->SetFrameEvent(10000000, true); + out->Display(); + // Sleep for 1/60 second (one frame) + uint64_t timeLeft = whenToResume - ClockNowMicroSeconds(); + if(timeLeft > 0) + { + struct timespec sleepTime = {}; + sleepTime.tv_nsec = timeLeft * 1000LL; + nanosleep(&sleepTime, NULL); + } + } + + Finalize(); +} + +void sig_handler(int signo) +{ + if(usingKillSignal) + killSignal = true; + else + exit(1); +} int main(int argc, char *argv[]) { - return 0; + setlocale(LC_CTYPE, ""); + + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + + GlobalEnvironment env; + + // add compiled-in support to version line + { + std::string support = "APIs supported at compile-time: "; + int count = 0; + +#if defined(RENDERDOC_SUPPORT_VULKAN) + support += "Vulkan, "; + count++; +#endif + + if(count == 0) + { + support += "None."; + } + else + { + // remove trailing ', ' + support.pop_back(); + support.pop_back(); + support += "."; + } + + add_version_line(support); + + support = "Windowing systems supported at compile-time: "; + count = 0; + + support += "GGP, "; + count++; + +#if defined(RENDERDOC_SUPPORT_VULKAN) + support += "Vulkan KHR_display, "; + count++; +#endif + + if(count == 0) + { + support += "None."; + } + else + { + // remove trailing ', ' + support.pop_back(); + support.pop_back(); + support += "."; + } + + add_version_line(support); + } + + int ret = renderdoccmd(env, argc, argv); + + return ret; }