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 <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19953>
This commit is contained in:
Marek Olšák 2022-11-21 04:53:39 -05:00 committed by Marge Bot
parent b6e800af7d
commit a5851ca8b1
15 changed files with 107 additions and 63 deletions

View file

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

View file

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

View file

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

View file

@ -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.
*/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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