Move to IPC data version 2, includes the IMU data time in milliseconds, removes fields that the extension settings may own

This commit is contained in:
wheaney 2024-04-21 22:21:44 -07:00
parent 6a4de14eb4
commit a3efb03dd9
6 changed files with 83 additions and 58 deletions

View File

@ -5,12 +5,12 @@ uniform bool show_banner;
uniform sampler2D uDesktopTexture;
uniform mat4 imu_quat_data;
uniform vec4 look_ahead_cfg;
uniform float look_ahead_ms;
uniform float display_zoom;
uniform float display_north_offset;
uniform float lens_distance_ratio;
uniform bool sbs_enabled;
uniform bool sbs_content;
uniform bool sbs_mode_stretched;
uniform bool custom_banner_enabled;
uniform float stage_aspect_ratio;
uniform float display_aspect_ratio;
@ -19,7 +19,6 @@ uniform float trim_height_percent;
uniform float half_fov_z_rads;
uniform float half_fov_y_rads;
uniform float screen_distance;
uniform float frametime;
float look_ahead_ms_cap = 45.0;
@ -67,29 +66,29 @@ void PS_IMU_Transform(vec4 pos, vec2 texcoord, out vec4 color) {
float lens_z_offset = 0.0;
float aspect_ratio = stage_aspect_ratio;
if(enabled && sbs_enabled) {
bool right_display = texcoord.x > 0.5;
aspect_ratio /= 2;
// if(enabled && sbs_enabled) {
// bool right_display = texcoord.x > 0.5;
// aspect_ratio /= 2;
lens_y_offset = lens_distance_ratio / 3;
if(right_display)
lens_y_offset = -lens_y_offset;
if(sbs_content) {
// source video is SBS, left-half of the screen goes to the left lens, right-half to the right lens
if(right_display)
texcoord_x_min = 0.5;
else
texcoord_x_max = 0.5;
}
if(!sbs_mode_stretched) {
// if the content isn't stretched, assume it's centered in the middle 50% of the screen
texcoord_x_min = max(0.25, texcoord_x_min);
texcoord_x_max = min(0.75, texcoord_x_max);
}
// lens_y_offset = lens_distance_ratio / 3;
// if(right_display)
// lens_y_offset = -lens_y_offset;
// if(sbs_content) {
// // source video is SBS, left-half of the screen goes to the left lens, right-half to the right lens
// if(right_display)
// texcoord_x_min = 0.5;
// else
// texcoord_x_max = 0.5;
// }
// if(!sbs_mode_stretched) {
// // if the content isn't stretched, assume it's centered in the middle 50% of the screen
// texcoord_x_min = max(0.25, texcoord_x_min);
// texcoord_x_max = min(0.75, texcoord_x_max);
// }
// translate the texcoord respresenting the current lens's half of the screen to a full-screen texcoord
texcoord.x = (texcoord.x - (right_display ? 0.5 : 0.0)) * 2;
}
// // translate the texcoord respresenting the current lens's half of the screen to a full-screen texcoord
// texcoord.x = (texcoord.x - (right_display ? 0.5 : 0.0)) * 2;
// }
if(!enabled || show_banner) {
// vec2 banner_size = vec2(800.0 / ReShade::ScreenSize.x, 200.0 / ReShade::ScreenSize.y); // Assuming ScreenWidth and ScreenHeight are defined
@ -142,8 +141,8 @@ void PS_IMU_Transform(vec4 pos, vec2 texcoord, out vec4 color) {
float look_ahead_scanline_adjust = texcoord.y * look_ahead_cfg.z;
// use the 4th value of the look-ahead config to cap the look-ahead value
float look_ahead_ms = min(min(look_ahead_cfg.x + frametime * look_ahead_cfg.y, look_ahead_cfg.w), look_ahead_ms_cap) + look_ahead_scanline_adjust;
float look_ahead_ms_squared = pow(look_ahead_ms, 2);
float look_ahead_ms_capped = min(min(look_ahead_ms, look_ahead_cfg.w), look_ahead_ms_cap) + look_ahead_scanline_adjust;
float look_ahead_ms_squared = pow(look_ahead_ms_capped, 2);
// apply most recent velocity and acceleration to most recent position to get a predicted position
vec3 res = applyLookAhead(rotated_vector_t0, velocity_t0, accel_t0, look_ahead_ms, look_ahead_ms_squared) -

View File

@ -60,10 +60,13 @@ export default class BreezyDesktopExtension extends Extension {
}
_find_supported_monitor() {
const target_monitor_id = this._monitor_manager.getMonitorPropertiesList()?.find(
monitor => SUPPORTED_MONITOR_PRODUCTS.includes(monitor.product))?.index;
if (target_monitor_id !== undefined) {
return this._monitor_manager.getMonitors()[target_monitor_id];
const target_monitor = this._monitor_manager.getMonitorPropertiesList()?.find(
monitor => SUPPORTED_MONITOR_PRODUCTS.includes(monitor.product));
if (target_monitor !== undefined) {
return {
monitor: this._monitor_manager.getMonitors()[target_monitor.index],
refreshRate: target_monitor.refreshRate,
};
}
return null;
@ -74,10 +77,13 @@ export default class BreezyDesktopExtension extends Extension {
console.log('Monitors changed, disabling XR effect');
this._effect_disable();
}
this._target_monitor = this._find_supported_monitor();
const target_monitor = this._find_supported_monitor();
// if target_monitor isn't set, do nothing and wait for MonitorManager to call this again
if (this._target_monitor && this._running_poller_id === undefined) {
if (target_monitor && this._running_poller_id === undefined) {
this._target_monitor = target_monitor.monitor;
this._refresh_rate = target_monitor.refreshRate;
if (this._check_driver_running()) {
this._effect_enable();
} else {
@ -118,7 +124,7 @@ export default class BreezyDesktopExtension extends Extension {
this._xr_effect = new XREffect({
target_monitor: this._target_monitor,
target_framerate: 60
target_framerate: this._refresh_rate ?? 60
});
this._overlay.add_effect_with_name('xr-desktop', this._xr_effect);

View File

@ -20,6 +20,10 @@ export function dataViewUint(dataView, dataViewInfo) {
return dataView.getUint32(dataViewInfo[DATA_VIEW_INFO_OFFSET_INDEX], true);
}
export function dataViewBigUint(dataView, dataViewInfo) {
return Number(dataView.getBigUint64(dataViewInfo[DATA_VIEW_INFO_OFFSET_INDEX], true));
}
export function dataViewUintArray(dataView, dataViewInfo) {
const uintArray = []
let offset = dataViewInfo[DATA_VIEW_INFO_OFFSET_INDEX];

View File

@ -71,7 +71,11 @@ export function getMonitorConfig(displayConfigProxy, callback) {
const vendor = props['vendor'].get_string()[0];
const product = props['product'].get_string()[0];
const serial = props['serial'].get_string()[0];
monitors.push([displayName, connectorName, vendor, product, serial]);
// grab refresh rate from the modes array
const refreshRate = result[3][i][4];
monitors.push([displayName, connectorName, vendor, product, serial, refreshRate]);
}
callback(monitors, null);
}
@ -139,7 +143,7 @@ export default class MonitorManager {
}
const monitorProperties = [];
for (let i = 0; i < result.length; i++) {
const [monitorName, connectorName, vendor, product, serial] = result[i];
const [monitorName, connectorName, vendor, product, serial, refreshRate] = result[i];
const monitorIndex = this._backendManager.get_monitor_for_connector(connectorName);
console.log(`\n\nFound monitor ${monitorName}, vendor ${vendor}, product ${product}, serial ${serial}, connector ${connectorName}, index ${monitorIndex}\n\n`);
if (monitorIndex >= 0) {
@ -149,7 +153,8 @@ export default class MonitorManager {
vendor: vendor,
product: product,
serial: serial,
connector: connectorName
connector: connectorName,
refreshRate: refreshRate
};
}
}

View File

@ -1,3 +1,7 @@
export function getEpochSec() {
return Math.floor(Date.now() / 1000);
return toSec(Date.now());
}
export function toSec(milliseconds) {
return Math.floor(milliseconds / 1000);
}

View File

@ -7,7 +7,7 @@ import Globals from './globals.js';
import {
dataViewEnd,
dataViewUint8,
dataViewUint,
dataViewBigUint,
dataViewUintArray,
dataViewFloat,
dataViewFloatArray,
@ -20,28 +20,24 @@ import {
} from "./ipc.js";
import { degreeToRadian } from "./math.js";
import { getShaderSource } from "./shader.js";
import { getEpochSec } from "./time.js";
import { toSec } from "./time.js";
export const IPC_FILE_PATH = "/dev/shm/breezy_desktop_imu";
// the driver should be using the same data layout version
const DATA_LAYOUT_VERSION = 1;
const DATA_LAYOUT_VERSION = 2;
// DataView info: [offset, size, count]
const VERSION = [0, UINT8_SIZE, 1];
const ENABLED = [dataViewEnd(VERSION), BOOL_SIZE, 1];
const EPOCH_SEC = [dataViewEnd(ENABLED), UINT_SIZE, 1];
const LOOK_AHEAD_CFG = [dataViewEnd(EPOCH_SEC), FLOAT_SIZE, 4];
const LOOK_AHEAD_CFG = [dataViewEnd(ENABLED), FLOAT_SIZE, 4];
const DISPLAY_RES = [dataViewEnd(LOOK_AHEAD_CFG), UINT_SIZE, 2];
const DISPLAY_FOV = [dataViewEnd(DISPLAY_RES), FLOAT_SIZE, 1];
const DISPLAY_ZOOM = [dataViewEnd(DISPLAY_FOV), FLOAT_SIZE, 1];
const DISPLAY_NORTH_OFFSET = [dataViewEnd(DISPLAY_ZOOM), FLOAT_SIZE, 1];
const LENS_DISTANCE_RATIO = [dataViewEnd(DISPLAY_NORTH_OFFSET), FLOAT_SIZE, 1];
const LENS_DISTANCE_RATIO = [dataViewEnd(DISPLAY_FOV), FLOAT_SIZE, 1];
const SBS_ENABLED = [dataViewEnd(LENS_DISTANCE_RATIO), BOOL_SIZE, 1];
const SBS_CONTENT = [dataViewEnd(SBS_ENABLED), BOOL_SIZE, 1];
const SBS_MODE_STRETCHED = [dataViewEnd(SBS_CONTENT), BOOL_SIZE, 1];
const CUSTOM_BANNER_ENABLED = [dataViewEnd(SBS_MODE_STRETCHED), BOOL_SIZE, 1];
const IMU_QUAT_DATA = [dataViewEnd(CUSTOM_BANNER_ENABLED), FLOAT_SIZE, 16];
const CUSTOM_BANNER_ENABLED = [dataViewEnd(SBS_ENABLED), BOOL_SIZE, 1];
const EPOCH_MS = [dataViewEnd(CUSTOM_BANNER_ENABLED), UINT_SIZE, 2];
const IMU_QUAT_DATA = [dataViewEnd(EPOCH_MS), FLOAT_SIZE, 16];
const DATA_VIEW_LENGTH = dataViewEnd(IMU_QUAT_DATA);
// cached after first retrieval
@ -50,6 +46,7 @@ const shaderUniformLocations = {
'show_banner': null,
'imu_quat_data': null,
'look_ahead_cfg': null,
'look_ahead_ms': null,
'stage_aspect_ratio': null,
'display_aspect_ratio': null,
'trim_width_percent': null,
@ -59,12 +56,10 @@ const shaderUniformLocations = {
'lens_distance_ratio': null,
'sbs_enabled': null,
'sbs_content': null,
'sbs_mode_stretched': null,
'custom_banner_enabled': null,
'half_fov_z_rads': null,
'half_fov_y_rads': null,
'screen_distance': null,
'frametime': null
'screen_distance': null
};
function transferUniformBoolean(effect, location, dataView, dataViewInfo) {
@ -103,14 +98,25 @@ function setUniformMatrix(effect, locationName, components, dataView, dataViewIn
effect.set_uniform_matrix(shaderUniformLocations[locationName], true, components, floatArray);
}
function lookAheadMS(dataView) {
const lookAheadCfg = dataViewFloatArray(dataView, LOOK_AHEAD_CFG);
const imuDateMS = dataViewBigUint(dataView, EPOCH_MS);
// how stale the imu data is
const dataAge = Date.now() - imuDateMS;
return lookAheadCfg[0] + dataAge;
}
// most uniforms don't change frequently, this function should be called periodically
function setIntermittentUniformVariables() {
const dataView = this._dataView;
if (dataView.byteLength === DATA_VIEW_LENGTH) {
const version = dataViewUint8(dataView, VERSION);
const date = dataViewUint(dataView, EPOCH_SEC);
const validKeepalive = Math.abs(getEpochSec() - date) < 5;
const imuDateMS = dataViewBigUint(dataView, EPOCH_MS);
const currentDateMS = Date.now();
const validKeepalive = Math.abs(toSec(currentDateMS) - toSec(imuDateMS)) < 5;
const imuData = dataViewFloatArray(dataView, IMU_QUAT_DATA);
const imuResetState = imuData[0] === 0.0 && imuData[1] === 0.0 && imuData[2] === 0.0 && imuData[3] === 1.0;
const enabled = dataViewUint8(dataView, ENABLED) !== 0 && version === DATA_LAYOUT_VERSION && validKeepalive && !imuResetState;
@ -135,12 +141,8 @@ function setIntermittentUniformVariables() {
// all these values are transferred directly, unmodified from the driver
transferUniformFloat(this, 'look_ahead_cfg', dataView, LOOK_AHEAD_CFG);
transferUniformFloat(this, 'display_zoom', dataView, DISPLAY_ZOOM);
transferUniformFloat(this, 'display_north_offset', dataView, DISPLAY_NORTH_OFFSET);
transferUniformFloat(this, 'lens_distance_ratio', dataView, LENS_DISTANCE_RATIO);
transferUniformBoolean(this, 'sbs_enabled', dataView, SBS_ENABLED);
transferUniformBoolean(this, 'sbs_content', dataView, SBS_CONTENT);
transferUniformBoolean(this, 'sbs_mode_stretched', dataView, SBS_MODE_STRETCHED);
transferUniformBoolean(this, 'custom_banner_enabled', dataView, CUSTOM_BANNER_ENABLED);
// computed values with no dataViewInfo, so we set these manually
@ -152,7 +154,11 @@ function setIntermittentUniformVariables() {
setSingleFloat(this, 'half_fov_z_rads', halfFovZRads);
setSingleFloat(this, 'half_fov_y_rads', halfFovYRads);
setSingleFloat(this, 'screen_distance', screenDistance);
setSingleFloat(this, 'frametime', this._frametime);
// TOOD - drive from settings
setSingleFloat(this, 'display_zoom', 1.0);
setSingleFloat(this, 'display_north_offset', 1.0);
setSingleFloat(this, 'sbs_content', 0.0);
}
setSingleFloat(this, 'enabled', enabled ? 1.0 : 0.0);
} else if (dataView.byteLength !== 0) {
@ -217,6 +223,7 @@ export const XREffect = GObject.registerClass({
}
if (this._dataView.byteLength === DATA_VIEW_LENGTH) {
setSingleFloat(this, 'look_ahead_ms', lookAheadMS(this._dataView));
setUniformMatrix(this, 'imu_quat_data', 4, this._dataView, IMU_QUAT_DATA);
} else if (this._dataView.byteLength !== 0) {
console.error(`Invalid dataView.byteLength: ${this._dataView.byteLength} !== ${DATA_VIEW_LENGTH}`)