[Mesa-dev] [PATCH 5/5] i965/query: Cache whether the batch references the query BO.

Ian Romanick idr at freedesktop.org
Mon Dec 15 13:28:52 PST 2014


On 12/14/2014 04:39 PM, Ben Widawsky wrote:
> On Fri, Dec 12, 2014 at 11:15:42PM -0800, Kenneth Graunke wrote:
>> Chris Wilson noted that repeated calls to CheckQuery() would call
>> drm_intel_bo_references(brw->batch.bo, query->bo) on each invocation,
>> which is expensive.  Once we've flushed, we know that future batches
>> won't reference query->bo, so there's no point in asking more than once.
>>
>> This patch adds a brw_query_object::flushed flag, which is a
>> conservative estimate of whether the batch has been flushed.
>>
>> On the first call to CheckQuery() or WaitQuery(), we check if the
>> batch references query->bo.  If not, it must have been flushed for
>> some reason (such as being full).  We record that it was flushed.
>> If it does reference query->bo, we explicitly flush, and record that
>> we did so.
>>
>> Any subsequent checks will simply see that query->flushed is set,
>> and skip the drm_intel_bo_references() call.
>>
>> Inspired by a patch from Chris Wilson.
>>
>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86969
>> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
>> Cc: Chris Wilson <chris at chris-wilson.co.uk>
>> Cc: Eero Tamminen <eero.t.tamminen at intel.com>
>> ---
>>  src/mesa/drivers/dri/i965/brw_context.h   |  3 +++
>>  src/mesa/drivers/dri/i965/gen6_queryobj.c | 27 +++++++++++++++++++++++----
>>  2 files changed, 26 insertions(+), 4 deletions(-)
>>
>> ickle's patch in bug #86969 eliminated all calls to drm_intel_bo_references
>> in the query object code.  One consequence is that the first call to
>> CheckQuery or WaitQuery would always flush the batch, even if it wasn't
>> necessary (say, the batch had been flushed).
>>
>> Mine is a bit different - it still uses bo_references on the first call to
>> CheckQuery/WaitQuery - but then records that the batch has been flushed, so
>> we never have to call it again.
>>
>> Either approach should greatly reduce the overhead from repeatedly calling
>> drm_intel_bo_references.
>>
>> Eero, would you be able to test this and see if it solves the issue you
>> were seeing?  If so, could you provide some simple statistics showing the
>> benefit?  Thanks!
>>
>> This is available as the 'query-references' branch in my tree (~kwg/mesa).
>>
>> diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
>> index 1b8f0bb..a63c483 100644
>> --- a/src/mesa/drivers/dri/i965/brw_context.h
>> +++ b/src/mesa/drivers/dri/i965/brw_context.h
>> @@ -831,6 +831,9 @@ struct brw_query_object {
>>  
>>     /** Last index in bo with query data for this object. */
>>     int last_index;
>> +
>> +   /** True if we know the batch has been flushed since we ended the query. */
>> +   bool flushed;
>>  };
>>  
>>  struct intel_sync_object {
>> diff --git a/src/mesa/drivers/dri/i965/gen6_queryobj.c b/src/mesa/drivers/dri/i965/gen6_queryobj.c
>> index 0d51390..de71bb5 100644
>> --- a/src/mesa/drivers/dri/i965/gen6_queryobj.c
>> +++ b/src/mesa/drivers/dri/i965/gen6_queryobj.c
>> @@ -281,6 +281,27 @@ gen6_end_query(struct gl_context *ctx, struct gl_query_object *q)
>>     default:
>>        unreachable("Unrecognized query target in brw_end_query()");
>>     }
>> +
>> +   /* The current batch contains the commands to handle EndQuery(),
>> +    * but they won't actually execute until it is flushed.
>> +    */
>> +   query->flushed = false;
>> +}
> 
> I think it makes more sense to set the flushed state at BeginQuery, and to
> remove this hunk. I think that's feasible. Am I correct that this is the
> generalized regex for the callchain?
> BeginQuery->(flush_batch_if_needed)*->EndQuery->(flush_batch_if_needed)*->EndQuery


No.  It's BeginQuery->(flush_batch_if_needed)*->EndQuery.  The
application cannot ask for the query results until after the EndQuery.
I think the way Ken has it is correct.

> If this is correct, BeginBatch is the real marker of when we need to frob the
> flushed state, since EndQuery is either a transient point, or the final call in
> the Query object's life through the GL sequence.
> 
> Additionally, it looks like if we implement QueryCounter (consistent naming
> FTW), EndQuery would only ever be called the last time the query object is
> referenced, and that simplifies this even more.
> 
>> +
>> +/**
>> + * Flush the batch if it still references the query object BO.
>> + */
>> +static void
>> +flush_batch_if_needed(struct brw_context *brw, struct brw_query_object *query)
>> +{
>> +   /* If the batch doesn't reference the BO, it must have been flushed
>> +    * (for example, due to being full).  Record that it's been flushed.
>> +    */
>> +   query->flushed = query->flushed ||
>> +      !drm_intel_bo_references(brw->batch.bo, query->bo);
>> +
>> +   if (!query->flushed)
>> +      intel_batchbuffer_flush(brw);
>>  }
>>  
>>  /**
> 
> Do you want to add an always_flush_batch check here?
> 
>> @@ -298,8 +319,7 @@ static void gen6_wait_query(struct gl_context *ctx, struct gl_query_object *q)
>>      * still contributing to it, flush it now to finish that work so the
>>      * result will become available (eventually).
>>      */
>> -   if (drm_intel_bo_references(brw->batch.bo, query->bo))
>> -      intel_batchbuffer_flush(brw);
>> +   flush_batch_if_needed(brw, query);
>>  
>>     gen6_queryobj_get_results(ctx, query);
>>  }
>> @@ -328,8 +348,7 @@ static void gen6_check_query(struct gl_context *ctx, struct gl_query_object *q)
>>      *      not ready yet on the first time it is queried.  This ensures that
>>      *      the async query will return true in finite time.
>>      */
>> -   if (drm_intel_bo_references(brw->batch.bo, query->bo))
>> -      intel_batchbuffer_flush(brw);
>> +   flush_batch_if_needed(brw, query);
>>  
>>     if (!drm_intel_bo_busy(query->bo)) {
>>        gen6_queryobj_get_results(ctx, query);
> 
> So while I had a verbose nit (which may not even be correct), I don't see
> anything wrong here, so it's:
> Reviewed-by: Ben Widawsky <ben at bwidawsk.net>
> 
> I do hope to see some perf improvements.
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> 



More information about the mesa-dev mailing list