r600g: use common scissor and viewport code
authorMarek Olšák <marek.olsak@amd.com>
Sun, 10 Apr 2016 02:56:46 +0000 (04:56 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 12 Apr 2016 15:13:25 +0000 (17:13 +0200)
It's the same as radeonsi. This adds guard band support to r600g.

Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
Reviewed-by: Grigori Goronzy <greg@chown.ath.cx>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/r600_blit.c
src/gallium/drivers/r600/r600_hw_context.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_state_common.c

index 0e05587..6b6e816 100644 (file)
@@ -472,6 +472,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx,
 
        r600_init_command_buffer(&rs->buffer, 30);
 
+       rs->scissor_enable = state->scissor;
        rs->flatshade = state->flatshade;
        rs->sprite_coord_enable = state->sprite_coord_enable;
        rs->two_side = state->light_twoside;
@@ -528,7 +529,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx,
        r600_store_context_reg(&rs->buffer, R_0286D4_SPI_INTERP_CONTROL_0, spi_interp);
        r600_store_context_reg(&rs->buffer, R_028A48_PA_SC_MODE_CNTL_0,
                               S_028A48_MSAA_ENABLE(state->multisample) |
-                              S_028A48_VPORT_SCISSOR_ENABLE(state->scissor) |
+                              S_028A48_VPORT_SCISSOR_ENABLE(1) |
                               S_028A48_LINE_STIPPLE_ENABLE(state->line_stipple_enable));
 
        if (rctx->b.chip_class == CAYMAN) {
@@ -920,60 +921,12 @@ static void evergreen_get_scissor_rect(struct r600_context *rctx,
                                       unsigned tl_x, unsigned tl_y, unsigned br_x, unsigned br_y,
                                       uint32_t *tl, uint32_t *br)
 {
-       /* EG hw workaround */
-       if (br_x == 0)
-               tl_x = 1;
-       if (br_y == 0)
-               tl_y = 1;
+       struct pipe_scissor_state scissor = {tl_x, tl_y, br_x, br_y};
 
-       /* cayman hw workaround */
-       if (rctx->b.chip_class == CAYMAN) {
-               if (br_x == 1 && br_y == 1)
-                       br_x = 2;
-       }
+       evergreen_apply_scissor_bug_workaround(&rctx->b, &scissor);
 
-       *tl = S_028240_TL_X(tl_x) | S_028240_TL_Y(tl_y);
-       *br = S_028244_BR_X(br_x) | S_028244_BR_Y(br_y);
-}
-
-static void evergreen_set_scissor_states(struct pipe_context *ctx,
-                                         unsigned start_slot,
-                                         unsigned num_scissors,
-                                       const struct pipe_scissor_state *state)
-{
-       struct r600_context *rctx = (struct r600_context *)ctx;
-       struct r600_scissor_state *rstate = &rctx->scissor;
-       int i;
-
-       for (i = start_slot; i < start_slot + num_scissors; i++)
-               rstate->scissor[i] = state[i - start_slot];
-       rstate->dirty_mask |= ((1 << num_scissors) - 1) << start_slot;
-       rstate->atom.num_dw = util_bitcount(rstate->dirty_mask) * 4;
-       r600_mark_atom_dirty(rctx, &rstate->atom);
-}
-
-static void evergreen_emit_scissor_state(struct r600_context *rctx, struct r600_atom *atom)
-{
-       struct radeon_winsys_cs *cs = rctx->b.gfx.cs;
-       struct r600_scissor_state *rstate = &rctx->scissor;
-       struct pipe_scissor_state *state;
-       uint32_t dirty_mask;
-       unsigned i, offset;
-       uint32_t tl, br;
-
-       dirty_mask = rstate->dirty_mask;
-       while (dirty_mask != 0) {
-               i = u_bit_scan(&dirty_mask);
-               state = &rstate->scissor[i];
-               evergreen_get_scissor_rect(rctx, state->minx, state->miny, state->maxx, state->maxy, &tl, &br);
-
-               offset = i * 4 * 2;
-               radeon_set_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL + offset, 2);
-               radeon_emit(cs, tl);
-               radeon_emit(cs, br);
-       }
-       rstate->dirty_mask = 0;
-       rstate->atom.num_dw = 0;
+       *tl = S_028240_TL_X(scissor.minx) | S_028240_TL_Y(scissor.miny);
+       *br = S_028244_BR_X(scissor.maxx) | S_028244_BR_Y(scissor.maxy);
 }
 
 /**
@@ -2484,12 +2437,6 @@ static void cayman_init_atom_start_cs(struct r600_context *rctx)
        r600_store_context_reg(cb, R_028230_PA_SC_EDGERULE, 0xAAAAAAAA);
        r600_store_context_reg(cb, R_028820_PA_CL_NANINF_CNTL, 0);
 
-       r600_store_context_reg_seq(cb, CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ, 4);
-       r600_store_value(cb, fui(1.0)); /* CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ */
-       r600_store_value(cb, fui(1.0)); /* CM_R_028BEC_PA_CL_GB_VERT_DISC_ADJ */
-       r600_store_value(cb, fui(1.0)); /* CM_R_028BF0_PA_CL_GB_HORZ_CLIP_ADJ */
-       r600_store_value(cb, fui(1.0)); /* CM_R_028BF4_PA_CL_GB_HORZ_DISC_ADJ */
-
        r600_store_context_reg_seq(cb, R_028240_PA_SC_GENERIC_SCISSOR_TL, 2);
        r600_store_value(cb, 0); /* R_028240_PA_SC_GENERIC_SCISSOR_TL */
        r600_store_value(cb, S_028244_BR_X(16384) | S_028244_BR_Y(16384)); /* R_028244_PA_SC_GENERIC_SCISSOR_BR */
@@ -2905,12 +2852,6 @@ void evergreen_init_atom_start_cs(struct r600_context *rctx)
        r600_store_value(cb, 0); /* R_028AC4_DB_SRESULTS_COMPARE_STATE1 */
        r600_store_value(cb, 0); /* R_028AC8_DB_PRELOAD_CONTROL */
 
-       r600_store_context_reg_seq(cb, R_028C0C_PA_CL_GB_VERT_CLIP_ADJ, 4);
-       r600_store_value(cb, fui(1.0)); /* R_028C0C_PA_CL_GB_VERT_CLIP_ADJ */
-       r600_store_value(cb, fui(1.0)); /* R_028C10_PA_CL_GB_VERT_DISC_ADJ */
-       r600_store_value(cb, fui(1.0)); /* R_028C14_PA_CL_GB_HORZ_CLIP_ADJ */
-       r600_store_value(cb, fui(1.0)); /* R_028C18_PA_CL_GB_HORZ_DISC_ADJ */
-
        r600_store_context_reg_seq(cb, R_028240_PA_SC_GENERIC_SCISSOR_TL, 2);
        r600_store_value(cb, 0); /* R_028240_PA_SC_GENERIC_SCISSOR_TL */
        r600_store_value(cb, S_028244_BR_X(16384) | S_028244_BR_Y(16384)); /* R_028244_PA_SC_GENERIC_SCISSOR_BR */
@@ -3712,8 +3653,8 @@ void evergreen_init_state_functions(struct r600_context *rctx)
        r600_init_atom(rctx, &rctx->dsa_state.atom, id++, r600_emit_cso_state, 0);
        r600_init_atom(rctx, &rctx->poly_offset_state.atom, id++, evergreen_emit_polygon_offset, 6);
        r600_init_atom(rctx, &rctx->rasterizer_state.atom, id++, r600_emit_cso_state, 0);
-       r600_init_atom(rctx, &rctx->scissor.atom, id++, evergreen_emit_scissor_state, 0);
-       r600_init_atom(rctx, &rctx->viewport.atom, id++, r600_emit_viewport_state, 0);
+       r600_add_atom(rctx, &rctx->b.scissors.atom, id++);
+       r600_add_atom(rctx, &rctx->b.viewports.atom, id++);
        r600_init_atom(rctx, &rctx->stencil_ref.atom, id++, r600_emit_stencil_ref, 4);
        r600_init_atom(rctx, &rctx->vertex_fetch_shader.atom, id++, evergreen_emit_vertex_fetch_shader, 5);
        r600_add_atom(rctx, &rctx->b.render_cond_atom, id++);
@@ -3732,7 +3673,6 @@ void evergreen_init_state_functions(struct r600_context *rctx)
        rctx->b.b.set_framebuffer_state = evergreen_set_framebuffer_state;
        rctx->b.b.set_polygon_stipple = evergreen_set_polygon_stipple;
        rctx->b.b.set_min_samples = evergreen_set_min_samples;
-       rctx->b.b.set_scissor_states = evergreen_set_scissor_states;
        rctx->b.b.set_tess_state = evergreen_set_tess_state;
        if (rctx->b.chip_class == EVERGREEN)
                 rctx->b.b.get_sample_position = evergreen_get_sample_position;
index 9664391..1a4cc42 100644 (file)
@@ -65,8 +65,8 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
        util_blitter_save_rasterizer(rctx->blitter, rctx->rasterizer_state.cso);
 
        if (op & R600_SAVE_FRAGMENT_STATE) {
-               util_blitter_save_viewport(rctx->blitter, &rctx->viewport.state[0]);
-               util_blitter_save_scissor(rctx->blitter, &rctx->scissor.scissor[0]);
+               util_blitter_save_viewport(rctx->blitter, &rctx->b.viewports.states[0]);
+               util_blitter_save_scissor(rctx->blitter, &rctx->b.scissors.states[0]);
                util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader);
                util_blitter_save_blend(rctx->blitter, rctx->blend_state.cso);
                util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa_state.cso);
index 0c3b580..2bc6d3f 100644 (file)
@@ -304,12 +304,10 @@ void r600_begin_new_cs(struct r600_context *ctx)
        r600_mark_atom_dirty(ctx, &ctx->poly_offset_state.atom);
        r600_mark_atom_dirty(ctx, &ctx->vgt_state.atom);
        r600_mark_atom_dirty(ctx, &ctx->sample_mask.atom);
-       ctx->scissor.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
-       ctx->scissor.atom.num_dw = R600_MAX_VIEWPORTS * 4;
-       r600_mark_atom_dirty(ctx, &ctx->scissor.atom);
-       ctx->viewport.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
-       ctx->viewport.atom.num_dw = R600_MAX_VIEWPORTS * 8;
-       r600_mark_atom_dirty(ctx, &ctx->viewport.atom);
+       ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
+       r600_mark_atom_dirty(ctx, &ctx->b.scissors.atom);
+       ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
+       r600_mark_atom_dirty(ctx, &ctx->b.viewports.atom);
        if (ctx->b.chip_class <= EVERGREEN) {
                r600_mark_atom_dirty(ctx, &ctx->config_state.atom);
        }
index 3af8607..6c2a48c 100644 (file)
@@ -219,12 +219,6 @@ struct r600_stencil_ref_state {
        struct pipe_stencil_ref pipe_state;
 };
 
