[Mesa-dev] [PATCH 02/31] mesa: stop using _NEW_STENCIL with st/mesa, use DriverFlags.NewStencil instead

Marek Olšák maraeo at gmail.com
Mon Jun 12 16:55:27 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

This bypasses _mesa_update_state_locked.

Before:
   DrawElements ( 1 VBOs, 4 UBOs,  8 Tex) w/ stencil enable change:    3.99 million
   DrawArrays   ( 1 VBOs, 4 UBOs,  8 Tex) w/ stencil enable change:    4.56 million

After:
   DrawElements ( 1 VBOs, 4 UBOs,  8 Tex) w/ stencil enable change:    4.93 million
   DrawArrays   ( 1 VBOs, 4 UBOs,  8 Tex) w/ stencil enable change:    5.84 million

It's quite a difference in the draw call rate when ctx->NewState stays
equal to 0 the whole time.
---
 src/mesa/main/enable.c              |  6 ++++--
 src/mesa/main/mtypes.h              |  3 +++
 src/mesa/main/stencil.c             | 33 ++++++++++++++++++++++-----------
 src/mesa/state_tracker/st_context.c |  4 ++--
 4 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index 91c1f0d..128b5a9 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -672,21 +672,22 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
             if (newEnabled != ctx->Scissor.EnableFlags) {
                FLUSH_VERTICES(ctx, _NEW_SCISSOR);
                ctx->NewDriverState |= ctx->DriverFlags.NewScissorTest;
                ctx->Scissor.EnableFlags = newEnabled;
             }
          }
          break;
       case GL_STENCIL_TEST:
          if (ctx->Stencil.Enabled == state)
             return;
-         FLUSH_VERTICES(ctx, _NEW_STENCIL);
+         FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+         ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
          ctx->Stencil.Enabled = state;
          break;
       case GL_TEXTURE_1D:
          if (ctx->API != API_OPENGL_COMPAT)
             goto invalid_enum_error;
          if (!enable_texture(ctx, state, TEXTURE_1D_BIT)) {
             return;
          }
          break;
       case GL_TEXTURE_2D:
@@ -898,21 +899,22 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
          }
          break;
 
       /* GL_EXT_stencil_two_side */
       case GL_STENCIL_TEST_TWO_SIDE_EXT:
          if (ctx->API != API_OPENGL_COMPAT)
             goto invalid_enum_error;
          CHECK_EXTENSION(EXT_stencil_two_side, cap);
          if (ctx->Stencil.TestTwoSide == state)
             return;
-         FLUSH_VERTICES(ctx, _NEW_STENCIL);
+         FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+         ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
          ctx->Stencil.TestTwoSide = state;
          if (state) {
             ctx->Stencil._BackFace = 2;
          } else {
             ctx->Stencil._BackFace = 1;
          }
          break;
 
       case GL_FRAGMENT_PROGRAM_ARB:
          if (ctx->API != API_OPENGL_COMPAT)
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 1e02ff0..283215f 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -4402,20 +4402,23 @@ struct gl_driver_flags
    uint64_t NewWindowRectangles;
 
    /** gl_context::Color::sRGBEnabled */
    uint64_t NewFramebufferSRGB;
 
    /** gl_context::Scissor::EnableFlags */
    uint64_t NewScissorTest;
 
    /** gl_context::Scissor::ScissorArray */
    uint64_t NewScissorRect;
+
+   /** gl_context::Stencil */
+   uint64_t NewStencil;
 };
 
 struct gl_uniform_buffer_binding
 {
    struct gl_buffer_object *BufferObject;
    /** Start of uniform block data in the buffer */
    GLintptr Offset;
    /** Size of data allowed to be referenced from the buffer (in bytes) */
    GLsizeiptr Size;
    /**
diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c
index 2547f45..ea04f2e 100644
--- a/src/mesa/main/stencil.c
+++ b/src/mesa/main/stencil.c
@@ -150,21 +150,22 @@ _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLui
    }
 
    /* set both front and back state */
    if (ctx->Stencil.Function[0] == frontfunc &&
        ctx->Stencil.Function[1] == backfunc &&
        ctx->Stencil.ValueMask[0] == mask &&
        ctx->Stencil.ValueMask[1] == mask &&
        ctx->Stencil.Ref[0] == ref &&
        ctx->Stencil.Ref[1] == ref)
       return;
-   FLUSH_VERTICES(ctx, _NEW_STENCIL);
+   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+   ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
    ctx->Stencil.Function[0]  = frontfunc;
    ctx->Stencil.Function[1]  = backfunc;
    ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
    ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
    if (ctx->Driver.StencilFuncSeparate) {
       ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
                                       frontfunc, ref, mask);
       ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
                                       backfunc, ref, mask);
    }
