Hi,

I've built several patches trying to reduce the propagation of state changes.

They are proof-of-concept, and I'd like to know what you think about
them, mainly :
- do you think it's worth it ? it adds complexity to state trackers,
but it avoids some possibly expensive driver function calls.
- if yes, what would you be the best design approach for this ?

For reference, Airlied built a patch similar to my 4th one, but with a
different approach (adding an incrementing 'Generation' field to
struct instead of comparing pointers) : http://fpaste.org/QTng/

(all tests done using 2.6.38.3/64 bits/r600g)
== Regression ? ==
- piglit quick.tests with all 4 patches applied => no regression

== Some simple benchmarking ==
Successive patches applied :
  * 01 : st_atom_constbuf
  * 02 : st_atom_rasterizer
  * 03 : st_atom_texture
  * 04 : st_atom_sampler

mesa-demos: drawoverhead (draws/sec):
   * Draw only :      2100t
   * Draw w/ nop sc : 2100t
   * Draw w/ sc :
|git from 05/18 | +01     | +01->02 | +01->03 | +01->04 |
|      227t        |   328t   |   328t    |   350t     |   365t     |

openarena (anholt benchmark, 3 runs average) :
|git from 05/18 | +01     | +01->02 | +01->03 | +01->04 |
|      74.6        |   75.0   |   74.4     |   75.7    |   74.7     |


-- Pierre-Eric
From fc58de87ddaf943942a81b0ec4deb8a0ce205534 Mon Sep 17 00:00:00 2001
From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com>
Date: Fri, 20 May 2011 22:52:43 +0200
Subject: [PATCH 1/4] st/mesa : reduced constant buffers upload

This patch add a checksum like computation before a upload constant buffer.
If the checksum equals the previous one, the upload is skipped.
---
 src/mesa/state_tracker/st_atom_constbuf.c |   35 +++++++++++++++++++++++-----
 src/mesa/state_tracker/st_atom_constbuf.h |    5 ++-
 src/mesa/state_tracker/st_cb_bitmap.c     |    2 +-
 src/mesa/state_tracker/st_cb_drawpixels.c |    4 +-
 4 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
index 05667a7..cccd7e7 100644
--- a/src/mesa/state_tracker/st_atom_constbuf.c
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -51,9 +51,10 @@
  * constant buffer.
  * \param shader_type  either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT
  */
