[Mesa-dev] [PATCH 9/9] i965: Pack simple pipelined query objects into the same buffer

Chris Wilson chris at chris-wilson.co.uk
Fri Jun 9 13:01:40 UTC 2017


Reuse the same query object buffer for multiple queries within the same
batch.

A task for the future is propagating the GL_NO_MEMORY errors.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Kenneth Graunke <kenneth at whitecape.org>
Cc: Matt Turner <mattst88 at gmail.com>
---
 src/mesa/drivers/dri/i965/brw_context.c   |  3 +++
 src/mesa/drivers/dri/i965/brw_context.h   | 10 ++++---
 src/mesa/drivers/dri/i965/brw_queryobj.c  | 16 +++++------
 src/mesa/drivers/dri/i965/gen6_queryobj.c | 44 ++++++++++++++++++++++++++-----
 4 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 6d27866fce..a0c0eb71d9 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -959,6 +959,7 @@ brwCreateContext(gl_api api,
    brw->has_swizzling = screen->hw_has_swizzling;
 
    isl_device_init(&brw->isl_dev, devinfo, screen->hw_has_swizzling);
+   brw->query.last_index = 4096;
 
    brw->vs.base.stage = MESA_SHADER_VERTEX;
    brw->tcs.base.stage = MESA_SHADER_TESS_CTRL;
@@ -1147,6 +1148,8 @@ intelDestroyContext(__DRIcontext * driContextPriv)
       brw_bo_unreference(brw->gs.base.scratch_bo);
    if (brw->wm.base.scratch_bo)
       brw_bo_unreference(brw->wm.base.scratch_bo);
+   if (brw->query.bo)
+      brw_bo_unreference(brw->query.bo);
 
    brw_destroy_hw_context(brw->bufmgr, brw->hw_ctx);
 
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 44e0d31c6d..32e92d9a2a 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -422,7 +422,7 @@ struct brw_query_object {
    uint64_t *results;
 
    /** Last index in bo with query data for this object. */
-   int last_index;
+   unsigned index;
 
    /** True if we know the batch has been flushed since we ended the query. */
    bool flushed;
@@ -433,13 +433,13 @@ struct brw_query_object {
 
 static inline unsigned gen6_query_predicate_offset(const struct brw_query_object *query)
 {
-   return GEN6_QUERY_PREDICATE * sizeof(uint64_t);
+   return (query->index + GEN6_QUERY_PREDICATE) * sizeof(uint64_t);
 }
 
 static inline unsigned gen6_query_results_offset(const struct brw_query_object *query,
                                                 unsigned idx)
 {
-   return (GEN6_QUERY_RESULTS + idx) * sizeof(uint64_t);
+   return (query->index + GEN6_QUERY_RESULTS + idx) * sizeof(uint64_t);
 }
 
 enum brw_gpu_ring {
@@ -1085,6 +1085,10 @@ struct brw_context
    } cc;
 
    struct {
+      struct brw_bo *bo;
+      uint64_t *map;
+      unsigned last_index;
+
       struct brw_query_object *obj;
       bool begin_emitted;
    } query;
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index a7b896243d..37c9d8fd0e 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -177,7 +177,7 @@ brw_queryobj_get_results(struct gl_context *ctx,
        * run out of space in the query's BO and allocated a new one.  If so,
        * this function was already called to accumulate the results so far.
        */
-      for (i = 0; i < query->last_index; i++) {
+      for (i = 0; i < query->index; i++) {
 	 query->Base.Result += results[i * 2 + 1] - results[i * 2];
       }
       break;
@@ -187,7 +187,7 @@ brw_queryobj_get_results(struct gl_context *ctx,
       /* If the starting and ending PS_DEPTH_COUNT from any of the batches
        * differ, then some fragments passed the depth test.
        */
-      for (i = 0; i < query->last_index; i++) {
+      for (i = 0; i < query->index; i++) {
 	 if (results[i * 2 + 1] != results[i * 2]) {
             query->Base.Result = GL_TRUE;
             break;
@@ -291,7 +291,7 @@ brw_begin_query(struct gl_context *ctx, struct gl_query_object *q)
        */
       brw_bo_unreference(query->bo);
       query->bo = NULL;
-      query->last_index = -1;
+      query->index = -1;
 
       brw->query.obj = query;
 
@@ -423,7 +423,7 @@ ensure_bo_has_space(struct gl_context *ctx, struct brw_query_object *query)
 
    assert(brw->gen < 6);
 
-   if (!query->bo || query->last_index * 2 + 1 >= 4096 / sizeof(uint64_t)) {
+   if (!query->bo || query->index * 2 + 1 >= 4096 / sizeof(uint64_t)) {
 
       if (query->bo != NULL) {
          /* The old query BO did not have enough space, so we allocated a new
@@ -434,7 +434,7 @@ ensure_bo_has_space(struct gl_context *ctx, struct brw_query_object *query)
       }
 
       query->bo = brw_bo_alloc(brw->bufmgr, "query", 4096, 1);
-      query->last_index = 0;
+      query->index = 0;
    }
 }
 
@@ -475,7 +475,7 @@ brw_emit_query_begin(struct brw_context *brw)
 
    ensure_bo_has_space(ctx, query);
 
-   brw_write_depth_count(brw, query->bo, query->last_index * 2);
+   brw_write_depth_count(brw, query->bo, query->index * 2);
 
    brw->query.begin_emitted = true;
 }
@@ -497,10 +497,10 @@ brw_emit_query_end(struct brw_context *brw)
    if (!brw->query.begin_emitted)
       return;
 
-   brw_write_depth_count(brw, query->bo, query->last_index * 2 + 1);
+   brw_write_depth_count(brw, query->bo, query->index * 2 + 1);
 
    brw->query.begin_emitted = false;
-   query->last_index++;
+   query->index++;
 }
 
 /**
diff --git a/src/mesa/drivers/dri/i965/gen6_queryobj.c b/src/mesa/drivers/dri/i965/gen6_queryobj.c
index ae7fd06c1c..08b9312714 100644
--- a/src/mesa/drivers/dri/i965/gen6_queryobj.c
+++ b/src/mesa/drivers/dri/i965/gen6_queryobj.c
@@ -298,20 +298,50 @@ gen6_queryobj_get_results(struct gl_context *ctx,
 static int gen6_alloc_query(struct brw_context *brw,
                             struct brw_query_object *query)
 {
+   int idx;
+
    /* Since we're starting a new query, we need to throw away old results. */
    if (query->bo)
       brw_bo_unreference(query->bo);
 
-   query->bo = brw_bo_alloc(brw->bufmgr, "query results", 4096, 4096);
-   brw_bo_set_cache_coherent(query->bo);
+   if (!brw_is_query_pipelined(query)) {
+      /* Non-pipecontrol queries may be large so give each their own page */
+      query->bo = brw_bo_alloc(brw->bufmgr, "query results", 4096, 4096);
+      brw_bo_set_cache_coherent(query->bo);
+
+      query->results =
+         brw_bo_map(brw, query->bo,
+                    MAP_READ | MAP_WRITE | MAP_COHERENT);
+
+      idx = 0;
+   } else {
+      /* Pack small queries in the same batch together into a common buffer */
+      if (brw->query.last_index > 4096/sizeof(uint64_t) - 3 ||
+          !brw->query.bo->idle) {
+         if (brw->query.bo)
+            brw_bo_unreference(brw->query.bo);
+
+         brw->query.bo = brw_bo_alloc(brw->bufmgr, "query results", 4096, 4096);
+         brw_bo_set_cache_coherent(brw->query.bo);
+
+         brw->query.map =
+            brw_bo_map(brw, brw->query.bo, MAP_READ | MAP_WRITE | MAP_COHERENT);
+         brw->query.last_index = 0;
+      }
 
-   query->results = brw_bo_map(brw, query->bo,
-                               MAP_READ | MAP_WRITE | MAP_COHERENT | MAP_ASYNC);
+      idx = brw->query.last_index;
+      brw->query.last_index += 3;
+
+      query->bo = brw->query.bo;
+      brw_bo_reference(brw->query.bo);
+
+      query->results = brw->query.map + idx;
+   }
 
    /* For ARB_query_buffer_object: The result is not available */
    query->results[GEN6_QUERY_PREDICATE] = false;
-
-   return 0;
+   query->index = idx;
+   return idx;
 }
 
 /**
@@ -407,7 +437,7 @@ gen6_end_query(struct gl_context *ctx, struct gl_query_object *q)
 {
    struct brw_context *brw = brw_context(ctx);
    struct brw_query_object *query = (struct brw_query_object *)q;
-   const int idx = GEN6_QUERY_RESULTS + 1;
+   const int idx = query->index + GEN6_QUERY_RESULTS + 1;
 
    switch (query->Base.Target) {
    case GL_TIME_ELAPSED:
-- 
2.11.0



More information about the mesa-dev mailing list