diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 9c33f52902..863cda2ba6 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -1827,9 +1827,28 @@ namespace rsx } } - u32 get_max_depth_value(rsx::surface_depth_format2 format) + f32 decode_e4m12(u32 value) { - return get_format_block_size_in_bytes(format) == 2 ? 0xFFFF : 0xFFFFFF; + // Rebias by 2^111: unsigned E4M12 with bias 16, see E4M12Conversion.glsl + const uint bits = (value << 11) & 0x07FFF800u; + return std::bit_cast(bits) * std::bit_cast(0x77000000u); + } + + f32 get_depth_clear_value(rsx::surface_depth_format2 format, u32 raw) + { + switch (format) + { + case rsx::surface_depth_format2::z16_uint: + return float(raw) / 0xFFFF; + case rsx::surface_depth_format2::z24s8_uint: + return float(raw) / 0xFFFFFF; + case rsx::surface_depth_format2::z16_float: + return decode_e4m12(raw); + case rsx::surface_depth_format2::z24s8_float: + return std::bit_cast(raw << 7); + default: + fmt::throw_exception("Unreachable"); + } } bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index 3ebcf932a1..6e4d2a9781 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -364,7 +364,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); - u32 get_max_depth_value(rsx::surface_depth_format2 format); + f32 get_depth_clear_value(rsx::surface_depth_format2 format, u32 raw); bool is_depth_stencil_format(rsx::surface_depth_format2 format); /** diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index d22153beac..7375c1053b 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -642,7 +642,7 @@ void GLGSRender::clear_surface(u32 arg) if (skip_current_frame) return; // If stencil write mask is disabled, remove clear_stencil bit - if (!rsx::method_registers.stencil_mask()) arg &= ~RSX_GCM_CLEAR_STENCIL_BIT; + if (!REGS(m_ctx)->stencil_mask()) arg &= ~RSX_GCM_CLEAR_STENCIL_BIT; // Ignore invalid clear flags if ((arg & RSX_GCM_CLEAR_ANY_MASK) == 0) return; @@ -659,22 +659,20 @@ void GLGSRender::clear_surface(u32 arg) gl::command_context cmd{ gl_state }; const bool full_frame = - rsx::method_registers.scissor_origin_x() == 0 && - rsx::method_registers.scissor_origin_y() == 0 && - rsx::method_registers.scissor_width() >= rsx::method_registers.surface_clip_width() && - rsx::method_registers.scissor_height() >= rsx::method_registers.surface_clip_height(); + REGS(m_ctx)->scissor_origin_x() == 0 && + REGS(m_ctx)->scissor_origin_y() == 0 && + REGS(m_ctx)->scissor_width() >= REGS(m_ctx)->surface_clip_width() && + REGS(m_ctx)->scissor_height() >= REGS(m_ctx)->surface_clip_height(); bool update_color = false, update_z = false; - rsx::surface_depth_format2 surface_depth_format = rsx::method_registers.surface_depth_fmt(); + rsx::surface_depth_format2 surface_depth_format = REGS(m_ctx)->surface_depth_fmt(); if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); arg & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK) { if (arg & RSX_GCM_CLEAR_DEPTH_BIT) { - u32 max_depth_value = get_max_depth_value(surface_depth_format); - u32 clear_depth = rsx::method_registers.z_clear_value(is_depth_stencil_format(surface_depth_format)); - - clear_cmd.clear_depth.value = f32(clear_depth) / max_depth_value; + const u32 clear_depth_bits = REGS(m_ctx)->z_clear_value(is_depth_stencil_format(surface_depth_format)); + clear_cmd.clear_depth.value = rsx::get_depth_clear_value(surface_depth_format, clear_depth_bits); clear_cmd.aspect_mask |= gl::image_aspect::depth; } @@ -682,8 +680,8 @@ void GLGSRender::clear_surface(u32 arg) { if (arg & RSX_GCM_CLEAR_STENCIL_BIT) { - clear_cmd.clear_stencil.mask = rsx::method_registers.stencil_mask(); - clear_cmd.clear_stencil.value = rsx::method_registers.stencil_clear_value(); + clear_cmd.clear_stencil.mask = REGS(m_ctx)->stencil_mask(); + clear_cmd.clear_stencil.value = REGS(m_ctx)->stencil_clear_value(); clear_cmd.aspect_mask |= gl::image_aspect::stencil; } } @@ -725,12 +723,12 @@ void GLGSRender::clear_surface(u32 arg) if (auto colormask = (arg & 0xf0)) { - u8 clear_a = rsx::method_registers.clear_color_a(); - u8 clear_r = rsx::method_registers.clear_color_r(); - u8 clear_g = rsx::method_registers.clear_color_g(); - u8 clear_b = rsx::method_registers.clear_color_b(); + u8 clear_a = REGS(m_ctx)->clear_color_a(); + u8 clear_r = REGS(m_ctx)->clear_color_r(); + u8 clear_g = REGS(m_ctx)->clear_color_g(); + u8 clear_b = REGS(m_ctx)->clear_color_b(); - switch (rsx::method_registers.surface_color()) + switch (REGS(m_ctx)->surface_color()) { case rsx::surface_color_format::x32: case rsx::surface_color_format::w16z16y16x16: diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index af6a25a442..790f062b4e 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -583,9 +583,8 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) // NOTE: Depth writes are always from a fp32 register. See issues section on nvidia's NV_fragment_program spec // https://www.khronos.org/registry/OpenGL/extensions/NV/NV_fragment_program.txt - // NOTE: Depth writes in OpenGL (and by extension RSX) are clamped to 0,1 range. - // Indeed, hardware tests on realhw prove that even in depth float mode, values outside this range are clamped. - OS << " gl_FragDepth = _saturate(r1.z);\n"; + // NOTE: Depth writes are unclamped. Targeted hardware tests disprove the theory that depth must be clamped. + OS << " gl_FragDepth = r1.z;\n"; } else { diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 929b70d9c5..c959122cec 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1328,18 +1328,14 @@ void VKGSRender::clear_surface(u32 mask) const bool full_frame = (scissor_w == fb_width && scissor_h == fb_height); bool update_color = false, update_z = false; - auto surface_depth_format = rsx::method_registers.surface_depth_fmt(); + auto surface_depth_format = REGS(m_ctx)->surface_depth_fmt(); if (auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); mask & RSX_GCM_CLEAR_DEPTH_STENCIL_MASK) { if (mask & RSX_GCM_CLEAR_DEPTH_BIT) { - u32 max_depth_value = get_max_depth_value(surface_depth_format); - - u32 clear_depth = rsx::method_registers.z_clear_value(is_depth_stencil_format(surface_depth_format)); - float depth_clear = static_cast(clear_depth) / max_depth_value; - - depth_stencil_clear_values.depthStencil.depth = depth_clear; + const u32 clear_depth_bits = REGS(m_ctx)->z_clear_value(is_depth_stencil_format(surface_depth_format)); + depth_stencil_clear_values.depthStencil.depth = rsx::get_depth_clear_value(surface_depth_format, clear_depth_bits); depth_stencil_clear_values.depthStencil.stencil = stencil_clear; depth_stencil_mask |= VK_IMAGE_ASPECT_DEPTH_BIT; @@ -1349,7 +1345,7 @@ void VKGSRender::clear_surface(u32 mask) { if (mask & RSX_GCM_CLEAR_STENCIL_BIT) { - u8 clear_stencil = rsx::method_registers.stencil_clear_value(); + u8 clear_stencil = REGS(m_ctx)->stencil_clear_value(); depth_stencil_clear_values.depthStencil.stencil = clear_stencil; depth_stencil_mask |= VK_IMAGE_ASPECT_STENCIL_BIT; @@ -1398,12 +1394,12 @@ void VKGSRender::clear_surface(u32 mask) if (!m_draw_buffers.empty()) { bool use_fast_clear = (colormask == RSX_GCM_CLEAR_COLOR_RGBA_MASK);; - u8 clear_a = rsx::method_registers.clear_color_a(); - u8 clear_r = rsx::method_registers.clear_color_r(); - u8 clear_g = rsx::method_registers.clear_color_g(); - u8 clear_b = rsx::method_registers.clear_color_b(); + u8 clear_a = REGS(m_ctx)->clear_color_a(); + u8 clear_r = REGS(m_ctx)->clear_color_r(); + u8 clear_g = REGS(m_ctx)->clear_color_g(); + u8 clear_b = REGS(m_ctx)->clear_color_b(); - switch (rsx::method_registers.surface_color()) + switch (REGS(m_ctx)->surface_color()) { case rsx::surface_color_format::x32: case rsx::surface_color_format::w16z16y16x16: @@ -1502,7 +1498,7 @@ void VKGSRender::clear_surface(u32 mask) if (depth_stencil_mask) { if ((depth_stencil_mask & VK_IMAGE_ASPECT_STENCIL_BIT) && - rsx::method_registers.stencil_mask() != 0xff) + REGS(m_ctx)->stencil_mask() != 0xff) { // Partial stencil clear. Disables fast stencil clear auto ds = std::get<1>(m_rtts.m_bound_depth_stencil); @@ -1512,7 +1508,7 @@ void VKGSRender::clear_surface(u32 mask) vk::get_overlay_pass()->run( *m_current_command_buffer, ds, region.rect, depth_stencil_clear_values.depthStencil.stencil, - rsx::method_registers.stencil_mask(), renderpass); + REGS(m_ctx)->stencil_mask(), renderpass); depth_stencil_mask &= ~VK_IMAGE_ASPECT_STENCIL_BIT; }