mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Process render commands 1 by 1 to allow pre-empting high frequency cmds
This commit is contained in:
@@ -231,6 +231,31 @@ bool RenderManager::IsRunning()
|
||||
return m_Thread && m_Thread->isRunning() && m_Running;
|
||||
}
|
||||
|
||||
void RenderManager::AsyncInvoke(const QString &tag, RenderManager::InvokeMethod m)
|
||||
{
|
||||
{
|
||||
QMutexLocker autolock(&m_RenderLock);
|
||||
for(int i = 0; i < m_RenderQueue.count();)
|
||||
{
|
||||
if(m_RenderQueue[i]->tag == tag)
|
||||
{
|
||||
InvokeHandle *cmd = m_RenderQueue.takeAt(i);
|
||||
if(cmd->selfdelete)
|
||||
delete cmd;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InvokeHandle *cmd = new InvokeHandle(m, tag);
|
||||
cmd->selfdelete = true;
|
||||
|
||||
PushInvoke(cmd);
|
||||
}
|
||||
|
||||
void RenderManager::AsyncInvoke(RenderManager::InvokeMethod m)
|
||||
{
|
||||
InvokeHandle *cmd = new InvokeHandle(m);
|
||||
@@ -373,7 +398,7 @@ void RenderManager::PushInvoke(RenderManager::InvokeHandle *cmd)
|
||||
}
|
||||
|
||||
QMutexLocker autolock(&m_RenderLock);
|
||||
m_RenderQueue.push_back(cmd);
|
||||
m_RenderQueue.enqueue(cmd);
|
||||
m_RenderCondition.wakeAll();
|
||||
}
|
||||
|
||||
@@ -396,31 +421,30 @@ void RenderManager::run()
|
||||
// main render command loop
|
||||
while(m_Running)
|
||||
{
|
||||
QQueue<InvokeHandle *> queue;
|
||||
InvokeHandle *cmd = NULL;
|
||||
|
||||
// wait for the condition to be woken, grab current queue,
|
||||
// wait for the condition to be woken, grab top of current queue,
|
||||
// unlock again.
|
||||
{
|
||||
QMutexLocker autolock(&m_RenderLock);
|
||||
m_RenderCondition.wait(&m_RenderLock, 10);
|
||||
m_RenderQueue.swap(queue);
|
||||
if(m_RenderQueue.isEmpty())
|
||||
m_RenderCondition.wait(&m_RenderLock, 10);
|
||||
|
||||
if(!m_RenderQueue.isEmpty())
|
||||
cmd = m_RenderQueue.dequeue();
|
||||
}
|
||||
|
||||
// process all the commands
|
||||
for(InvokeHandle *cmd : queue)
|
||||
{
|
||||
if(cmd == NULL)
|
||||
continue;
|
||||
if(cmd == NULL)
|
||||
continue;
|
||||
|
||||
if(cmd->method != NULL)
|
||||
cmd->method(renderer);
|
||||
if(cmd->method != NULL)
|
||||
cmd->method(renderer);
|
||||
|
||||
// if it's a throwaway command, delete it
|
||||
if(cmd->selfdelete)
|
||||
delete cmd;
|
||||
else
|
||||
cmd->processed.release();
|
||||
}
|
||||
// if it's a throwaway command, delete it
|
||||
if(cmd->selfdelete)
|
||||
delete cmd;
|
||||
else
|
||||
cmd->processed.release();
|
||||
}
|
||||
|
||||
// clean up anything left in the queue
|
||||
|
||||
@@ -131,6 +131,13 @@ public:
|
||||
|
||||
bool IsRunning();
|
||||
ReplayCreateStatus GetCreateStatus() { return m_CreateStatus; }
|
||||
// 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
|
||||
// processed.
|
||||
// the manager processes only the request on the top of the queue, so when a new tagged invoke
|
||||
// comes in, we remove any other requests in the queue before it that have the same tag
|
||||
void AsyncInvoke(const QString &tag, InvokeMethod m);
|
||||
void AsyncInvoke(InvokeMethod m);
|
||||
void BlockInvoke(InvokeMethod m);
|
||||
|
||||
@@ -155,12 +162,14 @@ public:
|
||||
private:
|
||||
struct InvokeHandle
|
||||
{
|
||||
InvokeHandle(InvokeMethod m)
|
||||
InvokeHandle(InvokeMethod m, const QString &t = QString())
|
||||
{
|
||||
tag = t;
|
||||
method = m;
|
||||
selfdelete = false;
|
||||
}
|
||||
|
||||
QString tag;
|
||||
InvokeMethod method;
|
||||
QSemaphore processed;
|
||||
bool selfdelete;
|
||||
|
||||
@@ -1889,7 +1889,7 @@ void BufferViewer::render_clicked(QMouseEvent *e)
|
||||
|
||||
if((e->buttons() & Qt::RightButton) && m_Output)
|
||||
{
|
||||
m_Ctx.Renderer().AsyncInvoke([this, curpos](IReplayRenderer *r) {
|
||||
m_Ctx.Renderer().AsyncInvoke("PickVertex", [this, curpos](IReplayRenderer *r) {
|
||||
uint32_t instanceSelected = 0;
|
||||
uint32_t vertSelected = m_Output->PickVertex(m_Ctx.CurEvent(), (uint32_t)curpos.x(),
|
||||
(uint32_t)curpos.y(), &instanceSelected);
|
||||
|
||||
@@ -2185,11 +2185,13 @@ void TextureViewer::render_mouseMove(QMouseEvent *e)
|
||||
m_PickedPoint.setX(qBound(0, m_PickedPoint.x(), (int)texptr->width - 1));
|
||||
m_PickedPoint.setY(qBound(0, m_PickedPoint.y(), (int)texptr->height - 1));
|
||||
|
||||
INVOKE_MEMFN(RT_PickPixelsAndUpdate);
|
||||
m_Ctx.Renderer().AsyncInvoke("PickPixelClick",
|
||||
[this](IReplayRenderer *r) { RT_PickPixelsAndUpdate(r); });
|
||||
}
|
||||
else if(e->buttons() == Qt::NoButton)
|
||||
{
|
||||
INVOKE_MEMFN(RT_PickHoverAndUpdate);
|
||||
m_Ctx.Renderer().AsyncInvoke("PickPixelHover",
|
||||
[this](IReplayRenderer *r) { RT_PickHoverAndUpdate(r); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user