From 659c39fafbb53e27e6816fa872ac6eb78772e519 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Wed, 12 Oct 2022 14:48:06 +0200 Subject: [PATCH] zink: rework primitive rasterization type logic There's a few things that depends on the primitive rasterization type, like point-sprite lowering and polygon offset. The effective state is a combination of several other states, and we currently kinda wing it a bit sometimes. This should improve the situation. In particular, we now go backwards through the pipeline, checking one overriding state at the time. The end result should be that we don't end up lowering point-coord replacement when not rendering with points. Part-of: --- src/gallium/drivers/zink/zink_compiler.c | 43 ---------------- src/gallium/drivers/zink/zink_draw.cpp | 42 ++++++++++------ src/gallium/drivers/zink/zink_program.c | 64 +++++++++++++++++++++--- src/gallium/drivers/zink/zink_program.h | 2 +- src/gallium/drivers/zink/zink_types.h | 3 +- 5 files changed, 84 insertions(+), 70 deletions(-) diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 2b3caa8717d..1c57322a0b3 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -2731,48 +2731,6 @@ handle_bindless_var(nir_shader *nir, nir_variable *var, const struct glsl_type * var->data.mode = nir_var_shader_temp; } -static enum pipe_prim_type -prim_to_pipe(enum shader_prim primitive_type) -{ - switch (primitive_type) { - case SHADER_PRIM_POINTS: - return PIPE_PRIM_POINTS; - case SHADER_PRIM_LINES: - case SHADER_PRIM_LINE_LOOP: - case SHADER_PRIM_LINE_STRIP: - case SHADER_PRIM_LINES_ADJACENCY: - case SHADER_PRIM_LINE_STRIP_ADJACENCY: - return PIPE_PRIM_LINES; - default: - return PIPE_PRIM_TRIANGLES; - } -} - -static enum pipe_prim_type -tess_prim_to_pipe(enum tess_primitive_mode prim_mode) -{ - switch (prim_mode) { - case TESS_PRIMITIVE_ISOLINES: - return PIPE_PRIM_LINES; - default: - return PIPE_PRIM_TRIANGLES; - } -} - -static enum pipe_prim_type -get_shader_base_prim_type(struct nir_shader *nir) -{ - switch (nir->info.stage) { - case MESA_SHADER_GEOMETRY: - return prim_to_pipe(nir->info.gs.output_primitive); - case MESA_SHADER_TESS_EVAL: - return nir->info.tess.point_mode ? PIPE_PRIM_POINTS : tess_prim_to_pipe(nir->info.tess._primitive_mode); - default: - break; - } - return PIPE_PRIM_MAX; -} - static bool convert_1d_shadow_tex(nir_builder *b, nir_instr *instr, void *data) { @@ -3127,7 +3085,6 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir, ret->sinfo.have_vulkan_memory_model = screen->info.have_KHR_vulkan_memory_model; ret->hash = _mesa_hash_pointer(ret); - ret->reduced_prim = get_shader_base_prim_type(nir); ret->programs = _mesa_pointer_set_create(NULL); simple_mtx_init(&ret->lock, mtx_plain); diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index 16f2d1bd93e..d8c9c3f08ea 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -359,6 +359,16 @@ update_gfx_pipeline(struct zink_context *ctx, struct zink_batch_state *bs, enum return pipeline_changed; } +static enum pipe_prim_type +zink_rast_prim(const struct zink_context *ctx, + const struct pipe_draw_info *dinfo) +{ + if (ctx->gfx_pipeline_state.shader_rast_prim != PIPE_PRIM_MAX) + return ctx->gfx_pipeline_state.shader_rast_prim; + + return u_reduced_prim((enum pipe_prim_type)dinfo->mode); +} + template void zink_draw(struct pipe_context *pctx, @@ -491,17 +501,21 @@ zink_draw(struct pipe_context *pctx, (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; - if (mode_changed) { - bool points_changed = false; - if (mode == PIPE_PRIM_POINTS) { - ctx->gfx_pipeline_state.has_points++; - points_changed = true; - } else if (ctx->gfx_pipeline_state.gfx_prim_mode == PIPE_PRIM_POINTS) { - ctx->gfx_pipeline_state.has_points--; - points_changed = true; + + bool rast_prim_changed = false; + if (mode_changed || ctx->gfx_pipeline_state.modules_changed) { + enum pipe_prim_type rast_prim = zink_rast_prim(ctx, dinfo); + if (rast_prim != ctx->gfx_pipeline_state.rast_prim) { + bool points_changed = + (ctx->gfx_pipeline_state.rast_prim == PIPE_PRIM_POINTS) != + (rast_prim == PIPE_PRIM_POINTS); + + ctx->gfx_pipeline_state.rast_prim = rast_prim; + rast_prim_changed = true; + + if (points_changed && ctx->rast_state->base.point_quad_rasterization) + zink_set_fs_point_coord_key(ctx); } - if (points_changed && ctx->rast_state->base.point_quad_rasterization) - zink_set_fs_point_coord_key(ctx); } ctx->gfx_pipeline_state.gfx_prim_mode = mode; @@ -666,13 +680,9 @@ zink_draw(struct pipe_context *pctx, } } - if (BATCH_CHANGED || rast_state_changed) { - enum pipe_prim_type reduced_prim = ctx->last_vertex_stage->reduced_prim; - if (reduced_prim == PIPE_PRIM_MAX) - reduced_prim = u_reduced_prim(mode); - + if (BATCH_CHANGED || rast_state_changed || rast_prim_changed) { bool depth_bias = false; - switch (reduced_prim) { + switch (ctx->gfx_pipeline_state.rast_prim) { case PIPE_PRIM_POINTS: depth_bias = rast_state->offset_point; break; diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index 6102ee4cd0a..7a20ae69881 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -1314,6 +1314,56 @@ bind_gfx_stage(struct zink_context *ctx, gl_shader_stage stage, struct zink_shad } } +static enum pipe_prim_type +gs_output_to_reduced_prim_type(struct shader_info *info) +{ + switch (info->gs.output_primitive) { + case SHADER_PRIM_POINTS: + return PIPE_PRIM_POINTS; + + case SHADER_PRIM_LINES: + case SHADER_PRIM_LINE_LOOP: + case SHADER_PRIM_LINE_STRIP: + case SHADER_PRIM_LINES_ADJACENCY: + case SHADER_PRIM_LINE_STRIP_ADJACENCY: + return PIPE_PRIM_LINES; + + case SHADER_PRIM_TRIANGLES: + case SHADER_PRIM_TRIANGLE_STRIP: + case SHADER_PRIM_TRIANGLE_FAN: + case SHADER_PRIM_TRIANGLES_ADJACENCY: + case SHADER_PRIM_TRIANGLE_STRIP_ADJACENCY: + return PIPE_PRIM_TRIANGLES; + + default: + unreachable("unexpected output primitive type"); + } +} + +static enum pipe_prim_type +update_rast_prim(struct zink_shader *shader) +{ + struct shader_info *info = &shader->nir->info; + if (info->stage == MESA_SHADER_GEOMETRY) + return gs_output_to_reduced_prim_type(info); + else if (info->stage == MESA_SHADER_TESS_EVAL) { + if (info->tess.point_mode) + return PIPE_PRIM_POINTS; + else { + switch (info->tess._primitive_mode) { + case TESS_PRIMITIVE_ISOLINES: + return PIPE_PRIM_LINES; + case TESS_PRIMITIVE_TRIANGLES: + case TESS_PRIMITIVE_QUADS: + return PIPE_PRIM_TRIANGLES; + default: + return PIPE_PRIM_MAX; + } + } + } + return PIPE_PRIM_MAX; +} + static void bind_last_vertex_stage(struct zink_context *ctx) { @@ -1325,6 +1375,12 @@ bind_last_vertex_stage(struct zink_context *ctx) else ctx->last_vertex_stage = ctx->gfx_stages[MESA_SHADER_VERTEX]; gl_shader_stage current = ctx->last_vertex_stage ? ctx->last_vertex_stage->nir->info.stage : MESA_SHADER_VERTEX; + + /* update rast_prim */ + ctx->gfx_pipeline_state.shader_rast_prim = + ctx->last_vertex_stage ? update_rast_prim(ctx->last_vertex_stage) : + PIPE_PRIM_MAX; + if (old != current) { if (!zink_screen(ctx->base.screen)->optimal_keys) { if (old != MESA_SHADER_STAGES) { @@ -1427,16 +1483,8 @@ zink_bind_gs_state(struct pipe_context *pctx, struct zink_context *ctx = zink_context(pctx); if (!cso && !ctx->gfx_stages[MESA_SHADER_GEOMETRY]) return; - bool had_points = ctx->gfx_stages[MESA_SHADER_GEOMETRY] ? ctx->gfx_stages[MESA_SHADER_GEOMETRY]->nir->info.gs.output_primitive == SHADER_PRIM_POINTS : false; bind_gfx_stage(ctx, MESA_SHADER_GEOMETRY, cso); bind_last_vertex_stage(ctx); - if (cso) { - if (!had_points && ctx->last_vertex_stage->nir->info.gs.output_primitive == SHADER_PRIM_POINTS) - ctx->gfx_pipeline_state.has_points++; - } else { - if (had_points) - ctx->gfx_pipeline_state.has_points--; - } } static void diff --git a/src/gallium/drivers/zink/zink_program.h b/src/gallium/drivers/zink/zink_program.h index 9b2848a7fcb..df7aa5d30ac 100644 --- a/src/gallium/drivers/zink/zink_program.h +++ b/src/gallium/drivers/zink/zink_program.h @@ -315,7 +315,7 @@ 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; + bool disable = ctx->gfx_pipeline_state.rast_prim != PIPE_PRIM_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) { diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index d6a9a2fac3e..05c056c86fd 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -658,7 +658,6 @@ struct zink_shader { struct util_live_shader base; uint32_t hash; struct nir_shader *nir; - enum pipe_prim_type reduced_prim; // PIPE_PRIM_MAX for vs struct zink_shader_info sinfo; @@ -748,7 +747,7 @@ struct zink_gfx_pipeline_state { uint32_t vertex_strides[PIPE_MAX_ATTRIBS]; struct zink_vertex_elements_hw_state *element_state; bool sample_locations_enabled; - uint8_t has_points; //either gs outputs points or prim type is points + enum pipe_prim_type shader_rast_prim, rast_prim; /* reduced type or max for unknown */ union { struct { struct zink_shader_key key[5];