diff --git a/Source/Core/VideoBackends/D3D/D3DMain.cpp b/Source/Core/VideoBackends/D3D/D3DMain.cpp index 9a25c1abde..5bb419ac8f 100644 --- a/Source/Core/VideoBackends/D3D/D3DMain.cpp +++ b/Source/Core/VideoBackends/D3D/D3DMain.cpp @@ -116,6 +116,7 @@ void VideoBackend::FillBackendInfo() g_Config.backend_info.bSupportsPartialMultisampleResolve = true; g_Config.backend_info.bSupportsDynamicVertexLoader = false; g_Config.backend_info.bSupportsHDROutput = true; + g_Config.backend_info.bSupportsUnrestrictedDepthRange = false; g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames(); g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter); diff --git a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp index 1b126a3909..fd42b262e7 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp +++ b/Source/Core/VideoBackends/D3D12/D3D12Gfx.cpp @@ -133,7 +133,7 @@ void Gfx::ClearRegion(const MathUtil::Rectangle& target_rc, bool color_enab ->TransitionToState(D3D12_RESOURCE_STATE_DEPTH_WRITE); // D3D does not support reversed depth ranges. - const float clear_depth = 1.0f - static_cast(z & 0xFFFFFF) / 16777216.0f; + const float clear_depth = 1.0f - static_cast(z & 0xFFFFFF) / 16777215.0f; d3d_frame_buffer->ClearDepth(clear_depth, &d3d_clear_rc); z_enable = false; } diff --git a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp index 171455cf34..13b1a2043d 100644 --- a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp +++ b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp @@ -91,6 +91,7 @@ void VideoBackend::FillBackendInfo() g_Config.backend_info.bSupportsDynamicVertexLoader = true; g_Config.backend_info.bSupportsVSLinePointExpand = true; g_Config.backend_info.bSupportsHDROutput = true; + g_Config.backend_info.bSupportsUnrestrictedDepthRange = false; // We can only check texture support once we have a device. if (g_dx_context) diff --git a/Source/Core/VideoBackends/Metal/MTLUtil.mm b/Source/Core/VideoBackends/Metal/MTLUtil.mm index de073280d7..d961725702 100644 --- a/Source/Core/VideoBackends/Metal/MTLUtil.mm +++ b/Source/Core/VideoBackends/Metal/MTLUtil.mm @@ -79,6 +79,7 @@ void Metal::Util::PopulateBackendInfo(VideoConfig* config) config->backend_info.bSupportsVSLinePointExpand = true; config->backend_info.bSupportsHDROutput = 1.0 < [[NSScreen deepestScreen] maximumPotentialExtendedDynamicRangeColorComponentValue]; + config->backend_info.bSupportsUnrestrictedDepthRange = false; } void Metal::Util::PopulateBackendInfoAdapters(VideoConfig* config, diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.cpp b/Source/Core/VideoBackends/OGL/OGLConfig.cpp index db369a157d..f245289c9b 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.cpp +++ b/Source/Core/VideoBackends/OGL/OGLConfig.cpp @@ -349,6 +349,8 @@ bool PopulateConfig(GLContext* m_main_gl_context) GLExtensions::Supports("GL_ARB_derivative_control") || GLExtensions::Version() >= 450; g_Config.backend_info.bSupportsTextureQueryLevels = GLExtensions::Supports("GL_ARB_texture_query_levels") || GLExtensions::Version() >= 430; + g_Config.backend_info.bSupportsUnrestrictedDepthRange = + GLExtensions::Supports("GL_NV_depth_buffer_float"); if (GLExtensions::Supports("GL_ARB_shader_storage_buffer_object")) { diff --git a/Source/Core/VideoBackends/OGL/OGLGfx.cpp b/Source/Core/VideoBackends/OGL/OGLGfx.cpp index fa20a76d11..dbd9d7cef6 100644 --- a/Source/Core/VideoBackends/OGL/OGLGfx.cpp +++ b/Source/Core/VideoBackends/OGL/OGLGfx.cpp @@ -118,6 +118,16 @@ static void APIENTRY ClearDepthf(GLfloat depthval) glClearDepth(depthval); } +// Two small overrides to support unrestricted depth range +static void APIENTRY DepthRangefNV(GLfloat neardepth, GLfloat fardepth) +{ + glDepthRangedNV(neardepth, fardepth); +} +static void APIENTRY ClearDepthfNV(GLfloat depthval) +{ + glClearDepthdNV(depthval); +} + OGLGfx::OGLGfx(std::unique_ptr main_gl_context, float backbuffer_scale) : m_main_gl_context(std::move(main_gl_context)), m_current_rasterization_state(RenderState::GetInvalidRasterizationState()), @@ -137,11 +147,16 @@ OGLGfx::OGLGfx(std::unique_ptr main_gl_context, float backbuffer_scal if (!m_main_gl_context->IsGLES()) { - // OpenGL 3 doesn't provide GLES like float functions for depth. - // They are in core in OpenGL 4.1, so almost every driver should support them. - // But for the oldest ones, we provide fallbacks to the old double functions. - if (!GLExtensions::Supports("GL_ARB_ES2_compatibility")) + if (g_ActiveConfig.backend_info.bSupportsUnrestrictedDepthRange) { + glDepthRangef = DepthRangefNV; + glClearDepthf = ClearDepthfNV; + } + else if (!GLExtensions::Supports("GL_ARB_ES2_compatibility")) + { + // OpenGL 3 doesn't provide GLES like float functions for depth. + // They are in core in OpenGL 4.1, so almost every driver should support them. + // But for the oldest ones, we provide fallbacks to the old double functions. glDepthRangef = DepthRangef; glClearDepthf = ClearDepthf; } @@ -387,7 +402,7 @@ void OGLGfx::ClearRegion(const MathUtil::Rectangle& target_rc, bool colorEn if (zEnable) { glDepthMask(zEnable ? GL_TRUE : GL_FALSE); - glClearDepthf(float(z & 0xFFFFFF) / 16777216.0f); + glClearDepthf(float(z & 0xFFFFFF) / 16777215.0f); clear_mask |= GL_DEPTH_BUFFER_BIT; } diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index 58f1b10a04..9529ad74a7 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -44,9 +44,15 @@ GLenum OGLTexture::GetGLInternalFormatForTextureFormat(AbstractTextureFormat for case AbstractTextureFormat::D24_S8: return GL_DEPTH24_STENCIL8; case AbstractTextureFormat::D32F: - return GL_DEPTH_COMPONENT32F; + if (g_ActiveConfig.backend_info.bSupportsUnrestrictedDepthRange) + return GL_DEPTH_COMPONENT32F_NV; + else + return GL_DEPTH_COMPONENT32F; case AbstractTextureFormat::D32F_S8: - return GL_DEPTH32F_STENCIL8; + if (g_ActiveConfig.backend_info.bSupportsUnrestrictedDepthRange) + return GL_DEPTH32F_STENCIL8_NV; + else + return GL_DEPTH32F_STENCIL8; default: PanicAlertFmt("Unhandled texture format."); return storage ? GL_RGBA8 : GL_RGBA; diff --git a/Source/Core/VideoBackends/Vulkan/VKGfx.cpp b/Source/Core/VideoBackends/Vulkan/VKGfx.cpp index d65a5d4680..d6f1e73fe4 100644 --- a/Source/Core/VideoBackends/Vulkan/VKGfx.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKGfx.cpp @@ -117,7 +117,7 @@ void VKGfx::ClearRegion(const MathUtil::Rectangle& target_rc, bool color_en clear_color_value.color.float32[1] = static_cast((color >> 8) & 0xFF) / 255.0f; clear_color_value.color.float32[2] = static_cast((color >> 0) & 0xFF) / 255.0f; clear_color_value.color.float32[3] = static_cast((color >> 24) & 0xFF) / 255.0f; - clear_depth_value.depthStencil.depth = static_cast(z & 0xFFFFFF) / 16777216.0f; + clear_depth_value.depthStencil.depth = static_cast(z & 0xFFFFFF) / 16777215.0f; if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange) clear_depth_value.depthStencil.depth = 1.0f - clear_depth_value.depthStencil.depth; diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index ed2407775a..93c3a6b4c7 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -471,6 +471,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config) config->backend_info.bSupportsDynamicVertexLoader = true; // Assumed support. config->backend_info.bSupportsVSLinePointExpand = true; // Assumed support. config->backend_info.bSupportsHDROutput = true; // Assumed support. + config->backend_info.bSupportsUnrestrictedDepthRange = false; // Dependent on features. } void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list) @@ -676,6 +677,9 @@ bool VulkanContext::SelectDeviceExtensions(bool enable_surface) AddExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false); AddExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, false); + g_Config.backend_info.bSupportsUnrestrictedDepthRange = + AddExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, false); + return true; } diff --git a/Source/Core/VideoCommon/AbstractGfx.cpp b/Source/Core/VideoCommon/AbstractGfx.cpp index 4c386b12ca..a1a33b4000 100644 --- a/Source/Core/VideoCommon/AbstractGfx.cpp +++ b/Source/Core/VideoCommon/AbstractGfx.cpp @@ -75,7 +75,7 @@ void AbstractGfx::ClearRegion(const MathUtil::Rectangle& target_rc, bool co static_cast((color >> 8) & 0xFF) / 255.0f, static_cast((color >> 0) & 0xFF) / 255.0f, static_cast((color >> 24) & 0xFF) / 255.0f}, - static_cast(z & 0xFFFFFF) / 16777216.0f}; + static_cast(z & 0xFFFFFF) / 16777215.0f}; if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange) uniforms.clear_depth = 1.0f - uniforms.clear_depth; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); diff --git a/Source/Core/VideoCommon/BPFunctions.cpp b/Source/Core/VideoCommon/BPFunctions.cpp index ecb045e6ad..bba443c096 100644 --- a/Source/Core/VideoCommon/BPFunctions.cpp +++ b/Source/Core/VideoCommon/BPFunctions.cpp @@ -203,8 +203,8 @@ void SetScissorAndViewport() float y = g_framebuffer_manager->EFBToScaledYf(raw_y); float width = g_framebuffer_manager->EFBToScaledXf(raw_width); float height = g_framebuffer_manager->EFBToScaledYf(raw_height); - float min_depth = (xfmem.viewport.farZ - xfmem.viewport.zRange) / 16777216.0f; - float max_depth = xfmem.viewport.farZ / 16777216.0f; + float min_depth = (xfmem.viewport.farZ / 16777215.0f - xfmem.viewport.zRange / 16777215.0f); + float max_depth = xfmem.viewport.farZ / 16777215.0f; if (width < 0.f) { x += width; @@ -216,17 +216,12 @@ void SetScissorAndViewport() height *= -1; } - // The maximum depth that is written to the depth buffer should never exceed this value. - // This is necessary because we use a 2^24 divisor for all our depth values to prevent - // floating-point round-trip errors. However the console GPU doesn't ever write a value - // to the depth buffer that exceeds 2^24 - 1. - constexpr float GX_MAX_DEPTH = 16777215.0f / 16777216.0f; if (!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 = std::clamp(min_depth, 0.0f, GX_MAX_DEPTH); - max_depth = std::clamp(max_depth, 0.0f, GX_MAX_DEPTH); + min_depth = std::clamp(min_depth, 0.0f, 1.0f); + max_depth = std::clamp(max_depth, 0.0f, 1.0f); } if (VertexShaderManager::UseVertexDepthRange()) @@ -235,13 +230,13 @@ void SetScissorAndViewport() // Taking into account whether the depth range is inverted or not. if (xfmem.viewport.zRange < 0.0f && g_ActiveConfig.backend_info.bSupportsReversedDepthRange) { - min_depth = GX_MAX_DEPTH; + min_depth = 1.0f; max_depth = 0.0f; } else { min_depth = 0.0f; - max_depth = GX_MAX_DEPTH; + max_depth = 1.0f; } } diff --git a/Source/Core/VideoCommon/FramebufferManager.cpp b/Source/Core/VideoCommon/FramebufferManager.cpp index 3c83bce2c4..8a08a362c3 100644 --- a/Source/Core/VideoCommon/FramebufferManager.cpp +++ b/Source/Core/VideoCommon/FramebufferManager.cpp @@ -131,13 +131,7 @@ AbstractTextureFormat FramebufferManager::GetEFBColorFormat() AbstractTextureFormat FramebufferManager::GetEFBDepthFormat() { - // 32-bit depth clears are broken in the Adreno Vulkan driver, and have no effect. - // To work around this, we use a D24_S8 buffer instead, which results in a loss of accuracy. - // We still resolve this to a R32F texture, as there is no 24-bit format. - if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_D32F_CLEAR)) - return AbstractTextureFormat::D24_S8; - else - return AbstractTextureFormat::D32F; + return AbstractTextureFormat::D24_S8; } AbstractTextureFormat FramebufferManager::GetEFBDepthCopyFormat() diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index a76681634f..e42a21694c 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -1261,9 +1261,9 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos else { if (!host_config.backend_reversed_depth_range) - out.Write("\tint zCoord = int((1.0 - rawpos.z) * 16777216.0);\n"); + out.Write("\tint zCoord = int((1.0 - rawpos.z) * 16777215.0);\n"); else - out.Write("\tint zCoord = int(rawpos.z * 16777216.0);\n"); + out.Write("\tint zCoord = int(rawpos.z * 16777215.0);\n"); } out.Write("\tzCoord = clamp(zCoord, 0, 0xFFFFFF);\n"); @@ -1278,9 +1278,9 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos if (uid_data->per_pixel_depth && early_ztest) { if (!host_config.backend_reversed_depth_range) - out.Write("\tdepth = 1.0 - float(zCoord) / 16777216.0;\n"); + out.Write("\tdepth = 1.0 - float(zCoord) / 16777215.0;\n"); else - out.Write("\tdepth = float(zCoord) / 16777216.0;\n"); + out.Write("\tdepth = float(zCoord) / 16777215.0;\n"); } // Note: depth texture output is only written to depth buffer if late depth test is used @@ -1299,9 +1299,9 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos if (uid_data->per_pixel_depth && uid_data->ztest == EmulatedZ::Late) { if (!host_config.backend_reversed_depth_range) - out.Write("\tdepth = 1.0 - float(zCoord) / 16777216.0;\n"); + out.Write("\tdepth = 1.0 - float(zCoord) / 16777215.0;\n"); else - out.Write("\tdepth = float(zCoord) / 16777216.0;\n"); + out.Write("\tdepth = float(zCoord) / 16777215.0;\n"); } // No dithering for RGB8 mode @@ -1977,14 +1977,14 @@ static void WriteFog(ShaderCode& out, const pixel_shader_uid_data* uid_data) // renderer) // Maybe we want to use "ze = (A << B_SHF)/((B << B_SHF) - Zs)" instead? // That's equivalent, but keeps the lower bits of Zs. - out.Write("\tfloat ze = (" I_FOGF ".x * 16777216.0) / float(" I_FOGI ".y - (zCoord >> " I_FOGI + out.Write("\tfloat ze = (" I_FOGF ".x * 16777215.0) / float(" I_FOGI ".y - (zCoord >> " I_FOGI ".w));\n"); } else { // orthographic // ze = a*Zs (here, no B_SHF) - out.Write("\tfloat ze = " I_FOGF ".x * float(zCoord) / 16777216.0;\n"); + out.Write("\tfloat ze = " I_FOGF ".x * float(zCoord) / 16777215.0;\n"); } // x_adjust = sqrt((x-center)^2 + k^2)/k diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 6962daa29b..500ab620a9 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -127,7 +127,7 @@ static void WriteSampleFunction(ShaderCode& code, const EFBCopyParams& params, A if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange) code.Write(" tex_sample.x = 1.0 - tex_sample.x;\n"); - code.Write(" uint depth = uint(tex_sample.x * 16777216.0);\n" + code.Write(" uint depth = uint(tex_sample.x * 16777215.0);\n" " return uint4((depth >> 16) & 255u, (depth >> 8) & 255u, depth & 255u, 255u);\n" "}}\n"); } diff --git a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp index da2e247a7f..de65036dc0 100644 --- a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp +++ b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp @@ -113,7 +113,7 @@ ShaderCode GeneratePixelShader(APIType api_type, const UidData* uid_data) if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange) out.Write(" tex_sample.x = 1.0 - tex_sample.x;\n"); - out.Write(" uint depth = uint(tex_sample.x * 16777216.0);\n" + out.Write(" uint depth = uint(tex_sample.x * 16777215.0);\n" " return uint4((depth >> 16) & 255u, (depth >> 8) & 255u, depth & 255u, 255u);\n" "}}\n"); } diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp index ca8f42ec8f..5a26383d10 100644 --- a/Source/Core/VideoCommon/UberShaderPixel.cpp +++ b/Source/Core/VideoCommon/UberShaderPixel.cpp @@ -1327,9 +1327,9 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, if (host_config.fast_depth_calc) { if (!host_config.backend_reversed_depth_range) - out.Write(" int zCoord = int((1.0 - rawpos.z) * 16777216.0);\n"); + out.Write(" int zCoord = int((1.0 - rawpos.z) * 16777215.0);\n"); else - out.Write(" int zCoord = int(rawpos.z * 16777216.0);\n"); + out.Write(" int zCoord = int(rawpos.z * 16777215.0);\n"); out.Write(" zCoord = clamp(zCoord, 0, 0xFFFFFF);\n" "\n"); } @@ -1383,9 +1383,9 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, " // If early depth isn't enabled, we write to the zbuffer here\n" " int zbuffer_zCoord = bpmem_late_ztest ? zCoord : early_zCoord;\n"); if (!host_config.backend_reversed_depth_range) - out.Write(" depth = 1.0 - float(zbuffer_zCoord) / 16777216.0;\n"); + out.Write(" depth = 1.0 - float(zbuffer_zCoord) / 16777215.0;\n"); else - out.Write(" depth = float(zbuffer_zCoord) / 16777216.0;\n"); + out.Write(" depth = float(zbuffer_zCoord) / 16777215.0;\n"); } out.Write(" // Alpha Test\n"); @@ -1454,12 +1454,12 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, BitfieldExtract<&FogParam3::proj>("bpmem_fogParam3")); out.Write(" // perspective\n" " // ze = A/(B - (Zs >> B_SHF)\n" - " ze = (" I_FOGF ".x * 16777216.0) / float(" I_FOGI ".y - (zCoord >> " I_FOGI + " ze = (" I_FOGF ".x * 16777215.0) / float(" I_FOGI ".y - (zCoord >> " I_FOGI ".w));\n" " }} else {{\n" " // orthographic\n" " // ze = a*Zs (here, no B_SHF)\n" - " ze = " I_FOGF ".x * float(zCoord) / 16777216.0;\n" + " ze = " I_FOGF ".x * float(zCoord) / 16777215.0;\n" " }}\n" "\n" " if (bool({})) {{\n", diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index 0415ac05dc..2dfb242361 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -139,6 +139,9 @@ void VertexShaderManager::SetProjectionMatrix(XFStateManager& xf_state_manager) bool VertexShaderManager::UseVertexDepthRange() { + if (g_Config.backend_info.bSupportsUnrestrictedDepthRange) + return false; + // We can't compute the depth range in the vertex shader if we don't support depth clamp. if (!g_ActiveConfig.backend_info.bSupportsDepthClamp) return false; diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 5cce23bfd2..0b8f189d35 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -338,6 +338,7 @@ struct VideoConfig final bool bSupportsVSLinePointExpand = false; bool bSupportsGLLayerInFS = true; bool bSupportsHDROutput = false; + bool bSupportsUnrestrictedDepthRange = false; } backend_info; // Utility