@@ -61,16 +61,21 @@ CompositorBase::CompositorBase()
6161, m_MirrorTexture(nullptr )
6262, m_OverlayCount(0 )
6363, m_ActiveOverlays()
64- , m_FrameMutex()
65- , m_FrameEvent()
64+ , m_FrameEvents()
6665{
6766// We want to handle all graphics tasks explicitly instead of implicitly letting WaitGetPoses execute them
6867vr::VRCompositor ()->SetExplicitTimingMode (vr::VRCompositorTimingMode_Explicit_ApplicationPerformsPostPresentHandoff);
69- m_FrameEvent[0 ] = CreateEvent (nullptr , true , true , nullptr );
68+
69+ // Create a ring buffer of events
70+ for (int i = 0 ; i < MAX_QUEUE_AHEAD; i++)
71+ m_FrameEvents[i] = CreateEvent (nullptr , true , i == 0 , nullptr );
7072}
7173
7274CompositorBase::~CompositorBase ()
7375{
76+ for (int i = 0 ; i < MAX_QUEUE_AHEAD; i++)
77+ CloseHandle (m_FrameEvents[i]);
78+
7479if (m_MirrorTexture)
7580delete m_MirrorTexture;
7681}
@@ -121,22 +126,9 @@ ovrResult CompositorBase::WaitToBeginFrame(ovrSession session, long long frameIn
121126{
122127MICROPROFILE_SCOPE (WaitToBeginFrame);
123128
124- // Find the event for the last frame
125- void * handle = nullptr ;
126- {
127- std::unique_lock<std::mutex> lk (m_FrameMutex);
128- handle = m_FrameEvent[frameIndex - 1 ];
129-
130- // If the last frame hasn't started yet, create a new event object for it
131- if (!handle)
132- {
133- handle = CreateEvent (nullptr , true , false , nullptr );
134- m_FrameEvent[frameIndex - 1 ] = handle;
135- }
136- }
137-
138129// Wait on the last frame completion with a 500ms timeout
139- bool timeout = WaitForSingleObject (handle, 500 ) != WAIT_OBJECT_0;
130+ assert (frameIndex - session->FrameIndex < MAX_QUEUE_AHEAD);
131+ bool timeout = WaitForSingleObject (m_FrameEvents[(frameIndex - 1 ) % MAX_QUEUE_AHEAD], 500 ) != WAIT_OBJECT_0;
140132
141133// Wait for the actual frame start
142134if (!session->Details ->UseHack (SessionDetails::HACK_WAIT_ON_SUBMIT))
@@ -151,34 +143,8 @@ ovrResult CompositorBase::BeginFrame(ovrSession session, long long frameIndex)
151143{
152144MICROPROFILE_SCOPE (BeginFrame);
153145
154- {
155- std::unique_lock<std::mutex> lk (m_FrameMutex);
156-
157- // Find the event from the last frame
158- auto it = m_FrameEvent.find (frameIndex - 1 );
159-
160- if (m_FrameEvent[frameIndex])
161- {
162- // If this frame already has an event, close the last one if it exists
163- if (it != m_FrameEvent.end ())
164- {
165- CloseHandle (it->second );
166- m_FrameEvent.erase (it);
167- }
168- }
169- else if (it != m_FrameEvent.end ())
170- {
171- // Reset the event from the last frame and reuse it for the next frame
172- ResetEvent (it->second );
173- m_FrameEvent[frameIndex] = it->second ;
174- m_FrameEvent.erase (it);
175- }
176- else
177- {
178- // Create a new event for this frame
179- m_FrameEvent[frameIndex] = CreateEvent (nullptr , true , false , nullptr );
180- }
181- }
146+ // Reset the event in the frame ring buffer
147+ ResetEvent (m_FrameEvents[frameIndex % MAX_QUEUE_AHEAD]);
182148
183149session->FrameIndex = frameIndex;
184150vr::VRCompositor ()->SubmitExplicitTimingData ();
@@ -289,14 +255,7 @@ ovrResult CompositorBase::EndFrame(ovrSession session, long long frameIndex, ovr
289255}
290256
291257// Frame now completed so we can let anyone waiting on the next frame call WaitGetPoses
292- {
293- std::unique_lock<std::mutex> lk (m_FrameMutex);
294- void * handle = m_FrameEvent[frameIndex];
295- if (handle)
296- SetEvent (handle);
297- else
298- m_FrameEvent[frameIndex] = CreateEvent (nullptr , true , true , nullptr );
299- }
258+ SetEvent (m_FrameEvents[frameIndex % MAX_QUEUE_AHEAD]);
300259
301260if (m_MirrorTexture && error == vr::VRCompositorError_None)
302261RenderMirrorTexture (m_MirrorTexture);
0 commit comments