From a5851ca8b1a68ad5bdb05c4b89d901ac27b78327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 21 Nov 2022 04:53:39 -0500 Subject: [PATCH] mesa: completely rewrite the edge flag state update logic This removes the edge flag logic from st_validate_state, which was always executed and added overhead there. Now it's done only when needed. Acked-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/mesa/main/arrayobj.h | 10 ---- src/mesa/main/attrib.c | 2 + src/mesa/main/draw.c | 2 + src/mesa/main/mtypes.h | 12 ++++ src/mesa/main/polygon.c | 4 ++ src/mesa/main/varray.c | 65 +++++++++++++++++++++ src/mesa/main/varray.h | 7 +++ src/mesa/state_tracker/st_atom.c | 30 ---------- src/mesa/state_tracker/st_atom.h | 1 - src/mesa/state_tracker/st_atom_rasterizer.c | 3 +- src/mesa/state_tracker/st_atom_shader.c | 4 +- src/mesa/state_tracker/st_context.h | 3 - src/mesa/state_tracker/st_draw.c | 15 ----- src/mesa/vbo/vbo_exec_api.c | 3 + src/mesa/vbo/vbo_save_draw.c | 9 +++ 15 files changed, 107 insertions(+), 63 deletions(-) diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index 5da0486f4c4..8d29bf3eff7 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -314,16 +314,6 @@ _mesa_draw_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr) } -/** - * Return true if we have the VERT_ATTRIB_EDGEFLAG array enabled. - */ -static inline bool -_mesa_draw_edge_flag_array_enabled(const struct gl_context *ctx) -{ - return ctx->Array._DrawVAOEnabledAttribs & VERT_BIT_EDGEFLAG; -} - - #ifdef __cplusplus } #endif diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 754a6e1929c..30f02998321 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -1313,6 +1313,8 @@ restore_array_attrib(struct gl_context *ctx, src->VAO->IndexBufferObj ? src->VAO->IndexBufferObj->Name : 0); } + + _mesa_update_edgeflag_state_vao(ctx); } diff --git a/src/mesa/main/draw.c b/src/mesa/main/draw.c index 3ea9c62350b..55b548e7106 100644 --- a/src/mesa/main/draw.c +++ b/src/mesa/main/draw.c @@ -110,6 +110,7 @@ _mesa_set_draw_vao(struct gl_context *ctx, struct gl_vertex_array_object *vao) if (*ptr != vao) { _mesa_reference_vao_(ctx, ptr, vao); + _mesa_update_edgeflag_state_vao(ctx); ctx->Array.NewVAO = true; } } @@ -135,6 +136,7 @@ _mesa_restore_draw_vao(struct gl_context *ctx, { _mesa_reference_vao(ctx, &ctx->Array._DrawVAO, NULL); ctx->Array._DrawVAO = saved; + _mesa_update_edgeflag_state_vao(ctx); ctx->Array.NewVAO = true; } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 697361d5b85..e36341ba0cb 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1753,6 +1753,18 @@ struct gl_array_attrib */ GLbitfield _DrawVAOEnabledAttribs; + /** + * Whether per-vertex edge flags are enabled and should be processed by + * the vertex shader. + */ + bool _PerVertexEdgeFlagsEnabled; + + /** + * Whether all edge flags are false, causing all points and lines generated + * by polygon mode to be not drawn. (i.e. culled) + */ + bool _PolygonModeAlwaysCulls; + /** * Whether the VAO has been changed. */ diff --git a/src/mesa/main/polygon.c b/src/mesa/main/polygon.c index 1297aa4ad98..1b19c48a2d5 100644 --- a/src/mesa/main/polygon.c +++ b/src/mesa/main/polygon.c @@ -39,6 +39,7 @@ #include "polygon.h" #include "mtypes.h" #include "api_exec_decl.h" +#include "varray.h" #include "state_tracker/st_context.h" @@ -193,6 +194,7 @@ polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode, bool no_error) GL_POLYGON_BIT); ctx->NewDriverState |= ST_NEW_RASTERIZER; ctx->Polygon.FrontMode = mode; + _mesa_update_edgeflag_state_vao(ctx); break; case GL_FRONT_AND_BACK: if (ctx->Polygon.FrontMode == mode && ctx->Polygon.BackMode == mode) @@ -202,6 +204,7 @@ polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode, bool no_error) ctx->NewDriverState |= ST_NEW_RASTERIZER; ctx->Polygon.FrontMode = mode; ctx->Polygon.BackMode = mode; + _mesa_update_edgeflag_state_vao(ctx); break; case GL_BACK: if (!no_error && ctx->API == API_OPENGL_CORE) { @@ -214,6 +217,7 @@ polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode, bool no_error) GL_POLYGON_BIT); ctx->NewDriverState |= ST_NEW_RASTERIZER; ctx->Polygon.BackMode = mode; + _mesa_update_edgeflag_state_vao(ctx); break; default: if (!no_error) diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 30b6f075a44..7b694b753ba 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -44,6 +44,9 @@ #include "main/dispatch.h" #include "api_exec_decl.h" +#include "state_tracker/st_atom.h" +#include "state_tracker/st_util.h" + /** Used to do error checking for GL_EXT_vertex_array_bgra */ #define BGRA_OR_4 5 @@ -1993,6 +1996,62 @@ _mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type, stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr); } +/** + * Set the per-vertex edge flag enablement according to the "enable" + * parameter. If "enable" is false, the zero-stride edge flag attribute value + * will be used instead. + * + * This is used by VAOs, glBegin/End and display lists. + */ +void +_mesa_update_edgeflag_state_explicit(struct gl_context *ctx, + bool per_vertex_enable) +{ + if (ctx->API != API_OPENGL_COMPAT) + return; + + /* Edge flags take effect only if the polygon mode is not FILL, and they + * determine whether a line or point is drawn with that polygon mode. + */ + bool edgeflags_have_effect = ctx->Polygon.FrontMode != GL_FILL || + ctx->Polygon.BackMode != GL_FILL; + per_vertex_enable &= edgeflags_have_effect; + + if (per_vertex_enable != ctx->Array._PerVertexEdgeFlagsEnabled) { + ctx->Array._PerVertexEdgeFlagsEnabled = per_vertex_enable; + + struct gl_program *vp = ctx->VertexProgram._Current; + if (vp) { + ctx->NewDriverState |= ST_NEW_VS_STATE | + ST_NEW_VERTEX_ARRAYS; + ctx->Array.NewVertexElements = true; + } + } + + /* If there are no per-vertex edge flags and the zero-stride edge flag is + * false, all front and back points and lines generated by polygon mode + * are not drawn. + */ + bool polygon_mode_always_culls = edgeflags_have_effect && + !ctx->Array._PerVertexEdgeFlagsEnabled && + !ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0]; + if (polygon_mode_always_culls != ctx->Array._PolygonModeAlwaysCulls) { + ctx->Array._PolygonModeAlwaysCulls = polygon_mode_always_culls; + ctx->NewDriverState |= ST_NEW_RASTERIZER; + } +} + +/** + * Set the edge flag state using the current VAO and the zero-stride + * edge flag attribute value if per-vertex edge flags are disabled. + */ +void +_mesa_update_edgeflag_state_vao(struct gl_context *ctx) +{ + _mesa_update_edgeflag_state_explicit(ctx, + ctx->Array._DrawVAO->Enabled & + VERT_BIT_EDGEFLAG); +} void _mesa_enable_vertex_array_attribs(struct gl_context *ctx, @@ -2015,6 +2074,9 @@ _mesa_enable_vertex_array_attribs(struct gl_context *ctx, if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0)) update_attribute_map_mode(ctx, vao); + if (attrib_bits & VERT_BIT_EDGEFLAG) + _mesa_update_edgeflag_state_vao(ctx); + vao->_EnabledWithMapMode = _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled); } @@ -2116,6 +2178,9 @@ _mesa_disable_vertex_array_attribs(struct gl_context *ctx, if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0)) update_attribute_map_mode(ctx, vao); + if (attrib_bits & VERT_BIT_EDGEFLAG) + _mesa_update_edgeflag_state_vao(ctx); + vao->_EnabledWithMapMode = _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled); } diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h index 18298969bdd..8c61070617d 100644 --- a/src/mesa/main/varray.h +++ b/src/mesa/main/varray.h @@ -168,4 +168,11 @@ _mesa_init_varray(struct gl_context *ctx); extern void _mesa_free_varray_data(struct gl_context *ctx); +void +_mesa_update_edgeflag_state_explicit(struct gl_context *ctx, + bool per_vertex_enable); + +void +_mesa_update_edgeflag_state_vao(struct gl_context *ctx); + #endif diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index f2ceb59c4a1..0b9f90dad08 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -70,33 +70,6 @@ void st_destroy_atoms( struct st_context *st ) /* no-op */ } -void st_update_edgeflags(struct st_context *st, bool per_vertex_edgeflags) -{ - bool edgeflags_enabled = st->ctx->Polygon.FrontMode != GL_FILL || - st->ctx->Polygon.BackMode != GL_FILL; - bool vertdata_edgeflags = edgeflags_enabled && per_vertex_edgeflags; - - if (vertdata_edgeflags != st->vertdata_edgeflags) { - st->vertdata_edgeflags = vertdata_edgeflags; - - struct gl_program *vp = st->ctx->VertexProgram._Current; - if (vp) - st->dirty |= ST_NEW_VERTEX_PROGRAM(st->ctx, vp); - } - - bool edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags && - !st->ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0]; - if (edgeflag_culls_prims != st->edgeflag_culls_prims) { - st->edgeflag_culls_prims = edgeflag_culls_prims; - st->dirty |= ST_NEW_RASTERIZER; - } -} - -static void check_attrib_edgeflag(struct st_context *st) -{ - st_update_edgeflags(st, _mesa_draw_edge_flag_array_enabled(st->ctx)); -} - /*********************************************************************** * Update all derived state: */ @@ -118,9 +91,6 @@ void st_validate_state( struct st_context *st, enum st_pipeline pipeline ) switch (pipeline) { case ST_PIPELINE_RENDER: case ST_PIPELINE_RENDER_NO_VARRAYS: - if (st->ctx->API == API_OPENGL_COMPAT) - check_attrib_edgeflag(st); - if (pipeline == ST_PIPELINE_RENDER) pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK; else diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h index 58874bd584f..241d21eebfb 100644 --- a/src/mesa/state_tracker/st_atom.h +++ b/src/mesa/state_tracker/st_atom.h @@ -62,7 +62,6 @@ enum st_pipeline { void st_init_atoms( struct st_context *st ); void st_destroy_atoms( struct st_context *st ); void st_validate_state( struct st_context *st, enum st_pipeline pipeline ); -void st_update_edgeflags(struct st_context *st, bool per_vertex_edgeflags); void st_setup_arrays(struct st_context *st, diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 0e6bfdb5dc6..fda7f36e506 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -287,8 +287,7 @@ st_update_rasterizer(struct st_context *st) raster->tile_raster_order_increasing_y = ctx->TileRasterOrderIncreasingY; } - if (st->edgeflag_culls_prims) { - /* All edge flags are FALSE. Cull the affected faces. */ + if (ctx->Array._PolygonModeAlwaysCulls) { if (raster->fill_front != PIPE_POLYGON_MODE_FILL) raster->cull_face |= PIPE_FACE_FRONT; if (raster->fill_back != PIPE_POLYGON_MODE_FILL) diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 96f4e1c04a6..643a3739c04 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -195,7 +195,7 @@ st_update_vp( struct st_context *st ) assert(vp->Target == GL_VERTEX_PROGRAM_ARB); if (st->shader_has_one_variant[MESA_SHADER_VERTEX] && - !st->vertdata_edgeflags) { + !st->ctx->Array._PerVertexEdgeFlagsEnabled) { st->vp_variant = st_common_variant(vp->variants); } else { struct st_common_variant_key key; @@ -210,7 +210,7 @@ st_update_vp( struct st_context *st ) * the input to the output. We'll need to use similar logic to set * up the extra vertex_element input for edgeflags. */ - key.passthrough_edgeflags = st->vertdata_edgeflags; + key.passthrough_edgeflags = st->ctx->Array._PerVertexEdgeFlagsEnabled; key.clamp_color = st->clamp_vert_color_in_shader && st->ctx->Light._ClampVertexColor && diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 556e074601c..57024f7cce3 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -254,9 +254,6 @@ struct st_context /** This masks out unused shader resources. Only valid in draw calls. */ uint64_t active_states; - GLboolean vertdata_edgeflags; - GLboolean edgeflag_culls_prims; - /** * The number of currently active queries (excluding timer queries). * This is used to know if we need to pause any queries for meta ops. diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 080184c7be1..92862313313 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -349,12 +349,6 @@ st_draw_gallium_vertex_state(struct gl_context *ctx, bool per_vertex_edgeflags) { struct st_context *st = st_context(ctx); - bool old_vertdata_edgeflags = st->vertdata_edgeflags; - - /* We don't flag any other states to make st_validate state update edge - * flags, so we need to update them here. - */ - st_update_edgeflags(st, per_vertex_edgeflags); prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK_NO_VARRAYS, ST_PIPELINE_RENDER_NO_VARRAYS); @@ -383,15 +377,6 @@ st_draw_gallium_vertex_state(struct gl_context *ctx, } } } - - /* If per-vertex edge flags are different than the non-display-list state, - * just flag ST_NEW_VERTEX_ARRAY, which will also completely revalidate - * edge flags in st_validate_state. - */ - if (st->vertdata_edgeflags != old_vertdata_edgeflags) { - ctx->Array.NewVertexElements = true; - st->dirty |= ST_NEW_VERTEX_ARRAYS; - } } void diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 03f1882a4fc..29a7414a0b2 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -211,6 +211,9 @@ vbo_exec_copy_to_current(struct vbo_exec_context *exec) i == VBO_ATTRIB_MAT_BACK_SHININESS) ctx->NewState |= _NEW_FF_VERT_PROGRAM; } else { + if (i == VBO_ATTRIB_EDGEFLAG) + _mesa_update_edgeflag_state_vao(ctx); + ctx->NewState |= _NEW_CURRENT_ATTRIB; ctx->PopAttribState |= GL_CURRENT_BIT; } diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 093cbe79edf..a57faa847ef 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -78,6 +78,9 @@ copy_vao(struct gl_context *ctx, const struct gl_vertex_array_object *vao, current_index == VBO_ATTRIB_MAT_BACK_SHININESS) ctx->NewState |= _NEW_FF_VERT_PROGRAM; + if (current_index == VBO_ATTRIB_EDGEFLAG) + _mesa_update_edgeflag_state_vao(ctx); + ctx->NewState |= state; ctx->PopAttribState |= pop_state; } @@ -270,6 +273,9 @@ vbo_save_playback_vertex_list_gallium(struct gl_context *ctx, info.take_vertex_state_ownership = true; } + /* Set edge flags. */ + _mesa_update_edgeflag_state_explicit(ctx, enabled & VERT_BIT_EDGEFLAG); + /* Fast path using a pre-built gallium vertex buffer state. */ if (node->modes || node->num_draws > 1) { ctx->Driver.DrawGalliumVertexState(ctx, state, info, @@ -284,6 +290,9 @@ vbo_save_playback_vertex_list_gallium(struct gl_context *ctx, enabled & VERT_ATTRIB_EDGEFLAG); } + /* Restore edge flag state. */ + _mesa_update_edgeflag_state_vao(ctx); + if (copy_to_current) playback_copy_to_current(ctx, node); return DONE;