mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 09:00:44 +00:00
Make event selection 'soft' blocking instead of hard blocking
* Normally SetEventID is synchronous and blocking, and will stall the UI while it is processing. However we can at least pop up a progress dialog and allow the UI to function (if not be interactive due to the blocking progress dialog) when some other long-running task is delaying the processing on the replay thread.
This commit is contained in:
@@ -1478,15 +1478,36 @@ void CaptureContext::SetEventID(const rdcarray<ICaptureViewer *> &exclude, uint3
|
||||
uint32_t prevEventID = m_EventID;
|
||||
m_EventID = eventId;
|
||||
|
||||
m_Replay.BlockInvoke([this, eventId, force](IReplayController *r) {
|
||||
bool done = false;
|
||||
|
||||
QString tag = lit("replaySetEvent");
|
||||
|
||||
// we can't return until the event is selected, but a blocking invoke on the UI thread can cause
|
||||
// the UI to stall. We ideally want to have at least an interactive UI and a progress bar.
|
||||
m_Replay.AsyncInvoke(tag, [this, eventId, force, &done](IReplayController *r) {
|
||||
r->SetFrameEvent(eventId, force);
|
||||
m_CurD3D11PipelineState = r->GetD3D11PipelineState();
|
||||
m_CurD3D12PipelineState = r->GetD3D12PipelineState();
|
||||
m_CurGLPipelineState = r->GetGLPipelineState();
|
||||
m_CurVulkanPipelineState = r->GetVulkanPipelineState();
|
||||
m_CurPipelineState = &r->GetPipelineState();
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
// wait a short while before displaying the progress dialog (which won't show if we're already
|
||||
// done by the time we reach it).
|
||||
// Keep waiting if the current tag is a set event, we don't want to be popping up progress bars
|
||||
// when the user is browsing the frame if it's going slow. If that's the case we'll just block the
|
||||
// UI thread. Instead only pop up the progress bar if some other large task is blocking.
|
||||
for(int i = 0; !done && (i < 100 || m_Replay.GetCurrentProcessingTag().isEmpty() ||
|
||||
m_Replay.GetCurrentProcessingTag() == tag);
|
||||
i++)
|
||||
QThread::msleep(5);
|
||||
|
||||
ShowProgressDialog(m_MainWindow->Widget(), tr("Please wait, working..."),
|
||||
[&done]() { return done; });
|
||||
|
||||
bool updateSelectedEvent = force || prevSelectedEventID != selectedEventID;
|
||||
bool updateEvent = force || prevEventID != eventId;
|
||||
|
||||
|
||||
@@ -240,6 +240,12 @@ float ReplayManager::GetCurrentProcessingTime()
|
||||
return m_CommandTimer.isValid() ? double(m_CommandTimer.elapsed()) / 1000.0 : 0.0;
|
||||
}
|
||||
|
||||
QString ReplayManager::GetCurrentProcessingTag()
|
||||
{
|
||||
QMutexLocker lock(&m_TimerLock);
|
||||
return m_CommandTag;
|
||||
}
|
||||
|
||||
void ReplayManager::AsyncInvoke(const rdcstr &tag, ReplayManager::InvokeCallback m)
|
||||
{
|
||||
QString qtag(tag);
|
||||
@@ -486,6 +492,7 @@ void ReplayManager::run(int proxyRenderer, const QString &capturefile, const Rep
|
||||
{
|
||||
QMutexLocker lock(&m_TimerLock);
|
||||
m_CommandTimer.start();
|
||||
m_CommandTag = cmd->tag;
|
||||
}
|
||||
|
||||
cmd->method(m_Renderer);
|
||||
@@ -493,6 +500,7 @@ void ReplayManager::run(int proxyRenderer, const QString &capturefile, const Rep
|
||||
{
|
||||
QMutexLocker lock(&m_TimerLock);
|
||||
m_CommandTimer.invalidate();
|
||||
m_CommandTag = QString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
bool IsRunning();
|
||||
ReplayStatus GetCreateStatus() { return m_CreateStatus; }
|
||||
float GetCurrentProcessingTime();
|
||||
QString GetCurrentProcessingTag();
|
||||
// this tagged version is for cases when we might send a request - e.g. to pick a vertex or pixel
|
||||
// - and want to pre-empt it with a new request before the first has returned. Either because some
|
||||
// other work is taking a while or because we're sending requests faster than they can be
|
||||
@@ -119,6 +120,7 @@ private:
|
||||
|
||||
QMutex m_TimerLock;
|
||||
QElapsedTimer m_CommandTimer;
|
||||
QString m_CommandTag;
|
||||
|
||||
QMutex m_RenderLock;
|
||||
QQueue<InvokeHandle *> m_RenderQueue;
|
||||
|
||||
Reference in New Issue
Block a user