OGL: Check for GL_DEPTH_CLAMP support.

It's not available in OpenGL ES and officially it's not supported on OpenGL 3.0/3.1.

Fallback to old depth range code if there is no method to disable depth clipping.
It's more important to have correct clipping than to have accurate depth values.
Inaccurate depth values can be fixed by slow depth.
This commit is contained in:
Jules Blok 2016-08-05 22:31:34 +02:00
parent 4582853af4
commit a141e91dd2
6 changed files with 46 additions and 12 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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<float>(
xfmem.viewport.farZ -
MathUtil::Clamp<float>(xfmem.viewport.zRange, -16777216.0f, 16777216.0f),
0.0f, 16777215.0f) /
16777216.0f;
float GLFar = MathUtil::Clamp<float>(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<GLint>(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,

View File

@ -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();

View File

@ -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

View File

@ -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