Mesa (master): st/mesa: optimize constant buffer uploads

Marek Olšák mareko at kemper.freedesktop.org
Thu Jan 6 15:27:40 UTC 2011


Module: Mesa
Branch: master
Commit: 58c5e782e351621bde2693fa945d0c90d140b855
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=58c5e782e351621bde2693fa945d0c90d140b855

Author: Marek Olšák <maraeo at gmail.com>
Date:   Wed Dec 29 03:17:43 2010 +0100

st/mesa: optimize constant buffer uploads

The overhead of resource_create, transfer_inline_write, and resource_destroy
to upload constant data is very visible with some apps in sysprof, and
as such should be eliminated.

My approach uses a user buffer to pass a pointer to a driver. This gives
the driver the freedom it needs to take the fast path, which may differ
for each driver.

This commit addresses the same issue as Jakob's one that suballocates out
of a big constant buffer, but it also eliminates the copy to the buffer.

---

 src/mesa/state_tracker/st_atom_constbuf.c |   27 +++++++++++++--------------
 src/mesa/state_tracker/st_context.c       |    7 -------
 src/mesa/state_tracker/st_context.h       |    5 ++++-
 src/mesa/state_tracker/st_draw_feedback.c |   15 +++------------
 4 files changed, 20 insertions(+), 34 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
index f1d08a3..05667a7 100644
--- a/src/mesa/state_tracker/st_atom_constbuf.c
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -56,7 +56,6 @@ void st_upload_constants( struct st_context *st,
                           unsigned shader_type)
 {
    struct pipe_context *pipe = st->pipe;
-   struct pipe_resource **cbuf = &st->state.constants[shader_type];
 
    assert(shader_type == PIPE_SHADER_VERTEX ||
           shader_type == PIPE_SHADER_FRAGMENT ||
@@ -64,6 +63,7 @@ void st_upload_constants( struct st_context *st,
 
    /* update constants */
    if (params && params->NumParameters) {
+      struct pipe_resource *cbuf;
       const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4;
 
       /* Update the constants which come from fixed-function state, such as
@@ -75,11 +75,12 @@ void st_upload_constants( struct st_context *st,
 
       /* 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.
        */
-      pipe_resource_reference(cbuf, NULL );
-      *cbuf = pipe_buffer_create(pipe->screen,
-				 PIPE_BIND_CONSTANT_BUFFER,
-				 paramBytes );
+      cbuf = pipe_user_buffer_create(pipe->screen,
+                                     params->ParameterValues,
+                                     paramBytes,
+                                     PIPE_BIND_CONSTANT_BUFFER);
 
       if (ST_DEBUG & DEBUG_CONSTANTS) {
 	 debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", 
@@ -88,17 +89,15 @@ void st_upload_constants( struct st_context *st,
          _mesa_print_parameter_list(params);
       }
 
-      /* load Mesa constants into the constant buffer */
-      pipe_buffer_write(st->pipe, *cbuf,
-				    0, paramBytes,
-				    params->ParameterValues);
+      st->pipe->set_constant_buffer(st->pipe, shader_type, 0, cbuf);
+      pipe_resource_reference(&cbuf, NULL);
 
-      st->pipe->set_constant_buffer(st->pipe, shader_type, 0, *cbuf);
+      st->state.constants[shader_type].ptr = params->ParameterValues;
+      st->state.constants[shader_type].size = paramBytes;
    }
-   else if (*cbuf) {
-      st->constants.tracked_state[shader_type].dirty.mesa = 0x0;
-
-      pipe_resource_reference(cbuf, NULL);
+   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);
    }
 }
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index 21bb91f..c7f3949 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -207,12 +207,6 @@ static void st_destroy_context_priv( struct st_context *st )
       pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
    }
 
-   for (i = 0; i < Elements(st->state.constants); i++) {
-      if (st->state.constants[i]) {
-         pipe_resource_reference(&st->state.constants[i], NULL);
-      }
-   }
-
    if (st->default_texture) {
       st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
       st->default_texture = NULL;
@@ -245,7 +239,6 @@ void st_destroy_context( struct st_context *st )
 
    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
       pipe->set_constant_buffer(pipe, i, 0, NULL);
-      pipe_resource_reference(&st->state.constants[i], NULL);
    }
 
    _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 1fd8005..f20eb54 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -92,7 +92,10 @@ struct st_context
       struct pipe_sampler_state             samplers[PIPE_MAX_SAMPLERS];
       struct pipe_sampler_state             *sampler_list[PIPE_MAX_SAMPLERS];
       struct pipe_clip_state clip;
-      struct pipe_resource *constants[PIPE_SHADER_TYPES];
+      struct {
+         void *ptr;
+         unsigned size;
+      } constants[PIPE_SHADER_TYPES];
       struct pipe_framebuffer_state framebuffer;
       struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
       struct pipe_scissor_state scissor;
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
index da67c71..0591799 100644
--- a/src/mesa/state_tracker/st_draw_feedback.c
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -109,9 +109,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
    struct pipe_index_buffer ibuffer;
    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
    struct pipe_transfer *ib_transfer = NULL;
-   struct pipe_transfer *cb_transfer;
    GLuint attr, i;
-   ubyte *mapped_constants;
    const void *mapped_indices = NULL;
 
    assert(draw);
@@ -242,14 +240,10 @@ st_feedback_draw_vbo(struct gl_context *ctx,
       draw_set_mapped_index_buffer(draw, mapped_indices);
    }
 
-   /* map constant buffers */
-   mapped_constants = pipe_buffer_map(pipe,
-                                      st->state.constants[PIPE_SHADER_VERTEX],
-                                      PIPE_TRANSFER_READ,
-				      &cb_transfer);
+   /* set the constant buffer */
    draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
-                                   mapped_constants,
-                                   st->state.constants[PIPE_SHADER_VERTEX]->width0);
+                                   st->state.constants[PIPE_SHADER_VERTEX].ptr,
+                                   st->state.constants[PIPE_SHADER_VERTEX].size);
 
 
    /* draw here */
@@ -258,9 +252,6 @@ st_feedback_draw_vbo(struct gl_context *ctx,
    }
 
 
-   /* unmap constant buffers */
-   pipe_buffer_unmap(pipe, cb_transfer);
-
    /*
     * unmap vertex/index buffers
     */




More information about the mesa-commit mailing list