panfrost: Split the direct and indirect draw logic
authorBoris Brezillon <boris.brezillon@collabora.com>
Thu, 14 Jan 2021 14:10:04 +0000 (15:10 +0100)
committerMarge Bot <eric+marge@anholt.net>
Thu, 11 Mar 2021 14:30:19 +0000 (14:30 +0000)
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9520>

src/gallium/drivers/panfrost/pan_context.c

index 7fb9f0f..3dd0c0e 100644 (file)
@@ -348,7 +348,6 @@ panfrost_is_implicit_prim_restart(const struct pipe_draw_info *info)
 static void
 panfrost_draw_emit_tiler(struct panfrost_batch *batch,
                          const struct pipe_draw_info *info,
-                         const struct pipe_draw_indirect_info *indirect,
                          const struct pipe_draw_start_count *draw,
                          void *invocation_template,
                          mali_ptr shared_mem, mali_ptr indices,
@@ -392,15 +391,11 @@ panfrost_draw_emit_tiler(struct panfrost_batch *batch,
 
                 cfg.job_task_split = 6;
 
+                cfg.index_count = draw->count;
                 if (info->index_size) {
                         cfg.index_type = panfrost_translate_index_size(info->index_size);
                         cfg.indices = indices;
                         cfg.base_vertex_offset = info->index_bias - ctx->offset_start;
-                        cfg.index_count = draw->count;
-                } else {
-                        cfg.index_count = indirect && indirect->count_from_stream_output ?
-                                          pan_so_target(indirect->count_from_stream_output)->offset :
-                                          ctx->vertex_count;
                 }
         }
 
@@ -471,40 +466,18 @@ panfrost_draw_emit_tiler(struct panfrost_batch *batch,
 }
 
 static void
-panfrost_draw_vbo(
-        struct pipe_context *pipe,
-        const struct pipe_draw_info *info,
-      const struct pipe_draw_indirect_info *indirect,
-      const struct pipe_draw_start_count *draws,
-      unsigned num_draws)
-{
-       if (num_draws > 1) {
-           struct pipe_draw_info tmp_info = *info;
-
-           for (unsigned i = 0; i < num_draws; i++) {
-              panfrost_draw_vbo(pipe, &tmp_info, indirect, &draws[i], 1);
-              if (tmp_info.increment_draw_id)
-                 tmp_info.drawid++;
-           }
-           return;
-       }
-
-        if (!indirect && (!draws[0].count || !info->instance_count))
-           return;
+panfrost_direct_draw(struct panfrost_context *ctx,
+                     const struct pipe_draw_info *info,
+                     const struct pipe_draw_start_count *draw)
+{
+        if (!draw->count || !info->instance_count)
+                return;
 
-        struct panfrost_context *ctx = pan_context(pipe);
         struct panfrost_device *device = pan_device(ctx->base.screen);
 
         if (!panfrost_render_condition_check(ctx))
                 return;
 
-        /* First of all, check the scissor to see if anything is drawn at all.
-         * If it's not, we drop the draw (mostly a conformance issue;
-         * well-behaved apps shouldn't hit this) */
-
-        if (panfrost_scissor_culls_everything(ctx))
-                return;
-
         int mode = info->mode;
 
         /* Fallback for unsupported modes */
@@ -512,13 +485,13 @@ panfrost_draw_vbo(
         assert(ctx->rasterizer != NULL);
 
         if (!(ctx->draw_modes & (1 << mode))) {
-                if (draws[0].count < 4) {
+                if (draw->count < 4) {
                         /* Degenerate case? */
                         return;
                 }
 
                 util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->rasterizer->base);
-                util_primconvert_draw_vbo(ctx->primconvert, info, &draws[0]);
+                util_primconvert_draw_vbo(ctx->primconvert, info, draw);
                 return;
         }
 
@@ -533,7 +506,7 @@ panfrost_draw_vbo(
         panfrost_batch_set_requirements(batch);
 
         /* Take into account a negative bias */
-        ctx->vertex_count = draws[0].count + (info->index_size ? abs(info->index_bias) : 0);
+        ctx->vertex_count = draw->count + (info->index_size ? abs(info->index_bias) : 0);
         ctx->instance_count = info->instance_count;
         ctx->active_prim = info->mode;
 
@@ -556,7 +529,7 @@ panfrost_draw_vbo(
         mali_ptr indices = 0;
 
         if (info->index_size) {
-                indices = panfrost_get_index_buffer_bounded(ctx, info, &draws[0],
+                indices = panfrost_get_index_buffer_bounded(ctx, info, draw,
                                                             &min_index,
                                                             &max_index);
 
@@ -564,7 +537,7 @@ panfrost_draw_vbo(
                 vertex_count = max_index - min_index + 1;
                 ctx->offset_start = min_index + info->index_bias;
         } else {
-                ctx->offset_start = draws[0].start;
+                ctx->offset_start = draw->start;
         }
 
         /* Encode the padded vertex count */
@@ -574,7 +547,7 @@ panfrost_draw_vbo(
         else
                 ctx->padded_count = vertex_count;
 
-        panfrost_statistics_record(ctx, info, &draws[0]);
+        panfrost_statistics_record(ctx, info, draw);
 
         struct mali_invocation_packed invocation;
         panfrost_pack_work_groups_compute(&invocation,
@@ -593,7 +566,7 @@ panfrost_draw_vbo(
         /* Fire off the draw itself */
         panfrost_draw_emit_vertex(batch, info, &invocation, shared_mem,
                                   vs_vary, varyings, vertex.cpu);
-        panfrost_draw_emit_tiler(batch, info, indirect, &draws[0], &invocation, shared_mem, indices,
+        panfrost_draw_emit_tiler(batch, info, draw, &invocation, shared_mem, indices,
                                  fs_vary, varyings, pos, psiz, tiler.cpu);
         panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler);
 
@@ -604,6 +577,58 @@ panfrost_draw_vbo(
         panfrost_update_streamout_offsets(ctx);
 }
 
+static void
+panfrost_indirect_draw(struct panfrost_context *ctx,
+                       const struct pipe_draw_info *info,
+                       const struct pipe_draw_indirect_info *indirect,
+                       const struct pipe_draw_start_count *draw)
+{
+        if (indirect->count_from_stream_output) {
+                struct pipe_draw_start_count tmp_draw = *draw;
+                struct panfrost_streamout_target *so =
+                        pan_so_target(indirect->count_from_stream_output);
+
+                tmp_draw.start = 0;
+                tmp_draw.count = so->offset;
+                panfrost_direct_draw(ctx, info, &tmp_draw);
+                return;
+        }
+
+        assert(0);
+}
+
+static void
+panfrost_draw_vbo(struct pipe_context *pipe,
+                  const struct pipe_draw_info *info,
+                  const struct pipe_draw_indirect_info *indirect,
+                  const struct pipe_draw_start_count *draws,
+                  unsigned num_draws)
+{
+        struct panfrost_context *ctx = pan_context(pipe);
+
+        /* First of all, check the scissor to see if anything is drawn at all.
+         * If it's not, we drop the draw (mostly a conformance issue;
+         * well-behaved apps shouldn't hit this) */
+
+        if (panfrost_scissor_culls_everything(ctx))
+                return;
+
+        if (indirect) {
+                assert(num_draws == 1);
+                panfrost_indirect_draw(ctx, info, indirect, &draws[0]);
+                return;
+        }
+
+        struct pipe_draw_info tmp_info = *info;
+
+        for (unsigned i = 0; i < num_draws; i++) {
+                panfrost_direct_draw(ctx, &tmp_info, &draws[i]);
+                if (tmp_info.increment_draw_id)
+                       tmp_info.drawid++;
+        }
+
+}
+
 /* CSO state */
 
 static void