summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2014-12-11 02:26:39 -0800
committerKenneth Graunke <[email protected]>2014-12-16 15:39:54 -0800
commit3eb6258db7b7590493e473bf654409212061b8b0 (patch)
treef6a7f7a0891414e9da00d57bd6c7ff2f73f27f7c
parentcb5cfb8361338c4a9e413f287591c1678187bcfc (diff)
i965/query: Cache whether the batch references the query BO.
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. According to Eero, this does not affect the performance of Witcher 2 on Haswell, but approximately halves the userspace CPU usage. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86969 Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Ben Widawsky <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h3
-rw-r--r--src/mesa/drivers/dri/i965/gen6_queryobj.c27
2 files changed, 26 insertions, 4 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 1b8f0bbfcac..a63c4834c26 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 0d513908cdf..de71bb565f5 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;
+}
+
+/**
+ * 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);
}
/**
@@ -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);