From 7fe842663efec4318853cd83ba02342a551930c6 Mon Sep 17 00:00:00 2001 From: Olivia Lee Date: Tue, 29 Apr 2025 13:34:52 -0700 Subject: [PATCH] pan/bi: push blend constants to FAU This improves blend shader performance slightly over loading the constants from the sysval UBO. On bifrost, we have 128 FAU words, so reserving 4 words for blend constants is not a significant cost. On midgard, register mapped uniforms share space with working registers. With high working register pressure, we only allocate 32 uniform registers, and so would lose 1/8 of available space to blend constants if we implemented the same optimization. This improves gfxbench gl_driver FPS on G610 from 40.48 to 42.39. I did not measure any regressions on benchmarks I tested that did not use blend shaders. Signed-off-by: Olivia Lee Reviewed-by: Mary Guillemard Acked-by: Ryan Mckeever Part-of: --- src/panfrost/compiler/bi_opt_push_ubo.c | 34 +++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/panfrost/compiler/bi_opt_push_ubo.c b/src/panfrost/compiler/bi_opt_push_ubo.c index d024d716ec7..bcd852cc3fb 100644 --- a/src/panfrost/compiler/bi_opt_push_ubo.c +++ b/src/panfrost/compiler/bi_opt_push_ubo.c @@ -84,8 +84,8 @@ bi_analyze_ranges(bi_context *ctx) assert(ubo < res.nr_blocks); assert(channels > 0 && channels <= 4); - /* Blend constants are always loaded from the sysval UBO in blend shaders, - * do not push them. */ + /* Blend constants are handled by bi_pick_blend_constants, don't push + * them a second time. */ if (ctx->stage == MESA_SHADER_FRAGMENT) { /* PAN_UBO_SYSVALS from the gallium driver */ unsigned sysval_ubo = 1; @@ -105,6 +105,34 @@ bi_analyze_ranges(bi_context *ctx) return res; } +/* We always map blend constants from the first slot in the sysval UBO to the + * first four FAU words, so that they can be accessed from a consistent + * location from the blend shader. */ +static void +bi_pick_blend_constants(bi_context *ctx, struct bi_ubo_analysis *analysis) +{ + /* PAN_UBO_SYSVALS from the gallium driver */ + unsigned sysval_ubo = 1; + unsigned offset = 0; + + assert(ctx->inputs->pushable_ubos & BITFIELD_BIT(sysval_ubo)); + assert(ctx->info.push->count == 0); + + for (unsigned channel = 0; channel < 4; channel++) { + struct panfrost_ubo_word word = { + .ubo = sysval_ubo, + .offset = offset + channel * 4, + }; + ctx->info.push->words[ctx->info.push->count++] = word; + assert(ctx->info.push->count < PAN_MAX_PUSH); + } + + BITSET_SET(analysis->blocks[sysval_ubo].pushed, offset); + + /* The blend constant FAU slots cannot be reordered */ + ctx->info.push_offset = MAX2(ctx->info.push_offset, ctx->info.push->count); +} + /* Select UBO words to push. A sophisticated implementation would consider the * number of uses and perhaps the control flow to estimate benefit. This is not * sophisticated. Select from the last UBO first to prioritize sysvals. */ @@ -146,6 +174,8 @@ bi_opt_push_ubo(bi_context *ctx) { struct bi_ubo_analysis analysis = bi_analyze_ranges(ctx); + if (ctx->stage == MESA_SHADER_FRAGMENT) + bi_pick_blend_constants(ctx, &analysis); bi_pick_ubo(ctx->info.push, &analysis); ctx->ubo_mask = 0;