freedreno/a6xx: only generate streamout for draw pass shader
authorRob Clark <robdclark@chromium.org>
Tue, 18 Aug 2020 19:00:37 +0000 (12:00 -0700)
committerMarge Bot <eric+marge@anholt.net>
Wed, 19 Aug 2020 14:03:42 +0000 (14:03 +0000)
Previously we were doing this both for draw and binning pass.. resulting
that the stateobj contained first the incorrect state (based on binning
pass shader with varyings DCEd) followed by the correct state.

Also, in the streamout case we should link binning pass VS against the
real FS, rather than the dummy FS, so that OUTLOC's match (since same
streamout stateobj is used for both draw and binning pass).

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

src/gallium/drivers/freedreno/a6xx/fd6_program.c

index 7d57b2d1b5d120aa7011ba3cc407561901789812..72212432d0c11e936077a0ba8ea5739013634969 100644 (file)
@@ -462,7 +462,17 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_screen *screen,
 
        struct ir3_shader_linkage l = {0};
        const struct ir3_shader_variant *last_shader = fd6_last_shader(state);
-       ir3_link_shaders(&l, last_shader, fs, true);
+
+       bool do_streamout = (last_shader->shader->stream_output.num_outputs > 0);
+
+       /* If we have streamout, link against the real FS, rather than the
+        * dummy FS used for binning pass state, to ensure the OUTLOC's
+        * match.  Depending on whether we end up doing sysmem or gmem,
+        * the actual streamout could happen with either the binning pass
+        * or draw pass program, but the same streamout stateobj is used
+        * in either case:
+        */
+       ir3_link_shaders(&l, last_shader, do_streamout ? state->fs : fs, true);
 
        bool primid_passthru = l.primid_loc != 0xff;
 
@@ -473,8 +483,7 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_screen *screen,
        OUT_RING(ring, ~l.varmask[3]);  /* VPC_VAR[3].DISABLE */
 
        /* Add stream out outputs after computing the VPC_VAR_DISABLE bitmask. */
-       if (last_shader->shader->stream_output.num_outputs > 0)
-               link_stream_out(&l, last_shader);
+       link_stream_out(&l, last_shader);
 
        if (VALIDREG(layer_regid)) {
                layer_loc = l.max_loc;
@@ -491,7 +500,13 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_screen *screen,
                ir3_link_add(&l, psize_regid, 0x1, l.max_loc);
        }
 
-       if (last_shader->shader->stream_output.num_outputs > 0) {
+       /* If we have stream-out, we use the full shader for binning
+        * pass, rather than the optimized binning pass one, so that we
+        * have all the varying outputs available for xfb.  So streamout
+        * state should always be derived from the non-binning pass
+        * program:
+        */
+       if (do_streamout && !binning_pass) {
                setup_stream_out(state, last_shader, &l);
        }