panfrost: Take into account a index_bias for glDrawElementsBaseVertex calls
authorRohan Garg <rohan.garg@collabora.com>
Wed, 17 Jul 2019 16:50:13 +0000 (18:50 +0200)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Wed, 7 Aug 2019 00:18:19 +0000 (17:18 -0700)
Midgard does not accept a index_bias directly and relies instead on a
bias correction offset (offset_bias_correction) in order to calculate
the unbiased vertex index.

We need to make sure we adjust offset_start and vertex_count in order to
take into account the index_bias as required by a
glDrawElementsBaseVertex call and then supply a additional
offset_bias_correction to the hardware.

Signed-off-by: Rohan Garg <rohan.garg@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/gallium/drivers/panfrost/pan_context.c
src/panfrost/include/panfrost-job.h
src/panfrost/pandecode/decode.c

index e9d18605dd021b70f223c56ebcd1e9bbe4661c7f..284c246677dfd39089369e047d6acdddd1ffc80b 100644 (file)
@@ -672,7 +672,7 @@ panfrost_stage_attributes(struct panfrost_context *ctx)
          * QED.
          */
 
-        unsigned start = ctx->payloads[PIPE_SHADER_VERTEX].draw_start;
+        unsigned start = ctx->payloads[PIPE_SHADER_VERTEX].offset_start;
 
         for (unsigned i = 0; i < so->num_elements; ++i) {
                 unsigned vbi = so->pipe[i].vertex_buffer_index;
@@ -1617,8 +1617,8 @@ panfrost_draw_vbo(
         if (panfrost_scissor_culls_everything(ctx))
                 return;
 
-        ctx->payloads[PIPE_SHADER_VERTEX].draw_start = info->start;
-        ctx->payloads[PIPE_SHADER_FRAGMENT].draw_start = info->start;
+        ctx->payloads[PIPE_SHADER_VERTEX].offset_start = info->start;
+        ctx->payloads[PIPE_SHADER_FRAGMENT].offset_start = info->start;
 
         int mode = info->mode;
 
@@ -1655,7 +1655,8 @@ panfrost_draw_vbo(
 
         ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.draw_mode = g2m_draw_mode(mode);
 
-        ctx->vertex_count = info->count;
+        /* Take into account a negative bias */
+        ctx->vertex_count = info->count + abs(info->index_bias);
         ctx->instance_count = info->instance_count;
 
         /* For non-indexed draws, they're the same */
@@ -1704,14 +1705,13 @@ panfrost_draw_vbo(
 
                 /* Use the corresponding values */
                 vertex_count = max_index - min_index + 1;
-                ctx->payloads[PIPE_SHADER_VERTEX].draw_start = min_index;
-                ctx->payloads[PIPE_SHADER_FRAGMENT].draw_start = min_index;
+                ctx->payloads[PIPE_SHADER_VERTEX].offset_start = min_index + info->index_bias;
+                ctx->payloads[PIPE_SHADER_FRAGMENT].offset_start = min_index + info->index_bias;
 
-                ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.negative_start = -min_index;
+                ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.offset_bias_correction = -min_index;
                 ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.index_count = MALI_POSITIVE(info->count);
 
                 //assert(!info->restart_index); /* TODO: Research */
-                assert(!info->index_bias);
 
                 draw_flags |= panfrost_translate_index_size(info->index_size);
                 ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.indices = panfrost_get_index_buffer_mapped(ctx, info);
@@ -1719,7 +1719,7 @@ panfrost_draw_vbo(
                 /* Index count == vertex count, if no indexing is applied, as
                  * if it is internally indexed in the expected order */
 
-                ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.negative_start = 0;
+                ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.offset_bias_correction = 0;
                 ctx->payloads[PIPE_SHADER_FRAGMENT].prefix.index_count = MALI_POSITIVE(ctx->vertex_count);
 
                 /* Reverse index state */
index 9179ceff2ec2f0e82e961755bcc1cedfb32e8782..98d77e718fcbd998967a33b73600377a2e082229 100644 (file)
@@ -935,8 +935,23 @@ struct mali_vertex_tiler_prefix {
         u32 workgroups_x_shift_3 : 6;
 
 
-        /* Negative of draw_start for TILER jobs from what I've seen */
-        int32_t negative_start;
+        /* Negative of min_index. This is used to compute
+         * the unbiased index in tiler/fragment shader runs.
+         * 
+         * The hardware adds offset_bias_correction in each run,
+         * so that absent an index bias, the first vertex processed is
+         * genuinely the first vertex (0). But with an index bias,
+         * the first vertex process is numbered the same as the bias.
+         *
+         * To represent this more conviniently:
+         * unbiased_index = lower_bound_index +
+         *                  index_bias +
+         *                  offset_bias_correction
+         *
+         * This is done since the hardware doesn't accept a index_bias
+         * and this allows it to recover the unbiased index.
+         */
+        int32_t offset_bias_correction;
         u32 zero1;
 
         /* Like many other strictly nonzero quantities, index_count is
@@ -1080,7 +1095,7 @@ struct midgard_payload_vertex_tiler {
         u8 zero4;
 
         /* Offset for first vertex in buffer */
-        u32 draw_start;
+        u32 offset_start;
 
        u64 zero5;
 
index 080d650fc5ada28bd52ab7d1c0f8dcb0c2565f36..78f6da6e56c64ecf7290a553c7afa15f67614314 100644 (file)
@@ -1334,8 +1334,8 @@ pandecode_vertex_tiler_prefix(struct mali_vertex_tiler_prefix *p, int job_no)
         if (p->index_count)
                 pandecode_prop("index_count = MALI_POSITIVE(%" PRId32 ")", p->index_count + 1);
 
-        if (p->negative_start)
-                pandecode_prop("negative_start = %d", p->negative_start);
+        if (p->offset_bias_correction)
+                pandecode_prop("offset_bias_correction = %d", p->offset_bias_correction);
 
         DYN_MEMORY_PROP(p, job_no, indices);
 
@@ -2181,8 +2181,8 @@ pandecode_vertex_or_tiler_job_mdg(const struct mali_job_descriptor_header *h,
                 pandecode_padded_vertices(v->instance_shift, v->instance_odd);
         }
 
-        if (v->draw_start)
-                pandecode_prop("draw_start = %d", v->draw_start);
+        if (v->offset_start)
+                pandecode_prop("offset_start = %d", v->offset_start);
 
         if (v->zero5) {
                 pandecode_msg("Zero tripped\n");