mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-04-17 16:21:28 -06:00
video_core: fix color blend min/max mode in OpenGL (#2038)
* video_core: fix check for fragment color blend emulation * video_core: Fix typo in gl fragment shader gen
This commit is contained in:
parent
1edc5de18e
commit
f1cd5f5ff4
@ -895,7 +895,11 @@ void FragmentModule::WriteLogicOp() {
|
||||
}
|
||||
|
||||
void FragmentModule::WriteBlending() {
|
||||
if (!config.EmulateBlend() || profile.is_vulkan) [[likely]] {
|
||||
bool requires_rgb_minmax_emulation =
|
||||
config.framebuffer.requested_rgb_blend.RequiresMinMaxEmulation();
|
||||
bool requires_alpha_minmax_emulation =
|
||||
config.framebuffer.requested_alpha_blend.RequiresMinMaxEmulation();
|
||||
if (!requires_rgb_minmax_emulation && !requires_alpha_minmax_emulation) [[likely]] {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -937,23 +941,25 @@ void FragmentModule::WriteBlending() {
|
||||
return "vec4(1.f)";
|
||||
}
|
||||
};
|
||||
|
||||
// At this point, the blend equation can only be min or max.
|
||||
const auto get_func = [](Pica::FramebufferRegs::BlendEquation eq) {
|
||||
return eq == Pica::FramebufferRegs::BlendEquation::Min ? "min" : "max";
|
||||
};
|
||||
|
||||
if (config.framebuffer.rgb_blend.eq != Pica::FramebufferRegs::BlendEquation::Add) {
|
||||
if (requires_rgb_minmax_emulation) {
|
||||
out += fmt::format(
|
||||
"combiner_output.rgb = {}(source_color.rgb * ({}).rgb, dest_color.rgb * ({}).rgb);\n",
|
||||
get_func(config.framebuffer.rgb_blend.eq),
|
||||
get_factor(config.framebuffer.rgb_blend.src_factor),
|
||||
get_factor(config.framebuffer.rgb_blend.dst_factor));
|
||||
get_func(config.framebuffer.requested_rgb_blend.eq),
|
||||
get_factor(config.framebuffer.requested_rgb_blend.src_factor),
|
||||
get_factor(config.framebuffer.requested_rgb_blend.dst_factor));
|
||||
}
|
||||
if (config.framebuffer.alpha_blend.eq != Pica::FramebufferRegs::BlendEquation::Add) {
|
||||
if (requires_alpha_minmax_emulation) {
|
||||
out +=
|
||||
fmt::format("combiner_output.a = {}(source_color.a * ({}).a, dest_color.a * ({}).a);\n",
|
||||
get_func(config.framebuffer.alpha_blend.eq),
|
||||
get_factor(config.framebuffer.alpha_blend.src_factor),
|
||||
get_factor(config.framebuffer.alpha_blend.dst_factor));
|
||||
get_func(config.framebuffer.requested_alpha_blend.eq),
|
||||
get_factor(config.framebuffer.requested_alpha_blend.src_factor),
|
||||
get_factor(config.framebuffer.requested_alpha_blend.dst_factor));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1239,7 +1245,8 @@ void FragmentModule::DefineExtensions() {
|
||||
use_fragment_shader_barycentric = false;
|
||||
}
|
||||
}
|
||||
if (config.EmulateBlend() && !profile.is_vulkan) {
|
||||
if (config.framebuffer.requested_rgb_blend.RequiresMinMaxEmulation() ||
|
||||
config.framebuffer.requested_alpha_blend.RequiresMinMaxEmulation()) [[unlikely]] {
|
||||
if (profile.has_gl_ext_framebuffer_fetch) {
|
||||
out += "#extension GL_EXT_shader_framebuffer_fetch : enable\n";
|
||||
out += "#define destFactor color\n";
|
||||
@ -1338,7 +1345,7 @@ void FragmentModule::DefineBindingsGL() {
|
||||
out += "layout(binding = 6) uniform sampler2D tex_normal;\n";
|
||||
}
|
||||
if (use_blend_fallback) {
|
||||
out += "layout(location = 7) uniform sampler2D tex_color;\n";
|
||||
out += "layout(binding = 7) uniform sampler2D tex_color;\n";
|
||||
}
|
||||
|
||||
// Shadow textures
|
||||
|
||||
@ -21,13 +21,13 @@ FramebufferConfig::FramebufferConfig(const Pica::RegsInternal& regs) {
|
||||
logic_op.Assign(Pica::FramebufferRegs::LogicOp::Copy);
|
||||
|
||||
if (alphablend_enable) {
|
||||
rgb_blend.eq = output_merger.alpha_blending.blend_equation_rgb.Value();
|
||||
rgb_blend.src_factor = output_merger.alpha_blending.factor_source_rgb;
|
||||
rgb_blend.dst_factor = output_merger.alpha_blending.factor_dest_rgb;
|
||||
requested_rgb_blend.eq = output_merger.alpha_blending.blend_equation_rgb.Value();
|
||||
requested_rgb_blend.src_factor = output_merger.alpha_blending.factor_source_rgb;
|
||||
requested_rgb_blend.dst_factor = output_merger.alpha_blending.factor_dest_rgb;
|
||||
|
||||
alpha_blend.eq = output_merger.alpha_blending.blend_equation_a.Value();
|
||||
alpha_blend.src_factor = output_merger.alpha_blending.factor_source_a;
|
||||
alpha_blend.dst_factor = output_merger.alpha_blending.factor_dest_a;
|
||||
requested_alpha_blend.eq = output_merger.alpha_blending.blend_equation_a.Value();
|
||||
requested_alpha_blend.src_factor = output_merger.alpha_blending.factor_source_a;
|
||||
requested_alpha_blend.dst_factor = output_merger.alpha_blending.factor_dest_a;
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,17 +37,10 @@ void FramebufferConfig::ApplyProfile(const Profile& profile) {
|
||||
logic_op.Assign(requested_logic_op);
|
||||
}
|
||||
|
||||
// Min/max blend emulation
|
||||
if (!profile.has_blend_minmax_factor && alphablend_enable) {
|
||||
if (rgb_blend.eq != Pica::FramebufferRegs::BlendEquation::Min &&
|
||||
rgb_blend.eq != Pica::FramebufferRegs::BlendEquation::Max) {
|
||||
rgb_blend = {};
|
||||
}
|
||||
|
||||
if (alpha_blend.eq != Pica::FramebufferRegs::BlendEquation::Min &&
|
||||
alpha_blend.eq != Pica::FramebufferRegs::BlendEquation::Max) {
|
||||
alpha_blend = {};
|
||||
}
|
||||
// Check if we don't need blend min/max emulation.
|
||||
if ((profile.has_blend_minmax_factor || profile.is_vulkan) && alphablend_enable) {
|
||||
requested_rgb_blend.SetMinMaxEmulationDisabled();
|
||||
requested_alpha_blend.SetMinMaxEmulationDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -43,6 +43,17 @@ struct BlendConfig {
|
||||
// fields
|
||||
FIELD_HASH(eq), FIELD_HASH(src_factor), FIELD_HASH(dst_factor));
|
||||
}
|
||||
|
||||
void SetMinMaxEmulationDisabled() {
|
||||
// If we don't need min/max emulation, set the blend equation
|
||||
// to "-1" as a clear marker that this config is disabled.
|
||||
eq = static_cast<Pica::FramebufferRegs::BlendEquation>(UINT32_MAX);
|
||||
}
|
||||
|
||||
bool RequiresMinMaxEmulation() {
|
||||
return eq == Pica::FramebufferRegs::BlendEquation::Min ||
|
||||
eq == Pica::FramebufferRegs::BlendEquation::Max;
|
||||
}
|
||||
};
|
||||
static_assert(std::has_unique_object_representations_v<BlendConfig>);
|
||||
|
||||
@ -58,8 +69,8 @@ struct FramebufferConfig {
|
||||
BitField<10, 1, u32> shadow_rendering;
|
||||
BitField<11, 1, u32> alphablend_enable;
|
||||
};
|
||||
BlendConfig rgb_blend{};
|
||||
BlendConfig alpha_blend{};
|
||||
BlendConfig requested_rgb_blend{};
|
||||
BlendConfig requested_alpha_blend{};
|
||||
|
||||
Pica::FramebufferRegs::LogicOp requested_logic_op{};
|
||||
|
||||
@ -78,7 +89,8 @@ struct FramebufferConfig {
|
||||
// fields
|
||||
FIELD_HASH(alpha_test_func), FIELD_HASH(scissor_test_mode), FIELD_HASH(depthmap_enable),
|
||||
FIELD_HASH(logic_op), FIELD_HASH(shadow_rendering), FIELD_HASH(alphablend_enable),
|
||||
FIELD_HASH(rgb_blend), FIELD_HASH(alpha_blend), FIELD_HASH(requested_logic_op),
|
||||
FIELD_HASH(requested_rgb_blend), FIELD_HASH(requested_alpha_blend),
|
||||
FIELD_HASH(requested_logic_op),
|
||||
|
||||
// nested layout
|
||||
BlendConfig::StructHash());
|
||||
@ -387,11 +399,6 @@ struct FSConfig {
|
||||
return (stage_index < 4) && ((texture.combiner_buffer_input >> 4) & (1 << stage_index));
|
||||
}
|
||||
|
||||
[[nodiscard]] bool EmulateBlend() const {
|
||||
return framebuffer.rgb_blend.eq != Pica::FramebufferRegs::BlendEquation::Add ||
|
||||
framebuffer.alpha_blend.eq != Pica::FramebufferRegs::BlendEquation::Add;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool UsesSpirvIncompatibleConfig() const {
|
||||
const auto texture0_type = texture.texture0_type.Value();
|
||||
return texture0_type == Pica::TexturingRegs::TextureConfig::ShadowCube ||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user