radeonsi: tell LLVM not to remove s_barrier instructions
[mesa.git] / src / gallium / drivers / r600 / r600_state_common.c
index 096caed8d367bc5cebc3f1427ebd1a5c62e70d48..7b52be36cda6e2bb73101476bb4e8ce21b530321 100644 (file)
@@ -99,6 +99,7 @@ static void r600_texture_barrier(struct pipe_context *ctx, unsigned flags)
                       R600_CONTEXT_FLUSH_AND_INV_CB |
                       R600_CONTEXT_FLUSH_AND_INV |
                       R600_CONTEXT_WAIT_3D_IDLE;
+       rctx->framebuffer.do_update_surf_dirtiness = true;
 }
 
 static unsigned r600_conv_pipe_prim(unsigned prim)
@@ -712,49 +713,47 @@ static void r600_update_compressed_colortex_mask(struct r600_samplerview_state *
 }
 
 /* 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)
+static inline void r600_shader_selector_key(const struct pipe_context *ctx,
+               const struct r600_pipe_shader_selector *sel,
+               union r600_shader_key *key)
 {
-       struct r600_context *rctx = (struct r600_context *)ctx;
-       union r600_shader_key key;
-       memset(&key, 0, sizeof(key));
+       const struct r600_context *rctx = (struct r600_context *)ctx;
+       memset(key, 0, sizeof(*key));
 
        switch (sel->type) {
        case PIPE_SHADER_VERTEX: {
-               key.vs.as_ls = (rctx->tes_shader != NULL);
-               if (!key.vs.as_ls)
-                       key.vs.as_es = (rctx->gs_shader != NULL);
+               key->vs.as_ls = (rctx->tes_shader != NULL);
+               if (!key->vs.as_ls)
+                       key->vs.as_es = (rctx->gs_shader != NULL);
 
                if (rctx->ps_shader->current->shader.gs_prim_id_input && !rctx->gs_shader) {
-                       key.vs.as_gs_a = true;
-                       key.vs.prim_id_out = rctx->ps_shader->current->shader.input[rctx->ps_shader->current->shader.ps_prim_id_input].spi_sid;
+                       key->vs.as_gs_a = true;
+                       key->vs.prim_id_out = rctx->ps_shader->current->shader.input[rctx->ps_shader->current->shader.ps_prim_id_input].spi_sid;
                }
                break;
        }
        case PIPE_SHADER_GEOMETRY:
                break;
        case PIPE_SHADER_FRAGMENT: {
-               key.ps.color_two_side = rctx->rasterizer && rctx->rasterizer->two_side;
-               key.ps.alpha_to_one = rctx->alpha_to_one &&
+               key->ps.color_two_side = rctx->rasterizer && rctx->rasterizer->two_side;
+               key->ps.alpha_to_one = rctx->alpha_to_one &&
                                      rctx->rasterizer && rctx->rasterizer->multisample_enable &&
                                      !rctx->framebuffer.cb0_is_integer;
-               key.ps.nr_cbufs = rctx->framebuffer.state.nr_cbufs;
+               key->ps.nr_cbufs = rctx->framebuffer.state.nr_cbufs;
                /* Dual-source blending only makes sense with nr_cbufs == 1. */
-               if (key.ps.nr_cbufs == 1 && rctx->dual_src_blend)
-                       key.ps.nr_cbufs = 2;
+               if (key->ps.nr_cbufs == 1 && rctx->dual_src_blend)
+                       key->ps.nr_cbufs = 2;
                break;
        }
        case PIPE_SHADER_TESS_EVAL:
-               key.tes.as_es = (rctx->gs_shader != NULL);
+               key->tes.as_es = (rctx->gs_shader != NULL);
                break;
        case PIPE_SHADER_TESS_CTRL:
-               key.tcs.prim_mode = rctx->tes_shader->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
+               key->tcs.prim_mode = rctx->tes_shader->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
                break;
        default:
                assert(0);
        }