-void st_upload_constants( struct st_context *st,
+int st_upload_constants( struct st_context *st,
                           struct gl_program_parameter_list *params,
-                          unsigned shader_type)
+                          unsigned shader_type,
+                         int previousTotal)
 {
    struct pipe_context *pipe = st->pipe;
 
@@ -73,6 +74,24 @@ void st_upload_constants( struct st_context *st,
        */
       _mesa_load_state_parameters(st->ctx, params);
 
+      unsigned int total = (((unsigned int) st) ^ params->NumParameters), tmp;
+      // fprintf(stdout, "[%p] Dump (%d bytes) : \n", st, paramBytes);
+      for(int i=0; i<params->NumParameters; i++) {
+         for(int j=0; j<4; j++) {
+            memcpy(&tmp, &params->ParameterValues[i][j], sizeof(int));
+            total = (total>>(sizeof(int)-1))^(total<<1)^tmp;
+
+            /*for(int k=0; k<4; ++k)
+               fprintf(stdout, "%02x ", ((unsigned char*) &tmp)[k]);*/
+         }
+         //fprintf(stdout, "\n");
+      }
+      //fprintf(stdout, "   Total : %08x\n", total);
+      if (previousTotal == total) {
+         //fprintf(stdout, "Early quit !\n");
+         return total;
+      }
+
       /* We always need to get a new buffer, to keep the drivers simple and
        * avoid gratuitous rendering synchronization.
        * Let's use a user buffer to avoid an unnecessary copy.
@@ -81,7 +100,6 @@ void st_upload_constants( struct st_context *st,
                                      params->ParameterValues,
                                      paramBytes,
                                      PIPE_BIND_CONSTANT_BUFFER);
-
       if (ST_DEBUG & DEBUG_CONSTANTS) {
 	 debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", 
                       __FUNCTION__, shader_type, params->NumParameters,
@@ -94,12 +112,14 @@ void st_upload_constants( struct st_context *st,
 
       st->state.constants[shader_type].ptr = params->ParameterValues;
       st->state.constants[shader_type].size = paramBytes;
+      return total;
    }
    else if (st->state.constants[shader_type].ptr) {
       st->state.constants[shader_type].ptr = NULL;
       st->state.constants[shader_type].size = 0;
       st->pipe->set_constant_buffer(st->pipe, shader_type, 0, NULL);
    }
+   return 0;
 }
 
 
@@ -108,10 +128,11 @@ void st_upload_constants( struct st_context *st,
  */
 static void update_vs_constants(struct st_context *st )
 {
+   static int previous_total = -1;
    struct st_vertex_program *vp = st->vp;
    struct gl_program_parameter_list *params = vp->Base.Base.Parameters;
 
-   st_upload_constants( st, params, PIPE_SHADER_VERTEX );
+   previous_total = st_upload_constants( st, params, PIPE_SHADER_VERTEX, previous_total );
 }
 
 
@@ -131,10 +152,10 @@ const struct st_tracked_state st_update_vs_constants = {
  */
 static void update_fs_constants(struct st_context *st )
 {
+   static int previous_total = -1;
    struct st_fragment_program *fp = st->fp;
    struct gl_program_parameter_list *params = fp->Base.Base.Parameters;
-
-   st_upload_constants( st, params, PIPE_SHADER_FRAGMENT );
+   previous_total = st_upload_constants( st, params, PIPE_SHADER_FRAGMENT, previous_total );
 }
 
 
@@ -156,7 +177,7 @@ static void update_gs_constants(struct st_context *st )
 
    if (gp) {
       params = gp->Base.Base.Parameters;
-      st_upload_constants( st, params, PIPE_SHADER_GEOMETRY );
+      st_upload_constants( st, params, PIPE_SHADER_GEOMETRY, -1 );
    }
 }
 
diff --git a/src/mesa/state_tracker/st_atom_constbuf.h b/src/mesa/state_tracker/st_atom_constbuf.h
index 97b0766..8749bf5 100644
--- a/src/mesa/state_tracker/st_atom_constbuf.h
+++ b/src/mesa/state_tracker/st_atom_constbuf.h
@@ -33,9 +33,10 @@ struct gl_program_parameter_list;
 struct st_context;
 
 
-void st_upload_constants( struct st_context *st,
+int st_upload_constants( struct st_context *st,
                           struct gl_program_parameter_list *params,
-                          unsigned id);
+                          unsigned id,
+                        int previousTotal);
 
 
 #endif /* ST_ATOM_CONSTBUF_H */
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 49b1960..0ffc729 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -437,7 +437,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
       GLfloat colorSave[4];
       COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
-      st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+      st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT, -1);
       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
    }
 
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 9948f8d..57ede72 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -1034,7 +1034,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
    }
 
    /* update fragment program constants */
-   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT, -1);
 
    /* draw with textured quad */
    {
@@ -1370,7 +1370,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    }
 
    /* update fragment program constants */
-   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT, -1);
 
 
    if (rbRead->Base.Wrapped)
-- 
1.7.5.1

From 50498d5fe884b1b5ee1a007fe21a5b3d6fe161ba Mon Sep 17 00:00:00 2001
From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com>
Date: Fri, 20 May 2011 22:54:19 +0200
Subject: [PATCH 2/4] st/mesa : reduce 'cso_set_rasterizer' calls count

cso_set_rasterizer is now called only if "struct pipe_rasterizer_state" content actually changed.
---
 src/mesa/state_tracker/st_atom_rasterizer.c |  178 ++++++++++++++++++---------
 1 files changed, 117 insertions(+), 61 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
