diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 1378c30efd..4662e531be 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -57,6 +57,37 @@ constexpr std::array TOPOLOGY_CLASS_REPRESENTATIVE_LUT = { Maxwell::PrimitiveTopology::Patches, // Patches }; +bool IsDualSourceBlendFactor(Maxwell::Blend::Factor factor) { + using F = Maxwell::Blend::Factor; + switch (factor) { + case F::Source1Color_D3D: + case F::OneMinusSource1Color_D3D: + case F::Source1Alpha_D3D: + case F::OneMinusSource1Alpha_D3D: + case F::Source1Color_GL: + case F::OneMinusSource1Color_GL: + case F::Source1Alpha_GL: + case F::OneMinusSource1Alpha_GL: + return true; + default: + return false; + } +} + +bool ComputeAttachment0DualSourceBlend(const Maxwell& regs) { + if (!regs.blend.enable[0]) { + return false; + } + const auto uses_dual_source = [](const auto& blend) { + return IsDualSourceBlendFactor(blend.color_source) || + IsDualSourceBlendFactor(blend.color_dest) || + IsDualSourceBlendFactor(blend.alpha_source) || + IsDualSourceBlendFactor(blend.alpha_dest); + }; + return regs.blend_per_target_enabled ? uses_dual_source(regs.blend_per_target[0]) + : uses_dual_source(regs.blend); +} + void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) { std::ranges::transform(regs.transform_feedback.controls, state.layouts.begin(), [](const auto& layout) { @@ -96,6 +127,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe ? TOPOLOGY_CLASS_REPRESENTATIVE_LUT[static_cast(topology_)] : topology_); msaa_mode.Assign(regs.anti_alias_samples_mode); + attachment0_dual_source_blend.Assign(ComputeAttachment0DualSourceBlend(regs) ? 1 : 0); raw2 = 0; diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 0b631a9e89..78a5fef365 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -211,6 +211,8 @@ struct FixedPipelineState { BitField<15, 5, u32> patch_control_points_minus_one; BitField<20, 1, u32> color_write_enable_dynamic; + BitField<21, 1, u32> attachment0_dual_source_blend; + BitField<24, 4, Maxwell::PrimitiveTopology> topology; BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode; }; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 903b97db6a..7fd87b17cd 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -246,32 +246,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span program key.state.UnpackComparisonOp(key.state.alpha_test_func.Value())); info.alpha_test_reference = std::bit_cast(key.state.alpha_test_ref); - // Check for dual source blending - const auto& blend0 = key.state.attachments[0]; - if (blend0.enable != 0) { - using F = Maxwell::Blend::Factor; - const auto src_rgb = blend0.SourceRGBFactor(); - const auto dst_rgb = blend0.DestRGBFactor(); - const auto src_a = blend0.SourceAlphaFactor(); - const auto dst_a = blend0.DestAlphaFactor(); - info.dual_source_blend = - src_rgb == F::Source1Color_D3D || src_rgb == F::OneMinusSource1Color_D3D || - src_rgb == F::Source1Alpha_D3D || src_rgb == F::OneMinusSource1Alpha_D3D || - src_rgb == F::Source1Color_GL || src_rgb == F::OneMinusSource1Color_GL || - src_rgb == F::Source1Alpha_GL || src_rgb == F::OneMinusSource1Alpha_GL || - dst_rgb == F::Source1Color_D3D || dst_rgb == F::OneMinusSource1Color_D3D || - dst_rgb == F::Source1Alpha_D3D || dst_rgb == F::OneMinusSource1Alpha_D3D || - dst_rgb == F::Source1Color_GL || dst_rgb == F::OneMinusSource1Color_GL || - dst_rgb == F::Source1Alpha_GL || dst_rgb == F::OneMinusSource1Alpha_GL || - src_a == F::Source1Color_D3D || src_a == F::OneMinusSource1Color_D3D || - src_a == F::Source1Alpha_D3D || src_a == F::OneMinusSource1Alpha_D3D || - src_a == F::Source1Color_GL || src_a == F::OneMinusSource1Color_GL || - src_a == F::Source1Alpha_GL || src_a == F::OneMinusSource1Alpha_GL || - dst_a == F::Source1Color_D3D || dst_a == F::OneMinusSource1Color_D3D || - dst_a == F::Source1Alpha_D3D || dst_a == F::OneMinusSource1Alpha_D3D || - dst_a == F::Source1Color_GL || dst_a == F::OneMinusSource1Color_GL || - dst_a == F::Source1Alpha_GL || dst_a == F::OneMinusSource1Alpha_GL; - } + info.dual_source_blend = key.state.attachment0_dual_source_blend != 0; if (device.IsMoltenVK()) { for (size_t i = 0; i < 8; ++i) {