Display warning overlay instead of scene when below min spec

This commit is contained in:
Brad Davis 2016-10-26 14:13:02 -07:00
parent 012e215f62
commit 018d945b85
5 changed files with 108 additions and 4 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View file

@ -37,7 +37,9 @@
#include <CrashReporter.h>
#endif
extern "C" {
typedef int(__stdcall * CHECKMINSPECPROC) ();
}
int main(int argc, const char* argv[]) {
#if HAS_BUGSPLAT
@ -155,6 +157,27 @@ int main(int argc, const char* argv[]) {
SteamClient::init();
#ifdef Q_OS_WIN
// If we're running in steam mode, we need to do an explicit check to ensure we're up to the required min spec
if (SteamClient::isRunning()) {
QString appPath;
{
char filename[MAX_PATH];
GetModuleFileName(NULL, filename, MAX_PATH);
QFileInfo appInfo(filename);
appPath = appInfo.absolutePath();
}
QString openvrDllPath = appPath + "/plugins/openvr.dll";
HMODULE openvrDll;
CHECKMINSPECPROC checkMinSpecPtr;
if ((openvrDll = LoadLibrary(openvrDllPath.toLocal8Bit().data())) &&
(checkMinSpecPtr = (CHECKMINSPECPROC)GetProcAddress(openvrDll, "CheckMinSpec"))) {
if (!checkMinSpecPtr()) {
return -1;
}
}
}
#endif
int exitCode;
{

View file

@ -379,9 +379,6 @@ void OpenVrDisplayPlugin::init() {
emit deviceConnected(getName());
}
// FIXME remove once OpenVR header is updated
#define VRCompositor_ReprojectionAsync 0x04
bool OpenVrDisplayPlugin::internalActivate() {
if (!_system) {
_system = acquireOpenVrSystem();

View file

@ -12,11 +12,13 @@
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <QtCore/QLoggingCategory>
#include <QtCore/QProcessEnvironment>
#include <QtGui/QInputMethodEvent>
#include <QtQuick/QQuickWindow>
#include <PathUtils.h>
#include <Windows.h>
#include <OffscreenUi.h>
#include <controllers/Pose.h>
@ -324,3 +326,83 @@ controller::Pose openVrControllerPoseToHandPose(bool isLeftHand, const mat4& mat
result.angularVelocity = angularVelocity;
return result;
}
#define FAILED_MIN_SPEC_OVERLAY_NAME "FailedMinSpecOverlay"
#define FAILED_MIN_SPEC_OVERLAY_FRIENDLY_NAME "Minimum specifications for SteamVR not met"
#define OVERLAY_UPDATE_INTERVAL_MS 10
#define OVERLAY_DISPLAY_INTERVAL_MS (MSECS_PER_SECOND * 10)
#define MIN_CORES_SPEC 5
void showMinSpecWarning() {
auto vrSystem = acquireOpenVrSystem();
auto vrOverlay = vr::VROverlay();
if (!vrOverlay) {
qFatal("Unable to initialize SteamVR overlay manager");
}
vr::VROverlayHandle_t minSpecFailedOverlay = 0;
if (vr::VROverlayError_None != vrOverlay->CreateOverlay(FAILED_MIN_SPEC_OVERLAY_NAME, FAILED_MIN_SPEC_OVERLAY_FRIENDLY_NAME, &minSpecFailedOverlay)) {
qFatal("Unable to create overlay");
}
// Needed here for PathUtils
QCoreApplication miniApp(__argc, __argv);
vrSystem->ResetSeatedZeroPose();
QString imagePath = PathUtils::resourcesPath() + "/images/steam-min-spec-failed.png";
vrOverlay->SetOverlayFromFile(minSpecFailedOverlay, imagePath.toLocal8Bit().toStdString().c_str());
vrOverlay->SetHighQualityOverlay(minSpecFailedOverlay);
vrOverlay->ShowOverlay(minSpecFailedOverlay);
QTimer* positionTimer = new QTimer(&miniApp);
positionTimer->setInterval(OVERLAY_UPDATE_INTERVAL_MS);
QObject::connect(positionTimer, &QTimer::timeout, [&] {
vr::TrackedDevicePose_t vrPoses[vr::k_unMaxTrackedDeviceCount];
vrSystem->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, 0, vrPoses, vr::k_unMaxTrackedDeviceCount);
auto headPose = toGlm(vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking);
auto overlayPose = toOpenVr(headPose * glm::translate(glm::mat4(), vec3(0, 0, -1)));
vrOverlay->SetOverlayTransformAbsolute(minSpecFailedOverlay, vr::TrackingUniverseSeated, &overlayPose);
});
positionTimer->start();
QTimer::singleShot(OVERLAY_DISPLAY_INTERVAL_MS, &miniApp, &QCoreApplication::quit);
miniApp.exec();
}
bool checkMinSpecImpl() {
// If OpenVR isn't supported, we have no min spec, so pass
if (!openVrSupported()) {
return true;
}
// If we have at least 5 cores, pass
auto coreCount = QThread::idealThreadCount();
if (coreCount >= MIN_CORES_SPEC) {
return true;
}
// Even if we have too few cores... if the compositor is using async reprojection, pass
auto system = acquireOpenVrSystem();
auto compositor = vr::VRCompositor();
if (system && compositor) {
vr::Compositor_FrameTiming timing;
memset(&timing, 0, sizeof(timing));
timing.m_nSize = sizeof(vr::Compositor_FrameTiming);
compositor->GetFrameTiming(&timing);
releaseOpenVrSystem();
if (timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync) {
return true;
}
}
// We're using OpenVR and we don't have enough cores...
showMinSpecWarning();
return false;
}
extern "C" {
__declspec(dllexport) int __stdcall CheckMinSpec() {
return checkMinSpecImpl() ? 1 : 0;
}
}

View file

@ -82,5 +82,7 @@ struct PoseData {
}
};
// FIXME remove once OpenVR header is updated
#define VRCompositor_ReprojectionAsync 0x04
controller::Pose openVrControllerPoseToHandPose(bool isLeftHand, const mat4& mat, const vec3& linearVelocity, const vec3& angularVelocity);