diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 2471135afd..92020481d4 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -72,6 +72,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsPaletteConversion = true; g_Config.backend_info.bSupportsClipControl = true; g_Config.backend_info.bSupportsDepthClamp = true; + g_Config.backend_info.bSupportsReversedDepthRange = false; IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Core/VideoBackends/D3D12/main.cpp b/Source/Core/VideoBackends/D3D12/main.cpp index f6e5512da1..0036a4a2f2 100644 --- a/Source/Core/VideoBackends/D3D12/main.cpp +++ b/Source/Core/VideoBackends/D3D12/main.cpp @@ -75,6 +75,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsPaletteConversion = true; g_Config.backend_info.bSupportsClipControl = true; g_Config.backend_info.bSupportsDepthClamp = true; + g_Config.backend_info.bSupportsReversedDepthRange = false; IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 69f06c6b52..cff3512370 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1160,9 +1160,16 @@ void Renderer::SetViewport() // value supported by the console GPU. If not, we simply clamp the near/far values // themselves to the maximum value as done above. if (g_ActiveConfig.backend_info.bSupportsDepthClamp) - glDepthRangef(GX_MAX_DEPTH, 0.0f); + { + if (xfmem.viewport.zRange < 0.0f) + glDepthRangef(0.0f, GX_MAX_DEPTH); + else + glDepthRangef(GX_MAX_DEPTH, 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 d27b763a88..b351ef48bb 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -102,6 +102,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bSupportsPostProcessing = true; g_Config.backend_info.bSupportsSSAA = true; + g_Config.backend_info.bSupportsReversedDepthRange = true; // Overwritten in Render.cpp later g_Config.backend_info.bSupportsDualSourceBlend = true; diff --git a/Source/Core/VideoCommon/PixelShaderManager.cpp b/Source/Core/VideoCommon/PixelShaderManager.cpp index b77f5e31a2..cb626bc31d 100644 --- a/Source/Core/VideoCommon/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/PixelShaderManager.cpp @@ -94,8 +94,8 @@ void PixelShaderManager::SetConstants() if (s_bViewPortChanged) { - constants.zbias[1][0] = (u32)xfmem.viewport.farZ; - constants.zbias[1][1] = (u32)xfmem.viewport.zRange; + constants.zbias[1][0] = (s32)xfmem.viewport.farZ; + constants.zbias[1][1] = (s32)xfmem.viewport.zRange; dirty = true; s_bViewPortChanged = false; } diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index 5f9f4affdc..e8f82d0bf5 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -392,8 +392,26 @@ void VertexShaderManager::SetConstants() // because the standard depth range equation pushes all depth values towards // the back of the depth buffer where conventionally depth buffers have the // least precision. - constants.pixelcentercorrection[2] = xfmem.viewport.zRange / 16777215.0f; - constants.pixelcentercorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f; + if (g_ActiveConfig.backend_info.bSupportsReversedDepthRange) + { + // For backends that support reversing the depth range we also support cases + // where the console also uses reversed depth with the same accuracy. We need + // to make sure the depth range is positive here and then reverse the depth in + // the backend viewport. + constants.pixelcentercorrection[2] = abs(xfmem.viewport.zRange) / 16777215.0f; + if (xfmem.viewport.zRange < 0.0f) + constants.pixelcentercorrection[3] = xfmem.viewport.farZ / 16777215.0f; + else + constants.pixelcentercorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f; + } + else + { + // For backends that don't support reversing the depth range we can still render + // cases where the console uses reversed depth correctly. But we simply can't + // provide the same accuracy as the console. + constants.pixelcentercorrection[2] = xfmem.viewport.zRange / 16777215.0f; + constants.pixelcentercorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f; + } dirty = true; // This is so implementation-dependent that we can't have it here. diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 3a1f984e87..c948077acc 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -172,6 +172,7 @@ struct VideoConfig final bool bSupportsClipControl; // Needed by VertexShaderGen, so must stay in VideoCommon bool bSupportsSSAA; bool bSupportsDepthClamp; // Needed by VertexShaderGen, so must stay in VideoCommon + bool bSupportsReversedDepthRange; } backend_info; // Utility