index 250cbb2..127d611 100644
--- a/src/mesa/state_tracker/st_atom_rasterizer.c
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -58,17 +58,25 @@ static GLuint translate_fill( GLenum mode )
 static void update_raster_state( struct st_context *st )
 {
    struct gl_context *ctx = st->ctx;
-   struct pipe_rasterizer_state *raster = &st->state.rasterizer;
+   struct pipe_rasterizer_state tmp;
+   struct pipe_rasterizer_state *raster = &tmp; // &st->state.rasterizer;
    const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current;
    const struct gl_fragment_program *fragProg = ctx->FragmentProgram._Current;
    uint i;
 
-   memset(raster, 0, sizeof(*raster));
+   bool change_occured = false;
+#define ASSIGN(field, value) { if (field!=value) { change_occured = true; field = value; } }
+#define EVAL_AND_ASSIGN(field, value, T) { T __tmp = (value); if (field!=__tmp) { change_occured = true; field = __tmp; } }
+
+   /* Only the changing fields are going to be updated and the change_occured flag will be set it needed
+    */
+   memcpy(raster, &st->state.rasterizer, sizeof(*raster));
 
    /* _NEW_POLYGON, _NEW_BUFFERS
     */
+   if ((st->dirty.mesa & _NEW_POLYGON) | (st->dirty.mesa & _NEW_BUFFERS))
    {
-      raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW);
+      unsigned v = (ctx->Polygon.FrontFace == GL_CCW);
 
       /*
        * Gallium's surfaces are Y=0=TOP orientation.  OpenGL is the
@@ -78,17 +86,19 @@ static void update_raster_state( struct st_context *st )
        */
       if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
          /* Drawing to an FBO.  The viewport will be inverted. */
-         raster->front_ccw ^= 1;
+         v ^= 1;
       }
+
+      ASSIGN(raster->front_ccw, v)
    }
 
    /* _NEW_LIGHT
     */
-   if (ctx->Light.ShadeModel == GL_FLAT)
-      raster->flatshade = 1;
-
-   if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION_EXT)
-      raster->flatshade_first = 1;
+   if (st->dirty.mesa & _NEW_LIGHT)
+   {
+      EVAL_AND_ASSIGN(raster->flatshade, (ctx->Light.ShadeModel == GL_FLAT), bool)
+      EVAL_AND_ASSIGN(raster->flatshade_first, (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION_EXT), bool)
+   }
 
    /* _NEW_LIGHT | _NEW_PROGRAM
     *
@@ -96,170 +106,216 @@ static void update_raster_state( struct st_context *st )
     * GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs/shaders (when
     * GL_VERTEX_PROGRAM_TWO_SIDE is set).  Note the logic here.
     */
+   if ((st->dirty.mesa & _NEW_LIGHT) | (st->dirty.mesa & _NEW_PROGRAM))
+   {
+      unsigned light_twoside = 0;
    if (ctx->VertexProgram._Current) {
       if (ctx->VertexProgram._Enabled ||
           (ctx->Shader.CurrentVertexProgram &&
            ctx->Shader.CurrentVertexProgram->LinkStatus)) {
          /* user-defined vertex program or shader */
-         raster->light_twoside = ctx->VertexProgram.TwoSideEnabled;
+                light_twoside = ctx->VertexProgram.TwoSideEnabled;
       }
       else {
          /* TNL-generated program */
-         raster->light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
+                light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
       }
    }
    else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
-      raster->light_twoside = 1;
+             light_twoside = 1;
+      }
+      ASSIGN(raster->light_twoside, light_twoside);
+      ASSIGN(raster->clamp_vertex_color, raster->clamp_vertex_color);
    }
-
-   raster->clamp_vertex_color = ctx->Light._ClampVertexColor;
 
    /* _NEW_POLYGON
     */
