[Mesa-dev] [PATCH 14/17] i965: Grow the batch/state buffers if we need space and can't flush.

Chris Wilson chris at chris-wilson.co.uk
Wed Sep 6 15:44:03 UTC 2017


Quoting Kenneth Graunke (2017-09-06 16:20:00)
> On Wednesday, September 6, 2017 3:08:44 AM PDT Chris Wilson wrote:
> > Quoting Kenneth Graunke (2017-09-06 01:09:47)
> > > Previously, we would just assert fail and die in this case.  The only
> > > safeguard is the "estimated max prim size" checks when starting a draw
> > > (or compute dispatch or BLORP operation)...which are woefully broken.
> > > 
> > > Growing is fairly straightforward:
> > > 
> > > 1. Allocate a new larger BO.
> > > 2. memcpy the existing contents over to the new buffer
> > > 3. Set the new BO to the same GTT offset as the old BO.  When emitting
> > >    relocations, we write the presumed GTT offset of the target BO.  If
> > >    we changed it, we'd have to update all the existing values (by
> > >    walking the relocation list and looking at offsets), which is more
> > >    expensive.  With the old BO freed, ideally the kernel could simply
> > >    place the new BO at that offset anyway.
> > > 4. Update the validation list to contain the new BO.
> > > 5. Update the relocation list to have the GEM handle for the new BO
> > >    (which we can skip if using I915_EXEC_HANDLE_LUT).
> > > ---
> > >  src/mesa/drivers/dri/i965/intel_batchbuffer.c | 104 ++++++++++++++++++++++++--
> > >  1 file changed, 99 insertions(+), 5 deletions(-)
> > > 
> > > diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
> > > index 909f56f9792..118f75c4d71 100644
> > > --- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
> > > +++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
> > > @@ -43,6 +43,9 @@
> > >  #define BATCH_SZ (8192*sizeof(uint32_t))
> > >  #define STATE_SZ (8192*sizeof(uint32_t))
> > >  
> > > +/* Don't exceed this - batchbuffers need to fit in the ring! */
> > 
> > I don't understand this comment. I probably just have the wrong pov, you
> > say ring and I then think of the legacy/lrc ringbuffer in the kernel.
> 
> My understanding was that the legacy Gen4-7.5 ringbuffer mode allocated a
> ringbuffer that was...128kB large?  So if you exceeded that size, the
> batch would not fit in the ring at all, and execbuf would fail.

We don't copy the batch into the ring, we just stick a
MI_BATCH_BUFFER_START in there (with a flush before/after and a
breadcrumb, along with any context switch, change of mm, etc).

64k is indeed a magic limit for the state batch though, but as there's
no limit on the batch buffer size (after converting it to a pure command
stream, just the prospect of a timeout). Well... There is an implicit
assumption that you don't exceed 256KiB for a batch (as a limit for a gen2
workaround and a different gen7 workaround).

Elsewhere, I have used 256KiB batches (and then shrunk to fit) simply
because of UINT16_MAX dwords. (Which is kind of why the kernel assumes
that the upper reasonable maximum size is 256KiB for its w/a.)

> > > +   brw_bo_reference(new_bo);
> > > +   brw_bo_unreference(old_bo);
> > 
> > > +
> > > +   if (!batch->use_batch_first) {
> > > +      /* We're not using I915_EXEC_HANDLE_LUT, which means we need to go
> > > +       * update the relocation list entries to point at the new BO as well.
> > > +       * (With newer kernels, the "handle" is an offset into the validation
> > > +       * list, which remains unchanged, so we can skip this.)
> > > +       */
> > > +      replace_bo_in_reloc_list(&batch->batch_relocs,
> > > +                               old_bo->gem_handle, new_bo->gem_handle);
> > > +      replace_bo_in_reloc_list(&batch->state_relocs,
> > > +                               old_bo->gem_handle, new_bo->gem_handle);
> > > +   }
> > > +
> > > +   /* Drop the *bo_ptr reference.  This should free the old BO. */
> > > +   brw_bo_unreference(old_bo);
> > 
> > Ok, just took a double take even with the comment in place.
> > 
> > > +   *bo_ptr = new_bo;
> > > +   *map_ptr = new_map;
> > > +}
> 
> Yeah...the double unreference is kind of spooky.  The alternative is to
> make the batch and state buffers not referenced by the validation list,
> which does save a few atomics, but adds a != batch_bo && != state_bo
> check in the validation list loops...so...seemed better to just do this.

It's not terrible, it just looked fishy! But I didn't like any of my
suggestions for the comment either.
-Chris


More information about the mesa-dev mailing list