summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/i915
diff options
context:
space:
mode:
authorJakob Bornecrantz <wallbraker@gmail.com>2010-12-01 05:45:42 +0100
committerJakob Bornecrantz <wallbraker@gmail.com>2011-01-21 20:53:29 +0100
commit0c3352b6df7972fd530a901396b392d0293d27ae (patch)
tree951a343ab506c1f3c99e2f42dbae5d5be840e2b9 /src/gallium/drivers/i915
parent2e60aa511dd232f88697d1cc2091442caaef79b2 (diff)
i915g: Don't do unnecessary copies of constants
Even tho st/mesa use user buffers for constants align buffers other state trackers doesn't use user buffers.
Diffstat (limited to 'src/gallium/drivers/i915')
-rw-r--r--src/gallium/drivers/i915/i915_context.c7
-rw-r--r--src/gallium/drivers/i915/i915_context.h2
-rw-r--r--src/gallium/drivers/i915/i915_resource_buffer.c3
-rw-r--r--src/gallium/drivers/i915/i915_state.c42
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c3
5 files changed, 32 insertions, 25 deletions
diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c
index 15454d02cf..ea3c10b5e7 100644
--- a/src/gallium/drivers/i915/i915_context.c
+++ b/src/gallium/drivers/i915/i915_context.c
@@ -80,7 +80,7 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
if (cbuf_dirty) {
draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
- i915->current.constants[PIPE_SHADER_VERTEX],
+ i915_buffer(i915->constants[PIPE_SHADER_VERTEX])->data,
(i915->current.num_user_constants[PIPE_SHADER_VERTEX] *
4 * sizeof(float)));
}
@@ -127,6 +127,11 @@ static void i915_destroy(struct pipe_context *pipe)
}
pipe_surface_reference(&i915->framebuffer.zsbuf, NULL);
+ /* unbind constant buffers */
+ for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+ pipe_resource_reference(&i915->constants[i], NULL);
+ }
+
FREE(i915);
}
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index 6dab3a14a5..b7f1fb2222 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -136,7 +136,6 @@ struct i915_state
unsigned immediate[I915_MAX_IMMEDIATE];
unsigned dynamic[I915_MAX_DYNAMIC];
- float constants[PIPE_SHADER_TYPES][I915_MAX_CONSTANT][4];
/** number of constants passed in through a constant buffer */
uint num_user_constants[PIPE_SHADER_TYPES];
@@ -214,7 +213,6 @@ struct i915_context {
struct pipe_blend_color blend_color;
struct pipe_stencil_ref stencil_ref;
struct pipe_clip_state clip;
- /* XXX unneded */
struct pipe_resource *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c
index 6e2b490f53..51482f54fc 100644
--- a/src/gallium/drivers/i915/i915_resource_buffer.c
+++ b/src/gallium/drivers/i915/i915_resource_buffer.c
@@ -147,8 +147,7 @@ i915_buffer_create(struct pipe_screen *screen,
buf->b.vtbl = &i915_buffer_vtbl;
pipe_reference_init(&buf->b.b.reference, 1);
buf->b.b.screen = screen;
-
- buf->data = MALLOC(template->width0);
+ buf->data = align_malloc(template->width0, 16);
buf->free_on_destroy = TRUE;
if (!buf->data)
diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c
index cc8bd3b0c3..4a1a4a04f6 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -525,36 +525,40 @@ static void i915_set_constant_buffer(struct pipe_context *pipe,
struct pipe_resource *buf)
{
struct i915_context *i915 = i915_context(pipe);
- draw_flush(i915->draw);
+ unsigned new_num = 0;
+ boolean diff = TRUE;
+
/* XXX don't support geom shaders now */
if (shader == PIPE_SHADER_GEOMETRY)
return;
- /* Make a copy of shader constants.
- * During fragment program translation we may add additional
- * constants to the array.
- *
- * We want to consider the situation where some user constants
- * (ex: a material color) may change frequently but the shader program
- * stays the same. In that case we should only be updating the first
- * N constants, leaving any extras from shader translation alone.
- */
+ /* if we have a new buffer compare it with the old one */
if (buf) {
struct i915_buffer *ir = i915_buffer(buf);
+ struct pipe_resource *old_buf = i915->constants[shader];
+ struct i915_buffer *old = old_buf ? i915_buffer(old_buf) : NULL;
- if (!memcmp(i915->current.constants[shader], ir->data, ir->b.b.width0))
- return;
+ new_num = ir->b.b.width0 / 4 * sizeof(float);
- memcpy(i915->current.constants[shader], ir->data, ir->b.b.width0);
- i915->current.num_user_constants[shader] = (ir->b.b.width0 /
- 4 * sizeof(float));
- }
- else {
- i915->current.num_user_constants[shader] = 0;
+ if (old && new_num != i915->current.num_user_constants[shader])
+ diff = memcmp(old->data, ir->data, ir->b.b.width0);
+ } else {
+ diff = i915->current.num_user_constants[shader] != 0;
}
- i915->dirty |= shader == PIPE_SHADER_VERTEX ? I915_NEW_VS_CONSTANTS : I915_NEW_FS_CONSTANTS;
+ /*
+ * flush before updateing the state.
+ * XXX: looks like its okay to skip the flush for vertex cbufs
+ */
+ if (diff && shader == PIPE_SHADER_FRAGMENT)
+ draw_flush(i915->draw);
+
+ pipe_resource_reference(&i915->constants[shader], buf);
+ i915->current.num_user_constants[shader] = new_num;
+
+ if (diff)
+ i915->dirty |= shader == PIPE_SHADER_VERTEX ? I915_NEW_VS_CONSTANTS : I915_NEW_FS_CONSTANTS;
}
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 86c0297649..5a89977c26 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -367,7 +367,8 @@ i915_emit_hardware_state(struct i915_context *i915 )
const uint *c;
if (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER) {
/* grab user-defined constant */
- c = (uint *) i915->current.constants[PIPE_SHADER_FRAGMENT][i];
+ c = (uint *) i915_buffer(i915->constants[PIPE_SHADER_FRAGMENT])->data;
+ c += 4 * i;
}
else {
/* emit program constant */