Hi, I've built several patches trying to reduce the propagation of state changes.
They are proof-of-concept, and I'd like to know what you think about them, mainly : - do you think it's worth it ? it adds complexity to state trackers, but it avoids some possibly expensive driver function calls. - if yes, what would you be the best design approach for this ? For reference, Airlied built a patch similar to my 4th one, but with a different approach (adding an incrementing 'Generation' field to struct instead of comparing pointers) : http://fpaste.org/QTng/ (all tests done using 2.6.38.3/64 bits/r600g) == Regression ? == - piglit quick.tests with all 4 patches applied => no regression == Some simple benchmarking == Successive patches applied : * 01 : st_atom_constbuf * 02 : st_atom_rasterizer * 03 : st_atom_texture * 04 : st_atom_sampler mesa-demos: drawoverhead (draws/sec): * Draw only : 2100t * Draw w/ nop sc : 2100t * Draw w/ sc : |git from 05/18 | +01 | +01->02 | +01->03 | +01->04 | | 227t | 328t | 328t | 350t | 365t | openarena (anholt benchmark, 3 runs average) : |git from 05/18 | +01 | +01->02 | +01->03 | +01->04 | | 74.6 | 75.0 | 74.4 | 75.7 | 74.7 | -- Pierre-Eric
From fc58de87ddaf943942a81b0ec4deb8a0ce205534 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com> Date: Fri, 20 May 2011 22:52:43 +0200 Subject: [PATCH 1/4] st/mesa : reduced constant buffers upload This patch add a checksum like computation before a upload constant buffer. If the checksum equals the previous one, the upload is skipped. --- src/mesa/state_tracker/st_atom_constbuf.c | 35 +++++++++++++++++++++++----- src/mesa/state_tracker/st_atom_constbuf.h | 5 ++- src/mesa/state_tracker/st_cb_bitmap.c | 2 +- src/mesa/state_tracker/st_cb_drawpixels.c | 4 +- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c index 05667a7..cccd7e7 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.c +++ b/src/mesa/state_tracker/st_atom_constbuf.c @@ -51,9 +51,10 @@ * constant buffer. * \param shader_type either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT */ -void st_upload_constants( struct st_context *st, +int st_upload_constants( struct st_context *st, struct gl_program_parameter_list *params, - unsigned shader_type) + unsigned shader_type, + int previousTotal) { struct pipe_context *pipe = st->pipe; @@ -73,6 +74,24 @@ void st_upload_constants( struct st_context *st, */ _mesa_load_state_parameters(st->ctx, params); + unsigned int total = (((unsigned int) st) ^ params->NumParameters), tmp; + // fprintf(stdout, "[%p] Dump (%d bytes) : \n", st, paramBytes); + for(int i=0; i<params->NumParameters; i++) { + for(int j=0; j<4; j++) { + memcpy(&tmp, ¶ms->ParameterValues[i][j], sizeof(int)); + total = (total>>(sizeof(int)-1))^(total<<1)^tmp; + + /*for(int k=0; k<4; ++k) + fprintf(stdout, "%02x ", ((unsigned char*) &tmp)[k]);*/ + } + //fprintf(stdout, "\n"); + } + //fprintf(stdout, " Total : %08x\n", total); + if (previousTotal == total) { + //fprintf(stdout, "Early quit !\n"); + return total; + } + /* 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. @@ -81,7 +100,6 @@ void st_upload_constants( struct st_context *st, params->ParameterValues, paramBytes, PIPE_BIND_CONSTANT_BUFFER); - if (ST_DEBUG & DEBUG_CONSTANTS) { debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", __FUNCTION__, shader_type, params->NumParameters, @@ -94,12 +112,14 @@ void st_upload_constants( struct st_context *st, st->state.constants[shader_type].ptr = params->ParameterValues; st->state.constants[shader_type].size = paramBytes; + return total; } 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); } + return 0; } @@ -108,10 +128,11 @@ void st_upload_constants( struct st_context *st, */ static void update_vs_constants(struct st_context *st ) { + static int previous_total = -1; struct st_vertex_program *vp = st->vp; struct gl_program_parameter_list *params = vp->Base.Base.Parameters; - st_upload_constants( st, params, PIPE_SHADER_VERTEX ); + previous_total = st_upload_constants( st, params, PIPE_SHADER_VERTEX, previous_total ); } @@ -131,10 +152,10 @@ const struct st_tracked_state st_update_vs_constants = { */ static void update_fs_constants(struct st_context *st ) { + static int previous_total = -1; struct st_fragment_program *fp = st->fp; struct gl_program_parameter_list *params = fp->Base.Base.Parameters; - - st_upload_constants( st, params, PIPE_SHADER_FRAGMENT ); + previous_total = st_upload_constants( st, params, PIPE_SHADER_FRAGMENT, previous_total ); } @@ -156,7 +177,7 @@ static void update_gs_constants(struct st_context *st ) if (gp) { params = gp->Base.Base.Parameters; - st_upload_constants( st, params, PIPE_SHADER_GEOMETRY ); + st_upload_constants( st, params, PIPE_SHADER_GEOMETRY, -1 ); } } diff --git a/src/mesa/state_tracker/st_atom_constbuf.h b/src/mesa/state_tracker/st_atom_constbuf.h index 97b0766..8749bf5 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.h +++ b/src/mesa/state_tracker/st_atom_constbuf.h @@ -33,9 +33,10 @@ struct gl_program_parameter_list; struct st_context; -void st_upload_constants( struct st_context *st, +int st_upload_constants( struct st_context *st, struct gl_program_parameter_list *params, - unsigned id); + unsigned id, + int previousTotal); #endif /* ST_ATOM_CONSTBUF_H */ diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 49b1960..0ffc729 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -437,7 +437,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); - st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT, -1); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 9948f8d..57ede72 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -1034,7 +1034,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, } /* update fragment program constants */ - st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT, -1); /* draw with textured quad */ { @@ -1370,7 +1370,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, } /* update fragment program constants */ - st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT, -1); if (rbRead->Base.Wrapped) -- 1.7.5.1
From 50498d5fe884b1b5ee1a007fe21a5b3d6fe161ba Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com> Date: Fri, 20 May 2011 22:54:19 +0200 Subject: [PATCH 2/4] st/mesa : reduce 'cso_set_rasterizer' calls count cso_set_rasterizer is now called only if "struct pipe_rasterizer_state" content actually changed. --- src/mesa/state_tracker/st_atom_rasterizer.c | 178 ++++++++++++++++++--------- 1 files changed, 117 insertions(+), 61 deletions(-) diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 250cbb2..127d611 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -58,17 +58,25 @@ static GLuint translate_fill( GLenum mode ) static void update_raster_state( struct st_context *st ) { struct gl_context *ctx = st->ctx; - struct pipe_rasterizer_state *raster = &st->state.rasterizer; + struct pipe_rasterizer_state tmp; + struct pipe_rasterizer_state *raster = &tmp; // &st->state.rasterizer; const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current; const struct gl_fragment_program *fragProg = ctx->FragmentProgram._Current; uint i; - memset(raster, 0, sizeof(*raster)); + bool change_occured = false; +#define ASSIGN(field, value) { if (field!=value) { change_occured = true; field = value; } } +#define EVAL_AND_ASSIGN(field, value, T) { T __tmp = (value); if (field!=__tmp) { change_occured = true; field = __tmp; } } + + /* Only the changing fields are going to be updated and the change_occured flag will be set it needed + */ + memcpy(raster, &st->state.rasterizer, sizeof(*raster)); /* _NEW_POLYGON, _NEW_BUFFERS */ + if ((st->dirty.mesa & _NEW_POLYGON) | (st->dirty.mesa & _NEW_BUFFERS)) { - raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW); + unsigned v = (ctx->Polygon.FrontFace == GL_CCW); /* * Gallium's surfaces are Y=0=TOP orientation. OpenGL is the @@ -78,17 +86,19 @@ static void update_raster_state( struct st_context *st ) */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { /* Drawing to an FBO. The viewport will be inverted. */ - raster->front_ccw ^= 1; + v ^= 1; } + + ASSIGN(raster->front_ccw, v) } /* _NEW_LIGHT */ - if (ctx->Light.ShadeModel == GL_FLAT) - raster->flatshade = 1; - - if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION_EXT) - raster->flatshade_first = 1; + if (st->dirty.mesa & _NEW_LIGHT) + { + EVAL_AND_ASSIGN(raster->flatshade, (ctx->Light.ShadeModel == GL_FLAT), bool) + EVAL_AND_ASSIGN(raster->flatshade_first, (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION_EXT), bool) + } /* _NEW_LIGHT | _NEW_PROGRAM * @@ -96,170 +106,216 @@ static void update_raster_state( struct st_context *st ) * GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs/shaders (when * GL_VERTEX_PROGRAM_TWO_SIDE is set). Note the logic here. */ + if ((st->dirty.mesa & _NEW_LIGHT) | (st->dirty.mesa & _NEW_PROGRAM)) + { + unsigned light_twoside = 0; if (ctx->VertexProgram._Current) { if (ctx->VertexProgram._Enabled || (ctx->Shader.CurrentVertexProgram && ctx->Shader.CurrentVertexProgram->LinkStatus)) { /* user-defined vertex program or shader */ - raster->light_twoside = ctx->VertexProgram.TwoSideEnabled; + light_twoside = ctx->VertexProgram.TwoSideEnabled; } else { /* TNL-generated program */ - raster->light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide; + light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide; } } else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { - raster->light_twoside = 1; + light_twoside = 1; + } + ASSIGN(raster->light_twoside, light_twoside); + ASSIGN(raster->clamp_vertex_color, raster->clamp_vertex_color); } - - raster->clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_POLYGON */ + if ((st->dirty.mesa & _NEW_POLYGON)) + { if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: - raster->cull_face = PIPE_FACE_FRONT; + ASSIGN(raster->cull_face, PIPE_FACE_FRONT) break; case GL_BACK: - raster->cull_face = PIPE_FACE_BACK; + ASSIGN(raster->cull_face, PIPE_FACE_BACK) break; case GL_FRONT_AND_BACK: - raster->cull_face = PIPE_FACE_FRONT_AND_BACK; + ASSIGN(raster->cull_face, PIPE_FACE_FRONT_AND_BACK) break; } } else { - raster->cull_face = PIPE_FACE_NONE; + ASSIGN(raster->cull_face, PIPE_FACE_NONE) } + /* _NEW_POLYGON */ { - raster->fill_front = translate_fill( ctx->Polygon.FrontMode ); - raster->fill_back = translate_fill( ctx->Polygon.BackMode ); + unsigned fill_front = translate_fill( ctx->Polygon.FrontMode ); + unsigned fill_back = translate_fill( ctx->Polygon.BackMode ); /* Simplify when culling is active: */ if (raster->cull_face & PIPE_FACE_FRONT) { - raster->fill_front = raster->fill_back; + fill_front = fill_back; } if (raster->cull_face & PIPE_FACE_BACK) { - raster->fill_back = raster->fill_front; + fill_back = fill_front; } + ASSIGN(raster->fill_front, fill_front) + ASSIGN(raster->fill_back, fill_back) } /* _NEW_POLYGON */ if (ctx->Polygon.OffsetUnits != 0.0 || ctx->Polygon.OffsetFactor != 0.0) { - raster->offset_point = ctx->Polygon.OffsetPoint; - raster->offset_line = ctx->Polygon.OffsetLine; - raster->offset_tri = ctx->Polygon.OffsetFill; + ASSIGN(raster->offset_point, ctx->Polygon.OffsetPoint) + ASSIGN(raster->offset_line, ctx->Polygon.OffsetLine) + ASSIGN(raster->offset_tri, ctx->Polygon.OffsetFill) + } else { + ASSIGN(raster->offset_point, 0) + ASSIGN(raster->offset_line, 0) + ASSIGN(raster->offset_tri, 0) } if (ctx->Polygon.OffsetPoint || ctx->Polygon.OffsetLine || ctx->Polygon.OffsetFill) { - raster->offset_units = ctx->Polygon.OffsetUnits; - raster->offset_scale = ctx->Polygon.OffsetFactor; + ASSIGN(raster->offset_units, ctx->Polygon.OffsetUnits) + ASSIGN(raster->offset_scale, ctx->Polygon.OffsetFactor) + } else { + ASSIGN(raster->offset_units, 0) + ASSIGN(raster->offset_scale, 0) } - if (ctx->Polygon.SmoothFlag) - raster->poly_smooth = 1; - - if (ctx->Polygon.StippleFlag) - raster->poly_stipple_enable = 1; + ASSIGN(raster->poly_smooth, ctx->Polygon.SmoothFlag) + ASSIGN(raster->poly_stipple_enable, ctx->Polygon.StippleFlag) + } /* _NEW_POINT */ - raster->point_size = ctx->Point.Size; - - if (!ctx->Point.PointSprite && ctx->Point.SmoothFlag) - raster->point_smooth = 1; + if (st->dirty.mesa & _NEW_POINT) + { + EVAL_AND_ASSIGN(raster->point_smooth, (!ctx->Point.PointSprite && ctx->Point.SmoothFlag), bool) + } /* _NEW_POINT | _NEW_PROGRAM */ + if ((st->dirty.mesa & _NEW_POINT) | (st->dirty.mesa & _NEW_PROGRAM)) + { if (ctx->Point.PointSprite) { /* origin */ if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^ (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM)) - raster->sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; + ASSIGN(raster->sprite_coord_mode, PIPE_SPRITE_COORD_UPPER_LEFT) else - raster->sprite_coord_mode = PIPE_SPRITE_COORD_LOWER_LEFT; + ASSIGN(raster->sprite_coord_mode, PIPE_SPRITE_COORD_LOWER_LEFT) /* Coord replacement flags. If bit 'k' is set that means * that we need to replace GENERIC[k] attrib with an automatically * computed texture coord. */ + unsigned sprite_coord_enable = 0; for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { if (ctx->Point.CoordReplace[i]) { - raster->sprite_coord_enable |= 1 << i; + sprite_coord_enable |= 1 << i; } } if (fragProg->Base.InputsRead & FRAG_BIT_PNTC) { - raster->sprite_coord_enable |= + sprite_coord_enable |= 1 << (FRAG_ATTRIB_PNTC - FRAG_ATTRIB_TEX0); } - - raster->point_quad_rasterization = 1; + ASSIGN(raster->sprite_coord_enable, sprite_coord_enable) + ASSIGN(raster->point_quad_rasterization, 1) + } else { + ASSIGN(raster->sprite_coord_mode, 0) + ASSIGN(raster->sprite_coord_enable, 0) + ASSIGN(raster->point_quad_rasterization, 0) + } } /* ST_NEW_VERTEX_PROGRAM */ + if (st->dirty.st & ST_NEW_VERTEX_PROGRAM) + { + bool point_size_per_vertex = FALSE; if (vertProg) { if (vertProg->Base.Id == 0) { if (vertProg->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) { /* generated program which emits point size */ - raster->point_size_per_vertex = TRUE; + point_size_per_vertex = TRUE; } } else if (ctx->VertexProgram.PointSizeEnabled) { /* user-defined program and GL_VERTEX_PROGRAM_POINT_SIZE set */ - raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled; + point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled; + } } + + ASSIGN(raster->point_size_per_vertex, point_size_per_vertex) } + if (!raster->point_size_per_vertex) { /* clamp size now */ - raster->point_size = CLAMP(ctx->Point.Size, + EVAL_AND_ASSIGN(raster->point_size, CLAMP( + ctx->Point.Size, ctx->Point.MinSize, - ctx->Point.MaxSize); + ctx->Point.MaxSize), float) + } else { + ASSIGN(raster->point_size, ctx->Point.Size); } /* _NEW_LINE */ - raster->line_smooth = ctx->Line.SmoothFlag; + if (st->dirty.mesa & _NEW_LINE) + { + ASSIGN(raster->line_smooth, ctx->Line.SmoothFlag) + if (ctx->Line.SmoothFlag) { - raster->line_width = CLAMP(ctx->Line.Width, + EVAL_AND_ASSIGN(raster->line_width, CLAMP(ctx->Line.Width, ctx->Const.MinLineWidthAA, - ctx->Const.MaxLineWidthAA); + ctx->Const.MaxLineWidthAA), float) } else { - raster->line_width = CLAMP(ctx->Line.Width, + EVAL_AND_ASSIGN(raster->line_width, CLAMP(ctx->Line.Width, ctx->Const.MinLineWidth, - ctx->Const.MaxLineWidth); + ctx->Const.MaxLineWidth), float) } - raster->line_stipple_enable = ctx->Line.StippleFlag; - raster->line_stipple_pattern = ctx->Line.StipplePattern; + ASSIGN(raster->line_stipple_enable, ctx->Line.StippleFlag) + ASSIGN(raster->line_stipple_pattern, ctx->Line.StipplePattern) /* GL stipple factor is in [1,256], remap to [0, 255] here */ - raster->line_stipple_factor = ctx->Line.StippleFactor - 1; + ASSIGN(raster->line_stipple_factor, ctx->Line.StippleFactor - 1) + } /* _NEW_MULTISAMPLE */ - if (ctx->Multisample._Enabled || st->force_msaa) - raster->multisample = 1; + if (st->dirty.mesa & _NEW_MULTISAMPLE) + { + EVAL_AND_ASSIGN(raster->multisample, (ctx->Multisample._Enabled || st->force_msaa), bool) + } /* _NEW_SCISSOR */ - if (ctx->Scissor.Enabled) - raster->scissor = 1; + if (st->dirty.mesa & _NEW_SCISSOR) + { + ASSIGN(raster->scissor, ctx->Scissor.Enabled) + } /* _NEW_FRAG_CLAMP */ - raster->clamp_fragment_color = ctx->Color._ClampFragmentColor; + if (st->dirty.mesa & _NEW_FRAG_CLAMP) + { + ASSIGN(raster->clamp_fragment_color, ctx->Color._ClampFragmentColor) + } - raster->gl_rasterization_rules = 1; + ASSIGN(raster->gl_rasterization_rules, 1) - cso_set_rasterizer(st->cso_context, raster); + if (change_occured) { + memcpy(&st->state.rasterizer, raster, sizeof(struct pipe_rasterizer_state)); + cso_set_rasterizer(st->cso_context, &st->state.rasterizer); // raster); + } } const struct st_tracked_state st_update_rasterizer = { -- 1.7.5.1
From d94fff49a92401bb0c36828e1ab8e0d3925b9c28 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com> Date: Fri, 20 May 2011 22:56:05 +0200 Subject: [PATCH 3/4] st/mesa : reduce cso_set_vertex_sampler_views/cso_set_fragment_sampler_views calls Above functions called only if samplers_view/samplervertex_view content have actually changed. --- src/gallium/auxiliary/cso_cache/cso_context.c | 1 + src/mesa/state_tracker/st_atom_texture.c | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletions(-) diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index fdd40fc..1b5f06b 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -1193,6 +1193,7 @@ set_sampler_views(struct cso_context *ctx, /* reference new views */ for (i = 0; i < count; i++) { + if (views[i] != info->views[i]) pipe_sampler_view_reference(&info->views[i], views[i]); } /* unref extra old views, if any */ diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 072eb97..c711715 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -256,8 +256,10 @@ update_vertex_textures(struct st_context *st) struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current; GLuint su; + int old_num_vertex_textures = st->state.num_vertex_textures; st->state.num_vertex_textures = 0; + bool change_occured = false; /* loop over sampler units (aka tex image units) */ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { struct pipe_sampler_view *sampler_view = NULL; @@ -274,10 +276,17 @@ update_vertex_textures(struct st_context *st) st->state.num_vertex_textures = su + 1; } + + if (sampler_view != st->state.sampler_vertex_views[su]) { pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], sampler_view); + change_occured = true; + } } - if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { + if (old_num_vertex_textures != st->state.num_vertex_textures) + change_occured = true; + + if (change_occured && st->ctx->Const.MaxVertexTextureImageUnits > 0) { GLuint numUnits = MIN2(st->state.num_vertex_textures, st->ctx->Const.MaxVertexTextureImageUnits); cso_set_vertex_sampler_views(st->cso_context, @@ -292,8 +301,10 @@ update_fragment_textures(struct st_context *st) struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; GLuint su; + int old_num_textures = st->state.num_textures; st->state.num_textures = 0; + bool change_occured = false; /* loop over sampler units (aka tex image units) */ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { struct pipe_sampler_view *sampler_view = NULL; @@ -309,9 +320,16 @@ update_fragment_textures(struct st_context *st) st->state.num_textures = su + 1; } + if (st->state.sampler_views[su] != sampler_view) { pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); + change_occured = true; } + } + + if (old_num_textures != st->state.num_textures) + change_occured = true; + if (change_occured) cso_set_fragment_sampler_views(st->cso_context, st->state.num_textures, st->state.sampler_views); -- 1.7.5.1
From 9df2b0250725fa6cc3a6278a8b1fe210b81afb27 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer <pell...@gmail.com> Date: Fri, 20 May 2011 22:58:30 +0200 Subject: [PATCH 4/4] st/mesa : reduce cso_single_sampler/cso_single_vertex_sampler calls Above functions called only if relevant samplers have changed. --- src/gallium/auxiliary/cso_cache/cso_context.c | 59 ------------------------- src/gallium/auxiliary/cso_cache/cso_context.h | 57 +++++++++++++++++++++++- src/mesa/state_tracker/st_atom_sampler.c | 18 +++++++- 3 files changed, 72 insertions(+), 62 deletions(-) diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 1b5f06b..d155cea 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -48,65 +48,6 @@ #include "cso_context.h" -/** - * Info related to samplers and sampler views. - * We have one of these for fragment samplers and another for vertex samplers. - */ -struct sampler_info -{ - struct { - void *samplers[PIPE_MAX_SAMPLERS]; - unsigned nr_samplers; - } hw; - - void *samplers[PIPE_MAX_SAMPLERS]; - unsigned nr_samplers; - - void *samplers_saved[PIPE_MAX_SAMPLERS]; - unsigned nr_samplers_saved; - - struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS]; - unsigned nr_views; - - struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS]; - unsigned nr_views_saved; -}; - - - -struct cso_context { - struct pipe_context *pipe; - struct cso_cache *cache; - - struct sampler_info fragment_samplers; - struct sampler_info vertex_samplers; - - uint nr_vertex_buffers; - struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; - - uint nr_vertex_buffers_saved; - struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS]; - - /** Current and saved state. - * The saved state is used as a 1-deep stack. - */ - void *blend, *blend_saved; - void *depth_stencil, *depth_stencil_saved; - void *rasterizer, *rasterizer_saved; - void *fragment_shader, *fragment_shader_saved, *geometry_shader; - void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved; - void *velements, *velements_saved; - - struct pipe_clip_state clip; - struct pipe_clip_state clip_saved; - - struct pipe_framebuffer_state fb, fb_saved; - struct pipe_viewport_state vp, vp_saved; - struct pipe_blend_color blend_color; - unsigned sample_mask; - struct pipe_stencil_ref stencil_ref, stencil_ref_saved; -}; - static boolean delete_blend_state(struct cso_context *ctx, void *state) { diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 00edc9f..6bc6564 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -38,7 +38,62 @@ extern "C" { #endif -struct cso_context; +/** + * Info related to samplers and sampler views. + * We have one of these for fragment samplers and another for vertex samplers. + */ +struct sampler_info +{ + struct { + void *samplers[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers; + } hw; + + void *samplers[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers; + + void *samplers_saved[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers_saved; + + struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS]; + unsigned nr_views; + + struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS]; + unsigned nr_views_saved; +}; + +struct cso_context { + struct pipe_context *pipe; + struct cso_cache *cache; + + struct sampler_info fragment_samplers; + struct sampler_info vertex_samplers; + + uint nr_vertex_buffers; + struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; + + uint nr_vertex_buffers_saved; + struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS]; + + /** Current and saved state. + * The saved state is used as a 1-deep stack. + */ + void *blend, *blend_saved; + void *depth_stencil, *depth_stencil_saved; + void *rasterizer, *rasterizer_saved; + void *fragment_shader, *fragment_shader_saved, *geometry_shader; + void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved; + void *velements, *velements_saved; + + struct pipe_clip_state clip; + struct pipe_clip_state clip_saved; + + struct pipe_framebuffer_state fb, fb_saved; + struct pipe_viewport_state vp, vp_saved; + struct pipe_blend_color blend_color; + unsigned sample_mask; + struct pipe_stencil_ref stencil_ref, stencil_ref_saved; +}; struct cso_context *cso_create_context( struct pipe_context *pipe ); diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 06024ad..43b67bc 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -204,6 +204,7 @@ update_vertex_samplers(struct st_context *st) struct pipe_sampler_state *sampler = st->state.vertex_samplers + su; if (vprog->Base.SamplersUsed & (1 << su)) { + if (st->cso_context->vertex_samplers.samplers[su] != sampler) { GLuint texUnit; texUnit = vprog->Base.SamplerUnits[su]; @@ -212,11 +213,18 @@ update_vertex_samplers(struct st_context *st) st->state.num_vertex_samplers = su + 1; + //fprintf(stderr, "%s su=%u non-null %p [%p]\n", __FUNCTION__, su, sampler, st->cso_context->vertex_samplers.samplers[su]); cso_single_vertex_sampler(st->cso_context, su, sampler); } else { + st->state.num_vertex_samplers = su + 1; + } + } else { + if (st->cso_context->vertex_samplers.samplers[su] != NULL) { + //fprintf(stderr, "%s su=%u null\n", __FUNCTION__, su); cso_single_vertex_sampler(st->cso_context, su, NULL); } } + } cso_single_vertex_sampler_done(st->cso_context); } @@ -234,6 +242,7 @@ update_fragment_samplers(struct st_context *st) if (fprog->Base.SamplersUsed & (1 << su)) { + if (st->cso_context->fragment_samplers.samplers[su] != sampler) { GLuint texUnit; texUnit = fprog->Base.SamplerUnits[su]; @@ -242,14 +251,19 @@ update_fragment_samplers(struct st_context *st) st->state.num_samplers = su + 1; - /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/ + // fprintf(stderr, "%s su=%u non-null %p [%p]\n", __FUNCTION__, su, sampler, st->cso_context->fragment_samplers.samplers[su]); cso_single_sampler(st->cso_context, su, sampler); + } else { + st->state.num_samplers = su + 1; + } } else { - /*printf("%s su=%u null\n", __FUNCTION__, su);*/ + if (st->cso_context->fragment_samplers.samplers[su] != NULL) { + // fprintf(stderr, "%s su=%u null\n", __FUNCTION__, su); cso_single_sampler(st->cso_context, su, NULL); } } + } cso_single_sampler_done(st->cso_context); } -- 1.7.5.1
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev