Skip to content

Commit 52db446

Browse files
committed
fix(server_openvr): ✨ Conditional HMD initialization strategy (#2875)
* fix(server_openvr): ⏪ Revert HMD initialization at driver startup * Initialize HMD early only when dashboard is alive * Address review comments
1 parent 460bfa6 commit 52db446

File tree

5 files changed

+63
-40
lines changed

5 files changed

+63
-40
lines changed

alvr/server_openvr/cpp/alvr_server/TrackedDevice.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ void TrackedDevice::submit_pose(vr::DriverPose_t pose) {
8383
);
8484
}
8585

86-
bool TrackedDevice::register_device() {
86+
bool TrackedDevice::register_device(bool await_activation) {
8787
if (!vr::VRServerDriverHost()->TrackedDeviceAdded(
8888
this->get_serial_number().c_str(),
8989
this->device_class,
@@ -94,12 +94,16 @@ bool TrackedDevice::register_device() {
9494
return false;
9595
}
9696

97-
auto lock = std::unique_lock<std::mutex>(this->activation_mutex);
98-
this->activation_condvar.wait_for(lock, std::chrono::seconds(1), [this] {
99-
return this->activation_state != ActivationState::Pending;
100-
});
97+
if (await_activation) {
98+
auto lock = std::unique_lock<std::mutex>(this->activation_mutex);
99+
this->activation_condvar.wait_for(lock, std::chrono::seconds(1), [this] {
100+
return this->activation_state != ActivationState::Pending;
101+
});
101102

102-
return this->activation_state == ActivationState::Success;
103+
return this->activation_state == ActivationState::Success;
104+
} else {
105+
return true;
106+
}
103107
}
104108

105109
vr::EVRInitError TrackedDevice::Activate(vr::TrackedDeviceIndex_t object_id) {

alvr/server_openvr/cpp/alvr_server/TrackedDevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class TrackedDevice : vr::ITrackedDeviceServerDriver {
1919
vr::PropertyContainerHandle_t prop_container = vr::k_ulInvalidPropertyContainer;
2020
vr::DriverPose_t last_pose;
2121

22-
bool register_device();
22+
bool register_device(bool await_activation);
2323
void set_prop(FfiOpenvrProperty prop);
2424

2525
protected:

alvr/server_openvr/cpp/alvr_server/alvr_server.cpp

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ static void load_debug_privilege(void) {
7979

8080
class DriverProvider : public vr::IServerTrackedDeviceProvider {
8181
public:
82+
bool early_hmd_initialization = false;
83+
8284
std::unique_ptr<Hmd> hmd;
8385
std::unique_ptr<Controller> left_controller, right_controller;
8486
std::unique_ptr<Controller> left_hand_tracker, right_hand_tracker;
@@ -94,6 +96,15 @@ class DriverProvider : public vr::IServerTrackedDeviceProvider {
9496
VR_INIT_SERVER_DRIVER_CONTEXT(pContext);
9597
InitDriverLog(vr::VRDriverLog());
9698

99+
if (this->early_hmd_initialization) {
100+
auto hmd = new Hmd();
101+
// Note: we disable awaiting for Acivate() call. That will only be called after
102+
// IServerTrackedDeviceProvider::Init() (this function) returns.
103+
hmd->register_device(false);
104+
this->hmd = std::unique_ptr<Hmd>(hmd);
105+
this->tracked_devices.insert({ HEAD_ID, this->hmd.get() });
106+
}
107+
97108
return vr::VRInitError_None;
98109
}
99110
virtual void Cleanup() override {
@@ -210,7 +221,9 @@ void (*SetOpenvrProps)(void* instancePtr, unsigned long long deviceID);
210221
void (*RegisterButtons)(void* instancePtr, unsigned long long deviceID);
211222
void (*WaitForVSync)();
212223

213-
void CppInit() {
224+
void CppInit(bool earlyHmdInitialization) {
225+
g_driver_provider.early_hmd_initialization = earlyHmdInitialization;
226+
214227
HookCrashHandler();
215228

216229
// Initialize path constants
@@ -235,13 +248,15 @@ bool InitializeStreaming() {
235248
Settings::Instance().Load();
236249

237250
if (!g_driver_provider.devices_initialized) {
238-
auto hmd = new Hmd();
239-
if (!hmd->register_device()) {
240-
Error("Failed to register HMD");
241-
return false;
251+
if (!g_driver_provider.early_hmd_initialization) {
252+
auto hmd = new Hmd();
253+
if (!hmd->register_device(false)) {
254+
Error("Failed to register HMD");
255+
return false;
256+
}
257+
g_driver_provider.hmd = std::unique_ptr<Hmd>(hmd);
258+
g_driver_provider.tracked_devices.insert({ HEAD_ID, g_driver_provider.hmd.get() });
242259
}
243-
g_driver_provider.hmd = std::unique_ptr<Hmd>(hmd);
244-
g_driver_provider.tracked_devices.insert({ HEAD_ID, g_driver_provider.hmd.get() });
245260

246261
// Note: for controllers, hands and trackers don't bail out if registration fails
247262
if (Settings::Instance().m_enableControllers) {
@@ -250,15 +265,15 @@ bool InitializeStreaming() {
250265
: vr::VRSkeletalTracking_Partial;
251266

252267
auto left_controller = new Controller(HAND_LEFT_ID, controllerSkeletonLevel);
253-
if (left_controller->register_device()) {
268+
if (left_controller->register_device(true)) {
254269
g_driver_provider.left_controller = std::unique_ptr<Controller>(left_controller);
255270
g_driver_provider.tracked_devices.insert(
256271
{ HAND_LEFT_ID, g_driver_provider.left_controller.get() }
257272
);
258273
}
259274

260275
auto right_controller = new Controller(HAND_RIGHT_ID, controllerSkeletonLevel);
261-
if (right_controller->register_device()) {
276+
if (right_controller->register_device(true)) {
262277
g_driver_provider.right_controller = std::unique_ptr<Controller>(right_controller);
263278
g_driver_provider.tracked_devices.insert(
264279
{ HAND_RIGHT_ID, g_driver_provider.right_controller.get() }
@@ -268,7 +283,7 @@ bool InitializeStreaming() {
268283
if (Settings::Instance().m_useSeparateHandTrackers) {
269284
auto left_hand_tracker
270285
= new Controller(HAND_TRACKER_LEFT_ID, vr::VRSkeletalTracking_Full);
271-
if (left_hand_tracker->register_device()) {
286+
if (left_hand_tracker->register_device(true)) {
272287
g_driver_provider.left_hand_tracker
273288
= std::unique_ptr<Controller>(left_hand_tracker);
274289
g_driver_provider.tracked_devices.insert(
@@ -278,7 +293,7 @@ bool InitializeStreaming() {
278293

279294
auto right_hand_tracker
280295
= new Controller(HAND_TRACKER_RIGHT_ID, vr::VRSkeletalTracking_Full);
281-
if (right_hand_tracker->register_device()) {
296+
if (right_hand_tracker->register_device(true)) {
282297
g_driver_provider.right_hand_tracker
283298
= std::unique_ptr<Controller>(right_hand_tracker);
284299
g_driver_provider.tracked_devices.insert(
@@ -290,55 +305,55 @@ bool InitializeStreaming() {
290305

291306
if (Settings::Instance().m_enableBodyTrackingFakeVive) {
292307
auto chestTracker = std::make_unique<FakeViveTracker>(BODY_CHEST_ID);
293-
if (chestTracker->register_device()) {
308+
if (chestTracker->register_device(true)) {
294309
g_driver_provider.tracked_devices.insert({ BODY_CHEST_ID, chestTracker.get() });
295310
g_driver_provider.generic_trackers.push_back(std::move(chestTracker));
296311
}
297312

298313
auto waistTracker = std::make_unique<FakeViveTracker>(BODY_HIPS_ID);
299-
if (waistTracker->register_device()) {
314+
if (waistTracker->register_device(true)) {
300315
g_driver_provider.tracked_devices.insert({ BODY_HIPS_ID, waistTracker.get() });
301316
g_driver_provider.generic_trackers.push_back(std::move(waistTracker));
302317
}
303318

304319
auto leftElbowTracker = std::make_unique<FakeViveTracker>(BODY_LEFT_ELBOW_ID);
305-
if (leftElbowTracker->register_device()) {
320+
if (leftElbowTracker->register_device(true)) {
306321
g_driver_provider.tracked_devices.insert({ BODY_LEFT_ELBOW_ID,
307322
leftElbowTracker.get() });
308323
g_driver_provider.generic_trackers.push_back(std::move(leftElbowTracker));
309324
}
310325

311326
auto rightElbowTracker = std::make_unique<FakeViveTracker>(BODY_RIGHT_ELBOW_ID);
312-
if (rightElbowTracker->register_device()) {
327+
if (rightElbowTracker->register_device(true)) {
313328
g_driver_provider.tracked_devices.insert({ BODY_RIGHT_ELBOW_ID,
314329
rightElbowTracker.get() });
315330
g_driver_provider.generic_trackers.push_back(std::move(rightElbowTracker));
316331
}
317332

318333
if (Settings::Instance().m_bodyTrackingHasLegs) {
319334
auto leftKneeTracker = std::make_unique<FakeViveTracker>(BODY_LEFT_KNEE_ID);
320-
if (leftKneeTracker->register_device()) {
335+
if (leftKneeTracker->register_device(true)) {
321336
g_driver_provider.tracked_devices.insert({ BODY_LEFT_KNEE_ID,
322337
leftKneeTracker.get() });
323338
g_driver_provider.generic_trackers.push_back(std::move(leftKneeTracker));
324339
}
325340

326341
auto leftFootTracker = std::make_unique<FakeViveTracker>(BODY_LEFT_FOOT_ID);
327-
if (leftFootTracker->register_device()) {
342+
if (leftFootTracker->register_device(true)) {
328343
g_driver_provider.tracked_devices.insert({ BODY_LEFT_FOOT_ID,
329344
leftFootTracker.get() });
330345
g_driver_provider.generic_trackers.push_back(std::move(leftFootTracker));
331346
}
332347

333348
auto rightKneeTracker = std::make_unique<FakeViveTracker>(BODY_RIGHT_KNEE_ID);
334-
if (rightKneeTracker->register_device()) {
349+
if (rightKneeTracker->register_device(true)) {
335350
g_driver_provider.tracked_devices.insert({ BODY_RIGHT_KNEE_ID,
336351
rightKneeTracker.get() });
337352
g_driver_provider.generic_trackers.push_back(std::move(rightKneeTracker));
338353
}
339354

340355
auto rightFootTracker = std::make_unique<FakeViveTracker>(BODY_RIGHT_FOOT_ID);
341-
if (rightFootTracker->register_device()) {
356+
if (rightFootTracker->register_device(true)) {
342357
g_driver_provider.tracked_devices.insert({ BODY_RIGHT_FOOT_ID,
343358
rightFootTracker.get() });
344359
g_driver_provider.generic_trackers.push_back(std::move(rightFootTracker));

alvr/server_openvr/cpp/alvr_server/bindings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ extern "C" void (*SetOpenvrProps)(void* instancePtr, unsigned long long deviceID
133133
extern "C" void (*RegisterButtons)(void* instancePtr, unsigned long long deviceID);
134134
extern "C" void (*WaitForVSync)();
135135

136-
extern "C" void CppInit();
136+
extern "C" void CppInit(bool earlyHmdInitialization);
137137
extern "C" void* CppOpenvrEntryPoint(const char* pInterfaceName, int* pReturnCode);
138138
extern "C" bool InitializeStreaming();
139139
extern "C" void DeinitializeStreaming();

alvr/server_openvr/src/lib.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -407,17 +407,6 @@ pub extern "C" fn shutdown_driver() {
407407
SERVER_CORE_CONTEXT.write().take();
408408
}
409409

410-
// Check that there is no active dashboard instance not part of this driver installation
411-
pub fn should_initialize_driver(driver_layout: &afs::Layout) -> bool {
412-
// Note: if the iterator is empty, `all()` returns true
413-
sysinfo::System::new_all()
414-
.processes_by_name(OsStr::new(&afs::dashboard_fname()))
415-
.all(|proc| {
416-
proc.exe()
417-
.is_none_or(|path| path == driver_layout.dashboard_exe()) // if path is unreadable then don't care
418-
})
419-
}
420-
421410
/// This is the SteamVR/OpenVR entry point
422411
/// # Safety
423412
#[no_mangle]
@@ -434,7 +423,17 @@ pub unsafe extern "C" fn HmdDriverFactory(
434423
return ptr::null_mut();
435424
};
436425

437-
if !should_initialize_driver(&filesystem_layout) {
426+
let dashboard_process_paths = sysinfo::System::new_all()
427+
.processes_by_name(OsStr::new(&afs::dashboard_fname()))
428+
.filter_map(|proc| Some(proc.exe()?.to_owned()))
429+
.collect::<Vec<_>>();
430+
431+
// Check that there is no active dashboard instance not part of this driver installation
432+
// Note: if the iterator is empty, `all()` returns true
433+
if !dashboard_process_paths
434+
.iter()
435+
.all(|path| *path == filesystem_layout.dashboard_exe())
436+
{
438437
return ptr::null_mut();
439438
}
440439

@@ -486,7 +485,12 @@ pub unsafe extern "C" fn HmdDriverFactory(
486485
WaitForVSync = Some(wait_for_vsync);
487486
ShutdownRuntime = Some(shutdown_driver);
488487

489-
CppInit();
488+
// When there is already a ALVR dashboard running, initialize the HMD device early to
489+
// avoid buggy SteamVR behavior
490+
// NB: we already bail out before if the dashboards don't belong to this streamer
491+
let early_hmd_initialization = !dashboard_process_paths.is_empty();
492+
493+
CppInit(early_hmd_initialization);
490494
}
491495

492496
let (context, events_receiver) = ServerCoreContext::new();

0 commit comments

Comments
 (0)