GS/HW: Use enum for blend_hw shader bit.

Better readability.
This commit is contained in:
lightningterror 2024-06-09 13:30:58 +02:00
parent abec2738b9
commit 7aea867a66
2 changed files with 27 additions and 15 deletions

View File

@ -167,6 +167,18 @@ enum ChannelFetch
ChannelFetch_GXBY = 6, ChannelFetch_GXBY = 6,
}; };
enum class HWBlendType
{
SRC_ONE_DST_FACTOR = 1, // Use the dest color as blend factor, Cs is set to 1.
SRC_ALPHA_DST_FACTOR = 2, // Use the dest color as blend factor, Cs is set to (Alpha - 1).
SRC_DOUBLE = 3, // Double source color.
SRC_HALF_ONE_DST_FACTOR = 4, // Use the dest color as blend factor, Cs is set to 0.5, additionally divide As or Af by 2.
BMIX1_ALPHA_HIGH_ONE = 1, // Blend formula is replaced when alpha is higher than 1.
BMIX1_SRC_HALF = 2, // Impossible blend will always be wrong on hw, divide Cs by 2.
BMIX2_OVERFLOW = 3, // Blending Cs might overflow, try to compensate.
};
struct alignas(16) DisplayConstantBuffer struct alignas(16) DisplayConstantBuffer
{ {
GSVector4 SourceRect; // +0,xyzw GSVector4 SourceRect; // +0,xyzw

View File

@ -4400,14 +4400,14 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Replace Cs*Alpha + Cd*(1 - Alpha) with Cs*Alpha - Cd*(Alpha - 1). // Replace Cs*Alpha + Cd*(1 - Alpha) with Cs*Alpha - Cd*(Alpha - 1).
blend.dst = GSDevice::SRC1_COLOR; blend.dst = GSDevice::SRC1_COLOR;
blend.op = GSDevice::OP_SUBTRACT; blend.op = GSDevice::OP_SUBTRACT;
m_conf.ps.blend_hw = 1; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::BMIX1_ALPHA_HIGH_ONE);
} }
else if (m_conf.ps.blend_a == m_conf.ps.blend_d) else if (m_conf.ps.blend_a == m_conf.ps.blend_d)
{ {
// Cd*(Alpha + 1) - Cs*Alpha will always be wrong. // Cd*(Alpha + 1) - Cs*Alpha will always be wrong.
// Let's cheat a little and divide blended Cs by Alpha. // Let's cheat a little and divide blended Cs by Alpha.
// Result will still be wrong but closer to what we want. // Result will still be wrong but closer to what we want.
m_conf.ps.blend_hw = 2; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::BMIX1_SRC_HALF);
} }
m_conf.ps.blend_a = 0; m_conf.ps.blend_a = 0;
@ -4419,7 +4419,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Allow to compensate when Cs*(Alpha + 1) overflows, // Allow to compensate when Cs*(Alpha + 1) overflows,
// to compensate we change the alpha output value for Cd*Alpha. // to compensate we change the alpha output value for Cd*Alpha.
blend.dst = GSDevice::SRC1_COLOR; blend.dst = GSDevice::SRC1_COLOR;
m_conf.ps.blend_hw = 3; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::BMIX2_OVERFLOW);
m_conf.ps.blend_a = 0; m_conf.ps.blend_a = 0;
m_conf.ps.blend_b = 2; m_conf.ps.blend_b = 2;
@ -4493,7 +4493,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
blend.dst = GSDevice::CONST_ONE; blend.dst = GSDevice::CONST_ONE;
// Render pass 2: Blend the result (Cd) from render pass 1 with alpha range of 0-2. // Render pass 2: Blend the result (Cd) from render pass 1 with alpha range of 0-2.
m_conf.blend_second_pass.enable = true; m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 2; m_conf.blend_second_pass.blend_hw = static_cast<u8>(HWBlendType::SRC_ALPHA_DST_FACTOR);
m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, (m_conf.ps.blend_c == 2) ? GSDevice::CONST_COLOR : GSDevice::SRC1_COLOR, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, m_conf.ps.blend_c == 2, AFIX}; m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, (m_conf.ps.blend_c == 2) ? GSDevice::CONST_COLOR : GSDevice::SRC1_COLOR, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, m_conf.ps.blend_c == 2, AFIX};
} }
else if ((alpha_c0_high_max_one || alpha_c1_high_no_rta_correct || alpha_c2_high_one) && (blend_flag & BLEND_HW1)) else if ((alpha_c0_high_max_one || alpha_c1_high_no_rta_correct || alpha_c2_high_one) && (blend_flag & BLEND_HW1))
@ -4501,11 +4501,11 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Alpha = As, Ad or Af. // Alpha = As, Ad or Af.
// Cd*(1 + Alpha). // Cd*(1 + Alpha).
// Render pass 1: Do Cd*(1 + Alpha) with a half result in the end. // Render pass 1: Do Cd*(1 + Alpha) with a half result in the end.
m_conf.ps.blend_hw = 4; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_HALF_ONE_DST_FACTOR);
blend.dst = (m_conf.ps.blend_c == 1) ? GSDevice::DST_ALPHA : GSDevice::SRC1_COLOR; blend.dst = (m_conf.ps.blend_c == 1) ? GSDevice::DST_ALPHA : GSDevice::SRC1_COLOR;
// Render pass 2: Take result (Cd) from render pass 1 and double it. // Render pass 2: Take result (Cd) from render pass 1 and double it.
m_conf.blend_second_pass.enable = true; m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 1; m_conf.blend_second_pass.blend_hw = static_cast<u8>(HWBlendType::SRC_ONE_DST_FACTOR);
m_conf.blend_second_pass.blend = {true, blend_second_pass.src, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0}; m_conf.blend_second_pass.blend = {true, blend_second_pass.src, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
} }
else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW3)) else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW3))
@ -4523,7 +4523,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Cs + Cd*Alpha, Cs - Cd*Alpha. // Cs + Cd*Alpha, Cs - Cd*Alpha.
const u8 dither = m_conf.ps.dither; const u8 dither = m_conf.ps.dither;
// Render pass 1: Calculate Cd*Alpha with an alpha range of 0-2. // Render pass 1: Calculate Cd*Alpha with an alpha range of 0-2.
m_conf.ps.blend_hw = 2; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_ALPHA_DST_FACTOR);
m_conf.ps.dither = 0; m_conf.ps.dither = 0;
blend.src = GSDevice::DST_COLOR; blend.src = GSDevice::DST_COLOR;
blend.dst = (m_conf.ps.blend_c == 2) ? GSDevice::CONST_COLOR : GSDevice::SRC1_COLOR; blend.dst = (m_conf.ps.blend_c == 2) ? GSDevice::CONST_COLOR : GSDevice::SRC1_COLOR;
@ -4541,7 +4541,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Render pass 1: Do (Cd - Cs)*Alpha, (Cs - Cd)*Alpha or Cd*Alpha on first pass. // Render pass 1: Do (Cd - Cs)*Alpha, (Cs - Cd)*Alpha or Cd*Alpha on first pass.
// Render pass 2: Take result (Cd) from render pass 1 and double it. // Render pass 2: Take result (Cd) from render pass 1 and double it.
m_conf.blend_second_pass.enable = true; m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 1; m_conf.blend_second_pass.blend_hw = static_cast<u8>(HWBlendType::SRC_ONE_DST_FACTOR);
m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, GSDevice::CONST_ONE, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0}; m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, GSDevice::CONST_ONE, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
} }
else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW6)) else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW6))
@ -4554,7 +4554,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
blend.src = GSDevice::CONST_COLOR; blend.src = GSDevice::CONST_COLOR;
// Render pass 2: Take result (Cd) from render pass 1 and double it. // Render pass 2: Take result (Cd) from render pass 1 and double it.
m_conf.blend_second_pass.enable = true; m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 1; m_conf.blend_second_pass.blend_hw = static_cast<u8>(HWBlendType::SRC_ONE_DST_FACTOR);
m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, GSDevice::CONST_ONE, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0}; m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, GSDevice::CONST_ONE, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
} }
else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW7)) else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW7))
@ -4562,13 +4562,13 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Alpha = Ad. // Alpha = Ad.
// Cd*(1 - Alpha). // Cd*(1 - Alpha).
// Render pass 1: Multiply Cd by 0.5, then do Cd - Cd*Alpha. // Render pass 1: Multiply Cd by 0.5, then do Cd - Cd*Alpha.
m_conf.ps.blend_hw = 4; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_HALF_ONE_DST_FACTOR);
blend.src = GSDevice::DST_COLOR; blend.src = GSDevice::DST_COLOR;
blend.dst = GSDevice::DST_ALPHA; blend.dst = GSDevice::DST_ALPHA;
blend.op = GSDevice::OP_SUBTRACT; blend.op = GSDevice::OP_SUBTRACT;
// Render pass 2: Take result (Cd) from render pass 1 and double it. // Render pass 2: Take result (Cd) from render pass 1 and double it.
m_conf.blend_second_pass.enable = true; m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 1; m_conf.blend_second_pass.blend_hw = static_cast<u8>(HWBlendType::SRC_ONE_DST_FACTOR);
m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, GSDevice::CONST_ONE, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0}; m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, GSDevice::CONST_ONE, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
} }
else if (blend_flag & BLEND_HW8) else if (blend_flag & BLEND_HW8)
@ -4578,7 +4578,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
// Render pass 1: Do Cs. // Render pass 1: Do Cs.
// Render pass 2: Try to double Cs, then take result (Cd) from render pass 1 and add Cs*Alpha to it. // Render pass 2: Try to double Cs, then take result (Cd) from render pass 1 and add Cs*Alpha to it.
m_conf.blend_second_pass.enable = true; m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 3; m_conf.blend_second_pass.blend_hw = static_cast<u8>(HWBlendType::SRC_DOUBLE);
m_conf.blend_second_pass.blend = {true, GSDevice::DST_ALPHA, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0}; m_conf.blend_second_pass.blend = {true, GSDevice::DST_ALPHA, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
} }
else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW9)) else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW9))
@ -4594,15 +4594,15 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
if (!m_conf.blend_second_pass.enable && blend_flag & BLEND_HW1) if (!m_conf.blend_second_pass.enable && blend_flag & BLEND_HW1)
{ {
m_conf.ps.blend_hw = 1; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_ONE_DST_FACTOR);
} }
else if (blend_flag & BLEND_HW2) else if (blend_flag & BLEND_HW2)
{ {
m_conf.ps.blend_hw = 2; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_ALPHA_DST_FACTOR);
} }
else if (!m_conf.blend_second_pass.enable && alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW3)) else if (!m_conf.blend_second_pass.enable && alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW3))
{ {
m_conf.ps.blend_hw = 3; m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_DOUBLE);
} }
if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == 2 || m_conf.ps.blend_hw == 4 || m_conf.blend_second_pass.blend_hw == 2)) if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == 2 || m_conf.ps.blend_hw == 4 || m_conf.blend_second_pass.blend_hw == 2))