rsx: Fix DEPTH_FLOAT decoding for clear values

This commit is contained in:
kd-11
2026-10-09 12:38:31 +03:00
committed by kd-11
parent 5e89a0061e
commit ffa4c71088
5 changed files with 50 additions and 38 deletions
+21 -2
View File
@@ -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<f32>(bits) * std::bit_cast<f32>(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<f32>(raw << 7);
default:
fmt::throw_exception("Unreachable");
}
}
bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode)
+1 -1
View File
@@ -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);
/**
+15 -17
View File
@@ -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:
+2 -3
View File
@@ -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
{
+11 -15
View File
@@ -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<float>(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<vk::stencil_clear_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;
}