diff --git a/qrenderdoc/Code/Interface/QRDInterface.h b/qrenderdoc/Code/Interface/QRDInterface.h index e0c6d4d79..32d2701d3 100644 --- a/qrenderdoc/Code/Interface/QRDInterface.h +++ b/qrenderdoc/Code/Interface/QRDInterface.h @@ -2107,28 +2107,9 @@ If no tag is present, the callback will be processed as normal. // // this is hidden from swig as for python the threading is less controlled there so we wrap the // ICaptureAccess with a force-blocking invoker - bool AccessInvoke(std::function callback, bool blocking, bool forceReplay, - rdcstr tag) - { - if(!GetCaptureAccess()) - return false; + virtual bool AccessInvoke(std::function callback, bool blocking, + bool forceReplay, rdcstr tag) = 0; - // some long running processes may be better to put on the replay thread even when local, so - // that we can keep the UI thread unblocked - if(CurrentRemote().IsConnected() || forceReplay) - { - if(blocking) - BlockInvoke([this, callback](IReplayController *) { callback(GetCaptureAccess()); }); - else - AsyncInvoke([this, callback](IReplayController *) { callback(GetCaptureAccess()); }, tag); - } - else - { - callback(GetCaptureAccess()); - } - - return true; - } // simple blocking access bool BlockAccessInvoke(std::function callback) { diff --git a/qrenderdoc/Code/ReplayManager.cpp b/qrenderdoc/Code/ReplayManager.cpp index 0a6e30448..388dad9cf 100644 --- a/qrenderdoc/Code/ReplayManager.cpp +++ b/qrenderdoc/Code/ReplayManager.cpp @@ -303,6 +303,37 @@ void ReplayManager::BlockInvoke(ReplayManager::ReplayInvokeCallback m) delete cmd; } +bool ReplayManager::AccessInvoke(std::function callback, bool blocking, + bool forceReplay, rdcstr tag) +{ + if(!GetCaptureAccess()) + return false; + + // some long running processes may be better to put on the replay thread even when local, so + // that we can keep the UI thread unblocked + if(CurrentRemote().IsConnected() || forceReplay) + { + if(!IsRunning()) + { + // if the replay thread isn't running, we won't be able to invoke so just treat this as-if + // it's a local capture and block + callback(GetCaptureAccess()); + return true; + } + + if(blocking) + BlockInvoke([this, callback](IReplayController *) { callback(GetCaptureAccess()); }); + else + AsyncInvoke([this, callback](IReplayController *) { callback(GetCaptureAccess()); }, tag); + } + else + { + callback(GetCaptureAccess()); + } + + return true; +} + void ReplayManager::CancelReplayLoop() { m_Renderer->CancelReplayLoop(); diff --git a/qrenderdoc/Code/ReplayManager.h b/qrenderdoc/Code/ReplayManager.h index d0d780d21..97f9aa023 100644 --- a/qrenderdoc/Code/ReplayManager.h +++ b/qrenderdoc/Code/ReplayManager.h @@ -68,6 +68,9 @@ public: using IReplayManager::AsyncInvoke; void BlockInvoke(ReplayInvokeCallback m); + bool AccessInvoke(std::function callback, bool blocking, bool forceReplay, + rdcstr tag); + void CancelReplayLoop(); void CloseThread(); diff --git a/qrenderdoc/Code/pyrenderdoc/PythonInvokers.cpp b/qrenderdoc/Code/pyrenderdoc/PythonInvokers.cpp index a965c2f6e..6d015d405 100644 --- a/qrenderdoc/Code/pyrenderdoc/PythonInvokers.cpp +++ b/qrenderdoc/Code/pyrenderdoc/PythonInvokers.cpp @@ -1027,6 +1027,13 @@ struct ReplayInvoker : IReplayManager } void BlockInvoke(ReplayInvokeCallback method) { return m_Replay.BlockInvoke(method); } + + // won't be available to python but we implement this for compile time matching + bool AccessInvoke(std::function callback, bool blocking, bool forceReplay, + rdcstr tag) + { + return m_Replay.AccessInvoke(callback, blocking, forceReplay, tag); + } }; struct IMainWindowInvoker : UIThreadInvoker