+   if ((st->dirty.mesa & _NEW_POLYGON))
+   {
    if (ctx->Polygon.CullFlag) {
       switch (ctx->Polygon.CullFaceMode) {
       case GL_FRONT:
-	 raster->cull_face = PIPE_FACE_FRONT;
+	     ASSIGN(raster->cull_face, PIPE_FACE_FRONT)
          break;
       case GL_BACK:
-	 raster->cull_face = PIPE_FACE_BACK;
+	     ASSIGN(raster->cull_face, PIPE_FACE_BACK)
          break;
       case GL_FRONT_AND_BACK:
-	 raster->cull_face = PIPE_FACE_FRONT_AND_BACK;
+	     ASSIGN(raster->cull_face, PIPE_FACE_FRONT_AND_BACK)
          break;
       }
    }
    else {
-      raster->cull_face = PIPE_FACE_NONE;
+          ASSIGN(raster->cull_face, PIPE_FACE_NONE)
    }
 
+
    /* _NEW_POLYGON
     */
    {
-      raster->fill_front = translate_fill( ctx->Polygon.FrontMode );
-      raster->fill_back = translate_fill( ctx->Polygon.BackMode );
+         unsigned fill_front = translate_fill( ctx->Polygon.FrontMode );
+         unsigned fill_back = translate_fill( ctx->Polygon.BackMode );
 
       /* Simplify when culling is active:
        */
       if (raster->cull_face & PIPE_FACE_FRONT) {
-	 raster->fill_front = raster->fill_back;
+	         fill_front = fill_back;
       }
       
       if (raster->cull_face & PIPE_FACE_BACK) {
-	 raster->fill_back = raster->fill_front;
+	         fill_back = fill_front;
       }
+         ASSIGN(raster->fill_front, fill_front)
+         ASSIGN(raster->fill_back, fill_back)
    }
 
    /* _NEW_POLYGON 
     */
    if (ctx->Polygon.OffsetUnits != 0.0 ||
        ctx->Polygon.OffsetFactor != 0.0) {
-      raster->offset_point = ctx->Polygon.OffsetPoint;
-      raster->offset_line = ctx->Polygon.OffsetLine;
-      raster->offset_tri = ctx->Polygon.OffsetFill;
+          ASSIGN(raster->offset_point, ctx->Polygon.OffsetPoint)
+          ASSIGN(raster->offset_line, ctx->Polygon.OffsetLine)
+          ASSIGN(raster->offset_tri, ctx->Polygon.OffsetFill)
+       } else {
+          ASSIGN(raster->offset_point, 0)
+          ASSIGN(raster->offset_line, 0)
+          ASSIGN(raster->offset_tri, 0)
    }
 
    if (ctx->Polygon.OffsetPoint ||
        ctx->Polygon.OffsetLine ||
        ctx->Polygon.OffsetFill) {
-      raster->offset_units = ctx->Polygon.OffsetUnits;
-      raster->offset_scale = ctx->Polygon.OffsetFactor;
+          ASSIGN(raster->offset_units, ctx->Polygon.OffsetUnits)
+          ASSIGN(raster->offset_scale, ctx->Polygon.OffsetFactor)
+       } else {
+            ASSIGN(raster->offset_units, 0)
+            ASSIGN(raster->offset_scale, 0)
    }
 
-   if (ctx->Polygon.SmoothFlag)
-      raster->poly_smooth = 1;
-
-   if (ctx->Polygon.StippleFlag)
-      raster->poly_stipple_enable = 1;
+       ASSIGN(raster->poly_smooth, ctx->Polygon.SmoothFlag)
+       ASSIGN(raster->poly_stipple_enable, ctx->Polygon.StippleFlag)
+   }
 
    /* _NEW_POINT
     */
-   raster->point_size = ctx->Point.Size;
-
-   if (!ctx->Point.PointSprite && ctx->Point.SmoothFlag)
-      raster->point_smooth = 1;
+   if (st->dirty.mesa & _NEW_POINT)
+   {
+      EVAL_AND_ASSIGN(raster->point_smooth, (!ctx->Point.PointSprite && ctx->Point.SmoothFlag), bool)
+   }
 
    /* _NEW_POINT | _NEW_PROGRAM
     */
