rsx/fp: RE work on precision modifier bits

- Testing DS2 has revealed clamping bits in SRC1 that were not respected and left negative values reaching the framebuffer
This commit is contained in:
kd-11 2017-11-13 22:07:23 +03:00
parent bbb3bdf008
commit a8c0dd649e
3 changed files with 18 additions and 13 deletions

View File

@ -38,10 +38,17 @@ void FragmentProgramDecompiler::SetDst(std::string code, bool append_mask)
if (!dst.no_dest)
{
code = NoOverflow(code);
if (dst.exp_tex)
{
//If dst.exp_tex really is _bx2 postfix, we need to unpack dynamic range
AddCode("//exp tex flag is set");
code = "((" + code + "- 0.5) * 2.)";
}
if (dst.saturate)
code = saturate(code);
else
code = ClampValue(code, dst.prec);
}
code += (append_mask ? "$m" : "");
@ -188,20 +195,13 @@ std::string FragmentProgramDecompiler::NotZeroPositive(const std::string& code)
return "max(abs(" + code + "), 1.E-10)";
}
std::string FragmentProgramDecompiler::NoOverflow(const std::string& code)
std::string FragmentProgramDecompiler::ClampValue(const std::string& code, u32 precision)
{
//FP16 is expected to overflow alot easier at 0+-65504
//FP32 can still work upto 0+-3.4E38
//See http://http.download.nvidia.com/developer/Papers/2005/FP_Specials/FP_Specials.pdf
if (dst.exp_tex)
{
//If dst.exp_tex really is _bx2 postfix, we need to unpack dynamic range
AddCode("//exp tex flag is set");
return "((" + code + "- 0.5) * 2.)";
}
switch (dst.prec)
switch (precision)
{
case 0:
break;
@ -209,6 +209,10 @@ std::string FragmentProgramDecompiler::NoOverflow(const std::string& code)
return "clamp(" + code + ", -65504., 65504.)";
case 2:
return "clamp(" + code + ", -2., 2.)";
case 3:
return "clamp(" + code + ", -1., 1.)";
case 4:
return "clamp(" + code + ", 0., 1.)";
}
return code;
@ -396,6 +400,7 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
if (src.abs) ret = "abs(" + ret + ")";
if (src.neg) ret = "-" + ret;
if (src1.input_prec_mod) ret = ClampValue(ret, src1.input_prec_mod);
return ret;
}

View File

@ -55,8 +55,8 @@ class FragmentProgramDecompiler
std::string NotZero(const std::string& code);
std::string NotZeroPositive(const std::string& code);
//Prevents operations from overflowing the max range (tested with fp_dynamic3 autotest sample)
std::string NoOverflow(const std::string& code);
//Prevents operations from overflowing the desired range (tested with fp_dynamic3 autotest sample, DS2 for src1.input_prec_mod)
std::string ClampValue(const std::string& code, u32 precision);
/**
* Returns true if the dst set is not a vector (i.e only a single component)

View File

@ -147,7 +147,7 @@ union SRC1
u32 swizzle_w : 2;
u32 neg : 1;
u32 abs : 1;
u32 input_mod_src0 : 3;
u32 input_prec_mod : 3; // Looks to be a precision clamping modifier affecting all inputs (tested with Dark Souls II)
u32 : 6;
u32 scale : 3;
u32 opcode_is_branch : 1;