-struct r600_viewport_state {
-       struct r600_atom atom;
-       struct pipe_viewport_state state[R600_MAX_VIEWPORTS];
-       uint32_t dirty_mask;
-};
-
 struct r600_shader_stages_state {
        struct r600_atom atom;
        unsigned geom_enable;
@@ -410,14 +404,6 @@ struct r600_cso_state
        struct r600_command_buffer *cb;
 };
 
-struct r600_scissor_state
-{
-       struct r600_atom                atom;
-       struct pipe_scissor_state       scissor[R600_MAX_VIEWPORTS];
-       uint32_t                        dirty_mask;
-       bool                            enable; /* r6xx only */
-};
-
 struct r600_fetch_shader {
        struct r600_resource            *buffer;
        unsigned                        offset;
@@ -478,12 +464,10 @@ struct r600_context {
        struct r600_poly_offset_state   poly_offset_state;
        struct r600_cso_state           rasterizer_state;
        struct r600_sample_mask         sample_mask;
-       struct r600_scissor_state       scissor;
        struct r600_seamless_cube_map   seamless_cube_map;
        struct r600_config_state        config_state;
        struct r600_stencil_ref_state   stencil_ref;
        struct r600_vgt_state           vgt_state;
-       struct r600_viewport_state      viewport;
        /* Shaders and shader resources. */
        struct r600_cso_state           vertex_fetch_shader;
        struct r600_shader_state        hw_shader_stages[EG_NUM_HW_STAGES];
@@ -728,7 +712,6 @@ void r600_emit_blend_color(struct r600_context *rctx, struct r600_atom *atom);
 void r600_emit_vgt_state(struct r600_context *rctx, struct r600_atom *atom);
 void r600_emit_clip_misc_state(struct r600_context *rctx, struct r600_atom *atom);
 void r600_emit_stencil_ref(struct r600_context *rctx, struct r600_atom *atom);
-void r600_emit_viewport_state(struct r600_context *rctx, struct r600_atom *atom);
 void r600_emit_shader(struct r600_context *rctx, struct r600_atom *a);
 void r600_add_atom(struct r600_context *rctx, struct r600_atom *atom, unsigned id);
 void r600_init_atom(struct r600_context *rctx, struct r600_atom *atom, unsigned id,
index 140f946..59fe2f4 100644 (file)
@@ -457,6 +457,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
 
        r600_init_command_buffer(&rs->buffer, 30);
 
+       rs->scissor_enable = state->scissor;
        rs->flatshade = state->flatshade;
        rs->sprite_coord_enable = state->sprite_coord_enable;
        rs->two_side = state->light_twoside;
@@ -501,10 +502,9 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
        if (rctx->b.chip_class >= R700) {
                sc_mode_cntl |= S_028A4C_FORCE_EOV_REZ_ENABLE(1) |
                                S_028A4C_R700_ZMM_LINE_OFFSET(1) |
-                               S_028A4C_R700_VPORT_SCISSOR_ENABLE(state->scissor);
+                               S_028A4C_R700_VPORT_SCISSOR_ENABLE(1);
        } else {
                sc_mode_cntl |= S_028A4C_WALK_ALIGN8_PRIM_FITS_ST(1);
-               rs->scissor_enable = state->scissor;
        }
 
        spi_interp = S_0286D4_FLAT_SHADE_ENA(1);
@@ -786,61 +786,6 @@ static void r600_set_polygon_stipple(struct pipe_context *ctx,
 {
 }
 
-static void r600_emit_scissor_state(struct r600_context *rctx, struct r600_atom *atom)
-{
-       struct radeon_winsys_cs *cs = rctx->b.gfx.cs;
-       struct r600_scissor_state *rstate = &rctx->scissor;
-       struct pipe_scissor_state *state;
-       bool do_disable_workaround = false;
-       uint32_t dirty_mask;
-       unsigned i, offset;
-       uint32_t tl, br;
-
-       if (rctx->b.chip_class == R600 && !rctx->scissor.enable) {
-               tl = S_028240_TL_X(0) | S_028240_TL_Y(0) | S_028240_WINDOW_OFFSET_DISABLE(1);
-               br = S_028244_BR_X(8192) | S_028244_BR_Y(8192);
-               do_disable_workaround = true;
-       }
-
-       dirty_mask = rstate->dirty_mask;
-       while (dirty_mask != 0)
-       {
-               i = u_bit_scan(&dirty_mask);
-               offset = i * 4 * 2;
-               radeon_set_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL + offset, 2);
-               if (!do_disable_workaround) {
-                       state = &rstate->scissor[i];
-                       tl = S_028240_TL_X(state->minx) | S_028240_TL_Y(state->miny) |
-                               S_028240_WINDOW_OFFSET_DISABLE(1);
-                       br = S_028244_BR_X(state->maxx) | S_028244_BR_Y(state->maxy);
-               }
-               radeon_emit(cs, tl);
-               radeon_emit(cs, br);
-       }
-       rstate->dirty_mask = 0;
-       rstate->atom.num_dw = 0;
-}
-
-static void r600_set_scissor_states(struct pipe_context *ctx,
-                                    unsigned start_slot,
-                                    unsigned num_scissors,
-                                    const struct pipe_scissor_state *state)
-{
-       struct r600_context *rctx = (struct r600_context *)ctx;
-       struct r600_scissor_state *rstate = &rctx->scissor;
-       int i;
-
-       for (i = start_slot ; i < start_slot + num_scissors; i++)
-               rstate->scissor[i] = state[i - start_slot];
-       rstate->dirty_mask |= ((1 << num_scissors) - 1) << start_slot;
-       rstate->atom.num_dw = util_bitcount(rstate->dirty_mask) * 4;
-
-       if (rctx->b.chip_class == R600 && !rstate->enable)
-               return;
-
-       r600_mark_atom_dirty(rctx, &rstate->atom);
-}
-
 static struct r600_resource *r600_buffer_create_helper(struct r600_screen *rscreen,
                                                       unsigned size, unsigned alignment)
 {
@@ -2443,12 +2388,6 @@ void r600_init_atom_start_cs(struct r600_context *rctx)
        r600_store_context_reg(cb, R_028820_PA_CL_NANINF_CNTL, 0);
        r600_store_context_reg(cb, R_028A48_PA_SC_MPASS_PS_CNTL, 0);
 
-       r600_store_context_reg_seq(cb, R_028C0C_PA_CL_GB_VERT_CLIP_ADJ, 4);
-       r600_store_value(cb, fui(1.0)); /* R_028C0C_PA_CL_GB_VERT_CLIP_ADJ */
-       r600_store_value(cb, fui(1.0)); /* R_028C10_PA_CL_GB_VERT_DISC_ADJ */
-       r600_store_value(cb, fui(1.0)); /* R_028C14_PA_CL_GB_HORZ_CLIP_ADJ */
-       r600_store_value(cb, fui(1.0)); /* R_028C18_PA_CL_GB_HORZ_DISC_ADJ */
-
        r600_store_context_reg_seq(cb, R_0282D0_PA_SC_VPORT_ZMIN_0, 2 * R600_MAX_VIEWPORTS);
        for (tmp = 0; tmp < R600_MAX_VIEWPORTS; tmp++) {
                r600_store_value(cb, 0); /* R_0282D0_PA_SC_VPORT_ZMIN_0 */
@@ -3151,8 +3090,8 @@ void r600_init_state_functions(struct r600_context *rctx)
        r600_init_atom(rctx, &rctx->dsa_state.atom, id++, r600_emit_cso_state, 0);
        r600_init_atom(rctx, &rctx->poly_offset_state.atom, id++, r600_emit_polygon_offset, 6);
        r600_init_atom(rctx, &rctx->rasterizer_state.atom, id++, r600_emit_cso_state, 0);
-       r600_init_atom(rctx, &rctx->scissor.atom, id++, r600_emit_scissor_state, 0);
-       r600_init_atom(rctx, &rctx->viewport.atom, id++, r600_emit_viewport_state, 0);
+       r600_add_atom(rctx, &rctx->b.scissors.atom, id++);
+       r600_add_atom(rctx, &rctx->b.viewports.atom, id++);
        r600_init_atom(rctx, &rctx->config_state.atom, id++, r600_emit_config_state, 3);
        r600_init_atom(rctx, &rctx->stencil_ref.atom, id++, r600_emit_stencil_ref, 4);
        r600_init_atom(rctx, &rctx->vertex_fetch_shader.atom, id++, r600_emit_vertex_fetch_shader, 5);
@@ -3172,7 +3111,6 @@ void r600_init_state_functions(struct r600_context *rctx)
        rctx->b.b.set_framebuffer_state = r600_set_framebuffer_state;
        rctx->b.b.set_polygon_stipple = r600_set_polygon_stipple;
        rctx->b.b.set_min_samples = r600_set_min_samples;
-       rctx->b.b.set_scissor_states = r600_set_scissor_states;
        rctx->b.b.get_sample_position = r600_get_sample_position;
        rctx->b.dma_copy = r600_dma_copy;
 }
index 95666a3..cb40c20 100644 (file)
@@ -364,14 +364,7 @@ static void r600_bind_rs_state(struct pipe_context *ctx, void *state)
                r600_mark_atom_dirty(rctx, &rctx->clip_misc_state.atom);
        }
 
-       /* Workaround for a missing scissor enable on r600. */
-       if (rctx->b.chip_class == R600 &&
-           rs->scissor_enable != rctx->scissor.enable) {
-               rctx->scissor.enable = rs->scissor_enable;
-               rctx->scissor.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
-               rctx->scissor.atom.num_dw = R600_MAX_VIEWPORTS * 4;
-               r600_mark_atom_dirty(rctx, &rctx->scissor.atom);
-       }
+       r600_set_scissor_enable(&rctx->b, rs->scissor_enable);
 
        /* Re-emit PA_SC_LINE_STIPPLE. */
        rctx->last_primitive_type = -1;
@@ -713,47 +706,6 @@ static void r600_update_compressed_colortex_mask(struct r600_samplerview_state *
        }
 }
 
-static void r600_set_viewport_states(struct pipe_context *ctx,
-                                     unsigned start_slot,
-                                     unsigned num_viewports,
-                                     const struct pipe_viewport_state *state)
-{
-       struct r600_context *rctx = (struct r600_context *)ctx;
-       struct r600_viewport_state *rstate = &rctx->viewport;
-       int i;
-
-       for (i = start_slot; i < start_slot + num_viewports; i++)
-               rstate->state[i] = state[i - start_slot];
-       rstate->dirty_mask |= ((1 << num_viewports) - 1) << start_slot;
-       rstate->atom.num_dw = util_bitcount(rstate->dirty_mask) * 8;
-       r600_mark_atom_dirty(rctx, &rctx->viewport.atom);
-}
-
-void r600_emit_viewport_state(struct r600_context *rctx, struct r600_atom *atom)
-{
-       struct radeon_winsys_cs *cs = rctx->b.gfx.cs;
-       struct r600_viewport_state *rstate = &rctx->viewport;
-       struct pipe_viewport_state *state;
-       uint32_t dirty_mask;
-       unsigned i, offset;
-
-       dirty_mask = rstate->dirty_mask;
-       while (dirty_mask != 0) {
-               i = u_bit_scan(&dirty_mask);
-               offset = i * 6 * 4;
-               radeon_set_context_reg_seq(cs, R_02843C_PA_CL_VPORT_XSCALE_0 + offset, 6);
-               state = &rstate->state[i];
-               radeon_emit(cs, fui(state->scale[0]));     /* R_02843C_PA_CL_VPORT_XSCALE_0  */
-               radeon_emit(cs, fui(state->translate[0])); /* R_028440_PA_CL_VPORT_XOFFSET_0 */
-               radeon_emit(cs, fui(state->scale[1]));     /* R_028444_PA_CL_VPORT_YSCALE_0  */
-               radeon_emit(cs, fui(state->translate[1])); /* R_028448_PA_CL_VPORT_YOFFSET_0 */
-               radeon_emit(cs, fui(state->scale[2]));     /* R_02844C_PA_CL_VPORT_ZSCALE_0  */
-               radeon_emit(cs, fui(state->translate[2])); /* R_028450_PA_CL_VPORT_ZOFFSET_0 */
-       }
-       rstate->dirty_mask = 0;
-       rstate->atom.num_dw = 0;
-}
-
 /* Compute the key for the hw shader variant */
 static inline union r600_shader_key r600_shader_selector_key(struct pipe_context * ctx,
                struct r600_pipe_shader_selector * sel)
@@ -961,6 +913,18 @@ static void r600_bind_ps_state(struct pipe_context *ctx, void *state)
        rctx->ps_shader = (struct r600_pipe_shader_selector *)state;
 }
 
+static struct tgsi_shader_info *r600_get_vs_info(struct r600_context *rctx)
+{
+       if (rctx->gs_shader)
+               return &rctx->gs_shader->info;
+       else if (rctx->tes_shader)
+               return &rctx->tes_shader->info;
+       else if (rctx->vs_shader)
+               return &rctx->vs_shader->info;
+       else
+               return NULL;
+}
+
 static void r600_bind_vs_state(struct pipe_context *ctx, void *state)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
@@ -969,6 +933,7 @@ static void r600_bind_vs_state(struct pipe_context *ctx, void *state)
                return;
 
        rctx->vs_shader = (struct r600_pipe_shader_selector *)state;
+       r600_update_vs_writes_viewport_index(&rctx->b, r600_get_vs_info(rctx));
        rctx->b.streamout.stride_in_dw = rctx->vs_shader->so.stride;
 }
 
