gpu: share pipelines when color and alpha blend equations match

This commit is contained in:
nmzik
2026-10-04 22:29:05 +04:00
parent f7bd0b436a
commit 96011cc5c9
3 changed files with 31 additions and 11 deletions
@@ -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.
+26 -7
View File
@@ -15860,24 +15860,43 @@ public:
alpha_blend.alpha_srcblend = static_cast<uint8_t>(Prospero::BlendFactor::kOne);
alpha_blend.color_destblend = alpha_blend.alpha_destblend =
static_cast<uint8_t>(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<uint8_t>(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<float, 4> destination{0.3f, 0.3f, 0.1f, 0.2f};
draw(pipeline(true, 2, 2), 3, std::bit_cast<std::array<u32, 4>>(destination));
draw(selected, 3, std::bit_cast<std::array<u32, 4>>(destination));
const auto blend_pixels = read_color();
const std::array<float, 4> expected{separate ? 0.65f : 0.4f, 0.35f, 0.35f, 0.5f};
const std::array<float, 4> 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<float>(blend_pixels[component]) -
+4
View File
@@ -12859,6 +12859,10 @@ void TestBlendMappingClassification() {
static_cast<uint8_t>(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<uint8_t>(Factor::kOne);
const auto exact = blend;
for (uint32_t changed = 0; changed < 6; changed++) {
blend = exact;