-
-       return key;
 }
 
 /* Select the hw shader variant depending on the current state.
@@ -767,8 +766,7 @@ static int r600_shader_select(struct pipe_context *ctx,
        struct r600_pipe_shader * shader = NULL;
        int r;
 
-       memset(&key, 0, sizeof(key));
-       key = r600_shader_selector_key(ctx, sel);
+       r600_shader_selector_key(ctx, sel, &key);
 
        /* Check if we don't need to change anything.
         * This path is also used for most shaders that don't need multiple
@@ -812,7 +810,7 @@ static int r600_shader_select(struct pipe_context *ctx,
                if (sel->type == PIPE_SHADER_FRAGMENT &&
                                sel->num_shaders == 0) {
                        sel->nr_ps_max_color_exports = shader->shader.nr_ps_max_color_exports;
-                       key = r600_shader_selector_key(ctx, sel);
+                       r600_shader_selector_key(ctx, sel, &key);
                }
 
                memcpy(&shader->key, &key, sizeof(key));
@@ -934,7 +932,7 @@ static void r600_bind_vs_state(struct pipe_context *ctx, void *state)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
 
-       if (!state)
+       if (!state || rctx->vs_shader == state)
                return;
 
        rctx->vs_shader = (struct r600_pipe_shader_selector *)state;
@@ -946,6 +944,9 @@ static void r600_bind_gs_state(struct pipe_context *ctx, void *state)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
 
+       if (state == rctx->gs_shader)
+               return;
+
        rctx->gs_shader = (struct r600_pipe_shader_selector *)state;
        r600_update_vs_writes_viewport_index(&rctx->b, r600_get_vs_info(rctx));
 
@@ -965,6 +966,9 @@ static void r600_bind_tes_state(struct pipe_context *ctx, void *state)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
 
+       if (state == rctx->tes_shader)
+               return;
+
        rctx->tes_shader = (struct r600_pipe_shader_selector *)state;
        r600_update_vs_writes_viewport_index(&rctx->b, r600_get_vs_info(rctx));
 
@@ -1669,6 +1673,32 @@ void r600_emit_clip_misc_state(struct r600_context *rctx, struct r600_atom *atom
                                       S_028AB4_REUSE_OFF(state->vs_out_viewport));
 }
 
+/* rast_prim is the primitive type after GS. */
+static inline void r600_emit_rasterizer_prim_state(struct r600_context *rctx)
+{
+       struct radeon_winsys_cs *cs = rctx->b.gfx.cs;
+       enum pipe_prim_type rast_prim = rctx->current_rast_prim;
+
+       /* Skip this if not rendering lines. */
+       if (rast_prim != PIPE_PRIM_LINES &&
+           rast_prim != PIPE_PRIM_LINE_LOOP &&
+           rast_prim != PIPE_PRIM_LINE_STRIP &&
+           rast_prim != PIPE_PRIM_LINES_ADJACENCY &&
+           rast_prim != PIPE_PRIM_LINE_STRIP_ADJACENCY)
+               return;
+
+       if (rast_prim == rctx->last_rast_prim)
+               return;
+
+       /* For lines, reset the stipple pattern at each primitive. Otherwise,
+        * reset the stipple pattern at each packet (line strips, line loops).
+        */
+       radeon_set_context_reg(cs, R_028A0C_PA_SC_LINE_STIPPLE,
+                              S_028A0C_AUTO_RESET_CNTL(rast_prim == PIPE_PRIM_LINES ? 1 : 2) |
+                              (rctx->rasterizer ? rctx->rasterizer->pa_sc_line_stipple : 0));
+       rctx->last_rast_prim = rast_prim;
+}
+
 static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
@@ -1683,7 +1713,12 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                return;
        }
 
