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

Samuel Pitoiset samuel.pitoiset at gmail.com
Wed Aug 2 19:42:25 UTC 2017


Before:
DrawElements (1 VBO, 8 UBO, 8 Tex) w/ viewport change: 3.61 million (43.7%)

After:
DrawElements (1 VBO, 8 UBO, 8 Tex) w/ viewport change: 4.95 million (60.2%)

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
 src/mesa/main/viewport.c | 89 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 31 deletions(-)

diff --git a/src/mesa/main/viewport.c b/src/mesa/main/viewport.c
index fc384909e6..ac23f2b93a 100644
--- a/src/mesa/main/viewport.c
+++ b/src/mesa/main/viewport.c
@@ -35,6 +35,36 @@
 #include "mtypes.h"
 #include "viewport.h"
 
+static bool
+is_viewport_equal(struct gl_context *ctx, unsigned idx,
+                  GLfloat x, GLfloat y, GLfloat width, GLfloat height)
+{
+   return ctx->ViewportArray[idx].X == x &&
+          ctx->ViewportArray[idx].Width == width &&
+          ctx->ViewportArray[idx].Y == y &&
+          ctx->ViewportArray[idx].Height == height;
+}
+
+static void
+set_new_viewport(struct gl_context *ctx, unsigned idx,
+                 GLfloat x, GLfloat y, GLfloat width, GLfloat height)
+{
+   ctx->ViewportArray[idx].X = x;
+   ctx->ViewportArray[idx].Width = width;
+   ctx->ViewportArray[idx].Y = y;
+   ctx->ViewportArray[idx].Height = height;
+}
+
+static void
+flush_viewport(struct gl_context *ctx)
+{
+   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewViewport ? 0 : _NEW_VIEWPORT);
+   ctx->NewDriverState |= ctx->DriverFlags.NewViewport;
+
+   if (ctx->Driver.Viewport)
+      ctx->Driver.Viewport(ctx);
+}
+
 static void
 clamp_viewport(struct gl_context *ctx, GLfloat *x, GLfloat *y,
                GLfloat *width, GLfloat *height)
@@ -61,26 +91,6 @@ clamp_viewport(struct gl_context *ctx, GLfloat *x, GLfloat *y,
    }
 }
 
-static void
-set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
-                       GLfloat x, GLfloat y,
-                       GLfloat width, GLfloat height)
-{
-   if (ctx->ViewportArray[idx].X == x &&
-       ctx->ViewportArray[idx].Width == width &&
-       ctx->ViewportArray[idx].Y == y &&
-       ctx->ViewportArray[idx].Height == height)
-      return;
-
-   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewViewport ? 0 : _NEW_VIEWPORT);
-   ctx->NewDriverState |= ctx->DriverFlags.NewViewport;
-
-   ctx->ViewportArray[idx].X = x;
-   ctx->ViewportArray[idx].Width = width;
-   ctx->ViewportArray[idx].Y = y;
-   ctx->ViewportArray[idx].Height = height;
-}
-
 struct gl_viewport_inputs {
    GLfloat X, Y;                /**< position */
    GLfloat Width, Height;       /**< size */
@@ -95,6 +105,7 @@ viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width,
          GLsizei height)
 {
    struct gl_viewport_inputs input = { x, y, width, height };
+   bool changed = false;
 
    /* Clamp the viewport to the implementation dependent values. */
    clamp_viewport(ctx, &input.X, &input.Y, &input.Width, &input.Height);
@@ -110,11 +121,17 @@ viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width,
     * Set all of the viewports supported by the implementation, but only
     * signal the driver once at the end.
     */
-   for (unsigned i = 0; i < ctx->Const.MaxViewports; i++)
-      set_viewport_no_notify(ctx, i, input.X, input.Y, input.Width, input.Height);
+   for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) {
+      if (!changed && is_viewport_equal(ctx, i, input.X, input.Y,
+                                        input.Width, input.Height))
+         continue;
 
-   if (ctx->Driver.Viewport)
-      ctx->Driver.Viewport(ctx);
+      changed = true;
+      set_new_viewport(ctx, i, x, y, width, height);
+   }
+
+   if (changed)
+      flush_viewport(ctx);
 }
 
 /**
@@ -164,26 +181,36 @@ _mesa_set_viewport(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y,
                     GLfloat width, GLfloat height)
 {
    clamp_viewport(ctx, &x, &y, &width, &height);
-   set_viewport_no_notify(ctx, idx, x, y, width, height);
 
-   if (ctx->Driver.Viewport)
-      ctx->Driver.Viewport(ctx);
+   if (is_viewport_equal(ctx, idx, x, y, width, height))
+      return;
+
+   set_new_viewport(ctx, idx, x, y, width, height);
+   flush_viewport(ctx);
 }
 
 static void
 viewport_array(struct gl_context *ctx, GLuint first, GLsizei count,
                struct gl_viewport_inputs *inputs)
 {
+   bool changed = false;
+
    for (GLsizei i = 0; i < count; i++) {
       clamp_viewport(ctx, &inputs[i].X, &inputs[i].Y,
                      &inputs[i].Width, &inputs[i].Height);
 
-      set_viewport_no_notify(ctx, i + first, inputs[i].X, inputs[i].Y,
-                             inputs[i].Width, inputs[i].Height);
+      if (!changed && is_viewport_equal(ctx, i + first,
+                                        inputs[i].X, inputs[i].Y,
+                                        inputs[i].Width, inputs[i].Height))
+         continue;
+
+      changed = true;
+      set_new_viewport(ctx, i + first, inputs[i].X, inputs[i].Y,
+                       inputs[i].Width, inputs[i].Height);
    }
 
-   if (ctx->Driver.Viewport)
-      ctx->Driver.Viewport(ctx);
+   if (changed)
+      flush_viewport(ctx);
 }
 
 void GLAPIENTRY
-- 
2.13.3



More information about the mesa-dev mailing list