[Mesa-dev] [PATCH 1/2] mesa: reduce CPU overhead when updating the scissor

Marek Olšák maraeo at gmail.com
Thu Aug 3 22:33:52 UTC 2017


Hi Samuel,

FLUSH_VERTICES must be called *before* any of the states are changed, not after.

Marek

On Wed, Aug 2, 2017 at 9:42 PM, Samuel Pitoiset
<samuel.pitoiset at gmail.com> wrote:
> Before:
> DrawElements (1 VBO, 8 UBO, 8 Tex) w/ scissor change: 3.67 million (44.4%)
>
> After:
> DrawElements (1 VBO, 8 UBO, 8 Tex) w/ scissor change: 5.02 million (62.1%)
>
> Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
> ---
>  src/mesa/main/scissor.c | 79 ++++++++++++++++++++++++++++++-------------------
>  1 file changed, 48 insertions(+), 31 deletions(-)
>
> diff --git a/src/mesa/main/scissor.c b/src/mesa/main/scissor.c
> index b38db06bc8..c2d85bae2e 100644
> --- a/src/mesa/main/scissor.c
> +++ b/src/mesa/main/scissor.c
> @@ -29,28 +29,20 @@
>  #include "main/mtypes.h"
>  #include "main/scissor.h"
>
> +static bool
> +is_scissor_equal(struct gl_context *ctx, unsigned idx,
> +                 GLint x, GLint y, GLsizei width, GLsizei height)
> +{
> +   return ctx->Scissor.ScissorArray[idx].X == x &&
> +          ctx->Scissor.ScissorArray[idx].Y == y &&
> +          ctx->Scissor.ScissorArray[idx].Width == width &&
> +          ctx->Scissor.ScissorArray[idx].Height == height;
> +}
>
> -/**
> - * Set scissor rectangle data directly in ScissorArray
> - *
> - * This is an internal function that performs no error checking on the
> - * supplied data.  It also does \b not call \c dd_function_table::Scissor.
> - *
> - * \sa _mesa_set_scissor
> - */
>  static void
> -set_scissor_no_notify(struct gl_context *ctx, unsigned idx,
> -                      GLint x, GLint y, GLsizei width, GLsizei height)
> +set_new_scissor(struct gl_context *ctx, unsigned idx,
> +                GLint x, GLint y, GLsizei width, GLsizei height)
>  {
> -   if (x == ctx->Scissor.ScissorArray[idx].X &&
> -       y == ctx->Scissor.ScissorArray[idx].Y &&
> -       width == ctx->Scissor.ScissorArray[idx].Width &&
> -       height == ctx->Scissor.ScissorArray[idx].Height)
> -      return;
> -
> -   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewScissorRect ? 0 : _NEW_SCISSOR);
> -   ctx->NewDriverState |= ctx->DriverFlags.NewScissorRect;
> -
>     ctx->Scissor.ScissorArray[idx].X = x;
>     ctx->Scissor.ScissorArray[idx].Y = y;
>     ctx->Scissor.ScissorArray[idx].Width = width;
> @@ -58,8 +50,19 @@ set_scissor_no_notify(struct gl_context *ctx, unsigned idx,
>  }
>
>  static void
> +flush_scissor(struct gl_context *ctx)
> +{
> +   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewScissorRect ? 0 : _NEW_SCISSOR);
> +   ctx->NewDriverState |= ctx->DriverFlags.NewScissorRect;
> +
> +   if (ctx->Driver.Scissor)
> +      ctx->Driver.Scissor(ctx);
> +}
> +
> +static void
>  scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height)
>  {
> +   bool changed = false;
>     unsigned i;
>
>     /* The GL_ARB_viewport_array spec says:
> @@ -74,11 +77,16 @@ scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height)
>      * Set the scissor rectangle for all of the viewports supported by the
>      * implementation, but only signal the driver once at the end.
>      */
> -   for (i = 0; i < ctx->Const.MaxViewports; i++)
> -      set_scissor_no_notify(ctx, i, x, y, width, height);
> +   for (i = 0; i < ctx->Const.MaxViewports; i++) {
> +      if (!changed && is_scissor_equal(ctx, i, x, y, width, height))
> +         continue;
>
> -   if (ctx->Driver.Scissor)
> -      ctx->Driver.Scissor(ctx);
> +      changed = true;
> +      set_new_scissor(ctx, i, x, y, width, height);
> +   }
> +
> +   if (changed)
> +      flush_scissor(ctx);
>  }
>
>  /**
> @@ -125,23 +133,31 @@ void
>  _mesa_set_scissor(struct gl_context *ctx, unsigned idx,
>                    GLint x, GLint y, GLsizei width, GLsizei height)
>  {
> -   set_scissor_no_notify(ctx, idx, x, y, width, height);
> +   if (is_scissor_equal(ctx, idx, x, y, width, height))
> +      return;
>
> -   if (ctx->Driver.Scissor)
> -      ctx->Driver.Scissor(ctx);
> +   set_new_scissor(ctx, idx, x, y, width, height);
> +   flush_scissor(ctx);
>  }
>
>  static void
>  scissor_array(struct gl_context *ctx, GLuint first, GLsizei count,
>                struct gl_scissor_rect *rect)
>  {
> +   bool changed = false;
> +
>     for (GLsizei i = 0; i < count; i++) {
> -      set_scissor_no_notify(ctx, i + first, rect[i].X, rect[i].Y,
> -                            rect[i].Width, rect[i].Height);
> +      if (!changed && is_scissor_equal(ctx, i + first, rect[i].X, rect[i].Y,
> +                                       rect[i].Width, rect[i].Height))
> +         continue;
> +
> +      changed = true;
> +      set_new_scissor(ctx, i + first, rect[i].X, rect[i].Y,
> +                      rect[i].Width, rect[i].Height);
>     }
>
> -   if (ctx->Driver.Scissor)
> -      ctx->Driver.Scissor(ctx);
> +   if (changed)
> +      flush_scissor(ctx);
>  }
>
>  /**
> @@ -328,5 +344,6 @@ _mesa_init_scissor(struct gl_context *ctx)
>      * so just initialize all of them.
>      */
>     for (i = 0; i < MAX_VIEWPORTS; i++)
> -      set_scissor_no_notify(ctx, i, 0, 0, 0, 0);
> +      set_new_scissor(ctx, i, 0, 0, 0, 0);
> +   flush_scissor(ctx);
>  }
> --
> 2.13.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list