mirror of
https://github.com/Toastconcern/FrameStudio.git
synced 2026-10-29 04:02:56 +01:00
- vr_compat.h: GetProjectionMatrix / GetEyeToHeadTransform called with Microsoft's member ABI on MinGW builds (SteamVR is built with MSVC; the hidden return pointer goes after this): the first frame crashed there. - When SteamVR asks it to quit (a game, room setup), Frame Home leaves at once instead of waiting for a load (SteamVR killed it after 5 s). - The panel keeps SteamVR's home app running on a PC: SteamVR doesn't start it again after it stopped on its own. - Logs on Windows: the environment and the panel always write logs/frame-home.log and logs/frame-switcher.log (SteamVR gives them a hidden console); the panel logs to a file on the headset too now. A crash writes the exception and the stack's return addresses there. - Tested on SteamVR's null driver: Frame Home started by SteamVR as its home app, the panel with it, SteamVR's background made from the home, a crash recovered in seconds, 0.79 ms GPU at 1976x1976 per eye with 4x MSAA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 lines
1.7 KiB
C++
31 lines
1.7 KiB
C++
#pragma once
|
|
// The OpenVR calls that return a struct, made the way SteamVR expects when Frame Home is built for Windows with
|
|
// MinGW (GCC or Clang). SteamVR is built with Microsoft's compiler, whose C++ ABI passes a member function's hidden
|
|
// return pointer after `this`; MinGW's (the Itanium ABI) passes it before. Called through the C++ interface, these
|
|
// jumped to garbage (a crash in the first frame). Here they go through the interface's vtable with Microsoft's order.
|
|
// Everywhere else (Linux, the Steam Frame, an MSVC build): the plain calls.
|
|
#include <openvr.h>
|
|
|
|
namespace vrcompat {
|
|
|
|
#if defined(_WIN32) && !defined(_MSC_VER)
|
|
// slot: the method's place in the interface's vtable, as openvr.h declares it for the version asked for (IVRSystem_026).
|
|
template <typename R, typename... A> R msvcMember(void* object, int slot, A... args) {
|
|
R result;
|
|
using Fn = R* (*)(void*, R*, A...); // x64: this, the return pointer, then the arguments, as Microsoft's members take them
|
|
(*reinterpret_cast<Fn* const*>(object))[slot](object, &result, args...);
|
|
return result;
|
|
}
|
|
inline vr::HmdMatrix44_t projectionMatrix(vr::EVREye eye, float nearZ, float farZ) {
|
|
return msvcMember<vr::HmdMatrix44_t>(vr::VRSystem(), 1, eye, nearZ, farZ); // IVRSystem::GetProjectionMatrix
|
|
}
|
|
inline vr::HmdMatrix34_t eyeToHead(vr::EVREye eye) {
|
|
return msvcMember<vr::HmdMatrix34_t>(vr::VRSystem(), 5, eye); // IVRSystem::GetEyeToHeadTransform
|
|
}
|
|
#else
|
|
inline vr::HmdMatrix44_t projectionMatrix(vr::EVREye eye, float nearZ, float farZ) { return vr::VRSystem()->GetProjectionMatrix(eye, nearZ, farZ); }
|
|
inline vr::HmdMatrix34_t eyeToHead(vr::EVREye eye) { return vr::VRSystem()->GetEyeToHeadTransform(eye); }
|
|
#endif
|
|
|
|
} // namespace vrcompat
|