diff options
| author | Markus Wick <degasus@users.noreply.github.com> | 2017-03-10 18:05:52 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-03-10 18:05:52 +0100 |
| commit | e99cd57eb3827b246ea712e031bac3ffe92fe109 (patch) | |
| tree | f12d83d565f2e36d785046ff5917814be50fe62b /Source/Core/VideoBackends | |
| parent | a3f5e3e27dacc40082346bbb00d41eddd61b16b9 (diff) | |
| parent | 3f41e6d4cf9f1a318c6d32fea4d2b422684961a3 (diff) | |
Merge pull request #4935 from Armada651/depth-range-fix
VideoBackends: Set the maximum range when the depth range is oversized.
Diffstat (limited to 'Source/Core/VideoBackends')
| -rw-r--r-- | Source/Core/VideoBackends/D3D/Render.cpp | 13 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/D3D/main.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/D3D12/Render.cpp | 13 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/D3D12/main.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/Null/NullBackend.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/OGL/Render.cpp | 48 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/OGL/main.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/Software/SWmain.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/Renderer.cpp | 15 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/VulkanContext.cpp | 19 |
10 files changed, 71 insertions, 42 deletions
diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index f937ed60b4..b082963820 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -546,10 +546,8 @@ void Renderer::SetViewport() float Y = Renderer::EFBToScaledYf(xfmem.viewport.yOrig + xfmem.viewport.ht - scissorYOff); float Wd = Renderer::EFBToScaledXf(2.0f * xfmem.viewport.wd); float Ht = Renderer::EFBToScaledYf(-2.0f * xfmem.viewport.ht); - float range = MathUtil::Clamp<float>(xfmem.viewport.zRange, 0.0f, 16777215.0f); - float min_depth = - MathUtil::Clamp<float>(xfmem.viewport.farZ - range, 0.0f, 16777215.0f) / 16777216.0f; - float max_depth = MathUtil::Clamp<float>(xfmem.viewport.farZ, 0.0f, 16777215.0f) / 16777216.0f; + float min_depth = (xfmem.viewport.farZ - xfmem.viewport.zRange) / 16777216.0f; + float max_depth = xfmem.viewport.farZ / 16777216.0f; if (Wd < 0.0f) { X += Wd; @@ -561,10 +559,11 @@ void Renderer::SetViewport() Ht = -Ht; } - // If an inverted depth range is used, which D3D doesn't support, - // we need to calculate the depth range in the vertex shader. - if (xfmem.viewport.zRange < 0.0f) + // If an inverted or oversized depth range is used, we need to calculate the depth range in the + // vertex shader. + if (UseVertexDepthRange()) { + // We need to ensure depth values are clamped the maximum value supported by the console GPU. min_depth = 0.0f; max_depth = GX_MAX_DEPTH; } diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 2fc00dc037..eb7048a311 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -66,6 +66,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsOversizedViewports = false; + g_Config.backend_info.bSupportsOversizedDepthRanges = false; g_Config.backend_info.bSupportsGeometryShaders = true; g_Config.backend_info.bSupports3DVision = true; g_Config.backend_info.bSupportsPostProcessing = false; diff --git a/Source/Core/VideoBackends/D3D12/Render.cpp b/Source/Core/VideoBackends/D3D12/Render.cpp index e5ca00bd7e..da5e48c053 100644 --- a/Source/Core/VideoBackends/D3D12/Render.cpp +++ b/Source/Core/VideoBackends/D3D12/Render.cpp @@ -454,10 +454,8 @@ void Renderer::SetViewport() float y = Renderer::EFBToScaledYf(xfmem.viewport.yOrig + xfmem.viewport.ht - scissor_y_offset); float width = Renderer::EFBToScaledXf(2.0f * xfmem.viewport.wd); float height = Renderer::EFBToScaledYf(-2.0f * xfmem.viewport.ht); - float range = MathUtil::Clamp<float>(xfmem.viewport.zRange, 0.0f, 16777215.0f); - float min_depth = - MathUtil::Clamp<float>(xfmem.viewport.farZ - range, 0.0f, 16777215.0f) / 16777216.0f; - float max_depth = MathUtil::Clamp<float>(xfmem.viewport.farZ, 0.0f, 16777215.0f) / 16777216.0f; + float min_depth = (xfmem.viewport.farZ - xfmem.viewport.zRange) / 16777216.0f; + float max_depth = xfmem.viewport.farZ / 16777216.0f; if (width < 0.0f) { x += width; @@ -469,10 +467,11 @@ void Renderer::SetViewport() height = -height; } - // If an inverted depth range is used, which D3D doesn't support, - // we need to calculate the depth range in the vertex shader. - if (xfmem.viewport.zRange < 0.0f) + // If an inverted or oversized depth range is used, we need to calculate the depth range in the + // vertex shader. + if (UseVertexDepthRange()) { + // We need to ensure depth values are clamped the maximum value supported by the console GPU. min_depth = 0.0f; max_depth = GX_MAX_DEPTH; } diff --git a/Source/Core/VideoBackends/D3D12/main.cpp b/Source/Core/VideoBackends/D3D12/main.cpp index bae916e0f8..11ead5a4e1 100644 --- a/Source/Core/VideoBackends/D3D12/main.cpp +++ b/Source/Core/VideoBackends/D3D12/main.cpp @@ -69,6 +69,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsOversizedViewports = false; + g_Config.backend_info.bSupportsOversizedDepthRanges = false; g_Config.backend_info.bSupportsGeometryShaders = true; g_Config.backend_info.bSupports3DVision = true; g_Config.backend_info.bSupportsPostProcessing = false; diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp index 1fe0914a91..b4d85eee65 100644 --- a/Source/Core/VideoBackends/Null/NullBackend.cpp +++ b/Source/Core/VideoBackends/Null/NullBackend.cpp @@ -29,6 +29,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsOversizedViewports = true; + g_Config.backend_info.bSupportsOversizedDepthRanges = false; g_Config.backend_info.bSupportsGeometryShaders = true; g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bSupportsEarlyZ = true; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 621c21c539..391fa7d2bd 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -437,6 +437,8 @@ Renderer::Renderer() // 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_Config.backend_info.bSupportsOversizedDepthRanges = + GLExtensions::Supports("GL_NV_depth_buffer_float"); g_ogl_config.bSupportsGLSLCache = GLExtensions::Supports("GL_ARB_get_program_binary"); g_ogl_config.bSupportsGLPinnedMemory = GLExtensions::Supports("GL_AMD_pinned_memory"); @@ -625,7 +627,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%s", + WARN_LOG(VIDEO, "Missing OGL Extensions: %s%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 ", @@ -638,7 +640,8 @@ Renderer::Renderer() g_ActiveConfig.backend_info.bSupportsGSInstancing ? "" : "GSInstancing ", g_ActiveConfig.backend_info.bSupportsClipControl ? "" : "ClipControl ", g_ogl_config.bSupportsCopySubImage ? "" : "CopyImageSubData ", - g_ActiveConfig.backend_info.bSupportsDepthClamp ? "" : "DepthClamp "); + g_ActiveConfig.backend_info.bSupportsDepthClamp ? "" : "DepthClamp ", + g_ActiveConfig.backend_info.bSupportsOversizedDepthRanges ? "" : "DepthRangedNV "); s_last_multisamples = g_ActiveConfig.iMultisamples; s_MSAASamples = s_last_multisamples; @@ -1052,10 +1055,8 @@ void Renderer::SetViewport() (float)scissorYOff); float Width = EFBToScaledXf(2.0f * xfmem.viewport.wd); float Height = EFBToScaledYf(-2.0f * xfmem.viewport.ht); - float range = MathUtil::Clamp<float>(xfmem.viewport.zRange, -16777215.0f, 16777215.0f); - float min_depth = - MathUtil::Clamp<float>(xfmem.viewport.farZ - range, 0.0f, 16777215.0f) / 16777216.0f; - float max_depth = MathUtil::Clamp<float>(xfmem.viewport.farZ, 0.0f, 16777215.0f) / 16777216.0f; + float min_depth = (xfmem.viewport.farZ - xfmem.viewport.zRange) / 16777216.0f; + float max_depth = xfmem.viewport.farZ / 16777216.0f; if (Width < 0) { X += Width; @@ -1078,11 +1079,36 @@ void Renderer::SetViewport() glViewport(iceilf(X), iceilf(Y), iceilf(Width), iceilf(Height)); } - // Set the reversed depth range. If we do depth clipping and depth range in the - // vertex shader we only need to ensure depth values don't exceed the maximum - // value supported by the console GPU. If not, we simply clamp the near/far values - // themselves to the maximum value as done above. - glDepthRangef(max_depth, min_depth); + if (!g_ActiveConfig.backend_info.bSupportsOversizedDepthRanges && + !g_ActiveConfig.backend_info.bSupportsDepthClamp) + { + // There's no way to support oversized depth ranges in this situation. Let's just clamp the + // range to the maximum value supported by the console GPU and hope for the best. + min_depth = MathUtil::Clamp(min_depth, 0.0f, GX_MAX_DEPTH); + max_depth = MathUtil::Clamp(max_depth, 0.0f, GX_MAX_DEPTH); + } + + if (UseVertexDepthRange()) + { + // We need to ensure depth values are clamped the maximum value supported by the console GPU. + // Taking into account whether the depth range is inverted or not. + if (xfmem.viewport.zRange < 0.0f) + { + min_depth = GX_MAX_DEPTH; + max_depth = 0.0f; + } + else + { + min_depth = 0.0f; + max_depth = GX_MAX_DEPTH; + } + } + + // Set the reversed depth range. + if (g_ActiveConfig.backend_info.bSupportsOversizedDepthRanges) + glDepthRangedNV(max_depth, min_depth); + else + glDepthRangef(max_depth, min_depth); } 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 3be16a6cbf..f2901caa20 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -109,6 +109,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsInternalResolutionFrameDumps = true; // Overwritten in Render.cpp later + g_Config.backend_info.bSupportsOversizedDepthRanges = false; g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsPaletteConversion = true; diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 96ebdd8adb..b98eb0955f 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -129,6 +129,7 @@ void VideoSoftware::InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsEarlyZ = true; g_Config.backend_info.bSupportsOversizedViewports = true; + g_Config.backend_info.bSupportsOversizedDepthRanges = true; g_Config.backend_info.bSupportsPrimitiveRestart = false; g_Config.backend_info.bSupportsMultithreading = false; g_Config.backend_info.bSupportsInternalResolutionFrameDumps = false; diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index d44317b3de..0a65290dd0 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -1628,10 +1628,8 @@ void Renderer::SetViewport() float y = Renderer::EFBToScaledYf(xfmem.viewport.yOrig + xfmem.viewport.ht - scissor_y_offset); float width = Renderer::EFBToScaledXf(2.0f * xfmem.viewport.wd); float height = Renderer::EFBToScaledYf(-2.0f * xfmem.viewport.ht); - float range = MathUtil::Clamp<float>(xfmem.viewport.zRange, -16777215.0f, 16777215.0f); - float min_depth = - MathUtil::Clamp<float>(xfmem.viewport.farZ - range, 0.0f, 16777215.0f) / 16777216.0f; - float max_depth = MathUtil::Clamp<float>(xfmem.viewport.farZ, 0.0f, 16777215.0f) / 16777216.0f; + float min_depth = (xfmem.viewport.farZ - xfmem.viewport.zRange) / 16777216.0f; + float max_depth = xfmem.viewport.farZ / 16777216.0f; if (width < 0.0f) { x += width; @@ -1643,11 +1641,12 @@ void Renderer::SetViewport() height = -height; } - // If an inverted depth range is used, which the Vulkan drivers don't - // support, we need to calculate the depth range in the vertex shader. - // TODO: Make this into a DriverDetails bug and write a test for CTS. - if (xfmem.viewport.zRange < 0.0f) + // If an oversized or inverted depth range is used, we need to calculate the depth range in the + // vertex shader. + // TODO: Inverted depth ranges are bugged in all drivers, which should be added to DriverDetails. + if (UseVertexDepthRange()) { + // We need to ensure depth values are clamped the maximum value supported by the console GPU. min_depth = 0.0f; max_depth = GX_MAX_DEPTH; } diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index 1487e09afc..43051d4099 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -225,15 +225,16 @@ VulkanContext::GPUList VulkanContext::EnumerateGPUs(VkInstance instance) void VulkanContext::PopulateBackendInfo(VideoConfig* config) { config->backend_info.api_type = APIType::Vulkan; - config->backend_info.bSupportsExclusiveFullscreen = false; // Currently WSI does not allow this. - config->backend_info.bSupports3DVision = false; // D3D-exclusive. - config->backend_info.bSupportsOversizedViewports = true; // Assumed support. - config->backend_info.bSupportsEarlyZ = true; // Assumed support. - config->backend_info.bSupportsPrimitiveRestart = true; // Assumed support. - config->backend_info.bSupportsBindingLayout = false; // Assumed support. - config->backend_info.bSupportsPaletteConversion = true; // Assumed support. - config->backend_info.bSupportsClipControl = true; // Assumed support. - config->backend_info.bSupportsMultithreading = true; // Assumed support. + config->backend_info.bSupportsExclusiveFullscreen = false; // Currently WSI does not allow this. + config->backend_info.bSupports3DVision = false; // D3D-exclusive. + config->backend_info.bSupportsOversizedViewports = true; // Assumed support. + config->backend_info.bSupportsOversizedDepthRanges = false; // No support yet. + config->backend_info.bSupportsEarlyZ = true; // Assumed support. + config->backend_info.bSupportsPrimitiveRestart = true; // Assumed support. + config->backend_info.bSupportsBindingLayout = false; // Assumed support. + config->backend_info.bSupportsPaletteConversion = true; // Assumed support. + config->backend_info.bSupportsClipControl = true; // Assumed support. + config->backend_info.bSupportsMultithreading = true; // Assumed support. config->backend_info.bSupportsInternalResolutionFrameDumps = true; // Assumed support. config->backend_info.bSupportsPostProcessing = false; // No support yet. config->backend_info.bSupportsDualSourceBlend = false; // Dependent on features. |
