Skip to content

Commit

Permalink
feat: port prediction dampening from OpenXR toolkit
Browse files Browse the repository at this point in the history
  • Loading branch information
Detegr committed Sep 1, 2024
1 parent 66ce3c6 commit 813b4ed
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.2

- Implement prediction dampening for OpenXR

## 1.0.1

- Fix DirectX state block usage with reverse-z buffer to fix a bug where the
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ set(HEADERS

set(openRBRVR_Major 1)
set(openRBRVR_Minor 0)
set(openRBRVR_Patch 1)
set(openRBRVR_Patch 2)
set(openRBRVR_Tweak 0)
#set(openRBRVR_TweakStr "-rc${openRBRVR_Tweak}")

Expand Down
8 changes: 7 additions & 1 deletion src/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ struct Config {
D3DMULTISAMPLE_TYPE peripheral_msaa = D3DMULTISAMPLE_NONE;
bool openxr_motion_compensation = false; // OpenXR-MotionCompensation support https://github.com/BuzzteeBear/OpenXR-MotionCompensation
bool render_particles = true;
int64_t prediction_dampening = 0;

Config& operator=(const Config& rhs)
{
Expand Down Expand Up @@ -140,6 +141,7 @@ struct Config {
peripheral_msaa = rhs.peripheral_msaa;
openxr_motion_compensation = rhs.openxr_motion_compensation;
render_particles = rhs.render_particles;
prediction_dampening = rhs.prediction_dampening;
return *this;
}

Expand Down Expand Up @@ -169,7 +171,8 @@ struct Config {
&& wanted_quad_view_rendering == rhs.wanted_quad_view_rendering
&& peripheral_msaa == rhs.peripheral_msaa
&& openxr_motion_compensation == rhs.openxr_motion_compensation
&& render_particles == rhs.render_particles;
&& render_particles == rhs.render_particles
&& prediction_dampening == rhs.prediction_dampening;
}

bool write(const std::filesystem::path& path) const
Expand Down Expand Up @@ -231,6 +234,7 @@ struct Config {
openxr.insert("quadViewRendering", wanted_quad_view_rendering);
openxr.insert("peripheralAntiAliasing", peripheral_msaa);
openxr.insert("motionCompensation", openxr_motion_compensation);
openxr.insert("predictionDampening", prediction_dampening);
out.insert("OpenXR", openxr);

f << out;
Expand Down Expand Up @@ -317,6 +321,8 @@ struct Config {
cfg.quad_view_rendering = cfg.wanted_quad_view_rendering = oxrnode["quadViewRendering"].value_or(false);
cfg.peripheral_msaa = static_cast<D3DMULTISAMPLE_TYPE>(oxrnode["peripheralAntiAliasing"].value_or(0));
cfg.openxr_motion_compensation = oxrnode["motionCompensation"].value_or(false);
cfg.prediction_dampening = oxrnode["predicitonDampening"].value_or(0);
cfg.prediction_dampening = std::clamp(cfg.prediction_dampening, 0LL, 100LL);
}

return cfg;
Expand Down
12 changes: 12 additions & 0 deletions src/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,18 @@ static class Menu openxr_menu = { "openRBRVR OpenXR settings", {
.left_action = [] { Toggle(g::cfg.openxr_motion_compensation); },
.right_action = [] { Toggle(g::cfg.openxr_motion_compensation); },
},
{ .text = [] { return std::format("Prediction dampening: {}", g::cfg.prediction_dampening); },
.long_text = {
"Dampen the head movement prediction resulting in a smoother image.",
"",
"Useful in streaming for example to provide a smoother image",
"in the desktop window view.",
"",
"NOTE: does not work with motion reprojection!"
},
.left_action = [] { g::cfg.prediction_dampening = std::clamp(g::cfg.prediction_dampening - 1, 0LL, 100LL); },
.right_action = [] { g::cfg.prediction_dampening = std::clamp(g::cfg.prediction_dampening + 1, 0LL, 100LL); },
},
{ .text = id("Back to previous menu"),
.menu_color = IRBRGame::EMenuColors::MENU_TEXT,
.select_action = [] { select_menu(0); },
Expand Down
50 changes: 48 additions & 2 deletions src/OpenXR.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#define XR_USE_GRAPHICS_API_D3D11

#include "OpenXR.hpp"
#include "Config.hpp"
#include "Globals.hpp"
Expand Down Expand Up @@ -251,6 +249,28 @@ OpenXR::OpenXR()
throw std::runtime_error(std::format("OpenXR: Failed to enumerate API layers, error: {}", static_cast<int>(err)));
}

uint32_t extension_count;
if (auto err = xrEnumerateInstanceExtensionProperties(nullptr, 0, &extension_count, nullptr); err != XR_SUCCESS) {
throw std::runtime_error(std::format("OpenXR: Failed to enumerate extension properties, error: {}", static_cast<int>(err)));
}

std::vector<XrExtensionProperties> available_extensions(extension_count, { .type = XR_TYPE_EXTENSION_PROPERTIES });
if (auto err = xrEnumerateInstanceExtensionProperties(nullptr, extension_count, &extension_count, available_extensions.data()); err != XR_SUCCESS) {
throw std::runtime_error(std::format("OpenXR: Failed to enumerate extension properties, error: {}", static_cast<int>(err)));
}

if (auto ext = std::ranges::find_if(available_extensions, [](const XrExtensionProperties& p) {
return std::string(p.extensionName) == "XR_KHR_win32_convert_performance_counter_time";
});
ext != available_extensions.cend()) {
extensions.push_back(ext->extensionName);
} else {
// Prediction dampening requires "XR_KHR_win32_convert_performance_counter_time" extension
// If it does not exist, revert dampening setting
dbg("Prediction dampening not in use as XR_KHR_win32_convert_performance_counter_time extension is not present");
g::cfg.prediction_dampening = 0;
}

if (g::cfg.quad_view_rendering) {
auto quad_views_layer = std::ranges::find_if(available_api_layers, [](const XrApiLayerProperties& p) {
return std::string(p.layerName) == "XR_APILAYER_MBUCCHIA_quad_views_foveated";
Expand Down Expand Up @@ -303,6 +323,13 @@ OpenXR::OpenXR()
if (auto err = xrGetSystem(instance, &system_get_info, &system_id); err != XR_SUCCESS) {
throw std::runtime_error(std::format("Failed to initialize OpenXR: xrGetSystem {}", XrResultToString(instance, err)));
}

try {
xr_convert_win32_performance_counter_to_time = get_extension<PFN_xrConvertWin32PerformanceCounterToTimeKHR>(instance, "xrConvertWin32PerformanceCounterToTimeKHR");
} catch (const std::runtime_error& e) {
dbg("Not using prediction dampening as xrConvertWin32PerformanceCounterToTimeKHR function was not found");
xr_convert_win32_performance_counter_to_time = nullptr;
}
}

void OpenXR::init(IDirect3DDevice9* dev, IDirect3DVR9** vrdev, uint32_t companion_window_width, uint32_t companion_window_height, std::optional<XrPosef> old_view_pose)
Expand Down Expand Up @@ -1063,6 +1090,25 @@ bool OpenXR::update_vr_poses()
return false;
}

if (g::cfg.prediction_dampening > 0 && xr_convert_win32_performance_counter_to_time) {
// Ported from:
// https://github.com/mbucchia/OpenXR-Toolkit/blob/main/XR_APILAYER_MBUCCHIA_toolkit/layer.cpp#L2175-L2191
// MIT License
// Copyright (c) 2021-2022 Matthieu Bucchianeri
// Copyright (c) 2021-2022 Jean-Luc Dupiot - Reality XP

LARGE_INTEGER pc_now;
QueryPerformanceCounter(&pc_now);

XrTime xr_now;
xr_convert_win32_performance_counter_to_time(instance, &pc_now, &xr_now);

XrTime prediction_amount = frame_state.predictedDisplayTime - xr_now;
if (prediction_amount > 0) {
frame_state.predictedDisplayTime = xr_now + ((100 - g::cfg.prediction_dampening) * prediction_amount) / 100;
}
}

if (frame_state.shouldRender == XR_FALSE) {
// Oculus runtime has a bug where shouldRender is always false... o_o
// So we do nothing about it.
Expand Down
12 changes: 8 additions & 4 deletions src/OpenXR.hpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
#pragma once

#include "Config.hpp"
#include "VR.hpp"
#include <array>
#include <d3d11.h>
#include <d3d11_4.h>
#include <d3d9.h>

#define XR_USE_GRAPHICS_API_D3D11
#define XR_USE_PLATFORM_WIN32
#include <openxr_platform.h>
#include <openxr_reflection.h>
#include <optional>

#include "Config.hpp"
#include "VR.hpp"
#include <array>
#include <d3d9.h>

struct OpenXRRenderContext {
std::vector<XrSwapchain> swapchains;
std::vector<ID3D11Texture2D*> shared_textures;
Expand Down Expand Up @@ -57,6 +59,8 @@ class OpenXR : public VRInterface {
bool reset_view_requested;
bool has_views;

PFN_xrConvertWin32PerformanceCounterToTimeKHR xr_convert_win32_performance_counter_to_time;

struct {
uint64_t value;
ID3D11Fence* fence;
Expand Down
1 change: 0 additions & 1 deletion src/VR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

#include <d3d9_vr.h>

#define XR_USE_GRAPHICS_API_D3D11
#include <d3d9.h>
#include <openvr.h>
#include <openxr.h>
Expand Down

0 comments on commit 813b4ed

Please sign in to comment.