[Mesa-dev] [PATCH 3/3] st/mesa: move the logic of all_varyings_in_vbos into st_update_array

Nicolai Hähnle nhaehnle at gmail.com
Mon May 8 19:08:30 UTC 2017


On 08.05.2017 19:09, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> The function was pretty slow. This brings a substantial decrease in draw
> call overhead when min/max index bounds are not needed:
>
> Before:  DrawElements (1 VBO) w/ no state change:          5.75 million
> After:   DrawElements (1 VBO) w/ no state change:          7.03 million

Nice improvement! Series is

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>


> ---
>  src/mesa/state_tracker/st_atom_array.c |  7 +++++++
>  src/mesa/state_tracker/st_context.h    |  2 +-
>  src/mesa/state_tracker/st_draw.c       | 28 ++++------------------------
>  3 files changed, 12 insertions(+), 25 deletions(-)
>
> diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c
> index 1327a19..c7467eb 100644
> --- a/src/mesa/state_tracker/st_atom_array.c
> +++ b/src/mesa/state_tracker/st_atom_array.c
> @@ -548,20 +548,23 @@ setup_interleaved_attribs(struct st_context *st,
>        vbuffer.is_user_buffer = false;
>        vbuffer.buffer_offset = pointer_to_offset(low_addr);
>        vbuffer.stride = stride;
>     }
>     else {
>        /* all interleaved arrays in user memory */
>        vbuffer.buffer.user = low_addr;
>        vbuffer.is_user_buffer = !!low_addr; /* if NULL, then unbind */
>        vbuffer.buffer_offset = 0;
>        vbuffer.stride = stride;
> +
> +      if (low_addr)
> +         st->draw_needs_minmax_index = true;
>     }
>
>     set_vertex_attribs(st, &vbuffer, num_inputs ? 1 : 0,
>                        velements, num_inputs);
>  }
>
>  /**
>   * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
>   * vertex attribute.
>   * \param vbuffer  returns vertex buffer info
> @@ -640,20 +643,23 @@ setup_non_interleaved_attribs(struct st_context *st,
>                               st->pipe->stream_uploader,
>                            0, size, alignment, ptr,
>                            &vbuffer[bufidx].buffer_offset,
>                            &vbuffer[bufidx].buffer.resource);
>              unref_buffers |= 1u << bufidx;
>           } else {
>              assert(array->Ptr);
>              vbuffer[bufidx].buffer.user = array->Ptr;
>              vbuffer[bufidx].is_user_buffer = true;
>              vbuffer[bufidx].buffer_offset = 0;
> +
> +            if (!array->InstanceDivisor)
> +               st->draw_needs_minmax_index = true;
>           }
>        }
>
>        /* common-case setup */
>        vbuffer[bufidx].stride = stride; /* in bytes */
>
>        src_format = st_pipe_vertex_format(array->Type,
>                                           array->Size,
>                                           array->Format,
>                                           array->Normalized,
> @@ -674,20 +680,21 @@ setup_non_interleaved_attribs(struct st_context *st,
>  }
>
>  void st_update_array(struct st_context *st)
>  {
>     struct gl_context *ctx = st->ctx;
>     const struct gl_vertex_array **arrays = ctx->Array._DrawArrays;
>     const struct st_vertex_program *vp;
>     unsigned num_inputs;
>
>     st->vertex_array_out_of_memory = FALSE;
> +   st->draw_needs_minmax_index = false;
>
>     /* No drawing has been done yet, so do nothing. */
>     if (!arrays)
>        return;
>
>     /* vertex program validation must be done before this */
>     vp = st->vp;
>     num_inputs = st->vp_variant->num_inputs;
>
>     if (is_interleaved_arrays(vp, arrays, num_inputs))
> diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
> index 68fd9b9..520cd8d 100644
> --- a/src/mesa/state_tracker/st_context.h
> +++ b/src/mesa/state_tracker/st_context.h
> @@ -113,21 +113,21 @@ struct st_context
>      */
>     boolean shader_has_one_variant[MESA_SHADER_STAGES];
>
>     boolean needs_texcoord_semantic;
>     boolean apply_texture_swizzle_to_border_color;
>
>     /* On old libGL's for linux we need to invalidate the drawables
>      * on glViewpport calls, this is set via a option.
>      */
>     boolean invalidate_on_gl_viewport;
> -
> +   boolean draw_needs_minmax_index;
>     boolean vertex_array_out_of_memory;
>
>     /* Some state is contained in constant objects.
>      * Other state is just parameter values.
>      */
>     struct {
>        struct pipe_blend_state               blend;
>        struct pipe_depth_stencil_alpha_state depth_stencil;
>        struct pipe_rasterizer_state          rasterizer;
>        struct pipe_sampler_state samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
> diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
> index 15c5b80..019001f 100644
> --- a/src/mesa/state_tracker/st_draw.c
> +++ b/src/mesa/state_tracker/st_draw.c
> @@ -60,39 +60,20 @@
>  #include "util/u_inlines.h"
>  #include "util/u_format.h"
>  #include "util/u_prim.h"
>  #include "util/u_draw.h"
>  #include "util/u_upload_mgr.h"
>  #include "draw/draw_context.h"
>  #include "cso_cache/cso_context.h"
>
>
>  /**
> - * This is very similar to vbo_all_varyings_in_vbos() but we are
> - * only interested in per-vertex data.  See bug 38626.
> - */
> -static GLboolean
> -all_varyings_in_vbos(const struct gl_vertex_array *arrays[])
> -{
> -   GLuint i;
> -
> -   for (i = 0; i < VERT_ATTRIB_MAX; i++)
> -      if (arrays[i]->StrideB &&
> -          !arrays[i]->InstanceDivisor &&
> -          !_mesa_is_bufferobj(arrays[i]->BufferObj))
> -	 return GL_FALSE;
> -
> -   return GL_TRUE;
> -}
> -
> -
> -/**
>   * Set the restart index.
>   */
>  static void
>  setup_primitive_restart(struct gl_context *ctx, struct pipe_draw_info *info)
>  {
>     if (ctx->Array._PrimitiveRestart) {
>        unsigned index_size = info->index_size;
>
>        info->restart_index =
>           _mesa_primitive_restart_index(ctx, index_size);
> @@ -154,43 +135,42 @@ st_draw_vbo(struct gl_context *ctx,
>              const struct _mesa_index_buffer *ib,
>  	    GLboolean index_bounds_valid,
>              GLuint min_index,
>              GLuint max_index,
>              struct gl_transform_feedback_object *tfb_vertcount,
>              unsigned stream,
>              struct gl_buffer_object *indirect)
>  {
>     struct st_context *st = st_context(ctx);
>     struct pipe_draw_info info;
> -   const struct gl_vertex_array **arrays = ctx->Array._DrawArrays;
>     unsigned i;
>     unsigned start = 0;
>
>     prepare_draw(st, ctx);
>
>     if (st->vertex_array_out_of_memory)
>        return;
>
>     /* Initialize pipe_draw_info. */
>     info.primitive_restart = false;
>     info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
>     info.indirect = NULL;
>     info.count_from_stream_output = NULL;
>
>     if (ib) {
>        struct gl_buffer_object *bufobj = ib->obj;
>
>        /* Get index bounds for user buffers. */
> -      if (!index_bounds_valid)
> -         if (!all_varyings_in_vbos(arrays))
> -            vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
> -                                   nr_prims);
> +      if (!index_bounds_valid && st->draw_needs_minmax_index) {
> +         vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
> +                                nr_prims);
> +      }
>
>        info.index_size = ib->index_size;
>        info.min_index = min_index;
>        info.max_index = max_index;
>
>        if (_mesa_is_bufferobj(bufobj)) {
>           /* indices are in a real VBO */
>           info.has_user_indices = false;
>           info.index.resource = st_buffer_object(bufobj)->buffer;
>           start = pointer_to_offset(ib->ptr) / info.index_size;
>


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list