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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19048>
This commit is contained in:
Erik Faye-Lund 2022-10-12 14:48:06 +02:00 committed by Marge Bot
parent 811794f8d8
commit 659c39fafb
5 changed files with 84 additions and 70 deletions

View file

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

View file

@ -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 <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED, bool DRAW_STATE>
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;

View file

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

View file

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

View file

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