From 2294ba9565fbae49f1fc77ca171e9d6aafa34005 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 9 Jul 2015 16:34:59 +1000 Subject: [PATCH] radeon: add support for streams to the common streamout code. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Dave Airlie --- src/gallium/drivers/r600/r600_shader.c | 7 +++++ src/gallium/drivers/r600/r600_shader.h | 1 + src/gallium/drivers/r600/r600_state_common.c | 2 ++ src/gallium/drivers/radeon/r600_pipe_common.h | 1 + src/gallium/drivers/radeon/r600_streamout.c | 36 ++++++++++++++++--------- src/gallium/drivers/radeonsi/si_state_shaders.c | 18 ++++++++++--- 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index 1a72bf6..dda38f6 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -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) { diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index dd359d7..5d05c81 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -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 diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 0c78b50..455e59a 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -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; } } diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index 74d747f..fcb758b 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -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; diff --git a/src/gallium/drivers/radeon/r600_streamout.c b/src/gallium/drivers/radeon/r600_streamout.c index 815b641..026fb30 100644 --- a/src/gallium/drivers/radeon/r600_streamout.c +++ b/src/gallium/drivers/radeon/r600_streamout.c @@ -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; diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index 24afed0..18bddfd 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -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); -- 2.7.4