Skip to content

Commit 8982075

Browse files
authored
Merge pull request #31 from CertainLach/feature/provide-explicit-framerate
Explicitly provide framerate to SteamVR
2 parents 25b3a19 + 93bc507 commit 8982075

File tree

4 files changed

+171
-30
lines changed

4 files changed

+171
-30
lines changed

bin/driver-proxy/src/driver/hmd.rs

+64-5
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@ use std::{
44
rc::Rc,
55
};
66

7-
use crate::Result;
7+
use crate::{
8+
driver_context::{self, DRIVER_CONTEXT},
9+
settings::{set_properties, Property, PropertyValue, PROPERTIES},
10+
Result,
11+
};
812
use cppvtbl::{impl_vtables, HasVtable, VtableRef, WithVtables};
913
use lens_protocol::{Eye, LensClient};
10-
use openvr::HmdVector2_t;
14+
use openvr::{
15+
k_unFloatPropertyTag, EPropertyWriteType, ETrackedDeviceProperty, ETrackedPropertyError,
16+
HmdVector2_t, IVRProperties, PropertyWrite_t,
17+
};
1118
use tracing::{error, info, instrument};
12-
use vive_hid::Mode;
19+
use vive_hid::{Mode, ViveConfig, ViveDevice};
1320

1421
use crate::openvr::{
1522
DistortionCoordinates_t, DriverPose_t, EVREye, EVRInitError, ITrackedDeviceServerDriver,
@@ -150,15 +157,67 @@ impl IVRDisplayComponent for HmdDisplay {
150157

151158
#[impl_vtables(ITrackedDeviceServerDriver)]
152159
pub struct HmdDriver {
153-
// pub steam: Rc<SteamDevice>,
160+
pub vive: Rc<ViveDevice>,
161+
pub vive_config: ViveConfig,
154162
pub lens: Rc<dyn LensClient>,
155163
pub real: &'static VtableRef<ITrackedDeviceServerDriverVtable>,
156164
pub mode: Mode,
157165
}
158166

159167
impl ITrackedDeviceServerDriver for HmdDriver {
160168
fn Activate(&self, unObjectId: u32) -> EVRInitError {
161-
self.real.Activate(unObjectId)
169+
let res = self.real.Activate(unObjectId);
170+
if res != EVRInitError::VRInitError_None {
171+
return res;
172+
}
173+
let container = PROPERTIES.TrackedDeviceToPropertyContainer(unObjectId);
174+
175+
set_properties(
176+
container,
177+
vec![
178+
Property::new(
179+
ETrackedDeviceProperty::Prop_DisplayFrequency_Float,
180+
PropertyValue::Float(self.mode.frame_rate),
181+
),
182+
Property::new(
183+
ETrackedDeviceProperty::Prop_DisplaySupportsMultipleFramerates_Bool,
184+
PropertyValue::Bool(true),
185+
),
186+
Property::new(
187+
ETrackedDeviceProperty::Prop_SecondsFromVsyncToPhotons_Float,
188+
PropertyValue::Float(
189+
(1.0 / self.mode.frame_rate) + self.mode.extra_photon_vsync,
190+
),
191+
),
192+
// Property::new(
193+
// ETrackedDeviceProperty::Prop_MinimumIpdStepMeters_Float,
194+
// PropertyValue::Float(0.0005),
195+
// ),
196+
// Property::new(
197+
// ETrackedDeviceProperty::Prop_UserIpdMeters_Float,
198+
// // TODO
199+
// PropertyValue::Float(0.0005),
200+
// ),
201+
Property::new(
202+
ETrackedDeviceProperty::Prop_UserHeadToEyeDepthMeters_Float,
203+
PropertyValue::Float(0.015),
204+
),
205+
Property::new(
206+
ETrackedDeviceProperty::Prop_DisplayAvailableFrameRates_Float_Array,
207+
PropertyValue::FloatArray(if self.mode.frame_rate == 90.0 {
208+
vec![90.0, 120.0]
209+
} else {
210+
vec![120.0, 90.0]
211+
}),
212+
),
213+
Property::new(
214+
ETrackedDeviceProperty::Prop_DisplaySupportsRuntimeFramerateChange_Bool,
215+
PropertyValue::Bool(true),
216+
),
217+
],
218+
);
219+
220+
EVRInitError::VRInitError_None
162221
}
163222

164223
fn Deactivate(&self) {

bin/driver-proxy/src/server/driver_host.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,11 @@ impl IVRServerDriverHost for DriverHost {
5151
let mode = {
5252
let res = HMD_RESOLUTION.get();
5353
let modes = vive.query_modes();
54-
let mode = modes
55-
.iter()
56-
.find(|m| m.id == res as u8)
57-
.unwrap_or(
58-
modes
59-
.first()
60-
.expect("device has at least one mode if opened"),
61-
)
62-
.clone();
54+
let mode = *modes.iter().find(|m| m.id == res as u8).unwrap_or(
55+
modes
56+
.first()
57+
.expect("device has at least one mode if opened"),
58+
);
6359
HMD_RESOLUTION.set(mode.id as i32);
6460

6561
vive.set_mode(mode.id)?;
@@ -81,9 +77,9 @@ impl IVRServerDriverHost for DriverHost {
8177
vive.set_brightness(brightness as u8)?;
8278
}
8379

84-
let config = vive.read_config()?;
80+
let vive_config = vive.read_config()?;
8581

86-
let lens = start_lens_server(config.inhouse_lens_correction)
82+
let lens = start_lens_server(vive_config.inhouse_lens_correction.clone())
8783
.map(|v| Rc::new(v) as Rc<dyn LensClient>)
8884
.unwrap_or_else(|e| {
8985
let zenity = var_os("STEAM_ZENITY").unwrap_or_else(|| OsString::from("zenity"));
@@ -104,7 +100,8 @@ impl IVRServerDriverHost for DriverHost {
104100

105101
let hmd = Box::leak(Box::new(WithVtables::new(HmdDriver {
106102
// steam,
107-
// vive,
103+
vive,
104+
vive_config,
108105
lens,
109106
real,
110107
mode,

bin/driver-proxy/src/settings.rs

+69-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
use std::ffi::CString;
1+
use std::ffi::{c_void, CString};
22
use std::{marker::PhantomData, os::raw::c_char};
33

44
use cppvtbl::VtableRef;
55
use once_cell::sync::Lazy;
6+
use openvr::{
7+
k_unBoolPropertyTag, k_unFloatPropertyTag, EPropertyWriteType, ETrackedDeviceProperty,
8+
ETrackedPropertyError, IVRProperties, IVRPropertiesVtable, IVRProperties_Version,
9+
PropertyWrite_t,
10+
};
611
use tracing::{error, instrument};
712

813
use crate::driver_context::DRIVER_CONTEXT;
@@ -102,3 +107,66 @@ pub static SETTINGS: Lazy<&'static VtableRef<IVRSettingsVtable>> = Lazy::new(||
102107
.expect("there should be settings interface");
103108
unsafe { VtableRef::from_raw(raw as *const VtableRef<IVRSettingsVtable>) }
104109
});
110+
111+
pub enum PropertyValue {
112+
Float(f32),
113+
FloatArray(Vec<f32>),
114+
Bool(bool),
115+
}
116+
impl PropertyValue {
117+
fn tag(&self) -> u32 {
118+
match self {
119+
Self::Float(_) | Self::FloatArray(_) => k_unFloatPropertyTag,
120+
Self::Bool(_) => k_unBoolPropertyTag,
121+
}
122+
}
123+
fn size(&self) -> u32 {
124+
match self {
125+
PropertyValue::Float(_) => 4,
126+
PropertyValue::FloatArray(v) => 4 * v.len() as u32,
127+
PropertyValue::Bool(_) => 1,
128+
}
129+
}
130+
fn buf(&mut self) -> *mut c_void {
131+
match self {
132+
PropertyValue::Float(f) => (f as *mut f32).cast(),
133+
PropertyValue::FloatArray(f) => f.as_mut_ptr().cast(),
134+
PropertyValue::Bool(v) => (v as *mut bool).cast(),
135+
}
136+
}
137+
}
138+
pub struct Property {
139+
name: ETrackedDeviceProperty,
140+
value: PropertyValue,
141+
}
142+
impl Property {
143+
pub fn new(name: ETrackedDeviceProperty, value: PropertyValue) -> Self {
144+
Self { name, value }
145+
}
146+
}
147+
pub fn set_properties(container: u64, mut props: Vec<Property>) {
148+
let mut batch = Vec::with_capacity(props.len());
149+
for prop in props.iter_mut() {
150+
batch.push(PropertyWrite_t {
151+
writeType: EPropertyWriteType::PropertyWrite_Set,
152+
prop: prop.name,
153+
unTag: prop.value.tag(),
154+
unBufferSize: prop.value.size(),
155+
pvBuffer: prop.value.buf(),
156+
157+
eError: ETrackedPropertyError::TrackedProp_Success,
158+
eSetError: ETrackedPropertyError::TrackedProp_Success,
159+
});
160+
}
161+
PROPERTIES.WritePropertyBatch(container, batch.as_mut_ptr(), batch.len() as u32);
162+
}
163+
164+
pub static PROPERTIES: Lazy<&'static VtableRef<IVRPropertiesVtable>> = Lazy::new(|| {
165+
let ctx = DRIVER_CONTEXT
166+
.get()
167+
.expect("context should be initialized at this point");
168+
let raw = ctx
169+
.get_generic_interface(IVRProperties_Version)
170+
.expect("there should be properties interface");
171+
unsafe { VtableRef::from_raw(raw as *const VtableRef<IVRPropertiesVtable>) }
172+
});

crates/vive-hid/src/lib.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type Result<T, E = Error> = result::Result<T, E>;
2727

2828
static HIDAPI: OnceCell<HidApi> = OnceCell::new();
2929
pub fn get_hidapi() -> Result<&'static HidApi> {
30-
HIDAPI.get_or_try_init(|| HidApi::new()).map_err(From::from)
30+
HIDAPI.get_or_try_init(HidApi::new).map_err(From::from)
3131
}
3232

3333
const STEAM_VID: u16 = 0x28de;
@@ -154,25 +154,33 @@ pub struct Mode {
154154
pub width: u32,
155155
pub height: u32,
156156
pub frame_rate: f32,
157+
pub extra_photon_vsync: f32,
157158
}
158159
impl Mode {
159-
const fn new(id: u8, width: u32, height: u32, frame_rate: f32) -> Self {
160+
const fn new(
161+
id: u8,
162+
width: u32,
163+
height: u32,
164+
frame_rate: f32,
165+
extra_photon_vsync: f32,
166+
) -> Self {
160167
Self {
161168
id,
162169
width,
163170
height,
164171
frame_rate,
172+
extra_photon_vsync,
165173
}
166174
}
167175
}
168176

169177
const VIVE_PRO_2_MODES: [Mode; 6] = [
170-
Mode::new(0, 2448, 1224, 90.0),
171-
Mode::new(1, 2448, 1224, 120.0),
172-
Mode::new(2, 3264, 1632, 90.0),
173-
Mode::new(3, 3680, 1836, 90.0),
174-
Mode::new(4, 4896, 2448, 90.0),
175-
Mode::new(5, 4896, 2448, 120.0),
178+
Mode::new(0, 2448, 1224, 90.0, 0.0),
179+
Mode::new(1, 2448, 1224, 120.0, 0.0),
180+
Mode::new(2, 3264, 1632, 90.0, 0.00297),
181+
Mode::new(3, 3672, 1836, 90.0, 0.00332),
182+
Mode::new(4, 4896, 2448, 90.0, 0.0),
183+
Mode::new(5, 4896, 2448, 120.0, 0.0),
176184
];
177185

178186
pub struct ViveDevice(HidDevice);
@@ -240,12 +248,12 @@ impl ViveDevice {
240248
.map_err(|_| Error::ProtocolError("devsn is not a string"))?
241249
.to_string())
242250
}
243-
pub fn read_ipd(&self) -> Result<String> {
244-
self.write(0x02, b"mfg-r-ipdadc")?;
251+
pub fn read_reg(&self, reg: &str) -> Result<String> {
252+
self.write(0x02, reg.as_bytes())?;
245253
let mut out = [0u8; 62];
246254
let size = self.read(0x02, &[], &mut out)?;
247255
Ok(std::str::from_utf8(&out[..size])
248-
.map_err(|_| Error::ProtocolError("ipd is not a string"))?
256+
.map_err(|_| Error::ProtocolError("result is not a string"))?
249257
.to_string())
250258
}
251259
pub fn read_config(&self) -> Result<ViveConfig> {
@@ -283,7 +291,7 @@ impl ViveDevice {
283291
let string = std::str::from_utf8(&out[128..])
284292
.map_err(|_| Error::ProtocolError("config is not utf-8"))?;
285293

286-
serde_json::from_str(&string).map_err(|_| Error::ConfigReadFailed)
294+
serde_json::from_str(string).map_err(|_| Error::ConfigReadFailed)
287295
}
288296
/// Always returns at least one mode
289297
pub fn query_modes(&self) -> Vec<Mode> {
@@ -292,6 +300,7 @@ impl ViveDevice {
292300
pub fn set_mode(&self, resolution: u8) -> Result<(), Error> {
293301
self.write_feature(0x04, 0x2970, b"wireless,0")?;
294302
self.write_feature(0x04, 0x2970, format!("dtd,{}", resolution).as_bytes())?;
303+
self.write_feature(0x04, 0x2970, b"chipreset")?;
295304
// TODO: wait for reconnection
296305
Ok(())
297306
}
@@ -328,3 +337,11 @@ impl ViveDevice {
328337
Ok(())
329338
}
330339
}
340+
341+
#[test]
342+
fn test() -> Result<()> {
343+
let dev = ViveDevice::open_first()?;
344+
dbg!(dev.read_config()?);
345+
dev.set_mode(1)?;
346+
Ok(())
347+
}

0 commit comments

Comments
 (0)