@@ -196,42 +197,44 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
    if (!validate_stencil_func(ctx, func)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
       return;
    }
 
    if (face != 0) {
       if (ctx->Stencil.Function[face] == func &&
           ctx->Stencil.ValueMask[face] == mask &&
           ctx->Stencil.Ref[face] == ref)
          return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
       ctx->Stencil.Function[face] = func;
       ctx->Stencil.Ref[face] = ref;
       ctx->Stencil.ValueMask[face] = mask;
 
       /* Only propagate the change to the driver if EXT_stencil_two_side
        * is enabled.
        */
       if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
          ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
       }
    }
    else {
       /* set both front and back state */
       if (ctx->Stencil.Function[0] == func &&
           ctx->Stencil.Function[1] == func &&
           ctx->Stencil.ValueMask[0] == mask &&
           ctx->Stencil.ValueMask[1] == mask &&
           ctx->Stencil.Ref[0] == ref &&
           ctx->Stencil.Ref[1] == ref)
          return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
       ctx->Stencil.Function[0]  = ctx->Stencil.Function[1]  = func;
       ctx->Stencil.Ref[0]       = ctx->Stencil.Ref[1]       = ref;
       ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
       if (ctx->Driver.StencilFuncSeparate) {
          ctx->Driver.StencilFuncSeparate(ctx,
 					 ((ctx->Stencil.TestTwoSide)
 					  ? GL_FRONT : GL_FRONT_AND_BACK),
                                          func, ref, mask);
       }
    }
@@ -256,36 +259,38 @@ _mesa_StencilMask( GLuint mask )
    const GLint face = ctx->Stencil.ActiveFace;
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glStencilMask()\n");
 
    if (face != 0) {
       /* Only modify the EXT_stencil_two_side back-face state.
        */
       if (ctx->Stencil.WriteMask[face] == mask)
          return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
       ctx->Stencil.WriteMask[face] = mask;
 
       /* Only propagate the change to the driver if EXT_stencil_two_side
        * is enabled.
        */
       if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
          ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
       }
    }
    else {
       /* set both front and back state */
       if (ctx->Stencil.WriteMask[0] == mask &&
           ctx->Stencil.WriteMask[1] == mask)
          return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
       ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
       if (ctx->Driver.StencilMaskSeparate) {
          ctx->Driver.StencilMaskSeparate(ctx,
 					 ((ctx->Stencil.TestTwoSide)
 					  ? GL_FRONT : GL_FRONT_AND_BACK),
 					  mask);
       }
    }
 }
 
@@ -325,42 +330,44 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
       return;
    }
 
    if (face != 0) {
       /* only set active face state */
       if (ctx->Stencil.ZFailFunc[face] == zfail &&
           ctx->Stencil.ZPassFunc[face] == zpass &&
           ctx->Stencil.FailFunc[face] == fail)
          return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
       ctx->Stencil.ZFailFunc[face] = zfail;
       ctx->Stencil.ZPassFunc[face] = zpass;
       ctx->Stencil.FailFunc[face] = fail;
 
       /* Only propagate the change to the driver if EXT_stencil_two_side
        * is enabled.
        */
       if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
          ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
       }
    }
    else {
       /* set both front and back state */
       if (ctx->Stencil.ZFailFunc[0] == zfail &&
           ctx->Stencil.ZFailFunc[1] == zfail &&
           ctx->Stencil.ZPassFunc[0] == zpass &&
           ctx->Stencil.ZPassFunc[1] == zpass &&
           ctx->Stencil.FailFunc[0] == fail &&
           ctx->Stencil.FailFunc[1] == fail)
          return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+      ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
       ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
       ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
       ctx->Stencil.FailFunc[0]  = ctx->Stencil.FailFunc[1]  = fail;
       if (ctx->Driver.StencilOpSeparate) {
          ctx->Driver.StencilOpSeparate(ctx,
 				       ((ctx->Stencil.TestTwoSide)
 					? GL_FRONT : GL_FRONT_AND_BACK),
                                        fail, zfail, zpass);
       }
    }
