From 0c3352b6df7972fd530a901396b392d0293d27ae Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 1 Dec 2010 05:45:42 +0100 Subject: [PATCH] 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. --- src/gallium/drivers/i915/i915_context.c | 7 +++- src/gallium/drivers/i915/i915_context.h | 2 - .../drivers/i915/i915_resource_buffer.c | 3 +- src/gallium/drivers/i915/i915_state.c | 42 ++++++++++--------- src/gallium/drivers/i915/i915_state_emit.c | 3 +- 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 15454d02cfb..ea3c10b5e78 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 6dab3a14a58..b7f1fb22221 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 6e2b490f535..51482f54fc4 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 cc8bd3b0c39..4a1a4a04f6d 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 86c02976495..5a89977c26c 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 */ -- 2.30.2