Hi all

I have attached two patches that should help with speed on applications that
causes a lot of constant buffers to be emitted or lot of constant state as in
the case of the second patch as it eliminates a memcpy.

The first patch just adds a offset and size argument to the set_constant_buffer
call on the context, making it possible for the state tracker sub-allocate the
buffers out a larger buffer. For ipers this is a pretty big win. Even if we did
something similar inside the drivers various locks would have to be taken
because since create buffer is a screen function.

The second patch switches from a inline write to map buffer call and points the
_mesa_load_state_parameters to it directly. For ipers this is a minor loss but
for application that has a different ratio of number of constants vs number of
times the constants changes it will probably be a win.

I have tested the patches on i915g only, unfortunately I based the i915 part
of these patches on some other work I had laying around so there is no point
in sending them out since they wont apply.

Before I go and try and change the other drivers I would like to hear some input
on these changes. So comment please, anyways have a nice weekend.

Cheers Jakob.
From 04ed7ffa9ab63734643c15923066e2360e05047a Mon Sep 17 00:00:00 2001
From: Jakob Bornecrantz <[email protected]>
Date: Fri, 3 Dec 2010 04:45:57 +0100
Subject: [RFC][PATCH 1/2] gallium: Make it possible for state trackers to suballocate out of constant buffers

In applications that does a lot of constant state changes (like ipers) this
helps a lot with speed as it removes the needless create buffers calls.
---
 src/gallium/drivers/failover/fo_context.h  |    3 +-
 src/gallium/drivers/failover/fo_state.c    |    7 +++--
 src/gallium/drivers/galahad/glhd_context.c |    8 +++++-
 src/gallium/drivers/identity/id_context.c  |    8 +++++-
 src/gallium/drivers/rbug/rbug_context.c    |    8 +++++-
 src/gallium/drivers/trace/tr_context.c     |    7 ++++-
 src/gallium/include/pipe/p_context.h       |    3 +-
 src/mesa/state_tracker/st_atom_constbuf.c  |   33 ++++++++++++++++++---------
 src/mesa/state_tracker/st_context.c        |    4 +-
 src/mesa/state_tracker/st_context.h        |    2 +
 src/mesa/state_tracker/st_draw_feedback.c  |    4 +-
 11 files changed, 59 insertions(+), 28 deletions(-)

diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h
index 1afa6c9..25790b5 100644
--- a/src/gallium/drivers/failover/fo_context.h
+++ b/src/gallium/drivers/failover/fo_context.h
@@ -137,7 +137,8 @@ failover_context( struct pipe_context *pipe )
  */
 void
 failover_set_constant_buffer(struct pipe_context *pipe,
-                             uint shader, uint index,
+                             unsigned shader, unsigned index,
+                             unsigned offset, unsigned size,
                              struct pipe_resource *resource);
 
 
diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c
index c265f38..cff02f0 100644
--- a/src/gallium/drivers/failover/fo_state.c
+++ b/src/gallium/drivers/failover/fo_state.c
@@ -602,7 +602,8 @@ failover_set_index_buffer(struct pipe_context *pipe,
 
 void
 failover_set_constant_buffer(struct pipe_context *pipe,
-                             uint shader, uint index,
+                             unsigned shader, unsigned index,
+                             unsigned offset, unsigned size,
                              struct pipe_resource *res)
 {
    struct failover_context *failover = failover_context(pipe);
@@ -610,8 +611,8 @@ failover_set_constant_buffer(struct pipe_context *pipe,
    assert(shader < PIPE_SHADER_TYPES);
    assert(index == 0);
 
-   failover->sw->set_constant_buffer(failover->sw, shader, index, res);
-   failover->hw->set_constant_buffer(failover->hw, shader, index, res);
+   failover->sw->set_constant_buffer(failover->sw, shader, index, offset, size, res);
+   failover->hw->set_constant_buffer(failover->hw, shader, index, offset, size, res);
 }
 
 
diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c
index a572ad2..954ded3 100644
--- a/src/gallium/drivers/galahad/glhd_context.c
+++ b/src/gallium/drivers/galahad/glhd_context.c
@@ -454,8 +454,10 @@ galahad_set_sample_mask(struct pipe_context *_pipe,
 
 static void
 galahad_set_constant_buffer(struct pipe_context *_pipe,
-                             uint shader,
-                             uint index,
+                             unsigned shader,
+                             unsigned index,
+                             unsigned offset,
+                             unsigned size,
                              struct pipe_resource *_resource)
 {
    struct galahad_context *glhd_pipe = galahad_context(_pipe);
@@ -485,6 +487,8 @@ galahad_set_constant_buffer(struct pipe_context *_pipe,
    pipe->set_constant_buffer(pipe,
                              shader,
                              index,
+                             offset,
+                             size,
                              resource);
 }
 
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index 3efbd6a..bf08e18 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -409,8 +409,10 @@ identity_set_sample_mask(struct pipe_context *_pipe,
 
 static void
 identity_set_constant_buffer(struct pipe_context *_pipe,
-                             uint shader,
-                             uint index,
+                             unsigned shader,
+                             unsigned index,
+                             unsigned offset,
+                             unsigned size,
                              struct pipe_resource *_resource)
 {
    struct identity_context *id_pipe = identity_context(_pipe);
@@ -427,6 +429,8 @@ identity_set_constant_buffer(struct pipe_context *_pipe,
    pipe->set_constant_buffer(pipe,
                              shader,
                              index,
+                             offset,
+                             size,
                              resource);
 }
 
diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c
index 94e57e4..1772b96 100644
--- a/src/gallium/drivers/rbug/rbug_context.c
+++ b/src/gallium/drivers/rbug/rbug_context.c
@@ -511,8 +511,10 @@ rbug_set_clip_state(struct pipe_context *_pipe,
 
 static void
 rbug_set_constant_buffer(struct pipe_context *_pipe,
-                         uint shader,
-                         uint index,
+                         unsigned shader,
+                         unsigned index,
+                         unsigned offset,
+                         unsigned size,
                          struct pipe_resource *_resource)
 {
    struct rbug_context *rb_pipe = rbug_context(_pipe);
@@ -529,6 +531,8 @@ rbug_set_constant_buffer(struct pipe_context *_pipe,
    pipe->set_constant_buffer(pipe,
                              shader,
                              index,
+                             offset,
+                             size,
                              resource);
 }
 
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 2fdb6c9..0836409 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -716,7 +716,8 @@ trace_context_set_sample_mask(struct pipe_context *_pipe,
 
 static INLINE void
 trace_context_set_constant_buffer(struct pipe_context *_pipe,
-                                  uint shader, uint index,
+                                  unsigned shader, unsigned index,
+                                  unsigned offset, unsigned size,
                                   struct pipe_resource *buffer)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
@@ -731,9 +732,11 @@ trace_context_set_constant_buffer(struct pipe_context *_pipe,
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(uint, shader);
    trace_dump_arg(uint, index);
+   trace_dump_arg(uint, offset);
+   trace_dump_arg(uint, size);
    trace_dump_arg(ptr, buffer);
 
-   pipe->set_constant_buffer(pipe, shader, index, buffer);
+   pipe->set_constant_buffer(pipe, shader, index, offset, size, buffer);
 
    trace_dump_call_end();
 }
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 589cac2..a9e7c97 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -197,7 +197,8 @@ struct pipe_context {
                             const struct pipe_clip_state * );
 
    void (*set_constant_buffer)( struct pipe_context *,
-                                uint shader, uint index,
+                                unsigned shader, unsigned index,
+                                unsigned offset, unsigned size,
                                 struct pipe_resource *buf );
 
    void (*set_framebuffer_state)( struct pipe_context *,
diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
index 8d1dc79..470094b 100644
--- a/src/mesa/state_tracker/st_atom_constbuf.c
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -57,6 +57,8 @@ void st_upload_constants( struct st_context *st,
 {
    struct pipe_context *pipe = st->pipe;
    struct pipe_resource **cbuf = &st->state.constants[shader_type];
+   unsigned offset = st->state.constants_offsets[shader_type];
+   unsigned size = st->state.constants_sizes[shader_type];
 
    assert(shader_type == PIPE_SHADER_VERTEX ||
           shader_type == PIPE_SHADER_FRAGMENT ||
@@ -68,13 +70,17 @@ void st_upload_constants( struct st_context *st,
 
       _mesa_load_state_parameters(st->ctx, params);
 
-      /* We always need to get a new buffer, to keep the drivers simple and
-       * avoid gratuitous rendering synchronization.
-       */
-      pipe_resource_reference(cbuf, NULL );
-      *cbuf = pipe_buffer_create(pipe->screen,
-				 PIPE_BIND_CONSTANT_BUFFER,
-				 paramBytes );
+      /* Advance the offset or create a new buffer. */
+      if (!*cbuf || offset + size + paramBytes > (*cbuf)->width0) {
+         pipe_resource_reference(cbuf, NULL);
+         *cbuf = pipe_buffer_create(pipe->screen,
+                                    PIPE_BIND_CONSTANT_BUFFER,
+                                    MAX2(paramBytes, 4*4096));
+         offset = 0;
+      } else {
+         offset += size;
+      }
+      size = paramBytes;
 
       if (ST_DEBUG & DEBUG_CONSTANTS) {
 	 debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", 
@@ -85,17 +91,22 @@ void st_upload_constants( struct st_context *st,
 
       /* load Mesa constants into the constant buffer */
       pipe_buffer_write(st->pipe, *cbuf,
-				    0, paramBytes,
-				    params->ParameterValues);
+                        offset, paramBytes,
+                        params->ParameterValues);
 
-      st->pipe->set_constant_buffer(st->pipe, shader_type, 0, *cbuf);
+      st->pipe->set_constant_buffer(st->pipe, shader_type, 0, offset, paramBytes, *cbuf);
    }
    else if (*cbuf) {
       st->constants.tracked_state[shader_type].dirty.mesa = 0x0;
 
       pipe_resource_reference(cbuf, NULL);
-      st->pipe->set_constant_buffer(st->pipe, shader_type, 0, NULL);
+      offset = 0;
+      size = 0;
+      st->pipe->set_constant_buffer(st->pipe, shader_type, 0, 0, 0, NULL);
    }
+
+   st->state.constants_offsets[shader_type] = offset;
+   st->state.constants_sizes[shader_type] = size;
 }
 
 
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index d6628b1..303b924 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -244,8 +244,8 @@ void st_destroy_context( struct st_context *st )
    pipe->set_index_buffer(pipe, NULL);
 
    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
-      pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, NULL);
-      pipe_resource_reference(&st->state.constants[PIPE_SHADER_VERTEX], NULL);
+      pipe->set_constant_buffer(pipe, i, 0, 0, 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 d342c0c..7adc219 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -94,6 +94,8 @@ struct st_context
       struct pipe_sampler_state             *sampler_list[PIPE_MAX_SAMPLERS];
       struct pipe_clip_state clip;
       struct pipe_resource *constants[PIPE_SHADER_TYPES];
+      unsigned constants_offsets[PIPE_SHADER_TYPES];
+      unsigned constants_sizes[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 7f392fc..d83a19a 100644
--- a/src/mesa/state_tracker/st_draw_feedback.c
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -248,8 +248,8 @@ st_feedback_draw_vbo(struct gl_context *ctx,
                                       PIPE_TRANSFER_READ,
 				      &cb_transfer);
    draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
-                                   mapped_constants,
-                                   st->state.constants[PIPE_SHADER_VERTEX]->width0);
+                                   mapped_constants + st->state.constants_offsets[PIPE_SHADER_VERTEX],
+                                   st->state.constants_sizes[PIPE_SHADER_VERTEX]);
 
 
    /* draw here */
-- 
1.7.0.4

From 05d4b8ec9b0315d5436d6a31ad1fbf48a8a8d659 Mon Sep 17 00:00:00 2001
From: Jakob Bornecrantz <[email protected]>
Date: Fri, 3 Dec 2010 20:03:57 +0100
Subject: [RFC][PATCH 2/2] st/mesa: Map constant buffers instead of inline write

---
 src/mesa/program/prog_statevars.c         |   24 ++++++++++++++++++++++++
 src/mesa/program/prog_statevars.h         |    5 +++++
 src/mesa/state_tracker/st_atom_constbuf.c |   20 +++++++++++++++++---
 3 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index baac29f..88a16c9 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -1068,6 +1068,30 @@ _mesa_load_state_parameters(struct gl_context *ctx,
    }
 }
 
+void
+_mesa_load_state_parameters_to(struct gl_context *ctx,
+                               struct gl_program_parameter_list *paramList,
+                               void *ptr)
+{
+   GLuint i;
+
+   if (!paramList)
+      return;
+
+   /*assert(ctx->Driver.NeedFlush == 0);*/
+
+   for (i = 0; i < paramList->NumParameters; i++) {
+      if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
+         uintptr_t offset = (uintptr_t)&paramList->ParameterValues[i] -
+                            (uintptr_t)paramList->ParameterValues;
+         _mesa_fetch_state(ctx,
+                           (gl_state_index *) paramList->Parameters[i].StateIndexes,
+                           (void*)((char*)ptr + offset));
+      }
+   }
+}
+
+
 
 /**
  * Copy the 16 elements of a matrix into four consecutive program
diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h
index 6e5be53..3637f8a 100644
--- a/src/mesa/program/prog_statevars.h
+++ b/src/mesa/program/prog_statevars.h
@@ -128,6 +128,11 @@ extern void
 _mesa_load_state_parameters(struct gl_context *ctx,
                             struct gl_program_parameter_list *paramList);
 
+extern void
+_mesa_load_state_parameters_to(struct gl_context *ctx,
+                               struct gl_program_parameter_list *paramList,
+                               void *offset);
+
 
 extern GLbitfield
 _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]);
diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
index 470094b..45e5f9a 100644
--- a/src/mesa/state_tracker/st_atom_constbuf.c
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -67,8 +67,8 @@ void st_upload_constants( struct st_context *st,
    /* update constants */
    if (params && params->NumParameters) {
       const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4;
-
-      _mesa_load_state_parameters(st->ctx, params);
+      struct pipe_transfer *transfer = NULL;
+      void *ptr;
 
       /* Advance the offset or create a new buffer. */
       if (!*cbuf || offset + size + paramBytes > (*cbuf)->width0) {
@@ -89,10 +89,24 @@ void st_upload_constants( struct st_context *st,
          _mesa_print_parameter_list(params);
       }
 
-      /* load Mesa constants into the constant buffer */
+#if 1
+      ptr = pipe_buffer_map_range(st->pipe, *cbuf, offset, size,
+                                  (PIPE_TRANSFER_WRITE |
+                                   PIPE_TRANSFER_NOOVERWRITE),
+                                  &transfer);
+
+      _mesa_load_state_parameters_to(st->ctx, params, (char*)ptr + offset);
+
+      pipe_transfer_unmap(st->pipe, transfer);
+      pipe_transfer_destroy(st->pipe, transfer);
+#else
+      (void)ptr;
+      (void)transfer;
+      _mesa_load_state_parameters(st->ctx, params);
       pipe_buffer_write(st->pipe, *cbuf,
                         offset, paramBytes,
                         params->ParameterValues);
+#endif
 
       st->pipe->set_constant_buffer(st->pipe, shader_type, 0, offset, paramBytes, *cbuf);
    }
-- 
1.7.0.4

_______________________________________________
mesa-dev mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to