+   if ((st->dirty.mesa & _NEW_POINT) | (st->dirty.mesa & _NEW_PROGRAM))
+   {
    if (ctx->Point.PointSprite) {
       /* origin */
       if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^
           (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM))
-         raster->sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
+                ASSIGN(raster->sprite_coord_mode, PIPE_SPRITE_COORD_UPPER_LEFT)
       else 
-         raster->sprite_coord_mode = PIPE_SPRITE_COORD_LOWER_LEFT;
+                ASSIGN(raster->sprite_coord_mode, PIPE_SPRITE_COORD_LOWER_LEFT)
 
       /* Coord replacement flags.  If bit 'k' is set that means
        * that we need to replace GENERIC[k] attrib with an automatically
        * computed texture coord.
        */
+             unsigned sprite_coord_enable = 0;
       for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
          if (ctx->Point.CoordReplace[i]) {
-            raster->sprite_coord_enable |= 1 << i;
+                   sprite_coord_enable |= 1 << i;
          }
       }
       if (fragProg->Base.InputsRead & FRAG_BIT_PNTC) {
-         raster->sprite_coord_enable |=
+                sprite_coord_enable |=
             1 << (FRAG_ATTRIB_PNTC - FRAG_ATTRIB_TEX0);
       }
-
-      raster->point_quad_rasterization = 1;
+             ASSIGN(raster->sprite_coord_enable, sprite_coord_enable)
+             ASSIGN(raster->point_quad_rasterization, 1)
+         } else {
+            ASSIGN(raster->sprite_coord_mode, 0)
+            ASSIGN(raster->sprite_coord_enable, 0)
+            ASSIGN(raster->point_quad_rasterization, 0)
+      }
    }
 
    /* ST_NEW_VERTEX_PROGRAM
     */
+   if (st->dirty.st & ST_NEW_VERTEX_PROGRAM)
+   {
+      bool point_size_per_vertex = FALSE;
    if (vertProg) {
       if (vertProg->Base.Id == 0) {
          if (vertProg->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) {
             /* generated program which emits point size */
-            raster->point_size_per_vertex = TRUE;
+               point_size_per_vertex = TRUE;
          }
       }
       else if (ctx->VertexProgram.PointSizeEnabled) {
          /* user-defined program and GL_VERTEX_PROGRAM_POINT_SIZE set */
-         raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled;
+            point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled;
+         }
       }
+
+      ASSIGN(raster->point_size_per_vertex, point_size_per_vertex)
    }
+
    if (!raster->point_size_per_vertex) {
       /* clamp size now */
-      raster->point_size = CLAMP(ctx->Point.Size,
+      EVAL_AND_ASSIGN(raster->point_size, CLAMP(
+                                    ctx->Point.Size,
                                  ctx->Point.MinSize,
-                                 ctx->Point.MaxSize);
+                                    ctx->Point.MaxSize), float)
+   } else {
+      ASSIGN(raster->point_size, ctx->Point.Size);
    }
 
    /* _NEW_LINE
     */
-   raster->line_smooth = ctx->Line.SmoothFlag;
+   if (st->dirty.mesa & _NEW_LINE)
+   {
+      ASSIGN(raster->line_smooth, ctx->Line.SmoothFlag)
+
    if (ctx->Line.SmoothFlag) {
-      raster->line_width = CLAMP(ctx->Line.Width,
+            EVAL_AND_ASSIGN(raster->line_width, CLAMP(ctx->Line.Width,
                                 ctx->Const.MinLineWidthAA,
-                                ctx->Const.MaxLineWidthAA);
+                                      ctx->Const.MaxLineWidthAA), float)
    }
    else {
-      raster->line_width = CLAMP(ctx->Line.Width,
+            EVAL_AND_ASSIGN(raster->line_width, CLAMP(ctx->Line.Width,
                                 ctx->Const.MinLineWidth,
-                                ctx->Const.MaxLineWidth);
+                                      ctx->Const.MaxLineWidth), float)
    }
 
-   raster->line_stipple_enable = ctx->Line.StippleFlag;
-   raster->line_stipple_pattern = ctx->Line.StipplePattern;
+      ASSIGN(raster->line_stipple_enable, ctx->Line.StippleFlag)
+      ASSIGN(raster->line_stipple_pattern, ctx->Line.StipplePattern)
    /* GL stipple factor is in [1,256], remap to [0, 255] here */
-   raster->line_stipple_factor = ctx->Line.StippleFactor - 1;
+      ASSIGN(raster->line_stipple_factor, ctx->Line.StippleFactor - 1)
+   }
 
    /* _NEW_MULTISAMPLE */
