From 510f4c243e75bf1c6e8f0a777516525c2d53d9f5 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 7 Oct 2026 11:00:52 +0300 Subject: [PATCH] rsx: Fix depth_bounds range computation --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 17 +++++++++++++++++ rpcs3/Emu/RSX/Common/TextureUtils.h | 1 + rpcs3/Emu/RSX/GL/GLDraw.cpp | 8 ++++++-- rpcs3/Emu/RSX/VK/VKDraw.cpp | 11 +++++++---- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 863cda2ba6..b70f6669e3 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -1851,6 +1851,23 @@ namespace rsx } } + // Hardware behaves as if each depth bound is converted into the surface's depth encoding, clamped to the format's range. + f32 clamp_depth_bounds_value(rsx::surface_depth_format2 format, f32 value) + { + switch (format) + { + case rsx::surface_depth_format2::z16_uint: + case rsx::surface_depth_format2::z24s8_uint: + return std::clamp(value, 0.f, 1.f); + case rsx::surface_depth_format2::z16_float: + return std::clamp(value, 0.f, decode_e4m12(0xFFFF)); + case rsx::surface_depth_format2::z24s8_float: + return std::max(value, 0.f); + default: + fmt::throw_exception("Unreachable"); + } + } + bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode) { switch (mode) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index 6e4d2a9781..9abb29b531 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -365,6 +365,7 @@ namespace rsx bool is_compressed_host_format(const texture_uploader_capabilities& caps, u32 format); // Returns true for host-compressed formats (DXT) u8 get_format_sample_count(rsx::surface_antialiasing antialias); f32 get_depth_clear_value(rsx::surface_depth_format2 format, u32 raw); + f32 clamp_depth_bounds_value(rsx::surface_depth_format2 format, f32 value); bool is_depth_stencil_format(rsx::surface_depth_format2 format); /** diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 93428371a1..cbf318070a 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -91,9 +91,13 @@ void GLGSRender::update_draw_state() gl_state.depth_func(gl::comparison_op(rsx::method_registers.depth_func())); } - if (gl::get_driver_caps().EXT_depth_bounds_test_supported && (gl_state.enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT))) + if (gl::get_driver_caps().EXT_depth_bounds_test_supported && + (gl_state.enable(REGS(m_ctx)->depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT))) { - gl_state.depth_bounds(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max()); + const auto depth_format = REGS(m_ctx)->surface_depth_fmt(); + gl_state.depth_bounds( + rsx::clamp_depth_bounds_value(depth_format, REGS(m_ctx)->depth_bounds_min()), + rsx::clamp_depth_bounds_value(depth_format, REGS(m_ctx)->depth_bounds_max())); } if (gl::get_driver_caps().NV_depth_buffer_float_supported) diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 95c8b8613b..957948b930 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -9,6 +9,8 @@ #include "vkutils/chip_class.h" #include +#include "Emu/RSX/NV47/HW/context_accessors.define.h" + namespace vk { VkImageViewType get_view_type(rsx::texture_dimension_extended type) @@ -237,11 +239,12 @@ void VKGSRender::update_draw_state() if (m_device->get_depth_bounds_support()) { f32 bounds_min, bounds_max; - if (rsx::method_registers.depth_bounds_test_enabled()) + if (REGS(m_ctx)->depth_bounds_test_enabled()) { - // Update depth bounds min/max - bounds_min = rsx::method_registers.depth_bounds_min(); - bounds_max = rsx::method_registers.depth_bounds_max(); + // Update depth bounds min/max, saturated into the RSX depth format's range as hardware does + const auto depth_format = REGS(m_ctx)->surface_depth_fmt(); + bounds_min = rsx::clamp_depth_bounds_value(depth_format, REGS(m_ctx)->depth_bounds_min()); + bounds_max = rsx::clamp_depth_bounds_value(depth_format, REGS(m_ctx)->depth_bounds_max()); } else {