diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index c6ae5b449f..1d285fa46d 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -58,8 +58,6 @@ void GLVertexDecompilerThread::insertInputs(std::stringstream& OS, const std::ve void GLVertexDecompilerThread::insertConstants(std::stringstream& OS, const std::vector& constants) { - - for (const ParamType &PT: constants) { for (const ParamItem &PI : PT.items) @@ -131,6 +129,7 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS) properties2.emulate_zclip_transform = true; properties2.emulate_depth_clip_only = dev_caps.NV_depth_buffer_float_supported; properties2.low_precision_tests = dev_caps.vendor_NVIDIA; + properties2.require_explicit_invariance = dev_caps.vendor_MESA; insert_glsl_legacy_function(OS, properties2); glsl::insert_vertex_input_fetch(OS, glsl::glsl_rules_opengl4, dev_caps.vendor_INTEL == false); diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp index 35feedda15..4d7eef1a0a 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp @@ -598,56 +598,65 @@ namespace glsl "}\n\n"; } - if (props.domain == glsl::program_domain::glsl_vertex_program && props.emulate_zclip_transform) + if (props.domain == glsl::program_domain::glsl_vertex_program) { - if (props.emulate_depth_clip_only) + if (props.require_explicit_invariance) { - // 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 << - "vec4 apply_zclip_xform(const in vec4 pos, const in float near_plane, const in float far_plane)\n" - "{\n" - " if (pos.w != 0.0)\n" - " {\n" - " const float real_n = min(far_plane, near_plane);\n" - " const float real_f = max(far_plane, near_plane);\n" - " const double depth_range = double(real_f - real_n);\n" - " const double inv_range = (depth_range > 0.000001) ? (1.0 / (depth_range * pos.w)) : 0.0;\n" - " const double actual_d = (double(pos.z) - double(real_n * pos.w)) * inv_range;\n" - " const double nearest_d = floor(actual_d + 0.5);\n" - " const double epsilon = (inv_range * pos.w) / 16777215.;\n" // Epsilon value is the minimum discernable change in Z that should affect the stored Z - " const double d = _select(actual_d, nearest_d, abs(actual_d - nearest_d) < epsilon);\n" - " return vec4(pos.xy, float(d * pos.w), pos.w);\n" - " }\n" - " else\n" - " {\n" - " return pos;\n" // Only values where Z=0 can ever pass this clip - " }\n" - "}\n\n"; + // PS3 has shader invariance, but we don't really care about most attributes outside ATTR0 + OS << "invariant gl_Position;\n\n"; } - else + + if (props.emulate_zclip_transform) { - OS << - "vec4 apply_zclip_xform(const in vec4 pos, const in float near_plane, const in float far_plane)\n" - "{\n" - " float d = float(pos.z / pos.w);\n" - " if (d < 0.f && d >= near_plane)\n" - " {\n" - " // Clamp\n" - " d = 0.f;\n" - " }\n" - " else if (d > 1.f && d <= far_plane)\n" - " {\n" - " // Compress Z and store towards highest end of the range\n" - " d = min(1., 0.99 + (0.01 * (pos.z - near_plane) / (far_plane - near_plane)));\n" - " }\n" - " else\n" // This catch-call also handles w=0 since d=inf - " {\n" - " return pos;\n" - " }\n" - "\n" - " return vec4(pos.x, pos.y, d * pos.w, pos.w);\n" - "}\n\n"; + if (props.emulate_depth_clip_only) + { + // 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 << + "vec4 apply_zclip_xform(const in vec4 pos, const in float near_plane, const in float far_plane)\n" + "{\n" + " if (pos.w != 0.0)\n" + " {\n" + " const float real_n = min(far_plane, near_plane);\n" + " const float real_f = max(far_plane, near_plane);\n" + " const double depth_range = double(real_f - real_n);\n" + " const double inv_range = (depth_range > 0.000001) ? (1.0 / (depth_range * pos.w)) : 0.0;\n" + " const double actual_d = (double(pos.z) - double(real_n * pos.w)) * inv_range;\n" + " const double nearest_d = floor(actual_d + 0.5);\n" + " const double epsilon = (inv_range * pos.w) / 16777215.;\n" // Epsilon value is the minimum discernable change in Z that should affect the stored Z + " const double d = _select(actual_d, nearest_d, abs(actual_d - nearest_d) < epsilon);\n" + " return vec4(pos.xy, float(d * pos.w), pos.w);\n" + " }\n" + " else\n" + " {\n" + " return pos;\n" // Only values where Z=0 can ever pass this clip + " }\n" + "}\n\n"; + } + else + { + OS << + "vec4 apply_zclip_xform(const in vec4 pos, const in float near_plane, const in float far_plane)\n" + "{\n" + " float d = float(pos.z / pos.w);\n" + " if (d < 0.f && d >= near_plane)\n" + " {\n" + " // Clamp\n" + " d = 0.f;\n" + " }\n" + " else if (d > 1.f && d <= far_plane)\n" + " {\n" + " // Compress Z and store towards highest end of the range\n" + " d = min(1., 0.99 + (0.01 * (pos.z - near_plane) / (far_plane - near_plane)));\n" + " }\n" + " else\n" // This catch-call also handles w=0 since d=inf + " {\n" + " return pos;\n" + " }\n" + "\n" + " return vec4(pos.x, pos.y, d * pos.w, pos.w);\n" + "}\n\n"; + } } return; diff --git a/rpcs3/Emu/RSX/Program/GLSLTypes.h b/rpcs3/Emu/RSX/Program/GLSLTypes.h index 8805a62191..7152cfe4cc 100644 --- a/rpcs3/Emu/RSX/Program/GLSLTypes.h +++ b/rpcs3/Emu/RSX/Program/GLSLTypes.h @@ -31,6 +31,7 @@ namespace glsl bool require_texture_expand : 1; bool require_srgb_to_linear : 1; bool require_linear_to_srgb : 1; + bool require_explicit_invariance: 1; bool emulate_coverage_tests : 1; bool emulate_shadow_compare : 1; bool emulate_zclip_transform : 1;