Files
mitch030504--AstroQuest-Frame/quest-host/cpp/xr_host.h
T
bigmak94andClaude Opus 5.5 b5f400bbbd AstroQuest 0.11: ASTRO BOT Rescue Mission in VR on Meta Quest 3 and PC VR
On top of the shadps4-arm64 core imported in the previous commit:

- PlayStation VR emulation: headset, tracker, reprojection, camera and social screen; the
  player's seat and view reset; head velocity for head-butts; field of view settings
- Sound: a native Ngs2 engine (samplers, submixers, effects), the Audio3d spatializer, virtual
  surround for headset speakers, microphone pass-through; libSceJson2; libSceFiber on FEX
- Fixes for CUSA12392 under emulation: real-time step, pace and resolution governor, larger
  render sizes on the PC, save loading at start
- Renderer: geometry shaders fed with fans/polygons/loops, cube-array layers of light probes,
  sample-count mismatches on Adreno, timeline semaphore hang, FXAA in place of the MSAA
  resolve, sharpening, VR frame export
- quest-host: the Quest app (OpenXR host that runs the glibc core as a child process, frames
  through AHardwareBuffers, DualSense mapping, hand-tracked controller placement, KGSL shim)
- PC: in-process OpenXR host (Virtual Desktop or any OpenXR runtime), Touch controllers as the
  gamepad, launcher with a settings window; vendored OpenXR SDK 1.1.63
- Builds keep the build machine's folders out of the binaries (-ffile-prefix-map); machine
  settings (Python, headset serial, signing key) live in git-ignored tools/*.local files
- tools: build, packaging and test scripts for Windows and the headset
- README with installation, license (GPL-2.0-or-later), third-party notices and thanks

No game files are part of the repository; .gitignore only lets listed paths in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:00:43 +02:00

89 lines
4.2 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <atomic>
#include <cstdint>
#include <mutex>
#include <vector>
#include <jni.h>
class CoreProcess;
/// A picture the Java side draws (text is far easier there) and the headset shows on a floating
/// panel whenever the game itself has nothing on screen.
struct StatusImage {
static constexpr int Width = 1024;
static constexpr int Height = 512;
std::mutex mutex;
std::vector<uint8_t> pixels; ///< RGBA, top row first
uint64_t version{};
};
struct XrHostOptions {
/// Display refresh rate to ask for, 0 keeps the system default.
float refresh_rate{0.0f};
/// Size of one eye in the buffers frames are delivered in.
uint32_t eye_width{1440};
uint32_t eye_height{1536};
/// Use the wearer's hands, as the headset sees them around the gamepad, to place the
/// controller in the game.
bool track_hands{true};
/// What the compositor does to the game's picture, which is coarser than the display, on
/// top of showing it: 0 and 1 nothing (with 1 the emulator sharpens the picture itself,
/// which is not this struct's business), 2 its Super Resolution filter on every refresh,
/// 3 the same but only while the system finds the GPU has the time for it, 4 its plainer
/// and cheaper sharpening filter.
int sharpen{1};
/// Have the compositor read the game's picture with a cubic filter instead of a linear
/// one where it enlarges it: sharper, for a little of the GPU's time on every refresh.
bool cubic{};
/// Keep the status panel in view (small, below the middle) while the game runs, for the
/// figures the app writes on it.
bool show_stats{};
/// Ask the system from moment to moment for the size it recommends for the picture. It
/// counts an app that asks among those that give way when the GPU is short, which is its
/// condition for the higher GPU clock levels. This app gives way where the GPU's time
/// goes: in the size the game draws its scene at, which the emulator sees to.
bool dynamic_resolution{true};
/// Also show the picture at the recommended size instead of at full size. That saves next
/// to nothing (the picture is copied once per frame of the game) and blurs what the game
/// drew; it is what the app did up to version 0.6.
bool follow_layer_size{};
/// Ask for the processor's "boost" level: its fastest clock for the first 45 seconds and
/// for up to a fifth of the time after that, as the system sees fit. That is when the
/// emulator translates most of the game's code.
bool cpu_boost{true};
/// For the probe that runs the host without anybody wearing the headset: ask the session
/// that never begins for everything that is otherwise asked when it does (refresh rate,
/// performance levels, thread hints), to have the answers in the log.
bool probe{};
/// How far beyond the next display refresh the head pose given to the game is predicted,
/// in milliseconds. A frame is on the display some tens of milliseconds after the game
/// read the pose it drew it for; aiming at that moment leaves the compositor less to
/// correct, which is what shows as black edges when the head turns.
float predict_ms{25.0f};
};
/// What a request to reset the view asks for (bits of the counter RunXrHost is given).
namespace XrRecenter {
/// The way the controller points right now is straight ahead.
inline constexpr uint32_t Pad = 1;
/// Where the head is now is where the player sits, and the way it faces is straight ahead.
inline constexpr uint32_t Seat = 2;
} // namespace XrRecenter
/// What the host worked out about the session, for the status panel and for logging.
struct XrHostStatus {
std::atomic<bool> session_running{};
std::atomic<bool> hands_tracked{};
std::atomic<float> refresh_rate{};
};
/// Owns the OpenXR session: feeds the head pose to the core and shows the stereo frames it
/// delivers. Blocks until `quit` is set or the system ends the session.
void RunXrHost(JavaVM* vm, jobject activity, CoreProcess& core, StatusImage& status,
const XrHostOptions& options, XrHostStatus& host_status, std::atomic<bool>& quit,
std::atomic<uint32_t>& recenter_requests);