Skip to content

Commit 3d88cbf

Browse files
committed
CompositorBase: Reimplement frame events with a ring buffer.
Restricts the maximum number of pipelined frames, but it gets rid of the locks and simplifies the code greatly.
1 parent e2939e3 commit 3d88cbf

File tree

2 files changed

+16
-58
lines changed

2 files changed

+16
-58
lines changed

Revive/CompositorBase.cpp

Lines changed: 13 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -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
6867
vr::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

7274
CompositorBase::~CompositorBase()
7375
{
76+
for (int i = 0; i < MAX_QUEUE_AHEAD; i++)
77+
CloseHandle(m_FrameEvents[i]);
78+
7479
if (m_MirrorTexture)
7580
delete m_MirrorTexture;
7681
}
@@ -121,22 +126,9 @@ ovrResult CompositorBase::WaitToBeginFrame(ovrSession session, long long frameIn
121126
{
122127
MICROPROFILE_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
142134
if (!session->Details->UseHack(SessionDetails::HACK_WAIT_ON_SUBMIT))
@@ -151,34 +143,8 @@ ovrResult CompositorBase::BeginFrame(ovrSession session, long long frameIndex)
151143
{
152144
MICROPROFILE_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

183149
session->FrameIndex = frameIndex;
184150
vr::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

301260
if (m_MirrorTexture && error == vr::VRCompositorError_None)
302261
RenderMirrorTexture(m_MirrorTexture);

Revive/CompositorBase.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
#include <openvr.h>
77
#include <vector>
8-
#include <mutex>
9-
#include <map>
8+
9+
#define MAX_QUEUE_AHEAD 5
1010

1111
class CompositorBase
1212
{
@@ -51,6 +51,5 @@ class CompositorBase
5151
std::vector<vr::VROverlayHandle_t> m_ActiveOverlays;
5252

5353
// Call order enforcement
54-
std::mutex m_FrameMutex;
55-
std::map<long long, void*> m_FrameEvent;
54+
void* m_FrameEvents[MAX_QUEUE_AHEAD];
5655
};

0 commit comments

Comments
 (0)