diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 8513500b86..5cd35fc590 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -644,30 +644,19 @@ bool Is2DVRObject(float* projMatrix, bool ortho) { return true; } - // Chceck if the projection matrix is identity - bool identity = true; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - float value = projMatrix[i * 4 + j]; - - // Other number than zero on non-diagonale - if ((i != j) && (fabs(value) > EPSILON)) identity = false; - // Other number than one on diagonale - if ((i == j) && (fabs(value - 1.0f) > EPSILON)) identity = false; - } - } - // Update 3D geometry count + bool identity = IsMatrixIdentity(projMatrix); if (!identity && !ortho) { vr3DGeometryCount++; } return identity; } -void UpdateVRParams(float* projMatrix) { +void UpdateVRParams(float* projMatrix, float* viewMatrix) { // Set mirroring of axes - if (!vrMirroring[VR_MIRRORING_UPDATED]) { + bool identityView = PSP_CoreParameter().compat.vrCompat().IdentityViewHack && IsMatrixIdentity(viewMatrix); + if (!vrMirroring[VR_MIRRORING_UPDATED] && !IsMatrixIdentity(projMatrix) && !identityView) { vrMirroring[VR_MIRRORING_UPDATED] = true; vrMirroring[VR_MIRRORING_AXIS_X] = projMatrix[0] < 0; vrMirroring[VR_MIRRORING_AXIS_Y] = projMatrix[5] < 0; @@ -708,6 +697,11 @@ void UpdateVRView(float* leftEye, float* rightEye) { float* matrix[] = {vrMatrix[VR_VIEW_MATRIX_LEFT_EYE], vrMatrix[VR_VIEW_MATRIX_RIGHT_EYE]}; for (int index = 0; index < 2; index++) { + // Validate the view matrix + if (PSP_CoreParameter().compat.vrCompat().IdentityViewHack && IsMatrixIdentity(dst[index])) { + return; + } + // Get view matrix from the game Lin::Matrix4x4 gameView = {}; memcpy(gameView.m, dst[index], 16 * sizeof(float)); diff --git a/Common/VR/PPSSPPVR.h b/Common/VR/PPSSPPVR.h index 8dd127a2cb..c47fada705 100644 --- a/Common/VR/PPSSPPVR.h +++ b/Common/VR/PPSSPPVR.h @@ -40,6 +40,6 @@ int GetVRPassesCount(); bool IsMultiviewSupported(); bool IsFlatVRScene(); bool Is2DVRObject(float* projMatrix, bool ortho); -void UpdateVRParams(float* projMatrix); +void UpdateVRParams(float* projMatrix, float* viewMatrix); void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye); void UpdateVRView(float* leftEye, float* rightEye); diff --git a/Common/VR/VRMath.cpp b/Common/VR/VRMath.cpp index 2fd7f1d538..d65f13a1a7 100644 --- a/Common/VR/VRMath.cpp +++ b/Common/VR/VRMath.cpp @@ -13,6 +13,20 @@ float ToRadians(float deg) { return (float)(deg * M_PI / 180.0f); } +bool IsMatrixIdentity(float* matrix) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + float value = matrix[i * 4 + j]; + + // Other number than zero on non-diagonale + if ((i != j) && (fabs(value) > EPSILON)) return false; + // Other number than one on diagonale + if ((i == j) && (fabs(value - 1.0f) > EPSILON)) return false; + } + } + return true; +} + /* ================================================================================ diff --git a/Common/VR/VRMath.h b/Common/VR/VRMath.h index 20317f4a8d..4f6e0610c9 100644 --- a/Common/VR/VRMath.h +++ b/Common/VR/VRMath.h @@ -9,6 +9,7 @@ float ToDegrees(float rad); float ToRadians(float deg); +bool IsMatrixIdentity(float* matrix); // XrPosef XrPosef XrPosef_Identity(); diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 21fb578456..b09eb67c14 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -122,6 +122,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { } void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { + CheckSetting(iniFile, gameID, "IdentityViewHack", &vrCompat_.IdentityViewHack); CheckSetting(iniFile, gameID, "Skyplane", &vrCompat_.Skyplane); CheckSetting(iniFile, gameID, "UnitsPerMeter", &vrCompat_.UnitsPerMeter); diff --git a/Core/Compatibility.h b/Core/Compatibility.h index c37541ce7a..86d139a536 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -93,6 +93,7 @@ struct CompatFlags { }; struct VRCompat { + bool IdentityViewHack; bool Skyplane; float UnitsPerMeter; }; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 1f75b7412b..7195bcd8af 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -411,7 +411,9 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu } else { UpdateVRProjection(gstate.projMatrix, leftEyeMatrix.m, rightEyeMatrix.m); } - UpdateVRParams(gstate.projMatrix); + float m4x4[16]; + ConvertMatrix4x3To4x4Transposed(m4x4, gstate.viewMatrix); + UpdateVRParams(gstate.projMatrix, m4x4); FlipProjMatrix(leftEyeMatrix, useBufferedRendering); FlipProjMatrix(rightEyeMatrix, useBufferedRendering); diff --git a/assets/compatvr.ini b/assets/compatvr.ini index b54081f4f5..b896196ab8 100644 --- a/assets/compatvr.ini +++ b/assets/compatvr.ini @@ -30,6 +30,18 @@ # ======================================================================================== +[IdentityViewHack] +# Disables head tracking for render passes where view matrix is Identity + +# Sonic Rivals 1 +ULES00622 = true +ULUS10195 = true + +# Sonic Rivals 2 +ULES00940 = true +ULUS10323 = true + + [Skyplane] # Workaround to remove the background skyplane and add clearing framebuffer with a fog color. @@ -53,6 +65,7 @@ ULJM05395 = true ULJM05884 = true ULUS10160 = true + [UnitsPerMeter] # Scale of game world to convert the world units into meters. This enables following VR features: # + 3D stereoscopy (that can work only with accurate values)