freedreno/ir3: handle VTXID_BASE for indirect draws
authorRob Clark <robdclark@gmail.com>
Mon, 18 Dec 2017 20:09:49 +0000 (15:09 -0500)
committerRob Clark <robdclark@gmail.com>
Tue, 19 Dec 2017 20:00:18 +0000 (15:00 -0500)
Need to do some gymnastics to copy the parameter from the indirect
parameters buffer to uniform so shader sees the correct base-vertex-id.

Fixes ./bin/arb_draw_indirect-vertexid on a5xx and probably a4xx too.

Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/drivers/freedreno/ir3/ir3_shader.c

index 3b1fcdfd5f9bb86a7153931118cbcbdb7d0ed2c8..5d67d4877f55c3463ec3924a0025c3a48dc5e91f 100644 (file)
@@ -827,8 +827,47 @@ ir3_emit_vs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin
                        }
 
                        fd_wfi(ctx->batch, ring);
-                       ctx->emit_const(ring, SHADER_VERTEX, offset * 4, 0,
-                                       vertex_params_size, vertex_params, NULL);
+
+                       bool needs_vtxid_base =
+                               ir3_find_sysval_regid(v, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) != regid(63, 0);
+
+                       /* for indirect draw, we need to copy VTXID_BASE from
+                        * indirect-draw parameters buffer.. which is annoying
+                        * and means we can't easily emit these consts in cmd
+                        * stream so need to copy them to bo.
+                        */
+                       if (info->indirect && needs_vtxid_base) {
+                               struct pipe_draw_indirect_info *indirect = info->indirect;
+                               struct pipe_resource *vertex_params_rsc =
+                                       pipe_buffer_create(&ctx->screen->base,
+                                               PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM,
+                                               vertex_params_size * 4);
+                               unsigned src_off = info->indirect->offset;;
+                               void *ptr;
+
+                               ptr = fd_bo_map(fd_resource(vertex_params_rsc)->bo);
+                               memcpy(ptr, vertex_params, vertex_params_size * 4);
+
+                               if (info->index_size) {
+                                       /* indexed draw, index_bias is 4th field: */
+                                       src_off += 3 * 4;
+                               } else {
+                                       /* non-indexed draw, start is 3rd field: */
+                                       src_off += 2 * 4;
+                               }
+
+                               /* copy index_bias or start from draw params: */
+                               ctx->mem_to_mem(ring, vertex_params_rsc, 0,
+                                               indirect->buffer, src_off, 1);
+
+                               ctx->emit_const(ring, SHADER_VERTEX, offset * 4, 0,
+                                               vertex_params_size, NULL, vertex_params_rsc);
+
+                               pipe_resource_reference(&vertex_params_rsc, NULL);
+                       } else {
+                               ctx->emit_const(ring, SHADER_VERTEX, offset * 4, 0,
+                                               vertex_params_size, vertex_params, NULL);
+                       }
 
                        /* if needed, emit stream-out buffer addresses: */
                        if (vertex_params[IR3_DP_VTXCNT_MAX] > 0) {