-   if (ctx->Multisample._Enabled || st->force_msaa)
-      raster->multisample = 1;
+   if (st->dirty.mesa & _NEW_MULTISAMPLE)
+   {
+      EVAL_AND_ASSIGN(raster->multisample, (ctx->Multisample._Enabled || st->force_msaa), bool)
+   }
 
    /* _NEW_SCISSOR */
-   if (ctx->Scissor.Enabled)
-      raster->scissor = 1;
+   if (st->dirty.mesa & _NEW_SCISSOR)
+   {
+      ASSIGN(raster->scissor, ctx->Scissor.Enabled)
+   }
 
    /* _NEW_FRAG_CLAMP */
-   raster->clamp_fragment_color = ctx->Color._ClampFragmentColor;
+   if (st->dirty.mesa & _NEW_FRAG_CLAMP)
+   {
+      ASSIGN(raster->clamp_fragment_color, ctx->Color._ClampFragmentColor)
+   }
 
-   raster->gl_rasterization_rules = 1;
+   ASSIGN(raster->gl_rasterization_rules, 1)
 
-   cso_set_rasterizer(st->cso_context, raster);
+   if (change_occured) {
+      memcpy(&st->state.rasterizer, raster, sizeof(struct pipe_rasterizer_state));
+      cso_set_rasterizer(st->cso_context, &st->state.rasterizer); // raster);
+   }
 }
 
 const struct st_tracked_state st_update_rasterizer = {
-- 
1.7.5.1

From d94fff49a92401bb0c36828e1ab8e0d3925b9c28 Mon Sep 17 00:00:00 2001
From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com>
Date: Fri, 20 May 2011 22:56:05 +0200
Subject: [PATCH 3/4] st/mesa : reduce
 cso_set_vertex_sampler_views/cso_set_fragment_sampler_views
 calls

Above functions called only if samplers_view/samplervertex_view content have actually changed.
---
 src/gallium/auxiliary/cso_cache/cso_context.c |    1 +
 src/mesa/state_tracker/st_atom_texture.c      |   20 +++++++++++++++++++-
 2 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index fdd40fc..1b5f06b 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -1193,6 +1193,7 @@ set_sampler_views(struct cso_context *ctx,
 
    /* reference new views */
    for (i = 0; i < count; i++) {
+      if (views[i] != info->views[i])
       pipe_sampler_view_reference(&info->views[i], views[i]);
    }
    /* unref extra old views, if any */
diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
index 072eb97..c711715 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -256,8 +256,10 @@ update_vertex_textures(struct st_context *st)
    struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
    GLuint su;
 
+   int old_num_vertex_textures = st->state.num_vertex_textures;
    st->state.num_vertex_textures = 0;
 
+   bool change_occured = false;
    /* loop over sampler units (aka tex image units) */
    for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
       struct pipe_sampler_view *sampler_view = NULL;
@@ -274,10 +276,17 @@ update_vertex_textures(struct st_context *st)
 	 st->state.num_vertex_textures = su + 1;
 
       }
+
+      if (sampler_view != st->state.sampler_vertex_views[su]) {
       pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], sampler_view);
+         change_occured = true;
+      }
    }
 
