diff --git a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp index e0479cce8..aeb66efd2 100644 --- a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp @@ -761,10 +761,7 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline( case ShaderAlphaBlendSource::SourceAlpha: blend.color_srcblend = RemapSourceAlphaFactor(blend.color_srcblend); blend.color_destblend = RemapSourceAlphaFactor(blend.color_destblend); - if (blend.separate_alpha_blend) { - blend.alpha_srcblend = RemapSourceAlphaFactor(blend.alpha_srcblend); - blend.alpha_destblend = RemapSourceAlphaFactor(blend.alpha_destblend); - } + blend.separate_alpha_blend = false; break; case ShaderAlphaBlendSource::SourceAlphaOne: // The second source carries the mapped source factor; its alpha stays logical Sa. diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index b7f01de4b..8e51b7c11 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -15860,24 +15860,43 @@ public: alpha_blend.alpha_srcblend = static_cast(Prospero::BlendFactor::kOne); alpha_blend.color_destblend = alpha_blend.alpha_destblend = static_cast(Prospero::BlendFactor::kOneMinusSrcAlpha); - for (const bool separate : {false, true}) { - alpha_blend.separate_alpha_blend = separate; + struct AlphaBlendCase { + bool separate; + Prospero::BlendFactor alpha_source; + ShaderAlphaBlendSource mode; + float alpha; + }; + uint64_t broadcast_program = 0; + vk::Pipeline broadcast_pipeline{}; + for (const auto test : { + AlphaBlendCase{false, Prospero::BlendFactor::kOne, ShaderAlphaBlendSource::SourceAlpha, 0.4f}, + AlphaBlendCase{true, Prospero::BlendFactor::kSrcAlpha, ShaderAlphaBlendSource::SourceAlpha, 0.4f}, + AlphaBlendCase{true, Prospero::BlendFactor::kOne, ShaderAlphaBlendSource::SourceAlphaOne, 0.65f}}) { + alpha_blend.separate_alpha_blend = test.separate; + alpha_blend.alpha_srcblend = static_cast(test.alpha_source); registers.SetBlendControl(0, alpha_blend); const auto programs = context.GetPipelineCache().GetGraphicsPrograms( native_vertex_regs, native_pixel_regs, registers.GetShaderRegisters(), registers, user_config, export_mapping, true, native_vertex_info, pixel); - const auto mode = separate ? ShaderAlphaBlendSource::SourceAlphaOne - : ShaderAlphaBlendSource::SourceAlpha; - Require(name, "logical alpha blend program", pixel.alpha_blend_source == mode && + Require(name, "logical alpha blend program", pixel.alpha_blend_source == test.mode && pixel.dual_source_blending, "the separate alpha equation did not reach the compiled pixel program"); vertex_shader = programs.vertex[0]; pixel_shader = programs.pixel; vertex = native_vertex_info[0]; + auto &selected = pipeline(true, 2, 2); + if (test.mode == ShaderAlphaBlendSource::SourceAlpha) { + Require(name, "equal blend equation cache reuse", + broadcast_program == 0 || (programs.pixel.id == broadcast_program && + selected.pipeline == broadcast_pipeline), + "equivalent separate alpha state created another shader or pipeline"); + broadcast_program = programs.pixel.id; + broadcast_pipeline = selected.pipeline; + } constexpr std::array destination{0.3f, 0.3f, 0.1f, 0.2f}; - draw(pipeline(true, 2, 2), 3, std::bit_cast>(destination)); + draw(selected, 3, std::bit_cast>(destination)); const auto blend_pixels = read_color(); - const std::array expected{separate ? 0.65f : 0.4f, 0.35f, 0.35f, 0.5f}; + const std::array expected{test.alpha, 0.35f, 0.35f, 0.5f}; for (size_t component = 0; component < blend_pixels.size(); component++) { Require(name, "logical alpha blend readback", std::abs(std::bit_cast(blend_pixels[component]) - diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index b959c1091..0002dc3be 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -12859,6 +12859,10 @@ void TestBlendMappingClassification() { static_cast(Factor::kOneMinusSrcAlpha); Check(classify(Prospero::ColorMappingAbgr) == Support::SourceAlphaOne, "separate alpha accumulation did not preserve its unit source factor"); + blend.alpha_srcblend = blend.color_srcblend; + Check(classify(Prospero::ColorMappingAbgr) == Support::SourceAlpha, + "equal separate alpha equations did not reuse the broadcast alpha mode"); + blend.alpha_srcblend = static_cast(Factor::kOne); const auto exact = blend; for (uint32_t changed = 0; changed < 6; changed++) { blend = exact;