[Mesa-dev] [PATCH 04/13] i965/draw: Delay when we get the bo for vertex buffers

Iago Toral itoral at igalia.com
Thu May 19 14:48:08 UTC 2016


On Thu, 2016-05-19 at 00:21 -0700, Jason Ekstrand wrote:
> The previous code got the BO the first time we encountered it.  However,
> this can potentially lead to problems if the BO is used for multiple arrays
> with the same buffer object because the range we declare as busy may not be
> quite right.  By delaying the call to intel_bufferobj_buffer, we can ensure
> that we have the full range for the given buffer.
> 
> Cc: "10.2" <mesa-stable at lists.freedesktop.org>
> ---
>  src/mesa/drivers/dri/i965/brw_draw_upload.c | 71 ++++++++++++++++++++---------
>  1 file changed, 49 insertions(+), 22 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
> index 3ec37f8..0a7725d 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
> +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
> @@ -453,6 +453,11 @@ brw_prepare_vertices(struct brw_context *brw)
>     if (brw->vb.nr_buffers)
>        return;
>  
> +   /* The range of data in a given buffer represented as [min, max) */
> +   struct intel_buffer_object *enabled_buffer[VERT_ATTRIB_MAX];
> +   uint32_t buffer_range_start[VERT_ATTRIB_MAX];
> +   uint32_t buffer_range_end[VERT_ATTRIB_MAX];
> +
>     for (i = j = 0; i < brw->vb.nr_enabled; i++) {
>        struct brw_vertex_element *input = brw->vb.enabled[i];
>        const struct gl_client_array *glarray = input->glarray;
> @@ -460,12 +465,31 @@ brw_prepare_vertices(struct brw_context *brw)
>        if (_mesa_is_bufferobj(glarray->BufferObj)) {
>  	 struct intel_buffer_object *intel_buffer =
>  	    intel_buffer_object(glarray->BufferObj);
> -	 unsigned k;
> +
> +         const uint32_t offset = (uintptr_t)glarray->Ptr;

Should we use uint64_t instead or do we know that these offsets need to
be within a 32-bit address?

> +         uint32_t start, range;
> +         if (glarray->InstanceDivisor) {
> +            start = offset;
> +            range = (glarray->StrideB * ((brw->num_instances /
> +                                         glarray->InstanceDivisor) - 1) +
> +                     glarray->_ElementSize);
> +         } else {
> +            if (!brw->vb.index_bounds_valid) {
> +               start = 0;
> +               range = intel_buffer->Base.Size;
> +            } else {
> +               start = offset + min_index * glarray->StrideB;
> +               range = (glarray->StrideB * (max_index - min_index) +
> +                        glarray->_ElementSize);
> +            }
> +         }
>  
>  	 /* If we have a VB set to be uploaded for this buffer object
>  	  * already, reuse that VB state so that we emit fewer
>  	  * relocations.
>  	  */
> +	 unsigned k;
>  	 for (k = 0; k < i; k++) {
>  	    const struct gl_client_array *other = brw->vb.enabled[k]->glarray;
>  	    if (glarray->BufferObj == other->BufferObj &&
> @@ -475,6 +499,9 @@ brw_prepare_vertices(struct brw_context *brw)
>  	    {
>  	       input->buffer = brw->vb.enabled[k]->buffer;
>  	       input->offset = glarray->Ptr - other->Ptr;
> +
> +               buffer_range_start[k] = MIN2(buffer_range_start[k], start);
> +               buffer_range_end[k] = MAX2(buffer_range_end[k], start + range);
>  	       break;
>  	    }
>  	 }
> @@ -482,29 +509,13 @@ brw_prepare_vertices(struct brw_context *brw)
>  	    struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
>  
>  	    /* Named buffer object: Just reference its contents directly. */
> -	    buffer->offset = (uintptr_t)glarray->Ptr;
> +	    buffer->offset = offset;
>  	    buffer->stride = glarray->StrideB;
>  	    buffer->step_rate = glarray->InstanceDivisor;
>  
> -            uint32_t offset, size;
> -            if (glarray->InstanceDivisor) {
> -               offset = buffer->offset;
> -               size = (buffer->stride * ((brw->num_instances /
> -                                          glarray->InstanceDivisor) - 1) +
> -                       glarray->_ElementSize);
> -            } else {
> -               if (!brw->vb.index_bounds_valid) {
> -                  offset = 0;
> -                  size = intel_buffer->Base.Size;
> -               } else {
> -                  offset = buffer->offset + min_index * buffer->stride;
> -                  size = (buffer->stride * (max_index - min_index) +
> -                          glarray->_ElementSize);
> -               }
> -            }
> -            buffer->bo = intel_bufferobj_buffer(brw, intel_buffer,
> -                                                offset, size);
> -            drm_intel_bo_reference(buffer->bo);
> +            enabled_buffer[j] = intel_buffer;
> +            buffer_range_start[j] = start;
> +            buffer_range_end[j] = start + range;
>  
>  	    input->buffer = j++;
>  	    input->offset = 0;
> @@ -519,7 +530,7 @@ brw_prepare_vertices(struct brw_context *brw)
>  	  * probably a service to the poor programmer to do so rather than
>  	  * trying to just not render.
>  	  */
> -	 assert(input->offset < brw->vb.buffers[input->buffer].bo->size);
> +	 assert(input->offset < intel_buffer->Base.Size);
>        } else {
>  	 /* Queue the buffer object up to be uploaded in the next pass,
>  	  * when we've decided if we're doing interleaved or not.
> @@ -554,6 +565,22 @@ brw_prepare_vertices(struct brw_context *brw)
>        }
>     }
>  
> +   /* Now that we've set up all of the buffers, we walk through and reference
> +    * each of them.  We do this late so that we get the right size in each
> +    * buffer and don't reference too little data.
> +    */
> +   for (i = 0; i < j; i++) {
> +      struct brw_vertex_buffer *buffer = &brw->vb.buffers[i];
> +      if (buffer->bo)
> +         continue;
> +
> +      const uint32_t start = buffer_range_start[i];
> +      const uint32_t range = buffer_range_end[i] - buffer_range_start[i];
> +
> +      buffer->bo = intel_bufferobj_buffer(brw, enabled_buffer[i], start, range);
> +      drm_intel_bo_reference(buffer->bo);
> +   }
> +
>     /* If we need to upload all the arrays, then we can trim those arrays to
>      * only the used elements [min_index, max_index] so long as we adjust all
>      * the values used in the 3DPRIMITIVE i.e. by setting the vertex bias.




More information about the mesa-dev mailing list