diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index e471e3715a..2471135afd 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -71,6 +71,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsPostProcessing = false; g_Config.backend_info.bSupportsPaletteConversion = true; g_Config.backend_info.bSupportsClipControl = true; + g_Config.backend_info.bSupportsDepthClamp = true; IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Core/VideoBackends/D3D12/main.cpp b/Source/Core/VideoBackends/D3D12/main.cpp index 69a53603f1..f6e5512da1 100644 --- a/Source/Core/VideoBackends/D3D12/main.cpp +++ b/Source/Core/VideoBackends/D3D12/main.cpp @@ -74,6 +74,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsPostProcessing = false; g_Config.backend_info.bSupportsPaletteConversion = true; g_Config.backend_info.bSupportsClipControl = true; + g_Config.backend_info.bSupportsDepthClamp = true; IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 692bf36e51..5af9407763 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -481,6 +481,9 @@ Renderer::Renderer() g_Config.backend_info.bSupportsBindingLayout = GLExtensions::Supports("GL_ARB_shading_language_420pack"); + // Clip distance support is useless without a method to clamp the depth range + g_Config.backend_info.bSupportsDepthClamp = GLExtensions::Supports("GL_ARB_depth_clamp"); + g_ogl_config.bSupportsGLSLCache = GLExtensions::Supports("GL_ARB_get_program_binary"); g_ogl_config.bSupportsGLPinnedMemory = GLExtensions::Supports("GL_AMD_pinned_memory"); g_ogl_config.bSupportsGLSync = GLExtensions::Supports("GL_ARB_sync"); @@ -520,6 +523,9 @@ Renderer::Renderer() g_ogl_config.bSupportsGLSLCache = true; g_ogl_config.bSupportsGLSync = true; + // TODO: Implement support for GL_EXT_clip_cull_distance when there is an extension for depth clamping. + g_Config.backend_info.bSupportsDepthClamp = false; + if (strstr(g_ogl_config.glsl_version, "3.0")) { g_ogl_config.eSupportedGLSLVersion = GLSLES_300; @@ -669,7 +675,7 @@ Renderer::Renderer() g_ogl_config.gl_renderer, g_ogl_config.gl_version), 5000); - WARN_LOG(VIDEO, "Missing OGL Extensions: %s%s%s%s%s%s%s%s%s%s%s%s%s", + WARN_LOG(VIDEO, "Missing OGL Extensions: %s%s%s%s%s%s%s%s%s%s%s%s%s%s", g_ActiveConfig.backend_info.bSupportsDualSourceBlend ? "" : "DualSourceBlend ", g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? "" : "PrimitiveRestart ", g_ActiveConfig.backend_info.bSupportsEarlyZ ? "" : "EarlyZ ", @@ -681,7 +687,8 @@ Renderer::Renderer() g_ActiveConfig.backend_info.bSupportsSSAA ? "" : "SSAA ", g_ActiveConfig.backend_info.bSupportsGSInstancing ? "" : "GSInstancing ", g_ActiveConfig.backend_info.bSupportsClipControl ? "" : "ClipControl ", - g_ogl_config.bSupportsCopySubImage ? "" : "CopyImageSubData "); + g_ogl_config.bSupportsCopySubImage ? "" : "CopyImageSubData ", + g_ActiveConfig.backend_info.bSupportsDepthClamp ? "" : "DepthClamp "); s_last_multisamples = g_ActiveConfig.iMultisamples; s_MSAASamples = s_last_multisamples; @@ -724,8 +731,11 @@ Renderer::Renderer() glClearDepthf(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - glEnable(GL_CLIP_DISTANCE0); - glEnable(GL_DEPTH_CLAMP); + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) + { + glEnable(GL_CLIP_DISTANCE0); + glEnable(GL_DEPTH_CLAMP); + } glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment @@ -1117,6 +1127,12 @@ void Renderer::SetViewport() (float)scissorYOff); float Width = EFBToScaledXf(2.0f * xfmem.viewport.wd); float Height = EFBToScaledYf(-2.0f * xfmem.viewport.ht); + float GLNear = MathUtil::Clamp( + xfmem.viewport.farZ - + MathUtil::Clamp(xfmem.viewport.zRange, -16777216.0f, 16777216.0f), + 0.0f, 16777215.0f) / + 16777216.0f; + float GLFar = MathUtil::Clamp(xfmem.viewport.farZ, 0.0f, 16777215.0f) / 16777216.0f; if (Width < 0) { X += Width; @@ -1138,7 +1154,11 @@ void Renderer::SetViewport() auto iceilf = [](float f) { return static_cast(ceilf(f)); }; glViewport(iceilf(X), iceilf(Y), iceilf(Width), iceilf(Height)); } - glDepthRangef(16777215.0f / 16777216.0f, 0.0f); + + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) + glDepthRangef(16777215.0f / 16777216.0f, 0.0f); + else + glDepthRangef(GLFar, GLNear); } void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 5f667efb1d..d27b763a88 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -108,6 +108,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsPaletteConversion = true; g_Config.backend_info.bSupportsClipControl = true; + g_Config.backend_info.bSupportsDepthClamp = true; g_Config.backend_info.Adapters.clear(); diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 9110cbfe99..85359ac6ee 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -399,13 +399,22 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("o.colors_1 = color1;\n"); } - // Since we're adjusting z for the depth range before the perspective divide, we have to do our - // own clipping. - out.Write("o.clipDist = o.pos.z + o.pos.w;\n"); + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) + { + // Since we're adjusting z for the depth range before the perspective divide, we have to do our + // own clipping. + out.Write("o.clipDist = o.pos.z + o.pos.w;\n"); - // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond - // the normal depth range of 0..1. - out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w - o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); + // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond + // the normal depth range of 0..1. + out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w - o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); + } + else + { + // User-defined clipping is not supported, thus we rely on the API to handle the depth range for us. + // We still need to take care of the reversed depth, so we do that here. + out.Write("o.pos.z = -o.pos.z;\n"); + } // write the true depth value, if the game uses depth textures pixel shaders will override with // the correct values @@ -457,7 +466,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("colors_1 = o.colors_1;\n"); } - out.Write("gl_ClipDistance[0] = o.clipDist;\n"); + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) + out.Write("gl_ClipDistance[0] = o.clipDist;\n"); out.Write("gl_Position = o.pos;\n"); } else // D3D diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 92be4726ef..c95706db53 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -171,6 +171,7 @@ struct VideoConfig final bool bSupportsPaletteConversion; bool bSupportsClipControl; // Needed by VertexShaderGen, so must stay in VideoCommon bool bSupportsSSAA; + bool bSupportsDepthClamp; // Needed by VertexShaderGen, so must stay in VideoCommon } backend_info; // Utility