radeon: add support for streams to the common streamout code. (v2)
authorDave Airlie <airlied@redhat.com>
Thu, 9 Jul 2015 06:34:59 +0000 (16:34 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 29 Jul 2015 09:48:47 +0000 (10:48 +0100)
This adds to the common radeon streamout code, support
for multiple streams.

It updates radeonsi/r600 to set the enabled mask up.

v2: update for changes in previous patch.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/r600/r600_shader.h
src/gallium/drivers/r600/r600_state_common.c
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeon/r600_streamout.c
src/gallium/drivers/radeonsi/si_state_shaders.c

index 1a72bf6e77e2ada2bb04d37aa5be7dd47f32affd..dda38f6f905029d64bbad01962ba8363c159e795 100644 (file)
@@ -310,6 +310,7 @@ struct r600_shader_ctx {
        int                                     gs_next_vertex;
        struct r600_shader      *gs_for_vs;
        int                                     gs_export_gpr_treg;
+       unsigned                                enabled_stream_buffers_mask;
 };
 
 struct r600_shader_tgsi_instruction {
@@ -1402,6 +1403,9 @@ static int emit_streamout(struct r600_shader_ctx *ctx, struct pipe_stream_output
                 * with MEM_STREAM instructions */
                output.array_size = 0xFFF;
                output.comp_mask = ((1 << so->output[i].num_components) - 1) << so->output[i].start_component;
+
+               ctx->enabled_stream_buffers_mask |= (1 << so->output[i].output_buffer);
+
                if (ctx->bc->chip_class >= EVERGREEN) {
                        switch (so->output[i].output_buffer) {
                        case 0:
@@ -1718,6 +1722,8 @@ static int generate_gs_copy_shader(struct r600_context *rctx,
        gs->gs_copy_shader = cshader;
 
        ctx.bc->nstack = 1;
+
+       cshader->enabled_stream_buffers_mask = ctx.enabled_stream_buffers_mask;
        cshader->shader.ring_item_size = ocnt * 16;
 
        return r600_bytecode_build(ctx.bc);
@@ -2261,6 +2267,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
            so.num_outputs && !use_llvm)
                emit_streamout(&ctx, &so);
 
+       pipeshader->enabled_stream_buffers_mask = ctx.enabled_stream_buffers_mask;
        convert_edgeflag_to_int(&ctx);
 
        if (ring_outputs) {
index dd359d7e9596e15b277622304cb7fa5692a32e31..5d05c8153d70538b1aa713c5516a1aed2f16c242 100644 (file)
@@ -125,6 +125,7 @@ struct r600_pipe_shader {
        struct r600_shader_key  key;
        unsigned                db_shader_control;
        unsigned                ps_depth_export;
+       unsigned                enabled_stream_buffers_mask;
 };
 
 /* return the table index 0-5 for TGSI_INTERPOLATE_LINEAR/PERSPECTIVE and
index 0c78b50aa0c5194493dd3b07c248d1058bd34ead..455e59aef6caf3cd0819506f86e557573ea5149c 100644 (file)
@@ -1208,6 +1208,7 @@ static bool r600_update_derived_state(struct r600_context *rctx)
                                rctx->clip_misc_state.clip_disable = rctx->gs_shader->current->shader.vs_position_window_space;
                                rctx->clip_misc_state.atom.dirty = true;
                        }
+                       rctx->b.streamout.enabled_stream_buffers_mask = rctx->gs_shader->current->gs_copy_shader->enabled_stream_buffers_mask;
                }
 
                r600_shader_select(ctx, rctx->vs_shader, &vs_dirty);
@@ -1242,6 +1243,7 @@ static bool r600_update_derived_state(struct r600_context *rctx)
                                rctx->clip_misc_state.clip_disable = rctx->vs_shader->current->shader.vs_position_window_space;
                                rctx->clip_misc_state.atom.dirty = true;
                        }
+                       rctx->b.streamout.enabled_stream_buffers_mask = rctx->vs_shader->current->enabled_stream_buffers_mask;
                }
        }
 
index 74d747f730bf94ebed1b4399f86eff22448f6071..fcb758b2086d2fd8c4f048ed17299a8e729ea7db 100644 (file)
@@ -328,6 +328,7 @@ struct r600_streamout {
        /* External state which comes from the vertex shader,
         * it must be set explicitly when binding a shader. */
        unsigned                        *stride_in_dw;
+       unsigned                        enabled_stream_buffers_mask; /* stream0 buffers0-3 in 4 LSB */
 
        /* The state of VGT_STRMOUT_BUFFER_(CONFIG|EN). */
        unsigned                        hw_enabled_mask;
index 815b641579caa90a43bd42034965da0fb7f707ba..026fb30f749051a82e49886be19924ef3c1c951d 100644 (file)
@@ -320,17 +320,24 @@ static bool r600_get_strmout_en(struct r600_common_context *rctx)
 static void r600_emit_streamout_enable(struct r600_common_context *rctx,
                                       struct r600_atom *atom)
 {
-       r600_write_context_reg(rctx->rings.gfx.cs,
-                              rctx->chip_class >= EVERGREEN ?
-                                      R_028B98_VGT_STRMOUT_BUFFER_CONFIG :
-                                      R_028B20_VGT_STRMOUT_BUFFER_EN,
-                              rctx->streamout.hw_enabled_mask);
-
-       r600_write_context_reg(rctx->rings.gfx.cs,
-                              rctx->chip_class >= EVERGREEN ?
-                                      R_028B94_VGT_STRMOUT_CONFIG :
-                                      R_028AB0_VGT_STRMOUT_EN,
-                              S_028B94_STREAMOUT_0_EN(r600_get_strmout_en(rctx)));
+       unsigned strmout_config_reg = R_028AB0_VGT_STRMOUT_EN;
+       unsigned strmout_config_val = S_028B94_STREAMOUT_0_EN(r600_get_strmout_en(rctx));
+       unsigned strmout_buffer_reg = R_028B20_VGT_STRMOUT_BUFFER_EN;
+       unsigned strmout_buffer_val = rctx->streamout.hw_enabled_mask &
+                                     rctx->streamout.enabled_stream_buffers_mask;
+
+       if (rctx->chip_class >= EVERGREEN) {
+               strmout_buffer_reg = R_028B98_VGT_STRMOUT_BUFFER_CONFIG;
+
+               strmout_config_reg = R_028B94_VGT_STRMOUT_CONFIG;
+               strmout_config_val |=
+                       S_028B94_RAST_STREAM(0) |
+                       S_028B94_STREAMOUT_1_EN(r600_get_strmout_en(rctx)) |
+                       S_028B94_STREAMOUT_2_EN(r600_get_strmout_en(rctx)) |
+                       S_028B94_STREAMOUT_3_EN(r600_get_strmout_en(rctx));
+       }
+       r600_write_context_reg(rctx->rings.gfx.cs, strmout_buffer_reg, strmout_buffer_val);
+       r600_write_context_reg(rctx->rings.gfx.cs, strmout_config_reg, strmout_config_val);
 }
 
 static void r600_set_streamout_enable(struct r600_common_context *rctx, bool enable)
@@ -339,7 +346,12 @@ static void r600_set_streamout_enable(struct r600_common_context *rctx, bool ena
        unsigned old_hw_enabled_mask = rctx->streamout.hw_enabled_mask;
 
        rctx->streamout.streamout_enabled = enable;
-       rctx->streamout.hw_enabled_mask = rctx->streamout.enabled_mask;
+
+       rctx->streamout.hw_enabled_mask = rctx->streamout.enabled_mask |
+                                         (rctx->streamout.enabled_mask << 4) |
+                                         (rctx->streamout.enabled_mask << 8) |
+                                         (rctx->streamout.enabled_mask << 12);
+
        if ((old_strmout_en != r600_get_strmout_en(rctx)) ||
             (old_hw_enabled_mask != rctx->streamout.hw_enabled_mask))
                rctx->streamout.enable_atom.dirty = true;
index 24afed06fce6d18163187a1bfcebbdb603325d4c..18bddfda26541a69295b22e08ec1056cf36741fd 100644 (file)
@@ -1245,6 +1245,18 @@ static void si_update_vgt_shader_config(struct si_context *sctx)
        si_pm4_bind_state(sctx, vgt_shader_config, *pm4);
 }
 
+static void si_update_so(struct si_context *sctx, struct si_shader_selector *shader)
+{
+       struct pipe_stream_output_info *so = &shader->so;
+       uint32_t enabled_stream_buffers_mask = 0;
+       int i;
+
+       for (i = 0; i < so->num_outputs; i++)
+               enabled_stream_buffers_mask |= (1 << so->output[i].output_buffer);
+       sctx->b.streamout.enabled_stream_buffers_mask = enabled_stream_buffers_mask;
+       sctx->b.streamout.stride_in_dw = shader->so.stride;
+}
+
 void si_update_shaders(struct si_context *sctx)
 {
        struct pipe_context *ctx = (struct pipe_context*)sctx;
@@ -1277,7 +1289,7 @@ void si_update_shaders(struct si_context *sctx)
                } else {
                        /* TES as VS */
                        si_pm4_bind_state(sctx, vs, sctx->tes_shader->current->pm4);
-                       sctx->b.streamout.stride_in_dw = sctx->tes_shader->so.stride;
+                       si_update_so(sctx, sctx->tes_shader);
                }
        } else if (sctx->gs_shader) {
                /* VS as ES */
@@ -1287,7 +1299,7 @@ void si_update_shaders(struct si_context *sctx)
                /* VS as VS */
                si_shader_select(ctx, sctx->vs_shader);
                si_pm4_bind_state(sctx, vs, sctx->vs_shader->current->pm4);
-               sctx->b.streamout.stride_in_dw = sctx->vs_shader->so.stride;
+               si_update_so(sctx, sctx->vs_shader);
        }
 
        /* Update GS. */
@@ -1295,7 +1307,7 @@ void si_update_shaders(struct si_context *sctx)
                si_shader_select(ctx, sctx->gs_shader);
                si_pm4_bind_state(sctx, gs, sctx->gs_shader->current->pm4);
                si_pm4_bind_state(sctx, vs, sctx->gs_shader->current->gs_copy_shader->pm4);
-               sctx->b.streamout.stride_in_dw = sctx->gs_shader->so.stride;
+               si_update_so(sctx, sctx->gs_shader);
 
                if (!sctx->gs_rings)
                        si_init_gs_rings(sctx);