Mesa (master): util/primconvert: Handle indirect and multi-draw

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Mar 27 19:47:57 UTC 2021


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

Author: Rob Clark <robdclark at chromium.org>
Date:   Sun Mar 21 11:08:14 2021 -0700

util/primconvert: Handle indirect and multi-draw

Indirect handling was completely missing.  And even though we have to
emulate multi-draw, this pushes it out of the fast/hot path in the
driver's draw_vbo()

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

---

 src/gallium/auxiliary/indices/u_primconvert.c  | 30 +++++++++++++++++++++++++-
 src/gallium/auxiliary/indices/u_primconvert.h  |  4 +++-
 src/gallium/drivers/d3d12/d3d12_draw.cpp       |  2 +-
 src/gallium/drivers/etnaviv/etnaviv_context.c  |  2 +-
 src/gallium/drivers/freedreno/freedreno_draw.c | 11 +---------
 src/gallium/drivers/panfrost/pan_context.c     |  2 +-
 src/gallium/drivers/v3d/v3dx_draw.c            |  2 +-
 src/gallium/drivers/vc4/vc4_draw.c             |  2 +-
 src/gallium/drivers/virgl/virgl_context.c      |  2 +-
 src/gallium/drivers/zink/zink_draw.c           |  7 +-----
 10 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/src/gallium/auxiliary/indices/u_primconvert.c b/src/gallium/auxiliary/indices/u_primconvert.c
index e270ec495c9..084182451ca 100644
--- a/src/gallium/auxiliary/indices/u_primconvert.c
+++ b/src/gallium/auxiliary/indices/u_primconvert.c
@@ -44,6 +44,7 @@
 #include "util/u_draw.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
+#include "util/u_prim.h"
 #include "util/u_prim_restart.h"
 #include "util/u_upload_mgr.h"
 
@@ -98,7 +99,9 @@ util_primconvert_save_rasterizer_state(struct primconvert_context *pc,
 void
 util_primconvert_draw_vbo(struct primconvert_context *pc,
                           const struct pipe_draw_info *info,
-                          const struct pipe_draw_start_count *draw)
+                          const struct pipe_draw_indirect_info *indirect,
+                          const struct pipe_draw_start_count *draws,
+                          unsigned num_draws)
 {
    struct pipe_draw_info new_info;
    struct pipe_draw_start_count new_draw;
@@ -109,6 +112,31 @@ util_primconvert_draw_vbo(struct primconvert_context *pc,
    void *dst;
    unsigned ib_offset;
 
+   /* indirect emulated prims is not possible, as we need to know
+    * draw start/count, so we must emulate.  Too bad, so sad, but
+    * we are already off the fast-path here.
+    */
+   if (indirect && indirect->buffer) {
+      /* num_draws is only applicable for direct draws: */
+      assert(num_draws == 1);
+      util_draw_indirect(pc->pipe, info, indirect);
+      return;
+   }
+
+   if (num_draws > 1) {
+      util_draw_multi(pc->pipe, info, indirect, draws, num_draws);
+      return;
+   }
+
+   const struct pipe_draw_start_count *draw = &draws[0];
+
+   /* Filter out degenerate primitives, u_upload_alloc() will assert
+    * on size==0 so just bail:
+    */
+   if (!info->primitive_restart &&
+       !u_trim_pipe_prim(info->mode, (unsigned*)&draw->count))
+      return;
+
    util_draw_init_info(&new_info);
    new_info.index_bounds_valid = info->index_bounds_valid;
    new_info.min_index = info->min_index;
diff --git a/src/gallium/auxiliary/indices/u_primconvert.h b/src/gallium/auxiliary/indices/u_primconvert.h
index 0aa2ba15146..f8750856da2 100644
--- a/src/gallium/auxiliary/indices/u_primconvert.h
+++ b/src/gallium/auxiliary/indices/u_primconvert.h
@@ -47,6 +47,8 @@ void util_primconvert_save_rasterizer_state(struct primconvert_context *pc,
                                             *rast);
 void util_primconvert_draw_vbo(struct primconvert_context *pc,
                                const struct pipe_draw_info *info,
-                               const struct pipe_draw_start_count *draw);
+                               const struct pipe_draw_indirect_info *indirect,
+                               const struct pipe_draw_start_count *draws,
+                               unsigned num_draws);
 
 #endif /* U_PRIMCONVERT_H_ */
diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp
index f7e564378fe..309a870160f 100644
--- a/src/gallium/drivers/d3d12/d3d12_draw.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp
@@ -453,7 +453,7 @@ d3d12_draw_vbo(struct pipe_context *pctx,
 
       ctx->initial_api_prim = dinfo->mode;
       util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base);
-      util_primconvert_draw_vbo(ctx->primconvert, dinfo, &draws[0]);
+      util_primconvert_draw_vbo(ctx->primconvert, dinfo, indirect, draws, num_draws);
       return;
    }
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
index 7eb2c0a39cc..2fae69da0c6 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
@@ -254,7 +254,7 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
    if (!(ctx->prim_hwsupport & (1 << info->mode))) {
       struct primconvert_context *primconvert = ctx->primconvert;
       util_primconvert_save_rasterizer_state(primconvert, ctx->rasterizer);
-      util_primconvert_draw_vbo(primconvert, info, &draws[0]);
+      util_primconvert_draw_vbo(primconvert, info, indirect, draws, num_draws);
       return;
    }
 
diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c
index 7e38b34447a..399bd1a2060 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -289,19 +289,10 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
 
 	/* emulate unsupported primitives: */
 	if (!fd_supported_prim(ctx, info->mode)) {
-		if (num_draws > 1) {
-			util_draw_multi(pctx, info, indirect, draws, num_draws);
-			return;
-		}
-
-		if (!indirect && !info->primitive_restart &&
-				!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count))
-			return;
-
 		if (ctx->streamout.num_targets > 0)
 			mesa_loge("stream-out with emulated prims");
 		util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer);
-		util_primconvert_draw_vbo(ctx->primconvert, info, &draws[0]);
+		util_primconvert_draw_vbo(ctx->primconvert, info, indirect, draws, num_draws);
 		return;
 	}
 
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index 855e694b1b6..fb976977ce4 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -491,7 +491,7 @@ panfrost_direct_draw(struct panfrost_context *ctx,
                 }
 
                 util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->rasterizer->base);
-                util_primconvert_draw_vbo(ctx->primconvert, info, draw);
+                util_primconvert_draw_vbo(ctx->primconvert, info, NULL, draw, 1);
                 return;
         }
 
diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c
index 5a708ad8ffd..0b151b38515 100644
--- a/src/gallium/drivers/v3d/v3dx_draw.c
+++ b/src/gallium/drivers/v3d/v3dx_draw.c
@@ -1135,7 +1135,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
 
         if (info->mode >= PIPE_PRIM_QUADS && info->mode <= PIPE_PRIM_POLYGON) {
                 util_primconvert_save_rasterizer_state(v3d->primconvert, &v3d->rasterizer->base);
-                util_primconvert_draw_vbo(v3d->primconvert, info, &draws[0]);
+                util_primconvert_draw_vbo(v3d->primconvert, info, indirect, draws, num_draws);
                 perf_debug("Fallback conversion for %d %s vertices\n",
                            draws[0].count, u_prim_name(info->mode));
                 return;
diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c
index 9c1466cab74..77e7159c2dc 100644
--- a/src/gallium/drivers/vc4/vc4_draw.c
+++ b/src/gallium/drivers/vc4/vc4_draw.c
@@ -318,7 +318,7 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
                         info = &local_info;
                 } else {
                         util_primconvert_save_rasterizer_state(vc4->primconvert, &vc4->rasterizer->base);
-                        util_primconvert_draw_vbo(vc4->primconvert, info, &draws[0]);
+                        util_primconvert_draw_vbo(vc4->primconvert, info, indirect, draws, num_draws);
                         perf_debug("Fallback conversion for %d %s vertices\n",
                                    draws[0].count, u_prim_name(info->mode));
                         return;
diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c
index dcbff1d7984..17afd77a9fc 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -884,7 +884,7 @@ static void virgl_draw_vbo(struct pipe_context *ctx,
 
    if (!(rs->caps.caps.v1.prim_mask & (1 << dinfo->mode))) {
       util_primconvert_save_rasterizer_state(vctx->primconvert, &vctx->rs_state.rs);
-      util_primconvert_draw_vbo(vctx->primconvert, dinfo, &draws[0]);
+      util_primconvert_draw_vbo(vctx->primconvert, dinfo, indirect, draws, num_draws);
       return;
    }
    if (info.index_size) {
diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c
index e5d8f21f6e0..150fed5c12b 100644
--- a/src/gallium/drivers/zink/zink_draw.c
+++ b/src/gallium/drivers/zink/zink_draw.c
@@ -860,12 +860,7 @@ zink_draw_vbo(struct pipe_context *pctx,
        (dinfo->mode == PIPE_PRIM_TRIANGLE_FAN && !screen->have_triangle_fans) ||
        dinfo->mode == PIPE_PRIM_LINE_LOOP) {
       util_primconvert_save_rasterizer_state(ctx->primconvert, &rast_state->base);
-      for (unsigned i = 0; i < num_draws; i++) {
-         /* TODO: is there actually a way to correctly handle this? no other driver does... */
-         if (!u_trim_pipe_prim(dinfo->mode, (unsigned *)&draws[i].count))
-            continue;
-         util_primconvert_draw_vbo(ctx->primconvert, dinfo, &draws[i]);
-      }
+      util_primconvert_draw_vbo(ctx->primconvert, dinfo, dindirect, draws, num_draws);
       return;
    }
    if (ctx->gfx_pipeline_state.vertices_per_patch != dinfo->vertices_per_patch)



More information about the mesa-commit mailing list