[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