@@ -977,6 +942,7 @@ static void r600_bind_gs_state(struct pipe_context *ctx, void *state)
        struct r600_context *rctx = (struct r600_context *)ctx;
 
        rctx->gs_shader = (struct r600_pipe_shader_selector *)state;
+       r600_update_vs_writes_viewport_index(&rctx->b, r600_get_vs_info(rctx));
 
        if (!state)
                return;
@@ -995,6 +961,7 @@ static void r600_bind_tes_state(struct pipe_context *ctx, void *state)
        struct r600_context *rctx = (struct r600_context *)ctx;
 
        rctx->tes_shader = (struct r600_pipe_shader_selector *)state;
+       r600_update_vs_writes_viewport_index(&rctx->b, r600_get_vs_info(rctx));
 
        if (!state)
                return;
@@ -2916,7 +2883,6 @@ void r600_init_common_state_functions(struct r600_context *rctx)
        rctx->b.b.set_constant_buffer = r600_set_constant_buffer;
        rctx->b.b.set_sample_mask = r600_set_sample_mask;
        rctx->b.b.set_stencil_ref = r600_set_pipe_stencil_ref;
-       rctx->b.b.set_viewport_states = r600_set_viewport_states;
        rctx->b.b.set_vertex_buffers = r600_set_vertex_buffers;
        rctx->b.b.set_index_buffer = r600_set_index_buffer;
        rctx->b.b.set_sampler_views = r600_set_sampler_views;