Mesa (main): aux/draw: add a util function for reading back indirect draw params

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 23 03:52:35 UTC 2021


Module: Mesa
Branch: main
Commit: 3eb99323172902d34c80782aaa2d110567749cd9
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3eb99323172902d34c80782aaa2d110567749cd9

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Fri May 21 05:34:28 2021 -0400

aux/draw: add a util function for reading back indirect draw params

the return type of this is a bit clunky because instance values can change,
but it's simpler to just return the full draw info struct than to force the
caller to keep pulling from arrays or whatever

Reviewed-by: Rob Clark <robdclark at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10973>

---

 src/gallium/auxiliary/util/u_draw.c | 60 +++++++++++++++++++++++++++++++++++++
 src/gallium/auxiliary/util/u_draw.h | 11 +++++++
 2 files changed, 71 insertions(+)

diff --git a/src/gallium/auxiliary/util/u_draw.c b/src/gallium/auxiliary/util/u_draw.c
index 57c78a9b859..d65ac6a6497 100644
--- a/src/gallium/auxiliary/util/u_draw.c
+++ b/src/gallium/auxiliary/util/u_draw.c
@@ -125,6 +125,66 @@ util_draw_max_index(
    return max_index + 1;
 }
 
+struct u_indirect_params *
+util_draw_indirect_read(struct pipe_context *pipe,
+                        const struct pipe_draw_info *info_in,
+                        const struct pipe_draw_indirect_info *indirect,
+                        unsigned *num_draws)
+{
+   struct pipe_transfer *transfer;
+   uint32_t *params;
+   struct u_indirect_params *draws;
+   unsigned num_params = info_in->index_size ? 5 : 4;
+
+   assert(indirect);
+   assert(!indirect->count_from_stream_output);
+
+   uint32_t draw_count = indirect->draw_count;
+   if (indirect->indirect_draw_count) {
+      struct pipe_transfer *dc_transfer;
+      uint32_t *dc_param = pipe_buffer_map_range(pipe,
+                                                 indirect->indirect_draw_count,
+                                                 indirect->indirect_draw_count_offset,
+                                                 4, PIPE_MAP_READ, &dc_transfer);
+      if (!dc_transfer) {
+         debug_printf("%s: failed to map indirect draw count buffer\n", __FUNCTION__);
+         return NULL;
+      }
+      if (dc_param[0] < draw_count)
+         draw_count = dc_param[0];
+      pipe_buffer_unmap(pipe, dc_transfer);
+   }
+   draws = malloc(sizeof(struct u_indirect_params) * draw_count);
+   if (!draws)
+      return NULL;
+
+   if (indirect->stride)
+      num_params = MIN2(indirect->stride / 4, num_params);
+   params = pipe_buffer_map_range(pipe,
+                                  indirect->buffer,
+                                  indirect->offset,
+                                  (num_params * indirect->draw_count) * sizeof(uint32_t),
+                                  PIPE_MAP_READ,
+                                  &transfer);
+   if (!transfer) {
+      debug_printf("%s: failed to map indirect buffer\n", __FUNCTION__);
+      free(draws);
+      return NULL;
+   }
+
+   for (unsigned i = 0; i < draw_count; i++) {
+      memcpy(&draws[i].info, info_in, sizeof(struct pipe_draw_info));
+      draws[i].draw.count = params[0];
+      draws[i].info.instance_count = params[1];
+      draws[i].draw.start = params[2];
+      draws[i].draw.index_bias = info_in->index_size ? params[3] : 0;
+      draws[i].info.start_instance = info_in->index_size ? params[4] : params[3];
+      params += indirect->stride / 4;
+   }
+   pipe_buffer_unmap(pipe, transfer);
+   *num_draws = draw_count;
+   return draws;
+}
 
 /* This extracts the draw arguments from the indirect resource,
  * puts them into a new instance of pipe_draw_info, and calls draw_vbo on it.
diff --git a/src/gallium/auxiliary/util/u_draw.h b/src/gallium/auxiliary/util/u_draw.h
index 6231d73dd29..7924061aed5 100644
--- a/src/gallium/auxiliary/util/u_draw.h
+++ b/src/gallium/auxiliary/util/u_draw.h
@@ -148,6 +148,17 @@ util_draw_elements_instanced(struct pipe_context *pipe,
    pipe->draw_vbo(pipe, &info, 0, NULL, &draw, 1);
 }
 
+struct u_indirect_params {
+   struct pipe_draw_info info;
+   struct pipe_draw_start_count_bias draw;
+};
+
+/* caller must free the return value */
+struct u_indirect_params *
+util_draw_indirect_read(struct pipe_context *pipe,
+                        const struct pipe_draw_info *info_in,
+                        const struct pipe_draw_indirect_info *indirect,
+                        unsigned *num_draws);
 
 /* This converts an indirect draw into a direct draw by mapping the indirect
  * buffer, extracting its arguments, and calling pipe->draw_vbo.



More information about the mesa-commit mailing list