[Mesa-dev] [PATCH 2/2] i965: Fix brw_finish_batch to grow the batchbuffer.

Kenneth Graunke kenneth at whitecape.org
Mon Sep 18 20:44:57 UTC 2017


On Monday, September 18, 2017 11:14:35 AM PDT Chris Wilson wrote:
> Quoting Kenneth Graunke (2017-09-18 18:56:57)
> > brw_finish_batch emits commands needed at the end of every batch buffer,
> > including any workarounds.  In the past, we freed up some "reserved"
> > batch space before calling it, so we would never have to flush during
> > it.  This was error prone and easy to screw up, so I deleted it a while
> > back in favor of growing the batch.
> > 
> > There were two problems:
> > 
> > 1. We're in the middle of flushing, so brw->no_batch_wrap is guaranteed
> >    not to be set.  Using BEGIN_BATCH() to emit commands would cause a
> >    recursive flush rather than growing the buffer as intended.
> 
> My bad. I've tripped over that same issue before.
> 
> > 2. We already recorded the throttling batch before growing, which
> >    replaces brw->batch.bo with a different (larger) buffer.  So growing
> >    would break throttling.
> 
> Ooh, in most cases that means we stored a later active handle.

Not exactly...we would set brw->throttle_batch[0] = brw->batch.bo, then
allocate a new brw->batch.bo, and throw away the old one (putting it back
in the BO cache).  So, brw->throttle_batch[0] might not ever be execbuf'd
at all...or it could get reused for a future batchbuffer.

Seems like nothing good could come of this.

> > These are easily remedied by shuffling some code around and whacking
> > brw->no_batch_wrap in brw_finish_batch().  This also now includes the
> > final workarounds in the batch usage statistics.  Found by inspection.
> 
> Ok, if it was ever hit it would cause infinite recursion in
> intel_batchbuffer_flush_fence, so pretty recognisable and doesn't need
> any assert to convert into something fatal.

Yeah, I don't think I've ever actually seen it happen.  If you recurse
there, we should crash, so it would be pretty obvious.

> > Fixes: 2c46a67b4138631217141f (i965: Delete BATCH_RESERVED handling.)
> > ---
> >  src/mesa/drivers/dri/i965/intel_batchbuffer.c | 17 ++++++++++-------
> >  1 file changed, 10 insertions(+), 7 deletions(-)
> > 
> > diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
> > index dd584f533b9..8d7a738dc28 100644
> > --- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
> > +++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
> > @@ -631,6 +631,8 @@ brw_finish_batch(struct brw_context *brw)
> >  {
> >     const struct gen_device_info *devinfo = &brw->screen->devinfo;
> >  
> > +   brw->no_batch_wrap = true;
> > +
> >     /* Capture the closing pipeline statistics register values necessary to
> >      * support query objects (in the non-hardware context world).
> >      */
> > @@ -672,6 +674,8 @@ brw_finish_batch(struct brw_context *brw)
> >        /* Round batchbuffer usage to 2 DWORDs. */
> >        intel_batchbuffer_emit_dword(&brw->batch, MI_NOOP);
> 
> You really don't have to emit a MI_NOOP after the bbe. You aren't
> emitting into the ring and so require a qword tail update, and batches
> are allocated in pages, so no worries about that qword read going beyond
> the end.

Good point.  I can write a patch to drop that.

> >     }
> > +
> > +   brw->no_batch_wrap = false;
> >  }
> >  
> >  static void
> > @@ -885,6 +889,12 @@ _intel_batchbuffer_flush_fence(struct brw_context *brw,
> >     if (USED_BATCH(brw->batch) == 0)
> >        return 0;
> >  
> > +   /* Check that we didn't just wrap our batchbuffer at a bad time. */
> > +   assert(!brw->no_batch_wrap);
> > +
> > +   brw_finish_batch(brw);
> > +   intel_upload_finish(brw);
> > +
> >     if (brw->throttle_batch[0] == NULL) {
> >        brw->throttle_batch[0] = brw->batch.bo;
> >        brw_bo_reference(brw->throttle_batch[0]);
> > @@ -904,13 +914,6 @@ _intel_batchbuffer_flush_fence(struct brw_context *brw,
> >                brw->batch.state_relocs.reloc_count);
> >     }
> >  
> > -   brw_finish_batch(brw);
> > -
> > -   intel_upload_finish(brw);
> > -
> > -   /* Check that we didn't just wrap our batchbuffer at a bad time. */
> > -   assert(!brw->no_batch_wrap);
> 
> Keep a sanity check !brw->no_batch_wrap after flushing?

I moved the assert(!brw->no_batch_wrap) before brw_finish_batch, so we'd
still guard against flushing-while-flushing.  We have to do that because
brw_finish_batch() now whacks it.  I could leave one here too, if you
like, but that would only guard against brw_finish_batch() bugs, rather
than bugs in callers...so it didn't seem as useful...

> > -
> >     ret = do_flush_locked(brw, in_fence_fd, out_fence_fd);
> >  
> >     if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) {
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170918/c27ed10b/attachment-0001.sig>


More information about the mesa-dev mailing list