[Vulkan]: Implement iterated blend workaround for DotEmu Games

This commit is contained in:
liberodark 2025-12-07 21:02:29 +01:00
parent 5284cd8b29
commit 04f477574f
4 changed files with 36 additions and 1 deletions

View file

@ -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

View file

@ -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());

View file

@ -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;
}

View file

@ -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]);