Mesa (master): gallium,u_threaded: add pipe_draw_info::take_index_buffer_ownership

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 28 00:13:26 UTC 2021


Module: Mesa
Branch: master
Commit: e6da78e4ccf00ecd97ae83e799c20242f92b4c1b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e6da78e4ccf00ecd97ae83e799c20242f92b4c1b

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Sat Jan  2 17:52:04 2021 -0500

gallium,u_threaded: add pipe_draw_info::take_index_buffer_ownership

to skip atomics in u_threaded_context. This will decrease CPU overhead.

Reviewed-by: Zoltán Böszörményi <zboszor at gmail.com>
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8298>

---

 src/gallium/auxiliary/cso_cache/cso_context.c   |  9 ++++++--
 src/gallium/auxiliary/util/u_threaded_context.c | 10 ++++++---
 src/gallium/auxiliary/util/u_vbuf.c             | 29 ++++++++++++++++---------
 src/gallium/include/pipe/p_state.h              |  4 +++-
 src/mesa/main/draw.c                            |  4 ++++
 src/mesa/state_tracker/st_draw.c                | 16 ++++++++++++++
 src/mesa/state_tracker/st_draw_feedback.c       |  1 +
 7 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index fc54dfc7be7..f10c61680e8 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -1435,9 +1435,14 @@ cso_multi_draw(struct cso_context *cso,
    struct u_vbuf *vbuf = cso->vbuf_current;
 
    if (vbuf) {
+      /* Increase refcount to be able to use take_index_buffer_ownership with
+       * all draws.
+       */
+      if (num_draws > 1 && info->take_index_buffer_ownership)
+         p_atomic_add(&info->index.resource->reference.count, num_draws - 1);
+
       for (unsigned i = 0; i < num_draws; i++) {
-         if (draws[i].count)
-            u_vbuf_draw_vbo(vbuf, info, NULL, draws[i]);
+         u_vbuf_draw_vbo(vbuf, info, NULL, draws[i]);
 
          if (info->increment_draw_id)
             info->drawid++;
diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c
index 187b6c367c3..39fbd23d413 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.c
+++ b/src/gallium/auxiliary/util/u_threaded_context.c
@@ -100,6 +100,7 @@ simplify_draw_info(struct pipe_draw_info *info)
     */
    info->has_user_indices = false;
    info->index_bounds_valid = false;
+   info->take_index_buffer_ownership = false;
    info->_pad = 0;
 
    /* This shouldn't be set when merging single draws. */
@@ -2335,6 +2336,7 @@ tc_call_draw_single(struct pipe_context *pipe, union tc_payload *payload)
 
    info->info.index_bounds_valid = false;
    info->info.has_user_indices = false;
+   info->info.take_index_buffer_ownership = false;
 
    pipe->draw_vbo(pipe, &info->info, NULL, draw, 1);
    if (info->info.index_size)
@@ -2353,6 +2355,7 @@ tc_call_draw_indirect(struct pipe_context *pipe, union tc_payload *payload)
    struct tc_draw_indirect *info = (struct tc_draw_indirect*)payload;
 
    info->info.index_bounds_valid = false;
+   info->info.take_index_buffer_ownership = false;
 
    pipe->draw_vbo(pipe, &info->info, &info->indirect, &info->draw, 1);
    if (info->info.index_size)
@@ -2376,6 +2379,7 @@ tc_call_draw_multi(struct pipe_context *pipe, union tc_payload *payload)
 
    info->info.has_user_indices = false;
    info->info.index_bounds_valid = false;
+   info->info.take_index_buffer_ownership = false;
 
    pipe->draw_vbo(pipe, &info->info, NULL, info->slot, info->num_draws);
    if (info->info.index_size)
@@ -2404,7 +2408,7 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info,
 
       struct tc_draw_indirect *p =
          tc_add_struct_typed_call(tc, TC_CALL_draw_indirect, tc_draw_indirect);
-      if (index_size) {
+      if (index_size && !info->take_index_buffer_ownership) {
          tc_set_resource_reference(&p->info.index.resource,
                                    info->index.resource);
       }
@@ -2452,7 +2456,7 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info,
          /* Non-indexed call or indexed with a real index buffer. */
          struct tc_draw_single *p =
             tc_add_struct_typed_call(tc, TC_CALL_draw_single, tc_draw_single);
-         if (index_size) {
+         if (index_size && !info->take_index_buffer_ownership) {
             tc_set_resource_reference(&p->info.index.resource,
                                       info->index.resource);
          }
@@ -2520,7 +2524,7 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info,
       struct tc_draw_multi *p =
          tc_add_slot_based_call(tc, TC_CALL_draw_multi, tc_draw_multi,
                                 num_draws);
-      if (index_size) {
+      if (index_size && !info->take_index_buffer_ownership) {
          tc_set_resource_reference(&p->info.index.resource,
                                    info->index.resource);
       }
diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c
index b51631f2cee..4775591abad 100644
--- a/src/gallium/auxiliary/util/u_vbuf.c
+++ b/src/gallium/auxiliary/util/u_vbuf.c
@@ -1278,6 +1278,12 @@ u_vbuf_split_indexed_multidraw(struct u_vbuf *mgr, struct pipe_draw_info *info,
                                unsigned *indirect_data, unsigned stride,
                                unsigned draw_count)
 {
+   /* Increase refcount to be able to use take_index_buffer_ownership with
+    * all draws.
+    */
+   if (draw_count > 1 && info->take_index_buffer_ownership)
+      p_atomic_add(&info->index.resource->reference.count, draw_count - 1);
+
    assert(info->index_size);
 
    for (unsigned i = 0; i < draw_count; i++) {
@@ -1286,10 +1292,6 @@ u_vbuf_split_indexed_multidraw(struct u_vbuf *mgr, struct pipe_draw_info *info,
 
       draw.count = indirect_data[offset + 0];
       info->instance_count = indirect_data[offset + 1];
-
-      if (!draw.count || !info->instance_count)
-         continue;
-
       draw.start = indirect_data[offset + 2];
       info->index_bias = indirect_data[offset + 3];
       info->start_instance = indirect_data[offset + 4];
@@ -1345,13 +1347,13 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
       }
 
       if (!draw_count)
-         return;
+         goto cleanup;
 
       unsigned data_size = (draw_count - 1) * indirect->stride +
                            (new_info.index_size ? 20 : 16);
       unsigned *data = malloc(data_size);
       if (!data)
-         return; /* report an error? */
+         goto cleanup; /* report an error? */
 
       /* Read the used buffer range only once, because the read can be
        * uncached.
@@ -1449,7 +1451,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
          new_info.instance_count = end_instance - new_info.start_instance;
 
          if (new_info.start_instance == ~0u || !new_info.instance_count)
-            return;
+            goto cleanup;
       } else {
          /* Non-indexed multidraw.
           *
@@ -1486,7 +1488,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
          new_info.instance_count = end_instance - new_info.start_instance;
 
          if (new_draw.start == ~0u || !new_draw.count || !new_info.instance_count)
-            return;
+            goto cleanup;
       }
    }
 
@@ -1540,7 +1542,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
                                   start_vertex, num_vertices,
                                   min_index, unroll_indices)) {
          debug_warn_once("u_vbuf_translate_begin() failed");
-         return;
+         goto cleanup;
       }
 
       if (unroll_indices) {
@@ -1562,7 +1564,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
                                 new_info.start_instance,
                                 new_info.instance_count) != PIPE_OK) {
          debug_warn_once("u_vbuf_upload_buffers() failed");
-         return;
+         goto cleanup;
       }
 
       mgr->dirty_real_vb_mask |= user_vb_mask;
@@ -1597,6 +1599,13 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
    if (mgr->using_translate) {
       u_vbuf_translate_end(mgr);
    }
+   return;
+
+cleanup:
+   if (info->take_index_buffer_ownership) {
+      struct pipe_resource *indexbuf = info->index.resource;
+      pipe_resource_reference(&indexbuf, NULL);
+   }
 }
 
 void u_vbuf_save_vertex_elements(struct u_vbuf *mgr)
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 54dc20f2a70..c1bdf5efc6c 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -750,7 +750,9 @@ struct pipe_draw_info
    bool index_bounds_valid:1; /**< whether min_index and max_index are valid;
                                    they're always invalid if index_size == 0 */
    bool increment_draw_id:1;  /**< whether drawid increments for direct draws */
-   char _pad:4;               /**< padding for memcmp */
+   bool take_index_buffer_ownership:1; /**< callee inherits caller's refcount
+         (no need to reference indexbuf, but still needs to unreference it) */
+   char _pad:3;               /**< padding for memcmp */
 
    unsigned start_instance; /**< first instance id */
    unsigned instance_count; /**< number of instances */
diff --git a/src/mesa/main/draw.c b/src/mesa/main/draw.c
index 2438091ec5d..343b8439dc7 100644
--- a/src/mesa/main/draw.c
+++ b/src/mesa/main/draw.c
@@ -578,6 +578,7 @@ _mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
    info.has_user_indices = false;
    info.index_bounds_valid = true;
    info.increment_draw_id = false;
+   info.take_index_buffer_ownership = false;
    info._pad = 0;
    /* Packed section end. */
    info.start_instance = baseInstance;
@@ -929,6 +930,7 @@ _mesa_MultiDrawArrays(GLenum mode, const GLint *first,
    info.has_user_indices = false;
    info.index_bounds_valid = false;
    info.increment_draw_id = primcount > 1;
+   info.take_index_buffer_ownership = false;
    info._pad = 0;
    /* Packed section end. */
    info.start_instance = 0;
@@ -1064,6 +1066,7 @@ _mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
    info.has_user_indices = index_bo == NULL;
    info.index_bounds_valid = index_bounds_valid;
    info.increment_draw_id = false;
+   info.take_index_buffer_ownership = false;
    info._pad = 0;
    /* Packed section end. */
    info.start_instance = baseInstance;
@@ -1521,6 +1524,7 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
    info.has_user_indices = index_bo == NULL;
    info.index_bounds_valid = false;
    info.increment_draw_id = primcount > 1;
+   info.take_index_buffer_ownership = false;
    info._pad = 0;
    /* Packed section end. */
    info.start_instance = 0;
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index c95fbd411ad..be0ea865a83 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -158,6 +158,7 @@ st_draw_vbo(struct gl_context *ctx,
    info.restart_index = 0;
    info.start_instance = base_instance;
    info.instance_count = num_instances;
+   info.take_index_buffer_ownership = false;
    info._pad = 0;
 
    if (ib) {
@@ -305,6 +306,11 @@ st_draw_gallium_complex(struct gl_context *ctx,
             info->mode = mode[first];
             cso_multi_draw(cso, info, &draws[first], i - first);
             first = i;
+
+            /* We can pass the reference only once. st_buffer_object keeps
+             * the reference alive for later draws.
+             */
+            info->take_index_buffer_ownership = false;
          }
       }
       break;
@@ -315,6 +321,11 @@ st_draw_gallium_complex(struct gl_context *ctx,
             info->index_bias = base_vertex[first];
             cso_multi_draw(cso, info, &draws[first], i - first);
             first = i;
+
+            /* We can pass the reference only once. st_buffer_object keeps
+             * the reference alive for later draws.
+             */
+            info->take_index_buffer_ownership = false;
          }
       }
       break;
@@ -328,6 +339,11 @@ st_draw_gallium_complex(struct gl_context *ctx,
             info->index_bias = base_vertex[first];
             cso_multi_draw(cso, info, &draws[first], i - first);
             first = i;
+
+            /* We can pass the reference only once. st_buffer_object keeps
+             * the reference alive for later draws.
+             */
+            info->take_index_buffer_ownership = false;
          }
       }
       break;
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
index 206fa410bdc..3900c1644dd 100644
--- a/src/mesa/state_tracker/st_draw_feedback.c
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -124,6 +124,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
 
    /* Initialize pipe_draw_info. */
    info.primitive_restart = false;
+   info.take_index_buffer_ownership = false;
    info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
    info.restart_index = 0;
 



More information about the mesa-commit mailing list