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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24831>
This commit is contained in:
Mike Blumenkrantz 2023-08-22 12:43:00 -04:00 committed by Marge Bot
parent dae144aeac
commit fbf3f64c6d
3 changed files with 20 additions and 4 deletions

View file

@ -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;

View file

@ -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

View file

@ -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) {