diff --git a/src/common/settings.h b/src/common/settings.h index 2bc354aa1..dc4f1e9f1 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -666,4 +666,7 @@ void RestoreGlobalState(bool is_powered_on); bool IsConfiguringGlobal(); void SetConfiguringGlobal(bool is_global); +// Game-specific workarounds +bool use_squashed_iterated_blend{false}; + } // namespace Settings diff --git a/src/core/core.cpp b/src/core/core.cpp index f1fa56851..ab3fd427d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -341,6 +341,17 @@ struct System::Impl { LOG_INFO(Core, "Loading {} ({:016X}) ...", name, params.program_id); + // MARVEL Cosmic Invasion + constexpr u64 marvel_cosmic_invasion = 0x010059D020C26000ULL; + // Ninja Gaiden Ragebound + constexpr u64 ninja_gaiden_ragebound = 0x0100781020710000ULL; + + Settings::values.use_squashed_iterated_blend = false; + if (params.program_id == marvel_cosmic_invasion || params.program_id == ninja_gaiden_ragebound) { + LOG_INFO(Core, "Enabling game specific override: use_squashed_iterated_blend"); + Settings::values.use_squashed_iterated_blend = true; + } + // Make the process created be the application kernel.MakeApplicationProcess(process->GetHandle()); diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 133ab0170..e0cd062f4 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -8,6 +8,7 @@ #include "common/cityhash.h" #include "common/common_types.h" #include "common/polyfill_ranges.h" +#include "common/settings.h" #include "video_core/engines/draw_manager.h" #include "video_core/renderer_vulkan/fixed_pipeline_state.h" #include "video_core/renderer_vulkan/vk_state_tracker.h" @@ -191,6 +192,16 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t }; if (!regs.blend_per_target_enabled) { + if (regs.iterated_blend.enable && Settings::values.use_squashed_iterated_blend) { + equation_rgb.Assign(PackBlendEquation(Maxwell::Blend::Equation::Add_GL)); + equation_a.Assign(PackBlendEquation(Maxwell::Blend::Equation::Add_GL)); + factor_source_rgb.Assign(PackBlendFactor(Maxwell::Blend::Factor::One_GL)); + factor_dest_rgb.Assign(PackBlendFactor(Maxwell::Blend::Factor::One_GL)); + factor_source_a.Assign(PackBlendFactor(Maxwell::Blend::Factor::OneMinusSourceColor_GL)); + factor_dest_a.Assign(PackBlendFactor(Maxwell::Blend::Factor::Zero_GL)); + enable.Assign(1); + return; + } setup_blend(regs.blend); return; } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index fac631fb8..028c9559b 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1472,7 +1472,17 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { host_blend.alphaBlendOp = MaxwellToVK::BlendEquation(guest_blend.alpha_op); }; if (!regs.blend_per_target_enabled) { - blend_setup(regs.blend); + // Workaround for DotEmu engine games (iterated blending) + if (regs.iterated_blend.enable && Settings::values.use_squashed_iterated_blend) { + setup_blends[index].srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + setup_blends[index].dstColorBlendFactor = VK_BLEND_FACTOR_ONE; + setup_blends[index].colorBlendOp = VK_BLEND_OP_ADD; + setup_blends[index].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + setup_blends[index].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + setup_blends[index].alphaBlendOp = VK_BLEND_OP_ADD; + } else { + blend_setup(regs.blend); + } continue; } blend_setup(regs.blend_per_target[index]);