From de495952fdf64e3df2dd3d6ed9b4880a6d0917a7 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 20 Dec 2021 21:33:45 +0300 Subject: [PATCH] rsx: Enable fallback for devices without wide integer Z buffers --- rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 1 + rpcs3/Emu/RSX/Program/GLSLCommon.cpp | 13 ++++++++++++- rpcs3/Emu/RSX/Program/GLSLTypes.h | 1 + rpcs3/Emu/RSX/VK/VKVertexProgram.cpp | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index ee6a4e6660..010d3ebfc3 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -125,6 +125,7 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS) properties2.domain = glsl::glsl_vertex_program; properties2.require_lit_emulation = properties.has_lit_op; properties2.emulate_zclip_transform = true; + properties2.quantize_depth_values = dev_caps.vendor_AMD; properties2.emulate_depth_clip_only = dev_caps.NV_depth_buffer_float_supported; insert_glsl_legacy_function(OS, properties2); diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp index 3af0c083b7..96b2fed13f 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp @@ -603,6 +603,17 @@ namespace glsl { if (props.emulate_depth_clip_only) { + // Optionally quantize Z values. This doesn't work fully since fragment interpolation will add back intermediate values... + // But it helps make the values closer to the correct integral counterparts + if (!props.quantize_depth_values) [[likely]] + { + OS << "#define _quantize_z(value) (value)\n\n"; + } + else + { + OS << "#define _quantize_z(value) (double(uint(value * 0xFFFFFFu)) / 16777215.0)\n\n"; + } + // Technically the depth value here is the 'final' depth that should be stored in the Z buffer. // Forward mapping eqn is d' = d * (f - n) + n, where d' is the stored Z value (this) and d is the normalized API value. OS << @@ -615,7 +626,7 @@ namespace glsl " const double depth_range = double(real_f - real_n);\n" " const double inv_range = (depth_range > 0.0) ? (1.0 / (depth_range * pos.w)) : 0.0;\n" " const double d = (double(pos.z) - real_n) * inv_range;\n" - " return vec4(pos.xy, float(d * pos.w), pos.w);\n" + " return vec4(pos.xy, float(_quantize_z(d) * pos.w), pos.w);\n" " }\n" " else\n" " {\n" diff --git a/rpcs3/Emu/RSX/Program/GLSLTypes.h b/rpcs3/Emu/RSX/Program/GLSLTypes.h index ac9a917f76..9575a7980c 100644 --- a/rpcs3/Emu/RSX/Program/GLSLTypes.h +++ b/rpcs3/Emu/RSX/Program/GLSLTypes.h @@ -34,6 +34,7 @@ namespace glsl bool emulate_shadow_compare : 1; bool emulate_zclip_transform : 1; bool emulate_depth_clip_only : 1; + bool quantize_depth_values : 1; bool low_precision_tests : 1; bool disable_early_discard : 1; bool supports_native_fp16 : 1; diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 0d7576a34a..5472df9096 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -187,6 +187,7 @@ void VKVertexDecompilerThread::insertMainStart(std::stringstream & OS) properties2.domain = glsl::glsl_vertex_program; properties2.require_lit_emulation = properties.has_lit_op; properties2.emulate_zclip_transform = true; + properties2.quantize_depth_values = !vk::g_render_device->get_formats_support().d24_unorm_s8; properties2.emulate_depth_clip_only = vk::g_render_device->get_shader_types_support().allow_float64; glsl::insert_glsl_legacy_function(OS, properties2);