From c655036920d06754679bd4f0e59266562a5e218f Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 8 Jun 2019 13:15:54 +0300 Subject: [PATCH] rsx/fp: Ease pressure on fragment shaders when emulating clamp16 - TODO: Option to completely skip clamping in some architectures as it is not needed in most games - Mostly affects older GPUs that do not have access to native fp16 --- .../RSX/Common/FragmentProgramDecompiler.cpp | 17 +++++++++++------ rpcs3/Emu/RSX/RSXFragmentProgram.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 7263002c53..911a1a9f9c 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -274,18 +274,18 @@ std::string FragmentProgramDecompiler::ClampValue(const std::string& code, u32 p switch (precision) { - case 0: + case RSX_FP_PRECISION_REAL: // Full 32-bit precision break; - case 1: + case RSX_FP_PRECISION_HALF: return "clamp16(" + code + ")"; - case 2: + case RSX_FP_PRECISION_FIXED12: return "precision_clamp(" + code + ", -2., 2.)"; - case 3: + case RSX_FP_PRECISION_FIXED9: return "precision_clamp(" + code + ", -1., 1.)"; - case 4: + case RSX_FP_PRECISION_SATURATE: return "precision_clamp(" + code + ", 0., 1.)"; - case 5: + case RSX_FP_PRECISION_UNKNOWN: // Doesn't seem to do anything to the input from hw tests, same as 0 break; default: @@ -491,6 +491,11 @@ template std::string FragmentProgramDecompiler::GetSRC(T src) } } } + else if (src1.input_prec_mod == RSX_FP_PRECISION_HALF) + { + // clamp16() is not a cheap operation when emulated; avoid at all costs + apply_precision_modifier = false; + } ret += AddReg(src.tmp_reg_index, src.fp16); diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index 244374bf47..d8f875c45d 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -10,6 +10,16 @@ enum register_type RSX_FP_REGISTER_TYPE_UNKNOWN = 3, }; +enum register_precision +{ + RSX_FP_PRECISION_REAL = 0, + RSX_FP_PRECISION_HALF = 1, + RSX_FP_PRECISION_FIXED12 = 2, + RSX_FP_PRECISION_FIXED9 = 3, + RSX_FP_PRECISION_SATURATE = 4, + RSX_FP_PRECISION_UNKNOWN = 5 // Unknown what this actually does; seems to do nothing on hwtests but then why would their compiler emit it? +}; + enum fp_opcode { RSX_FP_OPCODE_NOP = 0x00, // No-Operation