v3d: support transform feedback with geometry shaders
authorIago Toral Quiroga <itoral@igalia.com>
Tue, 15 Oct 2019 06:32:47 +0000 (08:32 +0200)
committerIago Toral Quiroga <itoral@igalia.com>
Mon, 16 Dec 2019 07:42:37 +0000 (08:42 +0100)
Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
src/gallium/drivers/v3d/v3d_context.h
src/gallium/drivers/v3d/v3dx_emit.c

index bf85b42eb9d124dcbcd81ff2dedbb141b77cdb89..738c1f82319ab3a194f74ff53173adce5b41ff35 100644 (file)
@@ -625,7 +625,8 @@ v3d_ioctl(int fd, unsigned long request, void *arg)
 static inline bool
 v3d_transform_feedback_enabled(struct v3d_context *v3d)
 {
-        return v3d->prog.bind_vs->num_tf_specs != 0 &&
+        return (v3d->prog.bind_vs->num_tf_specs != 0 ||
+                (v3d->prog.bind_gs && v3d->prog.bind_gs->num_tf_specs != 0)) &&
                v3d->active_queries;
 }
 
index c5726c819f5cd7701c2964f16c14fe75988b9f5a..18c2473955bfb0378c6ac5a920411f1538075c15 100644 (file)
@@ -401,6 +401,15 @@ emit_varying_flags(struct v3d_job *job, uint32_t *flags,
         return emitted_any;
 }
 
+static inline struct v3d_uncompiled_shader *
+get_tf_shader(struct v3d_context *v3d)
+{
+        if (v3d->prog.bind_gs)
+                return v3d->prog.bind_gs;
+        else
+                return v3d->prog.bind_vs;
+}
+
 void
 v3dX(emit_state)(struct pipe_context *pctx)
 {
@@ -695,13 +704,14 @@ v3dX(emit_state)(struct pipe_context *pctx)
                           VC5_DIRTY_RASTERIZER |
                           VC5_DIRTY_PRIM_MODE)) {
                 struct v3d_streamout_stateobj *so = &v3d->streamout;
-
                 if (so->num_targets) {
                         bool psiz_per_vertex = (v3d->prim_mode == PIPE_PRIM_POINTS &&
                                                 v3d->rasterizer->base.point_size_per_vertex);
+                        struct v3d_uncompiled_shader *tf_shader =
+                                get_tf_shader(v3d);
                         uint16_t *tf_specs = (psiz_per_vertex ?
-                                              v3d->prog.bind_vs->tf_specs_psiz :
-                                              v3d->prog.bind_vs->tf_specs);
+                                              tf_shader->tf_specs_psiz :
+                                              tf_shader->tf_specs);
 
 #if V3D_VERSION >= 40
                         bool tf_enabled = v3d_transform_feedback_enabled(v3d);
@@ -709,7 +719,7 @@ v3dX(emit_state)(struct pipe_context *pctx)
 
                         cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) {
                                 tfe.number_of_16_bit_output_data_specs_following =
-                                        v3d->prog.bind_vs->num_tf_specs;
+                                        tf_shader->num_tf_specs;
                                 tfe.enable = tf_enabled;
                         };
 #else /* V3D_VERSION < 40 */
@@ -717,10 +727,10 @@ v3dX(emit_state)(struct pipe_context *pctx)
                                 tfe.number_of_32_bit_output_buffer_address_following =
                                         so->num_targets;
                                 tfe.number_of_16_bit_output_data_specs_following =
-                                        v3d->prog.bind_vs->num_tf_specs;
+                                        tf_shader->num_tf_specs;
                         };
 #endif /* V3D_VERSION < 40 */
-                        for (int i = 0; i < v3d->prog.bind_vs->num_tf_specs; i++) {
+                        for (int i = 0; i < tf_shader->num_tf_specs; i++) {
                                 cl_emit_prepacked(&job->bcl, &tf_specs[i]);
                         }
                 } else {
@@ -734,14 +744,15 @@ v3dX(emit_state)(struct pipe_context *pctx)
 
         /* Set up the trasnform feedback buffers. */
         if (v3d->dirty & VC5_DIRTY_STREAMOUT) {
+                struct v3d_uncompiled_shader *tf_shader = get_tf_shader(v3d);
                 struct v3d_streamout_stateobj *so = &v3d->streamout;
                 for (int i = 0; i < so->num_targets; i++) {
                         const struct pipe_stream_output_target *target =
                                 so->targets[i];
                         struct v3d_resource *rsc = target ?
                                 v3d_resource(target->buffer) : NULL;
-                        struct pipe_shader_state *vs = &v3d->prog.bind_vs->base;
-                        struct pipe_stream_output_info *info = &vs->stream_output;
+                        struct pipe_shader_state *ss = &tf_shader->base;
+                        struct pipe_stream_output_info *info = &ss->stream_output;
                         uint32_t offset = (v3d->streamout.offsets[i] *
                                            info->stride[i] * 4);