-   if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
+   if (old_num_vertex_textures != st->state.num_vertex_textures)
+      change_occured = true;
+
+   if (change_occured && st->ctx->Const.MaxVertexTextureImageUnits > 0) {
       GLuint numUnits = MIN2(st->state.num_vertex_textures,
                              st->ctx->Const.MaxVertexTextureImageUnits);
       cso_set_vertex_sampler_views(st->cso_context,
@@ -292,8 +301,10 @@ update_fragment_textures(struct st_context *st)
    struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
    GLuint su;
 
+   int old_num_textures = st->state.num_textures;
    st->state.num_textures = 0;
 
+   bool change_occured = false;
    /* loop over sampler units (aka tex image units) */
    for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
       struct pipe_sampler_view *sampler_view = NULL;
@@ -309,9 +320,16 @@ update_fragment_textures(struct st_context *st)
 
          st->state.num_textures = su + 1;
       }
+      if (st->state.sampler_views[su] != sampler_view) {
       pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view);
+         change_occured = true;
    }
+   }
+
+   if (old_num_textures != st->state.num_textures)
+      change_occured = true;
 
+   if (change_occured)
    cso_set_fragment_sampler_views(st->cso_context,
                                   st->state.num_textures,
                                   st->state.sampler_views);
-- 
1.7.5.1

From 9df2b0250725fa6cc3a6278a8b1fe210b81afb27 Mon Sep 17 00:00:00 2001
From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com>
Date: Fri, 20 May 2011 22:58:30 +0200
Subject: [PATCH 4/4] st/mesa : reduce
 cso_single_sampler/cso_single_vertex_sampler calls

Above functions called only if relevant samplers have changed.
---
 src/gallium/auxiliary/cso_cache/cso_context.c |   59 -------------------------
 src/gallium/auxiliary/cso_cache/cso_context.h |   57 +++++++++++++++++++++++-
 src/mesa/state_tracker/st_atom_sampler.c      |   18 +++++++-
 3 files changed, 72 insertions(+), 62 deletions(-)

diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index 1b5f06b..d155cea 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -48,65 +48,6 @@
 #include "cso_context.h"
 
 