-       if (unlikely(!rctx->vs_shader || !rctx->ps_shader)) {
+       if (unlikely(!rctx->vs_shader)) {
+               assert(0);
+               return;
+       }
+       if (unlikely(!rctx->ps_shader &&
+                    (!rctx->rasterizer || !rctx->rasterizer->rasterizer_discard))) {
                assert(0);
                return;
        }
@@ -1698,6 +1733,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
        if (unlikely(dirty_tex_counter != rctx->b.last_dirty_tex_counter)) {
                rctx->b.last_dirty_tex_counter = dirty_tex_counter;
                r600_mark_atom_dirty(rctx, &rctx->framebuffer.atom);
+               rctx->framebuffer.do_update_surf_dirtiness = true;
        }
 
        if (!r600_update_derived_state(rctx)) {
@@ -1707,6 +1743,10 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                return;
        }
 
+       rctx->current_rast_prim = (rctx->gs_shader)? rctx->gs_shader->gs_output_prim
+               : (rctx->tes_shader)? rctx->tes_shader->info.properties[TGSI_PROPERTY_TES_PRIM_MODE]
+               : info->mode;
+
        if (info->indexed) {
                /* Initialize the index buffer struct. */
                pipe_resource_reference(&ib.buffer, rctx->index_buffer.buffer);
@@ -1866,17 +1906,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
 
        /* Update the primitive type. */
        if (rctx->last_primitive_type != info->mode) {
-               unsigned ls_mask = 0;
-
-               if (info->mode == PIPE_PRIM_LINES)
-                       ls_mask = 1;
-               else if (info->mode == PIPE_PRIM_LINE_STRIP ||
-                        info->mode == PIPE_PRIM_LINE_LOOP)
-                       ls_mask = 2;
-
-               radeon_set_context_reg(cs, R_028A0C_PA_SC_LINE_STIPPLE,
-                                      S_028A0C_AUTO_RESET_CNTL(ls_mask) |
-                                      (rctx->rasterizer ? rctx->rasterizer->pa_sc_line_stipple : 0));
+               r600_emit_rasterizer_prim_state(rctx);
                radeon_set_config_reg(cs, R_008958_VGT_PRIMITIVE_TYPE,
                                      r600_conv_pipe_prim(info->mode));
 
@@ -2006,29 +2036,32 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SQ_NON_EVENT));
        }
 
-       /* Set the depth buffer as dirty. */
-       if (rctx->framebuffer.state.zsbuf) {
-               struct pipe_surface *surf = rctx->framebuffer.state.zsbuf;
-               struct r600_texture *rtex = (struct r600_texture *)surf->texture;
+       if (rctx->framebuffer.do_update_surf_dirtiness) {
+               /* Set the depth buffer as dirty. */
+               if (rctx->framebuffer.state.zsbuf) {
+                       struct pipe_surface *surf = rctx->framebuffer.state.zsbuf;
+                       struct r600_texture *rtex = (struct r600_texture *)surf->texture;
 
-               rtex->dirty_level_mask |= 1 << surf->u.tex.level;
+                       rtex->dirty_level_mask |= 1 << surf->u.tex.level;
 
-               if (rtex->surface.flags & RADEON_SURF_SBUFFER)
-                       rtex->stencil_dirty_level_mask |= 1 << surf->u.tex.level;
-       }
-       if (rctx->framebuffer.compressed_cb_mask) {
-               struct pipe_surface *surf;
-               struct r600_texture *rtex;
-               unsigned mask = rctx->framebuffer.compressed_cb_mask;
+                       if (rtex->surface.flags & RADEON_SURF_SBUFFER)
+                               rtex->stencil_dirty_level_mask |= 1 << surf->u.tex.level;
+               }
+               if (rctx->framebuffer.compressed_cb_mask) {
+                       struct pipe_surface *surf;
+                       struct r600_texture *rtex;
+                       unsigned mask = rctx->framebuffer.compressed_cb_mask;
 
-               do {
-                       unsigned i = u_bit_scan(&mask);
-                       surf = rctx->framebuffer.state.cbufs[i];
-                       rtex = (struct r600_texture*)surf->texture;
+                       do {
+                               unsigned i = u_bit_scan(&mask);
+                               surf = rctx->framebuffer.state.cbufs[i];
+                               rtex = (struct r600_texture*)surf->texture;
 
-                       rtex->dirty_level_mask |= 1 << surf->u.tex.level;
+                               rtex->dirty_level_mask |= 1 << surf->u.tex.level;
 
-               } while (mask);
+                       } while (mask);
+               }
+               rctx->framebuffer.do_update_surf_dirtiness = false;
        }
 
        pipe_resource_reference(&ib.buffer, NULL);