Skip to content

Commit 112984a

Browse files
committed
Implement dynamic framerate
Reduce tracking frequency to head fps
1 parent 9064bbc commit 112984a

File tree

11 files changed

+87
-29
lines changed

11 files changed

+87
-29
lines changed

alvr/client_core/src/c_api.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,14 @@ pub extern "C" fn alvr_get_tracker_prediction_offset_ns() -> u64 {
398398
}
399399

400400
#[no_mangle]
401-
pub extern "C" fn alvr_report_submit(target_timestamp_ns: u64, vsync_queue_ns: u64) {
401+
pub extern "C" fn alvr_report_submit(
402+
target_timestamp_ns: u64,
403+
frame_interval_ns: u64,
404+
vsync_queue_ns: u64,
405+
) {
402406
crate::report_submit(
403407
Duration::from_nanos(target_timestamp_ns),
408+
Duration::from_nanos(frame_interval_ns),
404409
Duration::from_nanos(vsync_queue_ns),
405410
);
406411
}

alvr/client_core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,9 @@ pub fn get_tracker_prediction_offset() -> Duration {
197197
}
198198
}
199199

200-
pub fn report_submit(target_timestamp: Duration, vsync_queue: Duration) {
200+
pub fn report_submit(target_timestamp: Duration, frame_interval: Duration, vsync_queue: Duration) {
201201
if let Some(stats) = &mut *STATISTICS_MANAGER.lock() {
202-
stats.report_submit(target_timestamp, vsync_queue);
202+
stats.report_submit(target_timestamp, frame_interval, vsync_queue);
203203

204204
if let Some(sender) = &*STATISTICS_SENDER.lock() {
205205
if let Some(stats) = stats.summary(target_timestamp) {

alvr/client_core/src/statistics.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,15 @@ impl StatisticsManager {
9595
}
9696

9797
// vsync_queue is the latency between this call and the vsync. it cannot be measured by ALVR and
98-
// should be reported by the VR runtime
99-
pub fn report_submit(&mut self, target_timestamp: Duration, vsync_queue: Duration) {
98+
// should be reported by the VR runtime.
99+
// predicted_frame_interval is the frame interval returned by the runtime. this is more stable
100+
// any any interval mearued by us.
101+
pub fn report_submit(
102+
&mut self,
103+
target_timestamp: Duration,
104+
predicted_frame_interval: Duration,
105+
vsync_queue: Duration,
106+
) {
100107
let now = Instant::now();
101108

102109
if let Some(frame) = self
@@ -118,6 +125,8 @@ impl StatisticsManager {
118125
let vsync = now + vsync_queue;
119126
frame.client_stats.frame_interval = vsync.saturating_duration_since(self.prev_vsync);
120127
self.prev_vsync = vsync;
128+
129+
frame.client_stats.predicted_frame_interval = predicted_frame_interval
121130
}
122131
}
123132

alvr/client_mock/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ fn tracking_thread(streaming: Arc<RelaxedAtomic>, fps: f32, input: Arc<RwLock<Wi
196196

197197
drop(input_lock);
198198

199-
loop_deadline += Duration::from_secs_f32(1.0 / fps / 3.0);
199+
loop_deadline += Duration::from_secs_f32(1.0 / fps);
200200
thread::sleep(loop_deadline.saturating_duration_since(Instant::now()))
201201
}
202202
}
@@ -271,6 +271,7 @@ fn client_thread(
271271

272272
alvr_client_core::report_submit(
273273
window_output.current_frame_timestamp,
274+
Duration::from_secs_f32(1.0 / window_output.fps),
274275
Duration::from_millis(input_lock.emulated_vsync_ms),
275276
);
276277

alvr/client_openxr/src/lib.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ pub fn entry_point() {
446446
let mut views_history = VecDeque::new();
447447

448448
let (history_view_sender, history_view_receiver) = mpsc::channel();
449+
let mut frame_interval_sender = None;
449450
let mut reference_space_sender = None::<mpsc::Sender<_>>;
450451

451452
let default_view = xr::View {
@@ -667,10 +668,13 @@ pub fn entry_point() {
667668

668669
let (sender, reference_space_receiver) = mpsc::channel();
669670
reference_space_sender = Some(sender);
671+
let (sender, frame_interval_receiver) = mpsc::channel();
672+
frame_interval_sender = Some(sender);
670673

671674
streaming_input_thread = Some(thread::spawn(move || {
672675
let mut deadline = Instant::now();
673-
let frame_interval = Duration::from_secs_f32(1.0 / refresh_rate_hint);
676+
let mut frame_interval =
677+
Duration::from_secs_f32(1.0 / refresh_rate_hint);
674678

675679
while is_streaming.value() {
676680
update_streaming_input(&mut context);
@@ -679,7 +683,11 @@ pub fn entry_point() {
679683
context.reference_space = reference_space;
680684
}
681685

682-
deadline += frame_interval / 3;
686+
if let Ok(interval) = frame_interval_receiver.try_recv() {
687+
frame_interval = interval;
688+
}
689+
690+
deadline += frame_interval;
683691
thread::sleep(deadline.saturating_duration_since(Instant::now()));
684692
}
685693
}));
@@ -765,6 +773,10 @@ pub fn entry_point() {
765773
let vsync_time =
766774
Duration::from_nanos(frame_state.predicted_display_time.as_nanos() as _);
767775

776+
if let Some(sender) = &frame_interval_sender {
777+
sender.send(frame_interval).ok();
778+
}
779+
768780
xr_frame_stream.begin().unwrap();
769781

770782
if !frame_state.should_render {
@@ -841,7 +853,11 @@ pub fn entry_point() {
841853

842854
if !hardware_buffer.is_null() {
843855
if let Some(now) = xr_runtime_now(&xr_instance) {
844-
alvr_client_core::report_submit(timestamp, vsync_time.saturating_sub(now));
856+
alvr_client_core::report_submit(
857+
timestamp,
858+
frame_interval,
859+
vsync_time.saturating_sub(now),
860+
);
845861
}
846862
}
847863

alvr/packets/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ pub struct ClientStatistics {
204204
pub rendering: Duration,
205205
pub vsync_queue: Duration,
206206
pub total_pipeline_latency: Duration,
207+
pub predicted_frame_interval: Duration,
207208
}
208209

209210
#[derive(Serialize, Deserialize, Clone, Debug)]

alvr/server/cpp/alvr_server/alvr_server.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,6 @@ void DeinitializeStreaming() {
227227
}
228228
}
229229

230-
void SendVSync() { vr::VRServerDriverHost()->VsyncEvent(0.0); }
231-
232230
void RequestIDR() {
233231
if (g_driver_provider.hmd && g_driver_provider.hmd->m_encoder) {
234232
g_driver_provider.hmd->m_encoder->InsertIDR();

alvr/server/cpp/alvr_server/bindings.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ extern "C" void (*WaitForVSync)();
128128
extern "C" void *CppEntryPoint(const char *pInterfaceName, int *pReturnCode);
129129
extern "C" void InitializeStreaming();
130130
extern "C" void DeinitializeStreaming();
131-
extern "C" void SendVSync();
132131
extern "C" void RequestIDR();
133132
extern "C" void SetTracking(unsigned long long targetTimestampNs,
134133
float controllerPoseTimeOffsetS,

alvr/server/src/lib.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ use alvr_common::{
2828
once_cell::sync::{Lazy, OnceCell},
2929
parking_lot::{Mutex, RwLock},
3030
prelude::*,
31-
RelaxedAtomic,
31+
RelaxedAtomic, HEAD_ID,
3232
};
3333
use alvr_events::EventType;
3434
use alvr_filesystem::{self as afs, Layout};
3535
use alvr_packets::{
3636
ClientListAction, DecoderInitializationConfig, Haptics, ServerControlPacket, VideoPacketHeader,
3737
};
3838
use alvr_server_io::ServerDataManager;
39-
use alvr_session::CodecType;
39+
use alvr_session::{CodecType, OpenvrPropValue, OpenvrPropertyKey};
4040
use bitrate::BitrateManager;
4141
use statistics::StatisticsManager;
4242
use std::{
@@ -479,13 +479,14 @@ pub unsafe extern "C" fn HmdDriverFactory(
479479
}
480480

481481
extern "C" fn wait_for_vsync() {
482-
let wait_duration = STATISTICS_MANAGER
483-
.lock()
484-
.as_mut()
485-
.map(|stats| stats.duration_until_next_vsync());
482+
if let Some(stats) = &mut *STATISTICS_MANAGER.lock() {
483+
openvr_props::set_prop(
484+
*HEAD_ID,
485+
OpenvrPropertyKey::DisplayFrequency,
486+
OpenvrPropValue::Float(1.0 / stats.get_frame_interval().as_secs_f32()),
487+
);
486488

487-
if let Some(duration) = wait_duration {
488-
thread::sleep(duration);
489+
thread::sleep(stats.duration_until_next_vsync());
489490
}
490491
}
491492

alvr/server/src/openvr_props.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// todo: fill out more properties for headset and controllers
33
// todo: add more emulation modes
44

5-
use crate::{FfiOpenvrProperty, FfiOpenvrPropertyValue, SERVER_DATA_MANAGER};
5+
use crate::{openvr_props, FfiOpenvrProperty, FfiOpenvrPropertyValue, SERVER_DATA_MANAGER};
66
use alvr_common::{prelude::*, settings_schema::Switch, HEAD_ID, LEFT_HAND_ID, RIGHT_HAND_ID};
77
use alvr_session::{
88
ControllersEmulationMode, HeadsetEmulationMode, OpenvrPropValue,
@@ -13,6 +13,12 @@ use std::{
1313
ptr,
1414
};
1515

16+
pub fn set_prop(device_id: u64, key: OpenvrPropertyKey, value: OpenvrPropValue) {
17+
unsafe {
18+
crate::SetOpenvrProperty(device_id, to_ffi_openvr_prop(key, value));
19+
}
20+
}
21+
1622
pub fn to_ffi_openvr_prop(key: OpenvrPropertyKey, value: OpenvrPropValue) -> FfiOpenvrProperty {
1723
let type_ = match value {
1824
OpenvrPropValue::Bool(_) => crate::FfiOpenvrPropertyType_Bool,
@@ -113,9 +119,7 @@ pub extern "C" fn set_device_openvr_props(device_id: u64) {
113119
if device_id == *HEAD_ID {
114120
fn set_prop(key: OpenvrPropertyKey, value: OpenvrPropValue) {
115121
info!("Setting head OpenVR prop: {key:?} => {value:?}");
116-
unsafe {
117-
crate::SetOpenvrProperty(*HEAD_ID, to_ffi_openvr_prop(key, value));
118-
}
122+
openvr_props::set_prop(*HEAD_ID, key, value);
119123
}
120124
fn set_string(key: OpenvrPropertyKey, value: &str) {
121125
set_prop(key, OpenvrPropValue::String(value.into()));

0 commit comments

Comments
 (0)