-/**
- * Info related to samplers and sampler views.
- * We have one of these for fragment samplers and another for vertex samplers.
- */
-struct sampler_info
-{
-   struct {
-      void *samplers[PIPE_MAX_SAMPLERS];
-      unsigned nr_samplers;
-   } hw;
-
-   void *samplers[PIPE_MAX_SAMPLERS];
-   unsigned nr_samplers;
-
-   void *samplers_saved[PIPE_MAX_SAMPLERS];
-   unsigned nr_samplers_saved;
-
-   struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
-   unsigned nr_views;
-
-   struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS];
-   unsigned nr_views_saved;
-};
-
-
-
-struct cso_context {
-   struct pipe_context *pipe;
-   struct cso_cache *cache;
-
-   struct sampler_info fragment_samplers;
-   struct sampler_info vertex_samplers;
-
-   uint nr_vertex_buffers;
-   struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
-
-   uint nr_vertex_buffers_saved;
-   struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
-
-   /** Current and saved state.
-    * The saved state is used as a 1-deep stack.
-    */
-   void *blend, *blend_saved;
-   void *depth_stencil, *depth_stencil_saved;
-   void *rasterizer, *rasterizer_saved;
-   void *fragment_shader, *fragment_shader_saved, *geometry_shader;
-   void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved;
-   void *velements, *velements_saved;
-
-   struct pipe_clip_state clip;
-   struct pipe_clip_state clip_saved;
-
-   struct pipe_framebuffer_state fb, fb_saved;
-   struct pipe_viewport_state vp, vp_saved;
-   struct pipe_blend_color blend_color;
-   unsigned sample_mask;
-   struct pipe_stencil_ref stencil_ref, stencil_ref_saved;
-};
-
 
 static boolean delete_blend_state(struct cso_context *ctx, void *state)
 {
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h
index 00edc9f..6bc6564 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.h
+++ b/src/gallium/auxiliary/cso_cache/cso_context.h
@@ -38,7 +38,62 @@
 extern "C" {
 #endif
 
-struct cso_context;
+/**
+ * Info related to samplers and sampler views.
+ * We have one of these for fragment samplers and another for vertex samplers.
+ */
+struct sampler_info
+{
+   struct {
+      void *samplers[PIPE_MAX_SAMPLERS];
+      unsigned nr_samplers;
+   } hw;
+
+   void *samplers[PIPE_MAX_SAMPLERS];
+   unsigned nr_samplers;
+
+   void *samplers_saved[PIPE_MAX_SAMPLERS];
+   unsigned nr_samplers_saved;
+
+   struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
+   unsigned nr_views;
+
+   struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS];
+   unsigned nr_views_saved;
+};
+
+struct cso_context {
+   struct pipe_context *pipe;
+   struct cso_cache *cache;
+
+   struct sampler_info fragment_samplers;
+   struct sampler_info vertex_samplers;
+
+   uint nr_vertex_buffers;
+   struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
+
+   uint nr_vertex_buffers_saved;
+   struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
+
+   /** Current and saved state.
+    * The saved state is used as a 1-deep stack.
+    */
+   void *blend, *blend_saved;
+   void *depth_stencil, *depth_stencil_saved;
+   void *rasterizer, *rasterizer_saved;
+   void *fragment_shader, *fragment_shader_saved, *geometry_shader;
+   void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved;
+   void *velements, *velements_saved;
+
+   struct pipe_clip_state clip;
+   struct pipe_clip_state clip_saved;
+
+   struct pipe_framebuffer_state fb, fb_saved;
+   struct pipe_viewport_state vp, vp_saved;
+   struct pipe_blend_color blend_color;
+   unsigned sample_mask;
+   struct pipe_stencil_ref stencil_ref, stencil_ref_saved;
+};
 
 struct cso_context *cso_create_context( struct pipe_context *pipe );
 
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
index 06024ad..43b67bc 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -204,6 +204,7 @@ update_vertex_samplers(struct st_context *st)
       struct pipe_sampler_state *sampler = st->state.vertex_samplers + su;
 
       if (vprog->Base.SamplersUsed & (1 << su)) {
+         if (st->cso_context->vertex_samplers.samplers[su] != sampler) {
 	 GLuint texUnit;
 
 	 texUnit = vprog->Base.SamplerUnits[su];
@@ -212,11 +213,18 @@ update_vertex_samplers(struct st_context *st)
 
 	 st->state.num_vertex_samplers = su + 1;
 
+            //fprintf(stderr, "%s su=%u non-null %p [%p]\n", __FUNCTION__, su, sampler, st->cso_context->vertex_samplers.samplers[su]);
 	 cso_single_vertex_sampler(st->cso_context, su, sampler);
       } else {
+            st->state.num_vertex_samplers = su + 1;
+         }
+      } else {
+         if (st->cso_context->vertex_samplers.samplers[su] != NULL) {
+            //fprintf(stderr, "%s su=%u null\n", __FUNCTION__, su);
 	 cso_single_vertex_sampler(st->cso_context, su, NULL);
       }
    }
+   }
    cso_single_vertex_sampler_done(st->cso_context);
 }
 
@@ -234,6 +242,7 @@ update_fragment_samplers(struct st_context *st)
 
 
       if (fprog->Base.SamplersUsed & (1 << su)) {
+         if (st->cso_context->fragment_samplers.samplers[su] != sampler) {
          GLuint texUnit;
 
 	 texUnit = fprog->Base.SamplerUnits[su];
@@ -242,14 +251,19 @@ update_fragment_samplers(struct st_context *st)
 
          st->state.num_samplers = su + 1;
 
-         /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/
+            // fprintf(stderr, "%s su=%u non-null %p [%p]\n", __FUNCTION__, su, sampler, st->cso_context->fragment_samplers.samplers[su]);
          cso_single_sampler(st->cso_context, su, sampler);
+         } else {
+            st->state.num_samplers = su + 1;
+         }
       }
       else {
-         /*printf("%s su=%u null\n", __FUNCTION__, su);*/
+         if (st->cso_context->fragment_samplers.samplers[su] != NULL) {
+            // fprintf(stderr, "%s su=%u null\n", __FUNCTION__, su);
          cso_single_sampler(st->cso_context, su, NULL);
       }
    }
+   }
 
    cso_single_sampler_done(st->cso_context);
 }
-- 
1.7.5.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to