diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index aa0f9bb1e7..e5e6a5530a 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -557,6 +557,13 @@ + + + + + + + @@ -989,6 +996,76 @@ + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 0cb9e79423..e04ecff0c8 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -425,6 +425,27 @@ Math + + VR + + + VR + + + VR + + + VR + + + VR + + + VR + + + VR + @@ -803,6 +824,27 @@ Math + + VR + + + VR + + + VR + + + VR + + + VR + + + VR + + + VR + @@ -907,6 +949,9 @@ {7b17065c-729c-47c3-a02d-66dc383529dd} + + {9d1c29fd-8ac7-4475-8ea6-c8c759b695fe} + diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 47874252e3..84f1b1a375 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -648,7 +648,7 @@ retry_depth: currentReadHandle_ = fbo->handle; } -void GLQueueRunner::RunSteps(const std::vector &steps, bool skipGLCalls, bool keepSteps) { +void GLQueueRunner::RunSteps(const std::vector &steps, bool skipGLCalls, bool keepSteps, bool useVR) { if (skipGLCalls) { if (keepSteps) { return; diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index 1e009787ae..e9ad214eb4 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -363,7 +363,7 @@ public: void RunInitSteps(const std::vector &steps, bool skipGLCalls); - void RunSteps(const std::vector &steps, bool skipGLCalls, bool keepSteps = false); + void RunSteps(const std::vector &steps, bool skipGLCalls, bool keepSteps, bool useVR); void LogSteps(const std::vector &steps); void CreateDeviceObjects(); diff --git a/Common/GPU/OpenGL/GLRenderManager.cpp b/Common/GPU/OpenGL/GLRenderManager.cpp index bca19e274f..c3d14bb4a7 100644 --- a/Common/GPU/OpenGL/GLRenderManager.cpp +++ b/Common/GPU/OpenGL/GLRenderManager.cpp @@ -581,11 +581,11 @@ void GLRenderManager::Run(int frame) { int passes = GetVRPassesCount(); for (int i = 0; i < passes; i++) { PreVRFrameRender(i); - queueRunner_.RunSteps(stepsOnThread, skipGLCalls_, i < passes - 1); + queueRunner_.RunSteps(stepsOnThread, skipGLCalls_, i < passes - 1, true); PostVRFrameRender(); } } else { - queueRunner_.RunSteps(stepsOnThread, skipGLCalls_); + queueRunner_.RunSteps(stepsOnThread, skipGLCalls_, false, false); } stepsOnThread.clear(); diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index b0c2ab370b..52ece65731 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -308,8 +308,7 @@ void VulkanSetAvailable(bool available) { } bool VulkanMayBeAvailable() { - - //unsupported in VR at the moment + // Unsupported in VR at the moment if (IsVRBuild()) { return false; } diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index e430374079..b771342e49 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -74,19 +74,21 @@ void CenterDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &f bool rotated = rotation == ROTATION_LOCKED_VERTICAL || rotation == ROTATION_LOCKED_VERTICAL180; + SmallDisplayZoom zoomType = (SmallDisplayZoom)g_Config.iSmallDisplayZoomType; + if (IsVRBuild()) { if (IsFlatVRScene()) { - g_Config.iSmallDisplayZoomType = (int)SmallDisplayZoom::AUTO; + zoomType = SmallDisplayZoom::AUTO; } else { - g_Config.iSmallDisplayZoomType = (int)SmallDisplayZoom::STRETCH; + zoomType = SmallDisplayZoom::STRETCH; } } - if (g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::STRETCH) { + if (zoomType == SmallDisplayZoom::STRETCH) { outW = frame.w; outH = frame.h; } else { - if (g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::MANUAL) { + if (zoomType == SmallDisplayZoom::MANUAL) { float offsetX = (g_Config.fSmallDisplayOffsetX - 0.5f) * 2.0f * frame.w + frame.x; float offsetY = (g_Config.fSmallDisplayOffsetY - 0.5f) * 2.0f * frame.h + frame.y; // Have to invert Y for GL @@ -109,7 +111,7 @@ void CenterDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &f rc->h = floorf(smallDisplayW); return; } - } else if (g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::AUTO) { + } else if (zoomType == SmallDisplayZoom::AUTO) { // Stretch to 1080 for 272*4. But don't distort if not widescreen (i.e. ultrawide of halfwide.) float pixelCrop = frame.h / 270.0f; float resCommonWidescreen = pixelCrop - floor(pixelCrop); @@ -130,13 +132,13 @@ void CenterDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &f outW = frame.w; outH = frame.w / origRatio; // Stretch a little bit - if (!rotated && g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::PARTIAL_STRETCH) + if (!rotated && zoomType == SmallDisplayZoom::PARTIAL_STRETCH) outH = (frame.h + outH) / 2.0f; // (408 + 720) / 2 = 564 } else { // Image is taller than frame. Center horizontally. outW = frame.h * origRatio; outH = frame.h; - if (rotated && g_Config.iSmallDisplayZoomType == (int)SmallDisplayZoom::PARTIAL_STRETCH) + if (rotated && zoomType == SmallDisplayZoom::PARTIAL_STRETCH) outW = (frame.h + outH) / 2.0f; // (408 + 720) / 2 = 564 } } diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 45433a72d7..64258d1103 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -23,7 +23,6 @@ #include "Common/GPU/OpenGL/GLFeatures.h" #include "Common/GPU/ShaderWriter.h" #include "Common/GPU/thin3d.h" -#include "Common/VR/PPSSPPVR.h" #include "Core/Config.h" #include "GPU/ge_constants.h" #include "GPU/GPUState.h" @@ -149,10 +148,11 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag if (gl_extensions.ARB_cull_distance && id.Bit(VS_BIT_VERTEX_RANGE_CULLING)) { gl_exts.push_back("#extension GL_ARB_cull_distance : enable"); } + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY) && gstate_c.Use(GPU_USE_SINGLE_PASS_STEREO)) { + gl_exts.push_back("#extension GL_OVR_multiview2 : enable\nlayout(num_views=2) in;"); + } } - if (IsVRBuild() && IsMultiviewSupported()) { - gl_exts.push_back("#extension GL_OVR_multiview2 : enable\nlayout(num_views=2) in;"); - } + ShaderWriter p(buffer, compat, ShaderStage::Vertex, gl_exts.data(), gl_exts.size()); bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); @@ -480,8 +480,8 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, "uniform mat4 u_proj_through;\n"); *uniformMask |= DIRTY_PROJTHROUGHMATRIX; } else if (useHWTransform) { - if (IsVRBuild()) { - if (IsMultiviewSupported()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { + if (gstate_c.Use(GPU_USE_SINGLE_PASS_STEREO)) { WRITE(p, "layout(shared) uniform ProjectionMatrix { uniform mat4 u_proj_lens[2]; };\n"); } else { WRITE(p, "uniform mat4 u_proj_lens;\n"); @@ -495,7 +495,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag // When transforming by hardware, we need a great deal more uniforms... // TODO: Use 4x3 matrices where possible. Though probably doesn't matter much. WRITE(p, "uniform mat4 u_world;\n"); - if (IsVRBuild() && IsMultiviewSupported()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY) && gstate_c.Use(GPU_USE_SINGLE_PASS_STEREO)) { WRITE(p, "layout(shared) uniform ViewMatrices { uniform mat4 u_view[2]; };\n"); } else { WRITE(p, "uniform mat4 u_view;\n"); @@ -560,7 +560,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, "uniform lowp float u_rotation;\n"); } - if (IsVRBuild()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { WRITE(p, "uniform lowp float u_scaleX;\n"); WRITE(p, "uniform lowp float u_scaleY;\n"); } @@ -920,7 +920,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } std::string matrixPostfix; - if (IsVRBuild() && IsMultiviewSupported()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY) && gstate_c.Use(GPU_USE_SINGLE_PASS_STEREO)) { matrixPostfix = "[gl_ViewID_OVR]"; } @@ -928,14 +928,14 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag // Final view and projection transforms. if (gstate_c.Use(GPU_ROUND_DEPTH_TO_16BIT)) { - if (IsVRBuild()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { WRITE(p, " vec4 outPos = depthRoundZVP(mul(u_proj_lens%s, viewPos));\n", matrixPostfix.c_str()); WRITE(p, " vec4 orgPos = depthRoundZVP(mul(u_proj, viewPos));\n"); } else { WRITE(p, " vec4 outPos = depthRoundZVP(mul(u_proj, viewPos));\n"); } } else { - if (IsVRBuild()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { WRITE(p, " vec4 outPos = mul(u_proj_lens%s, viewPos);\n", matrixPostfix.c_str()); WRITE(p, " vec4 orgPos = mul(u_proj, viewPos);\n"); } else { @@ -1284,7 +1284,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, " }\n"); } - if (vertexRangeCulling && !IsVRBuild()) { + if (vertexRangeCulling && !gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { WRITE(p, " vec3 projPos = outPos.xyz / outPos.w;\n"); WRITE(p, " float projZ = (projPos.z - u_depthRange.z) * u_depthRange.w;\n"); @@ -1325,7 +1325,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag // We've named the output gl_Position in HLSL as well. WRITE(p, " %sgl_Position = outPos;\n", compat.vsOutPrefix); - if (IsVRBuild()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { // Z correction for the depth buffer if (useHWTransform) { WRITE(p, " %sgl_Position.z = orgPos.z / abs(orgPos.w) * abs(outPos.w);\n", compat.vsOutPrefix); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index c2740460db..b6b2b6a661 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -22,6 +22,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/File/FileUtil.h" #include "Common/GraphicsContext.h" +#include "Common/VR/PPSSPPVR.h" #include "Core/Config.h" #include "Core/Debugger/Breakpoints.h" @@ -209,6 +210,13 @@ u32 GPU_GLES::CheckGPUFeatures() const { features |= GPU_USE_FRAGMENT_TEST_CACHE; } + if (IsVRBuild()) { + features |= GPU_USE_VIRTUAL_REALITY; + } + if (IsMultiviewSupported()) { + features |= GPU_USE_SINGLE_PASS_STEREO; + } + return features; } diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 055d626b28..db721ab475 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -130,10 +130,9 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, queries.push_back({ &u_cullRangeMax, "u_cullRangeMax" }); queries.push_back({ &u_rotation, "u_rotation" }); - if (IsVRBuild()) { - queries.push_back({ &u_scaleX, "u_scaleX" }); - queries.push_back({ &u_scaleY, "u_scaleY" }); - } + // These two are only used for VR, but let's always query them for simplicity. + queries.push_back({ &u_scaleX, "u_scaleX" }); + queries.push_back({ &u_scaleY, "u_scaleY" }); #ifdef USE_BONE_ARRAY queries.push_back({ &u_bone, "u_bone" }); @@ -378,7 +377,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu } bool is2D, flatScreen; - if (IsVRBuild()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { // Analyze scene is2D = Is2DVRObject(gstate.projMatrix, gstate.isModeThrough()); flatScreen = IsFlatVRScene(); @@ -402,7 +401,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu // Update any dirty uniforms before we draw if (dirty & DIRTY_PROJMATRIX) { - if (IsVRBuild()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { Matrix4x4 leftEyeMatrix, rightEyeMatrix; if (flatScreen || is2D) { memcpy(&leftEyeMatrix, gstate.projMatrix, 16 * sizeof(float)); @@ -536,7 +535,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu SetMatrix4x3(render_, &u_world, gstate.worldMatrix); } if (dirty & DIRTY_VIEWMATRIX) { - if (IsVRBuild()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { float leftEyeView[16]; float rightEyeView[16]; ConvertMatrix4x3To4x4Transposed(leftEyeView, gstate.viewMatrix); diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 272b39d70e..e7a15e9536 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -497,6 +497,11 @@ enum { GPU_ROUND_DEPTH_TO_16BIT = FLAG_BIT(23), // Can be disabled either per game or if we use a real 16-bit depth buffer GPU_USE_CLIP_DISTANCE = FLAG_BIT(24), GPU_USE_CULL_DISTANCE = FLAG_BIT(25), + + // VR flags (reserved or in-use) + GPU_USE_VIRTUAL_REALITY = FLAG_BIT(29), + GPU_USE_SINGLE_PASS_STEREO = FLAG_BIT(30), + GPU_USE_SIMPLE_STEREO_PERSPECTIVE = FLAG_BIT(31), }; struct KnownVertexBounds { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 93b11fd53e..36ce962ea4 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1296,7 +1296,6 @@ bool NativeTouch(const TouchInput &touch) { } bool NativeKey(const KeyInput &key) { - // Hack to quickly enable 2D mode in VR game mode. if (IsVRBuild()) { UpdateVRScreenKey(key);