mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-23 21:08:06 -05:00
Throttle SetEvent call in render thread (#3511)
Reduce unnecessary SetEvent CPU overhead by using `std::atomic_flag` to avoid setting kernel events when the painting thread is already awake and running.
This commit is contained in:
@@ -17,6 +17,8 @@ RenderThread::RenderThread() :
|
||||
_fKeepRunning(true),
|
||||
_hPaintEnabledEvent(nullptr)
|
||||
{
|
||||
_fNextFrameRequested.clear();
|
||||
_fPainting.clear();
|
||||
}
|
||||
|
||||
RenderThread::~RenderThread()
|
||||
@@ -158,10 +160,21 @@ DWORD WINAPI RenderThread::_ThreadProc()
|
||||
while (_fKeepRunning)
|
||||
{
|
||||
WaitForSingleObject(_hPaintEnabledEvent, INFINITE);
|
||||
WaitForSingleObject(_hEvent, INFINITE);
|
||||
|
||||
// Skip waiting if next frame is requested.
|
||||
if (_fNextFrameRequested.test_and_set(std::memory_order_relaxed))
|
||||
{
|
||||
_fNextFrameRequested.clear(std::memory_order_relaxed);
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitForSingleObject(_hEvent, INFINITE);
|
||||
}
|
||||
|
||||
ResetEvent(_hPaintCompletedEvent);
|
||||
|
||||
_fPainting.test_and_set(std::memory_order_acquire);
|
||||
|
||||
LOG_IF_FAILED(_pRenderer->PaintFrame());
|
||||
|
||||
SetEvent(_hPaintCompletedEvent);
|
||||
@@ -171,6 +184,8 @@ DWORD WINAPI RenderThread::_ThreadProc()
|
||||
{
|
||||
Sleep(s_FrameLimitMilliseconds);
|
||||
}
|
||||
|
||||
_fPainting.clear(std::memory_order_release);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
@@ -178,6 +193,14 @@ DWORD WINAPI RenderThread::_ThreadProc()
|
||||
|
||||
void RenderThread::NotifyPaint()
|
||||
{
|
||||
// If we are currently painting a frame, set _fNextFrameRequested flag
|
||||
// to indicate we want to paint next frame immediately.
|
||||
if (_fPainting.test_and_set(std::memory_order_acquire))
|
||||
{
|
||||
_fNextFrameRequested.test_and_set(std::memory_order_relaxed);
|
||||
return;
|
||||
}
|
||||
|
||||
SetEvent(_hEvent);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,5 +47,7 @@ namespace Microsoft::Console::Render
|
||||
IRenderer* _pRenderer; // Non-ownership pointer
|
||||
|
||||
bool _fKeepRunning;
|
||||
std::atomic_flag _fNextFrameRequested;
|
||||
std::atomic_flag _fPainting;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user