From 19fbdb9064efecd245b084ffe5a61564f7f20adc Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 1 Sep 2021 15:44:34 -0400 Subject: [PATCH] zink: move shader keys to be persistent on pipeline state save a cycle or two zeroing and populating this on every recalc Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_compiler.c | 2 +- src/gallium/drivers/zink/zink_compiler.h | 2 +- src/gallium/drivers/zink/zink_context.c | 51 ++++++-- src/gallium/drivers/zink/zink_context.h | 2 +- src/gallium/drivers/zink/zink_draw.cpp | 20 ++-- src/gallium/drivers/zink/zink_framebuffer.c | 4 +- src/gallium/drivers/zink/zink_pipeline.h | 10 +- src/gallium/drivers/zink/zink_program.c | 177 ++++++++-------------------- src/gallium/drivers/zink/zink_program.h | 53 +++++++++ src/gallium/drivers/zink/zink_shader_keys.h | 3 +- src/gallium/drivers/zink/zink_state.c | 61 ++++++++-- 11 files changed, 215 insertions(+), 170 deletions(-) diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 39cd814..dd8c531 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -782,7 +782,7 @@ zink_compiler_assign_io(nir_shader *producer, nir_shader *consumer) } VkShaderModule -zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *base_nir, struct zink_shader_key *key) +zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *base_nir, const struct zink_shader_key *key) { VkShaderModule mod = VK_NULL_HANDLE; void *streamout = NULL; diff --git a/src/gallium/drivers/zink/zink_compiler.h b/src/gallium/drivers/zink/zink_compiler.h index b9e7321..270bf12 100644 --- a/src/gallium/drivers/zink/zink_compiler.h +++ b/src/gallium/drivers/zink/zink_compiler.h @@ -99,7 +99,7 @@ zink_screen_init_compiler(struct zink_screen *screen); void zink_compiler_assign_io(nir_shader *producer, nir_shader *consumer); VkShaderModule -zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *nir, struct zink_shader_key *key); +zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *nir, const struct zink_shader_key *key); struct zink_shader * zink_shader_create(struct zink_screen *screen, struct nir_shader *nir, diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 0df1870..1d98bcb 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -1000,12 +1000,22 @@ zink_set_inlinable_constants(struct pipe_context *pctx, { struct zink_context *ctx = (struct zink_context *)pctx; const uint32_t bit = BITFIELD_BIT(shader); + uint32_t *inlinable_uniforms; + struct zink_shader_key *key = NULL; + if (shader == PIPE_SHADER_COMPUTE) { + inlinable_uniforms = ctx->compute_inlinable_uniforms; + } else { + key = &ctx->gfx_pipeline_state.shader_keys.key[shader]; + inlinable_uniforms = key->base.inlined_uniform_values; + } if (!(ctx->inlinable_uniforms_valid_mask & bit) || - memcmp(ctx->inlinable_uniforms[shader], values, num_values * 4)) { - memcpy(ctx->inlinable_uniforms[shader], values, num_values * 4); + memcmp(inlinable_uniforms, values, num_values * 4)) { + memcpy(inlinable_uniforms, values, num_values * 4); ctx->dirty_shader_stages |= bit; ctx->inlinable_uniforms_valid_mask |= bit; + if (key) + key->inline_uniforms = true; } } @@ -1020,6 +1030,21 @@ unbind_ubo(struct zink_context *ctx, struct zink_resource *res, enum pipe_shader } static void +invalidate_inlined_uniforms(struct zink_context *ctx, enum pipe_shader_type pstage) +{ + unsigned bit = BITFIELD_BIT(pstage); + if (!(ctx->inlinable_uniforms_valid_mask & bit)) + return; + ctx->inlinable_uniforms_valid_mask &= ~bit; + ctx->dirty_shader_stages |= bit; + if (pstage == PIPE_SHADER_COMPUTE) + return; + + struct zink_shader_key *key = &ctx->gfx_pipeline_state.shader_keys.key[pstage]; + key->inline_uniforms = false; +} + +static void zink_set_constant_buffer(struct pipe_context *pctx, enum pipe_shader_type shader, uint index, bool take_ownership, @@ -1086,7 +1111,7 @@ zink_set_constant_buffer(struct pipe_context *pctx, } if (index == 0) { /* Invalidate current inlinable uniforms. */ - ctx->inlinable_uniforms_valid_mask &= ~(1 << shader); + invalidate_inlined_uniforms(ctx, shader); } if (update) @@ -2066,7 +2091,6 @@ zink_set_framebuffer_state(struct pipe_context *pctx, ctx->scissor_changed = true; rebind_fb_state(ctx, NULL, true); ctx->fb_state.samples = util_framebuffer_get_num_samples(state); - uint8_t rast_samples = ctx->fb_state.samples - 1; /* get_framebuffer adds a ref if the fb is reused or created; * always do get_framebuffer first to avoid deleting the same fb * we're about to use @@ -2095,9 +2119,16 @@ zink_set_framebuffer_state(struct pipe_context *pctx, ctx->fb_changed |= ctx->framebuffer != fb; ctx->framebuffer = fb; - /* in vulkan, gl_SampleMask needs to be explicitly ignored for sampleCount == 1 */ - if ((ctx->gfx_pipeline_state.rast_samples > 0) != (rast_samples > 0)) - ctx->dirty_shader_stages |= 1 << PIPE_SHADER_FRAGMENT; + uint8_t rast_samples = ctx->fb_state.samples - 1; + /* update the shader key if applicable: + * if gl_SampleMask[] is written to, we have to ensure that we get a shader with the same sample count: + * in GL, rast_samples==1 means ignore gl_SampleMask[] + * in VK, gl_SampleMask[] is never ignored + */ + if (rast_samples != ctx->gfx_pipeline_state.rast_samples && + (!ctx->gfx_stages[PIPE_SHADER_FRAGMENT] || + ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK))) + zink_set_fs_key(ctx)->samples = ctx->fb_state.samples > 0; if (ctx->gfx_pipeline_state.rast_samples != rast_samples) { ctx->sample_locations_changed |= ctx->gfx_pipeline_state.sample_locations_enabled; ctx->gfx_pipeline_state.dirty = true; @@ -3646,6 +3677,12 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) if (!ctx->blitter) goto fail; + ctx->gfx_pipeline_state.shader_keys.last_vertex.key.vs_base.last_vertex_stage = true; + ctx->last_vertex_stage_dirty = true; + ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX].size = sizeof(struct zink_vs_key_base); + ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_TESS_EVAL].size = sizeof(struct zink_vs_key_base); + ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_GEOMETRY].size = sizeof(struct zink_vs_key_base); + ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT].size = sizeof(struct zink_fs_key); _mesa_hash_table_init(&ctx->compute_program_cache, ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); _mesa_hash_table_init(&ctx->framebuffer_cache, ctx, hash_framebuffer_imageless, equals_framebuffer_imageless); _mesa_set_init(&ctx->render_pass_state_cache, ctx, hash_rp_state, equals_rp_state); diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index d53b99d..abfe019 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -193,7 +193,7 @@ struct zink_context { unsigned shader_has_inlinable_uniforms_mask; unsigned inlinable_uniforms_valid_mask; - uint32_t inlinable_uniforms[PIPE_SHADER_TYPES][MAX_INLINABLE_UNIFORMS]; + uint32_t compute_inlinable_uniforms[MAX_INLINABLE_UNIFORMS]; struct pipe_constant_buffer ubos[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; struct pipe_shader_buffer ssbos[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index 1895cd3..fde0363 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -179,6 +179,9 @@ update_gfx_program(struct zink_context *ctx) if (ctx->last_vertex_stage_dirty) { enum pipe_shader_type pstage = pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage); ctx->dirty_shader_stages |= BITFIELD_BIT(pstage); + memcpy(&ctx->gfx_pipeline_state.shader_keys.key[pstage].key.vs_base, + &ctx->gfx_pipeline_state.shader_keys.last_vertex.key.vs_base, + sizeof(struct zink_vs_key_base)); ctx->last_vertex_stage_dirty = false; } unsigned bits = BITFIELD_MASK(PIPE_SHADER_COMPUTE); @@ -489,14 +492,13 @@ zink_draw_vbo(struct pipe_context *pctx, uint8_t vertices_per_patch = ctx->gfx_pipeline_state.patch_vertices ? ctx->gfx_pipeline_state.patch_vertices - 1 : 0; if (ctx->gfx_pipeline_state.vertices_per_patch != vertices_per_patch) ctx->gfx_pipeline_state.dirty = true; - bool drawid_broken = ctx->gfx_pipeline_state.drawid_broken; - ctx->gfx_pipeline_state.drawid_broken = false; + bool drawid_broken = false; if (reads_drawid && (!dindirect || !dindirect->buffer)) - ctx->gfx_pipeline_state.drawid_broken = (drawid_offset != 0 || - (!HAS_MULTIDRAW && num_draws > 1) || - (HAS_MULTIDRAW && num_draws > 1 && !dinfo->increment_draw_id)); - if (drawid_broken != ctx->gfx_pipeline_state.drawid_broken) - ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX); + drawid_broken = (drawid_offset != 0 || + (!HAS_MULTIDRAW && num_draws > 1) || + (HAS_MULTIDRAW && num_draws > 1 && !dinfo->increment_draw_id)); + if (drawid_broken != zink_get_last_vertex_key(ctx)->push_drawid) + zink_set_last_vertex_key(ctx)->push_drawid = drawid_broken; ctx->gfx_pipeline_state.vertices_per_patch = vertices_per_patch; if (mode_changed) { bool points_changed = false; @@ -508,7 +510,7 @@ zink_draw_vbo(struct pipe_context *pctx, points_changed = true; } if (points_changed && ctx->rast_state->base.point_quad_rasterization) - ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT); + zink_set_fs_point_coord_key(ctx); } ctx->gfx_pipeline_state.gfx_prim_mode = mode; @@ -762,7 +764,7 @@ zink_draw_vbo(struct pipe_context *pctx, VKCTX(CmdBeginTransformFeedbackEXT)(batch->state->cmdbuf, 0, ctx->num_so_targets, counter_buffers, counter_buffer_offsets); } - bool needs_drawid = reads_drawid && ctx->gfx_pipeline_state.drawid_broken; + bool needs_drawid = reads_drawid && zink_get_last_vertex_key(ctx)->push_drawid; work_count += num_draws; if (index_size > 0) { if (dindirect && dindirect->buffer) { diff --git a/src/gallium/drivers/zink/zink_framebuffer.c b/src/gallium/drivers/zink/zink_framebuffer.c index 3d0f1ed..ef785c5 100644 --- a/src/gallium/drivers/zink/zink_framebuffer.c +++ b/src/gallium/drivers/zink/zink_framebuffer.c @@ -160,7 +160,7 @@ zink_get_framebuffer_imageless(struct zink_context *ctx) state.width = MAX2(ctx->fb_state.width, 1); state.height = MAX2(ctx->fb_state.height, 1); state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1; - state.samples = ctx->gfx_pipeline_state.rast_samples; + state.samples = ctx->fb_state.samples - 1; struct zink_framebuffer *fb; struct hash_entry *entry = _mesa_hash_table_search(&ctx->framebuffer_cache, &state); @@ -289,7 +289,7 @@ zink_get_framebuffer(struct zink_context *ctx) state.width = MAX2(ctx->fb_state.width, 1); state.height = MAX2(ctx->fb_state.height, 1); state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1) - 1; - state.samples = ctx->gfx_pipeline_state.rast_samples; + state.samples = ctx->fb_state.samples - 1; struct zink_framebuffer *fb; simple_mtx_lock(&screen->framebuffer_mtx); diff --git a/src/gallium/drivers/zink/zink_pipeline.h b/src/gallium/drivers/zink/zink_pipeline.h index d79f50b..4acc6c4 100644 --- a/src/gallium/drivers/zink/zink_pipeline.h +++ b/src/gallium/drivers/zink/zink_pipeline.h @@ -27,6 +27,7 @@ #include #include "pipe/p_state.h" +#include "zink_shader_keys.h" #include "zink_state.h" struct zink_blend_state; @@ -75,11 +76,10 @@ struct zink_gfx_pipeline_state { bool have_EXT_extended_dynamic_state; bool have_EXT_extended_dynamic_state2; uint8_t has_points; //either gs outputs points or prim type is points - uint8_t coord_replace_bits; - bool coord_replace_yinvert; - bool drawid_broken; - uint32_t decomposed_attrs; - uint32_t decomposed_attrs_without_w; + struct { + struct zink_shader_key key[5]; + struct zink_shader_key last_vertex; + } shader_keys; struct zink_blend_state *blend_state; struct zink_render_pass *render_pass; VkPipeline pipeline; diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index 8d75ad8..a79cb5b 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -69,17 +69,15 @@ debug_describe_zink_compute_program(char *buf, const struct zink_compute_program /* copied from iris */ struct keybox { uint16_t size; - gl_shader_stage stage; uint8_t data[0]; }; static struct keybox * -make_keybox(void *mem_ctx, gl_shader_stage stage, const void *key, uint32_t key_size, void *base, uint32_t base_size) +make_keybox(void *mem_ctx, const void *key, uint32_t key_size, const void *base, uint32_t base_size) { struct keybox *keybox = ralloc_size(mem_ctx, sizeof(struct keybox) + key_size + base_size); - keybox->stage = stage; keybox->size = key_size + base_size; memcpy(keybox->data, key, key_size); if (base_size) @@ -91,7 +89,7 @@ static uint32_t keybox_hash(const void *void_key) { const struct keybox *key = void_key; - return _mesa_hash_data(&key->stage, key->size + sizeof(key->stage)); + return _mesa_hash_data(&key->data, key->size); } static bool @@ -104,81 +102,9 @@ keybox_equals(const void *void_a, const void *void_b) return memcmp(a->data, b->data, a->size) == 0; } -static void -shader_key_vs_gen(struct zink_screen *screen, struct zink_shader *zs, - struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key, - const struct zink_gfx_pipeline_state *state) -{ - struct zink_vs_key_base *vs_key = &key->key.vs_base; - const struct zink_rasterizer_hw_state *rast_state = (void*)state; - key->size = sizeof(struct zink_vs_key_base); - - vs_key->clip_halfz = rast_state->clip_halfz; - switch (zs->nir->info.stage) { - case MESA_SHADER_VERTEX: - vs_key->last_vertex_stage = !shaders[PIPE_SHADER_TESS_EVAL] && !shaders[PIPE_SHADER_GEOMETRY]; - vs_key->push_drawid = state->drawid_broken; - break; - case MESA_SHADER_TESS_EVAL: - vs_key->last_vertex_stage = !shaders[PIPE_SHADER_GEOMETRY]; - break; - case MESA_SHADER_GEOMETRY: - vs_key->last_vertex_stage = true; - break; - default: - unreachable("impossible case"); - } -} - -static void -shader_key_fs_gen(struct zink_screen *screen, struct zink_shader *zs, - struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key, - const struct zink_gfx_pipeline_state *state) -{ - struct zink_fs_key *fs_key = &key->key.fs; - key->size = sizeof(struct zink_fs_key); - - /* if gl_SampleMask[] is written to, we have to ensure that we get a shader with the same sample count: - * in GL, rast_samples==1 means ignore gl_SampleMask[] - * in VK, gl_SampleMask[] is never ignored - */ - if (zs->nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK)) - fs_key->samples = state->render_pass->state.samples; - fs_key->force_dual_color_blend = screen->driconf.dual_color_blend_by_location && - state->blend_state && - state->blend_state->dual_src_blend && - state->blend_state->attachments[1].blendEnable; - if (state->has_points && state->coord_replace_bits) { - fs_key->coord_replace_bits = state->coord_replace_bits; - fs_key->coord_replace_yinvert = state->coord_replace_yinvert; - } -} - -static void -shader_key_tcs_gen(struct zink_screen *screen, struct zink_shader *zs, - struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key, - const struct zink_gfx_pipeline_state *state) -{ - key->size = 0; -} - -typedef void (*zink_shader_key_gen)(struct zink_screen *screen, struct zink_shader *zs, - struct zink_shader *shaders[ZINK_SHADER_COUNT], - struct zink_shader_key *key, - const struct zink_gfx_pipeline_state *state); -static zink_shader_key_gen shader_key_vtbl[] = -{ - [MESA_SHADER_VERTEX] = shader_key_vs_gen, - [MESA_SHADER_TESS_CTRL] = shader_key_tcs_gen, - /* reusing vs key for now since we're only using clip_halfz */ - [MESA_SHADER_TESS_EVAL] = shader_key_vs_gen, - [MESA_SHADER_GEOMETRY] = shader_key_vs_gen, - [MESA_SHADER_FRAGMENT] = shader_key_fs_gen, -}; - /* return pointer to make function reusable */ static inline struct zink_shader_module ** -get_default_shader_module_ptr(struct zink_gfx_program *prog, struct zink_shader *zs, struct zink_shader_key *key) +get_default_shader_module_ptr(struct zink_gfx_program *prog, struct zink_shader *zs, const struct zink_shader_key *key) { if (zs->nir->info.stage == MESA_SHADER_VERTEX || zs->nir->info.stage == MESA_SHADER_TESS_EVAL) { @@ -196,60 +122,36 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen { gl_shader_stage stage = zs->nir->info.stage; enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage); - struct zink_shader_key key = {0}; VkShaderModule mod; struct zink_shader_module *zm; struct zink_shader_module **default_zm = NULL; struct keybox *keybox; uint32_t hash; unsigned base_size = 0; + bool is_default_variant; + const struct zink_shader_key *key = &state->shader_keys.key[pstage]; - shader_key_vtbl[stage](screen, zs, prog->shaders, &key, state); - if (ctx && stage == MESA_SHADER_VERTEX) { - unsigned size = MAX2(ctx->element_state->decomposed_attrs_size, ctx->element_state->decomposed_attrs_without_w_size); - switch (size) { - case 1: - key.key.vs.u8.decomposed_attrs = ctx->element_state->decomposed_attrs; - key.key.vs.u8.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w; - break; - case 2: - key.key.vs.u16.decomposed_attrs = ctx->element_state->decomposed_attrs; - key.key.vs.u16.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w; - break; - case 4: - key.key.vs.u32.decomposed_attrs = ctx->element_state->decomposed_attrs; - key.key.vs.u32.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w; - break; - default: break; - } - key.key.vs.size = size; - key.size += 2 * size; - } /* this is default variant if there is no default or it matches the default */ if (pstage != PIPE_SHADER_TESS_CTRL && prog->default_variant_key[pstage]) { const struct keybox *tmp = prog->default_variant_key[pstage]; /* if comparing against the existing default, use the base variant key size since * we're only checking the stage-specific data */ - key.is_default_variant = tmp->size == key.size && !memcmp(tmp->data, &key, key.size); + is_default_variant = tmp->size == key->size && !memcmp(tmp->data, &key, key->size); } else - key.is_default_variant = true; + is_default_variant = true; if (ctx && zs->nir->info.num_inlinable_uniforms && ctx->inlinable_uniforms_valid_mask & BITFIELD64_BIT(pstage)) { - key.inline_uniforms = true; - memcpy(key.base.inlined_uniform_values, - ctx->inlinable_uniforms[pstage], - zs->nir->info.num_inlinable_uniforms * 4); base_size = zs->nir->info.num_inlinable_uniforms * sizeof(uint32_t); - key.is_default_variant = false; + is_default_variant = false; } - if (key.is_default_variant) { - default_zm = get_default_shader_module_ptr(prog, zs, &key); + if (is_default_variant) { + default_zm = get_default_shader_module_ptr(prog, zs, key); if (*default_zm) return *default_zm; } - keybox = make_keybox(prog, stage, &key, key.size, &key.base, base_size); + keybox = make_keybox(prog, key, key->size, &key->base, base_size); hash = keybox_hash(keybox); struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(&prog->base.shader_cache[pstage], hash, keybox); @@ -264,7 +166,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen return NULL; } zm->hash = hash; - mod = zink_shader_compile(screen, zs, prog->nir[stage], &key); + mod = zink_shader_compile(screen, zs, prog->nir[stage], key); if (!mod) { ralloc_free(keybox); FREE(zm); @@ -273,7 +175,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen zm->shader = mod; _mesa_hash_table_insert_pre_hashed(&prog->base.shader_cache[pstage], hash, keybox, zm); - if (key.is_default_variant) { + if (is_default_variant) { /* previously returned */ *default_zm = zm; zm->default_variant = true; @@ -955,15 +857,34 @@ bind_stage(struct zink_context *ctx, enum pipe_shader_type stage, } static void +bind_last_vertex_stage(struct zink_context *ctx) +{ + enum pipe_shader_type old = ctx->last_vertex_stage ? pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage) : PIPE_SHADER_TYPES; + if (ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) + ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; + else if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) + ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]; + else + ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX]; + enum pipe_shader_type current = ctx->last_vertex_stage ? pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage) : PIPE_SHADER_VERTEX; + if (old != current) { + if (old != PIPE_SHADER_TYPES) { + memset(&ctx->gfx_pipeline_state.shader_keys.key[old].key.vs_base, 0, sizeof(struct zink_vs_key_base)); + ctx->dirty_shader_stages |= BITFIELD_BIT(old); + } + ctx->last_vertex_stage_dirty = true; + } +} + +static void zink_bind_vs_state(struct pipe_context *pctx, void *cso) { struct zink_context *ctx = zink_context(pctx); + if (!cso && !ctx->gfx_stages[PIPE_SHADER_VERTEX]) + return; + void *prev = ctx->gfx_stages[PIPE_SHADER_VERTEX]; bind_stage(ctx, PIPE_SHADER_VERTEX, cso); - if (!ctx->gfx_stages[PIPE_SHADER_GEOMETRY] && - !ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) { - ctx->last_vertex_stage = cso; - } if (cso) { struct zink_shader *zs = cso; ctx->shader_reads_drawid = BITSET_TEST(zs->nir->info.system_values_read, SYSTEM_VALUE_DRAW_ID); @@ -972,6 +893,9 @@ zink_bind_vs_state(struct pipe_context *pctx, ctx->shader_reads_drawid = false; ctx->shader_reads_basevertex = false; } + if (ctx->last_vertex_stage == prev) + ctx->last_vertex_stage = cso; + } static void @@ -979,6 +903,8 @@ zink_bind_fs_state(struct pipe_context *pctx, void *cso) { struct zink_context *ctx = zink_context(pctx); + if (!cso && !ctx->gfx_stages[PIPE_SHADER_FRAGMENT]) + return; bind_stage(ctx, PIPE_SHADER_FRAGMENT, cso); ctx->fbfetch_outputs = 0; if (cso) { @@ -998,20 +924,15 @@ zink_bind_gs_state(struct pipe_context *pctx, void *cso) { struct zink_context *ctx = zink_context(pctx); + if (!cso && !ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) + return; bool had_points = ctx->gfx_stages[PIPE_SHADER_GEOMETRY] ? ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->nir->info.gs.output_primitive == GL_POINTS : false; - if (!!ctx->gfx_stages[PIPE_SHADER_GEOMETRY] != !!cso) - ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX) | - BITFIELD_BIT(PIPE_SHADER_TESS_EVAL); bind_stage(ctx, PIPE_SHADER_GEOMETRY, cso); + bind_last_vertex_stage(ctx); if (cso) { - ctx->last_vertex_stage = cso; if (!had_points && ctx->last_vertex_stage->nir->info.gs.output_primitive == GL_POINTS) ctx->gfx_pipeline_state.has_points++; } else { - if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) - ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]; - else - ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX]; if (had_points) ctx->gfx_pipeline_state.has_points--; } @@ -1029,21 +950,17 @@ zink_bind_tes_state(struct pipe_context *pctx, void *cso) { struct zink_context *ctx = zink_context(pctx); + if (!cso && !ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) + return; if (!!ctx->gfx_stages[PIPE_SHADER_TESS_EVAL] != !!cso) { if (!cso) { /* if unsetting a TESS that uses a generated TCS, ensure the TCS is unset */ if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]->generated) ctx->gfx_stages[PIPE_SHADER_TESS_CTRL] = NULL; } - ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX); } bind_stage(ctx, PIPE_SHADER_TESS_EVAL, cso); - if (!ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) { - if (cso) - ctx->last_vertex_stage = cso; - else - ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX]; - } + bind_last_vertex_stage(ctx); } static void * diff --git a/src/gallium/drivers/zink/zink_program.h b/src/gallium/drivers/zink/zink_program.h index b0b586b..3ccbaa2 100644 --- a/src/gallium/drivers/zink/zink_program.h +++ b/src/gallium/drivers/zink/zink_program.h @@ -278,6 +278,59 @@ zink_program_has_descriptors(const struct zink_program *pg) { return pg->num_dsl > 0; } + +static inline struct zink_fs_key * +zink_set_fs_key(struct zink_context *ctx) +{ + ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT); + return (struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT]; +} + +static inline const struct zink_fs_key * +zink_get_fs_key(struct zink_context *ctx) +{ + return (const struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT]; +} + +static inline struct zink_vs_key * +zink_set_vs_key(struct zink_context *ctx) +{ + ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX); + return (struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX]; +} + +static inline const struct zink_vs_key * +zink_get_vs_key(struct zink_context *ctx) +{ + return (const struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX]; +} + +static inline struct zink_vs_key_base * +zink_set_last_vertex_key(struct zink_context *ctx) +{ + ctx->last_vertex_stage_dirty = true; + return (struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex; +} + +static inline const struct zink_vs_key_base * +zink_get_last_vertex_key(struct zink_context *ctx) +{ + return (const struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex; +} + +static inline void +zink_set_fs_point_coord_key(struct zink_context *ctx) +{ + const struct zink_fs_key *fs = zink_get_fs_key(ctx); + bool disable = !ctx->gfx_pipeline_state.has_points || !ctx->rast_state->base.sprite_coord_enable; + uint8_t coord_replace_bits = disable ? 0 : ctx->rast_state->base.sprite_coord_enable; + bool coord_replace_yinvert = disable ? false : !!ctx->rast_state->base.sprite_coord_mode; + if (fs->coord_replace_bits != coord_replace_bits || fs->coord_replace_yinvert != coord_replace_yinvert) { + zink_set_fs_key(ctx)->coord_replace_bits = coord_replace_bits; + zink_set_fs_key(ctx)->coord_replace_yinvert = coord_replace_yinvert; + } +} + #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/zink/zink_shader_keys.h b/src/gallium/drivers/zink/zink_shader_keys.h index a0731f8..318728e 100644 --- a/src/gallium/drivers/zink/zink_shader_keys.h +++ b/src/gallium/drivers/zink/zink_shader_keys.h @@ -26,6 +26,8 @@ #ifndef ZINK_SHADER_KEYS_H # define ZINK_SHADER_KEYS_H +#include "compiler/shader_info.h" + struct zink_vs_key_base { bool clip_halfz; bool push_drawid; @@ -79,7 +81,6 @@ struct zink_shader_key { struct zink_shader_key_base base; unsigned inline_uniforms:1; uint32_t size; - bool is_default_variant; }; static inline const struct zink_fs_key * diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index 00b4b38..68e8d41 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -25,6 +25,7 @@ #include "zink_context.h" #include "zink_format.h" +#include "zink_program.h" #include "zink_screen.h" #include "compiler/shader_enums.h" @@ -178,11 +179,45 @@ zink_bind_vertex_elements_state(struct pipe_context *pctx, ctx->vertex_state_changed = !zink_screen(pctx->screen)->info.have_EXT_vertex_input_dynamic_state; ctx->vertex_buffers_dirty = ctx->element_state->hw_state.num_bindings > 0; } - if (ctx->element_state->decomposed_attrs != state->decomposed_attrs || - ctx->element_state->decomposed_attrs_without_w != state->decomposed_attrs_without_w) - ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX); - state->decomposed_attrs = ctx->element_state->decomposed_attrs; - state->decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w; + const struct zink_vs_key *vs = zink_get_vs_key(ctx); + uint32_t decomposed_attrs = 0, decomposed_attrs_without_w = 0; + switch (vs->size) { + case 1: + decomposed_attrs = vs->u8.decomposed_attrs; + decomposed_attrs_without_w = vs->u8.decomposed_attrs_without_w; + break; + case 2: + decomposed_attrs = vs->u16.decomposed_attrs; + decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w; + break; + case 4: + decomposed_attrs = vs->u16.decomposed_attrs; + decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w; + break; + } + if (ctx->element_state->decomposed_attrs != decomposed_attrs || + ctx->element_state->decomposed_attrs_without_w != decomposed_attrs_without_w) { + unsigned size = MAX2(ctx->element_state->decomposed_attrs_size, ctx->element_state->decomposed_attrs_without_w_size); + struct zink_shader_key *key = (struct zink_shader_key *)zink_set_vs_key(ctx); + key->size -= 2 * key->key.vs.size; + switch (size) { + case 1: + key->key.vs.u8.decomposed_attrs = ctx->element_state->decomposed_attrs; + key->key.vs.u8.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w; + break; + case 2: + key->key.vs.u16.decomposed_attrs = ctx->element_state->decomposed_attrs; + key->key.vs.u16.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w; + break; + case 4: + key->key.vs.u32.decomposed_attrs = ctx->element_state->decomposed_attrs; + key->key.vs.u32.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w; + break; + default: break; + } + key->key.vs.size = size; + key->size += 2 * size; + } state->element_state = &ctx->element_state->hw_state; } else { state->element_state = NULL; @@ -380,6 +415,10 @@ zink_bind_blend_state(struct pipe_context *pctx, void *cso) state->blend_state = cso; state->blend_id = blend ? blend->hash : 0; state->dirty = true; + bool force_dual_color_blend = zink_screen(pctx->screen)->driconf.dual_color_blend_by_location && + blend && blend->dual_src_blend && state->blend_state->attachments[1].blendEnable; + if (force_dual_color_blend != zink_get_fs_key(ctx)->force_dual_color_blend) + zink_set_fs_key(ctx)->force_dual_color_blend = force_dual_color_blend; ctx->blend_state_changed = true; } } @@ -635,7 +674,6 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso) { struct zink_context *ctx = zink_context(pctx); struct zink_screen *screen = zink_screen(pctx->screen); - bool clip_halfz = ctx->rast_state ? ctx->rast_state->base.clip_halfz : false; bool point_quad_rasterization = ctx->rast_state ? ctx->rast_state->base.point_quad_rasterization : false; bool scissor = ctx->rast_state ? ctx->rast_state->base.scissor : false; bool pv_last = ctx->rast_state ? ctx->rast_state->hw_state.pv_last : false; @@ -654,8 +692,8 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso) ctx->gfx_pipeline_state.dirty = true; ctx->rast_state_changed = true; - if (clip_halfz != ctx->rast_state->base.clip_halfz) { - ctx->last_vertex_stage_dirty = true; + if (zink_get_last_vertex_key(ctx)->clip_halfz != ctx->rast_state->base.clip_halfz) { + zink_set_last_vertex_key(ctx)->clip_halfz = ctx->rast_state->base.clip_halfz; ctx->vp_state_changed = true; } @@ -663,11 +701,8 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso) ctx->gfx_pipeline_state.dyn_state1.front_face = ctx->rast_state->front_face; ctx->gfx_pipeline_state.dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state; } - if (ctx->rast_state->base.point_quad_rasterization != point_quad_rasterization) { - ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT); - ctx->gfx_pipeline_state.coord_replace_bits = ctx->rast_state->base.sprite_coord_enable; - ctx->gfx_pipeline_state.coord_replace_yinvert = !!ctx->rast_state->base.sprite_coord_mode; - } + if (ctx->rast_state->base.point_quad_rasterization != point_quad_rasterization) + zink_set_fs_point_coord_key(ctx); if (ctx->rast_state->base.scissor != scissor) ctx->scissor_changed = true; } -- 2.7.4