mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-12 02:09:17 +00:00
rsx: Fix DEPTH_FLOAT decoding for clear values
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user