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)¶mList->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