Use the same logic for lerp bias for color and alpha

It doesn't make sense for alpha to add the bias ONLY when dividing by 2, while color doesn't apply the bias for divide by 2 only; hardware testing indicates that alpha should have the bias.

This fixes the menus in Mario Kart Wii (https://bugs.dolphin-emu.org/issues/11909) but reintroduces the white rectangle in Fortune Street.

This reverts commit 5aaa5141ed (and several other matching changes elsewhere).
This commit is contained in:
Pokechu22 2022-01-24 22:05:31 -08:00
parent b4c7f2b1e8
commit 0327e6acb4
3 changed files with 25 additions and 21 deletions

View File

@ -297,7 +297,7 @@ void Tev::DrawAlphaRegular(const TevStageCombiner::AlphaCombiner& ac, const Inpu
s32 temp = InputReg.a * (256 - c) + (InputReg.b * c);
temp <<= m_ScaleLShiftLUT[u32(ac.scale.Value())];
temp += (ac.scale != TevScale::Divide2) ? 0 : (ac.op == TevOp::Sub) ? 127 : 128;
temp += (ac.scale == TevScale::Divide2) ? 0 : (ac.op == TevOp::Sub) ? 127 : 128;
temp = ac.op == TevOp::Sub ? (-temp >> 8) : (temp >> 8);
s32 result =

View File

@ -852,7 +852,7 @@ uint WrapCoord(int coord, uint wrap, int size) {{
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
APIType api_type, bool stereo);
static void WriteTevRegular(ShaderCode& out, std::string_view components, TevBias bias, TevOp op,
bool clamp, TevScale scale, bool alpha);
bool clamp, TevScale scale);
static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_data, APIType api_type,
bool per_pixel_depth, bool use_dual_source);
static void WriteFog(ShaderCode& out, const pixel_shader_uid_data* uid_data);
@ -1677,7 +1677,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
out.Write("\t{} = clamp(", tev_c_output_table[cc.dest]);
if (cc.bias != TevBias::Compare)
{
WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.scale, false);
WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.scale);
}
else
{
@ -1710,7 +1710,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
out.Write("\t{} = clamp(", tev_a_output_table[ac.dest]);
if (ac.bias != TevBias::Compare)
{
WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.scale, true);
WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.scale);
}
else
{
@ -1742,7 +1742,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
}
static void WriteTevRegular(ShaderCode& out, std::string_view components, TevBias bias, TevOp op,
bool clamp, TevScale scale, bool alpha)
bool clamp, TevScale scale)
{
static constexpr Common::EnumMap<const char*, TevScale::Divide2> tev_scale_table_left{
"", // Scale1
@ -1780,12 +1780,14 @@ static void WriteTevRegular(ShaderCode& out, std::string_view components, TevBia
// - c is scaled from 0..255 to 0..256, which allows dividing the result by 256 instead of 255
// - if scale is bigger than one, it is moved inside the lerp calculation for increased accuracy
// - a rounding bias is added before dividing by 256
// TODO: Is the rounding bias still added when the scale is divide by 2? Currently we do not
// apply it.
out.Write("(((tevin_d.{}{}){})", components, tev_bias_table[bias], tev_scale_table_left[scale]);
out.Write(" {} ", tev_op_table[op]);
out.Write("(((((tevin_a.{0}<<8) + "
"(tevin_b.{0}-tevin_a.{0})*(tevin_c.{0}+(tevin_c.{0}>>7))){1}){2})>>8)",
components, tev_scale_table_left[scale],
((scale == TevScale::Divide2) == alpha) ? tev_lerp_bias[op] : "");
(scale != TevScale::Divide2) ? tev_lerp_bias[op] : "");
out.Write("){}", tev_scale_table_right[scale]);
}

View File

@ -334,8 +334,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
const auto WriteTevLerp = [&out](std::string_view components) {
out.Write(
"// TEV's Linear Interpolate, plus bias, add/subtract and scale\n"
"int{0} tevLerp{0}(int{0} A, int{0} B, int{0} C, int{0} D, uint bias, bool op, bool alpha, "
"uint shift) {{\n"
"int{0} tevLerp{0}(int{0} A, int{0} B, int{0} C, int{0} D, uint bias, bool op, "
"uint scale) {{\n"
" // Scale C from 0..255 to 0..256\n"
" C += C >> 7;\n"
"\n"
@ -344,12 +344,14 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
" else if (bias == 2u) D -= 128;\n"
"\n"
" int{0} lerp = (A << 8) + (B - A)*C;\n"
" if (shift != 3u) {{\n"
" lerp = lerp << shift;\n"
" D = D << shift;\n"
" if (scale != 3u) {{\n"
" lerp = lerp << scale;\n"
" D = D << scale;\n"
" }}\n"
"\n"
" if ((shift == 3u) == alpha)\n"
" // TODO: Is this rounding bias still added when the scale is divide by 2? Currently we "
"do not apply it.\n"
" if (scale != 3u)\n"
" lerp = lerp + (op ? 127 : 128);\n"
"\n"
" int{0} result = lerp >> 8;\n"
@ -360,9 +362,9 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
" else // Add\n"
" result = D + result;\n"
"\n"
" // Most of the Shift was moved inside the lerp for improved precision\n"
" // Most of the Scale was moved inside the lerp for improved precision\n"
" // But we still do the divide by 2 here\n"
" if (shift == 3u)\n"
" if (scale == 3u)\n"
" result = result >> 1;\n"
" return result;\n"
"}}\n\n",
@ -810,13 +812,13 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
BitfieldExtract<&TevStageCombiner::ColorCombiner::op>("ss.cc"));
out.Write(" bool color_clamp = bool({});\n",
BitfieldExtract<&TevStageCombiner::ColorCombiner::clamp>("ss.cc"));
out.Write(" uint color_shift = {};\n",
out.Write(" uint color_scale = {};\n",
BitfieldExtract<&TevStageCombiner::ColorCombiner::scale>("ss.cc"));
out.Write(" uint color_dest = {};\n",
BitfieldExtract<&TevStageCombiner::ColorCombiner::dest>("ss.cc"));
out.Write(
" uint color_compare_op = color_shift << 1 | uint(color_op);\n"
" uint color_compare_op = color_scale << 1 | uint(color_op);\n"
"\n"
" int3 color_A = selectColorInput(s, ss, {0}colors_0, {0}colors_1, color_a) & "
"int3(255, 255, 255);\n"
@ -831,8 +833,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
out.Write(
" int3 color;\n"
" if (color_bias != 3u) {{ // Normal mode\n"
" color = tevLerp3(color_A, color_B, color_C, color_D, color_bias, color_op, false, "
"color_shift);\n"
" color = tevLerp3(color_A, color_B, color_C, color_D, color_bias, color_op, "
"color_scale);\n"
" }} else {{ // Compare mode\n"
" // op 6 and 7 do a select per color channel\n"
" if (color_compare_op == 6u) {{\n"
@ -880,13 +882,13 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
BitfieldExtract<&TevStageCombiner::AlphaCombiner::op>("ss.ac"));
out.Write(" bool alpha_clamp = bool({});\n",
BitfieldExtract<&TevStageCombiner::AlphaCombiner::clamp>("ss.ac"));
out.Write(" uint alpha_shift = {};\n",
out.Write(" uint alpha_scale = {};\n",
BitfieldExtract<&TevStageCombiner::AlphaCombiner::scale>("ss.ac"));
out.Write(" uint alpha_dest = {};\n",
BitfieldExtract<&TevStageCombiner::AlphaCombiner::dest>("ss.ac"));
out.Write(
" uint alpha_compare_op = alpha_shift << 1 | uint(alpha_op);\n"
" uint alpha_compare_op = alpha_scale << 1 | uint(alpha_op);\n"
"\n"
" int alpha_A;\n"
" int alpha_B;\n"
@ -904,7 +906,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
" int alpha;\n"
" if (alpha_bias != 3u) {{ // Normal mode\n"
" alpha = tevLerp(alpha_A, alpha_B, alpha_C, alpha_D, alpha_bias, alpha_op, "
"true, alpha_shift);\n"
"alpha_scale);\n"
" }} else {{ // Compare mode\n"
" if (alpha_compare_op == 6u) {{\n"
" // TevCompareMode::A8, TevComparison::GT\n"