@@ -416,33 +423,35 @@ _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
       return;
    }
 
    if (face != GL_BACK) {
       /* set front */
       if (ctx->Stencil.ZFailFunc[0] != zfail ||
           ctx->Stencil.ZPassFunc[0] != zpass ||
           ctx->Stencil.FailFunc[0] != sfail){
-         FLUSH_VERTICES(ctx, _NEW_STENCIL);
+         FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+         ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
          ctx->Stencil.ZFailFunc[0] = zfail;
          ctx->Stencil.ZPassFunc[0] = zpass;
          ctx->Stencil.FailFunc[0] = sfail;
          set = GL_TRUE;
       }
    }
    if (face != GL_FRONT) {
       /* set back */
       if (ctx->Stencil.ZFailFunc[1] != zfail ||
           ctx->Stencil.ZPassFunc[1] != zpass ||
           ctx->Stencil.FailFunc[1] != sfail) {
-         FLUSH_VERTICES(ctx, _NEW_STENCIL);
+         FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+         ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
          ctx->Stencil.ZFailFunc[1] = zfail;
          ctx->Stencil.ZPassFunc[1] = zpass;
          ctx->Stencil.FailFunc[1] = sfail;
          set = GL_TRUE;
       }
    }
    if (set && ctx->Driver.StencilOpSeparate) {
       ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
    }
 }
@@ -459,21 +468,22 @@ _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
 
    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
       return;
    }
    if (!validate_stencil_func(ctx, func)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
       return;
    }
 
-   FLUSH_VERTICES(ctx, _NEW_STENCIL);
+   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+   ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
 
    if (face != GL_BACK) {
       /* set front */
       ctx->Stencil.Function[0] = func;
       ctx->Stencil.Ref[0] = ref;
       ctx->Stencil.ValueMask[0] = mask;
    }
    if (face != GL_FRONT) {
       /* set back */
       ctx->Stencil.Function[1] = func;
@@ -493,21 +503,22 @@ _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
    GET_CURRENT_CONTEXT(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glStencilMaskSeparate()\n");
 
    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
       return;
    }
 
-   FLUSH_VERTICES(ctx, _NEW_STENCIL);
+   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewStencil ? 0 : _NEW_STENCIL);
+   ctx->NewDriverState |= ctx->DriverFlags.NewStencil;
 
    if (face != GL_BACK) {
       ctx->Stencil.WriteMask[0] = mask;
    }
    if (face != GL_FRONT) {
       ctx->Stencil.WriteMask[1] = mask;
    }
    if (ctx->Driver.StencilMaskSeparate) {
       ctx->Driver.StencilMaskSeparate(ctx, face, mask);
    }
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index b99a53b..b9ebc38 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -186,22 +186,21 @@ st_invalidate_state(struct gl_context * ctx)
 {
    GLbitfield new_state = ctx->NewState;
    struct st_context *st = st_context(ctx);
 
    if (new_state & _NEW_BUFFERS) {
       st_invalidate_buffers(st);
    } else {
       /* These set a subset of flags set by _NEW_BUFFERS, so we only have to
        * check them when _NEW_BUFFERS isn't set.
        */
-      if (new_state & (_NEW_DEPTH |
-                       _NEW_STENCIL))
+      if (new_state & _NEW_DEPTH)
          st->dirty |= ST_NEW_DSA;
 
       if (new_state & _NEW_PROGRAM)
          st->dirty |= ST_NEW_RASTERIZER;
 
       if (new_state & _NEW_FOG)
          st->dirty |= ST_NEW_FS_STATE;
 
       if (new_state & _NEW_POLYGONSTIPPLE)
          st->dirty |= ST_NEW_POLY_STIPPLE;
@@ -514,20 +513,21 @@ static void st_init_driver_flags(struct st_context *st)
    f->NewUniformBuffer = ST_NEW_UNIFORM_BUFFER;
    f->NewDefaultTessLevels = ST_NEW_TESS_STATE;
    f->NewTextureBuffer = ST_NEW_SAMPLER_VIEWS;
    f->NewAtomicBuffer = ST_NEW_ATOMIC_BUFFER;
    f->NewShaderStorageBuffer = ST_NEW_STORAGE_BUFFER;
    f->NewImageUnits = ST_NEW_IMAGE_UNITS;
    f->NewWindowRectangles = ST_NEW_WINDOW_RECTANGLES;
    f->NewFramebufferSRGB = ST_NEW_FRAMEBUFFER;
    f->NewScissorRect = ST_NEW_SCISSOR;
    f->NewScissorTest = ST_NEW_SCISSOR | ST_NEW_RASTERIZER;
+   f->NewStencil = ST_NEW_DSA;
 }
 
 struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
                                      const struct gl_config *visual,
                                      struct st_context *share,
                                      const struct st_config_options *options)
 {
    struct gl_context *ctx;
    struct gl_context *shareCtx = share ? share->ctx : NULL;
    struct dd_function_table funcs;
-- 
2.7.4



More information about the mesa-dev mailing list