From fbf3f64c6dd47978578ea833b4afcdcc9502a3d8 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 22 Aug 2023 12:43:00 -0400 Subject: [PATCH] zink: sanitize optimal keys shader keys represent pipeline states which trigger variants, but not all shaders are affected by certain states this adds some sanitizing for the optimal path to ignore shader variants which won't have any effect for the currently bound shaders, thus reducing the number of pipelines compiled (both unoptimized and optimized) Part-of: --- src/gallium/drivers/zink/zink_program.c | 4 ++-- src/gallium/drivers/zink/zink_program.h | 15 +++++++++++++++ src/gallium/drivers/zink/zink_program_state.hpp | 5 +++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index 44abd6cbae0..a6c2549c5a7 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -714,7 +714,7 @@ zink_gfx_program_update_optimal(struct zink_context *ctx) struct zink_screen *screen = zink_screen(ctx->base.screen); if (ctx->gfx_dirty) { struct zink_gfx_program *prog = NULL; - ctx->gfx_pipeline_state.optimal_key = ctx->gfx_pipeline_state.shader_keys_optimal.key.val; + ctx->gfx_pipeline_state.optimal_key = zink_sanitize_optimal_key(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val); struct hash_table *ht = &ctx->program_cache[zink_program_cache_stages(ctx->shader_stages)]; const uint32_t hash = ctx->gfx_hash; simple_mtx_lock(&ctx->program_lock[zink_program_cache_stages(ctx->shader_stages)]); @@ -752,7 +752,7 @@ zink_gfx_program_update_optimal(struct zink_context *ctx) ctx->gfx_pipeline_state.final_hash ^= ctx->curr_program->last_variant_hash; } else if (ctx->dirty_gfx_stages) { /* remove old hash */ - ctx->gfx_pipeline_state.optimal_key = ctx->gfx_pipeline_state.shader_keys_optimal.key.val; + ctx->gfx_pipeline_state.optimal_key = zink_sanitize_optimal_key(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val); ctx->gfx_pipeline_state.final_hash ^= ctx->curr_program->last_variant_hash; if (ctx->curr_program->is_separable && !(zink_debug & ZINK_DEBUG_NOOPT)) { struct zink_gfx_program *prog = ctx->curr_program; diff --git a/src/gallium/drivers/zink/zink_program.h b/src/gallium/drivers/zink/zink_program.h index b8142cce066..8df5e3388ab 100644 --- a/src/gallium/drivers/zink/zink_program.h +++ b/src/gallium/drivers/zink/zink_program.h @@ -428,6 +428,21 @@ zink_driver_thread_add_job(struct pipe_screen *pscreen, void *data, const size_t job_size); equals_gfx_pipeline_state_func zink_get_gfx_pipeline_eq_func(struct zink_screen *screen, struct zink_gfx_program *prog); + +static inline uint32_t +zink_sanitize_optimal_key(struct zink_shader **shaders, uint32_t val) +{ + union zink_shader_key_optimal k; + if (shaders[MESA_SHADER_TESS_EVAL] && !shaders[MESA_SHADER_TESS_CTRL]) + k.val = val; + else + k.val = zink_shader_key_optimal_no_tcs(val); + if (!(shaders[MESA_SHADER_FRAGMENT]->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK))) + k.fs.samples = false; + if (!(shaders[MESA_SHADER_FRAGMENT]->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DATA1))) + k.fs.force_dual_color_blend = false; + return k.val; +} #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/zink/zink_program_state.hpp b/src/gallium/drivers/zink/zink_program_state.hpp index 0c6c85a95a4..bdf3a872a89 100644 --- a/src/gallium/drivers/zink/zink_program_state.hpp +++ b/src/gallium/drivers/zink/zink_program_state.hpp @@ -128,8 +128,9 @@ zink_get_gfx_pipeline(struct zink_context *ctx, /* extra safety asserts for optimal path to catch refactoring bugs */ if (prog->optimal_keys) { ASSERTED const union zink_shader_key_optimal *opt = (union zink_shader_key_optimal*)&prog->last_variant_hash; - assert(opt->val == state->shader_keys_optimal.key.val); - assert(state->optimal_key == state->shader_keys_optimal.key.val); + ASSERTED uint32_t sanitized = zink_sanitize_optimal_key(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val); + assert(opt->val == sanitized); + assert(state->optimal_key == sanitized); } /* recalc vertex state if missing optimal extensions */ if (DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 && DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT && ctx->vertex_state_changed) {