1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 12:42:41 +01:00

rsx: Fragment decompiler fixups

- Properly test for NaN and Inf when clamping down to fp16
- Optimize divsq a bit; mix(vec, vec, bvec) emits OpSelect which is what
we want here, instead of component-wise selection which is much slower.
This commit is contained in:
kd-11 2019-04-20 13:02:05 +03:00 committed by kd-11
parent abe7188acf
commit f12bd8068c

View File

@ -618,16 +618,35 @@ std::string FragmentProgramDecompiler::BuildCode()
insertGlobalFunctions(OS);
std::string float4 = getFloatTypeName(4);
const bool glsl = float4 == "vec4";
if (!device_props.has_native_half_support)
{
// Accurate float to half clamping (preserves IEEE-754 NaN)
std::string clamp_func =
"$float4 clamp16($float4 x)\n"
"{\n"
" $float4 sel = $float4(isnan(x));\n"
" $float4 clamped = clamp(x, -65504., +65504.);\n"
" return _select(clamped, x, sel);\n"
"{\n";
if (glsl)
{
clamp_func +=
" uvec4 bits = floatBitsToUint(x);\n"
" uvec4 extend = uvec4(0x7f800000);\n"
" bvec4 test = equal(bits & extend, extend);\n"
" vec4 clamped = clamp(x, -65504., +65504.);\n"
" return _select(clamped, x, test);\n";
}
else
{
clamp_func +=
" if (!isnan(x.x) && !isinf(x.x)) x.x = clamp(x.x, -65504., +65504.);\n"
" if (!isnan(x.x) && !isinf(x.x)) x.x = clamp(x.x, -65504., +65504.);\n"
" if (!isnan(x.x) && !isinf(x.x)) x.x = clamp(x.x, -65504., +65504.);\n"
" if (!isnan(x.x) && !isinf(x.x)) x.x = clamp(x.x, -65504., +65504.);\n"
" return x;\n";
}
clamp_func +=
"}\n\n";
OS << Format(clamp_func);
@ -668,12 +687,24 @@ std::string FragmentProgramDecompiler::BuildCode()
"$float4 _builtin_divsq($float4 a, float b)\n"
"{"
" $float4 tmp = a / sqrt(b);\n"
" $float4 choice = abs(a);\n"
" if (choice.x > 0.) a.x = tmp.x;\n"
" if (choice.y > 0.) a.y = tmp.y;\n"
" if (choice.z > 0.) a.z = tmp.z;\n"
" if (choice.w > 0.) a.w = tmp.w;\n"
" return a;\n"
" $float4 choice = abs(a);\n";
if (glsl)
{
divsq_func +=
" return _select(a, tmp, greaterThan(choice, vec4(0.)));\n";
}
else
{
divsq_func +=
" if (choice.x > 0.) a.x = tmp.x;\n"
" if (choice.y > 0.) a.y = tmp.y;\n"
" if (choice.z > 0.) a.z = tmp.z;\n"
" if (choice.w > 0.) a.w = tmp.w;\n"
" return a;\n";
}
divsq_func +=
"}\n\n";
OS << Format(divsq_func);