r600g: enable DUAL_EXPORT mode when possible on r6xx/r7xx
authorJerome Glisse <jglisse@redhat.com>
Tue, 26 Jun 2012 16:24:08 +0000 (12:24 -0400)
committerVadim Girlin <vadimgirlin@gmail.com>
Tue, 26 Jun 2012 22:06:55 +0000 (02:06 +0400)
DUAL_EXPORT can be enabled on r6xx/r7xx when all CBs use 16-bit export
and there is no depth/stencil export.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_state_common.c

index 72db0096dc454b99bd22646ac8b9288399d5353b..82c4a125024ee026ae9aba9998e1f57f127e390d 100644 (file)
@@ -476,6 +476,7 @@ boolean r600_is_format_supported(struct pipe_screen *screen,
                                 enum pipe_texture_target target,
                                 unsigned sample_count,
                                 unsigned usage);
+void r600_update_dual_export_state(struct r600_context * rctx);
 
 /* r600_texture.c */
 void r600_init_screen_texture_functions(struct pipe_screen *screen);
index d621aee920173db124e41e046c3e385b7c2c5a7c..bb72bf8035971265d1fe0721a1fdb8f4fc19d365 100644 (file)
@@ -1499,8 +1499,11 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate,
                     ntype != V_0280A0_NUMBER_UINT &&
                     ntype != V_0280A0_NUMBER_SINT) &&
                    G_0280A0_BLEND_CLAMP(color_info) &&
-                   !G_0280A0_BLEND_FLOAT32(color_info))
+                   !G_0280A0_BLEND_FLOAT32(color_info)) {
                        color_info |= S_0280A0_SOURCE_FORMAT(V_0280A0_EXPORT_NORM);
+               } else {
+                       rctx->export_16bpc = false;
+               }
        } else {
                /* EXPORT_NORM can be enabled if:
                 * - 11-bit or smaller UNORM/SNORM/SRGB
@@ -1511,8 +1514,11 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate,
                      desc->channel[i].type != UTIL_FORMAT_TYPE_FLOAT &&
                      ntype != V_0280A0_NUMBER_UINT && ntype != V_0280A0_NUMBER_SINT) ||
                    (desc->channel[i].size < 17 &&
-                    desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)))
+                    desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT))) {
                        color_info |= S_0280A0_SOURCE_FORMAT(V_0280A0_EXPORT_NORM);
+               } else {
+                       rctx->export_16bpc = false;
+               }
        }
 
        /* for possible dual-src MRT write color info 1 */
@@ -1644,6 +1650,7 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
 
        /* build states */
        rctx->have_depth_fb = 0;
+       rctx->export_16bpc = true;
        rctx->nr_cbufs = state->nr_cbufs;
 
        for (int i = 0; i < state->nr_cbufs; i++) {
@@ -2239,6 +2246,7 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad
        int pos_index = -1, face_index = -1;
        unsigned tmp, sid, ufi = 0;
        int need_linear = 0;
+       unsigned z_export = 0, stencil_export = 0;
 
        rstate->nregs = 0;
 
@@ -2278,23 +2286,23 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad
        db_shader_control = S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z);
        for (i = 0; i < rshader->noutput; i++) {
                if (rshader->output[i].name == TGSI_SEMANTIC_POSITION)
-                       db_shader_control |= S_02880C_Z_EXPORT_ENABLE(1);
+                       z_export = 1;
                if (rshader->output[i].name == TGSI_SEMANTIC_STENCIL)
-                       db_shader_control |= S_02880C_STENCIL_REF_EXPORT_ENABLE(1);
+                       stencil_export = 1;
        }
+       db_shader_control |= S_02880C_Z_EXPORT_ENABLE(z_export);
+       db_shader_control |= S_02880C_STENCIL_REF_EXPORT_ENABLE(stencil_export);
        if (rshader->uses_kill)
                db_shader_control |= S_02880C_KILL_ENABLE(1);
 
        exports_ps = 0;
-       num_cout = 0;
        for (i = 0; i < rshader->noutput; i++) {
                if (rshader->output[i].name == TGSI_SEMANTIC_POSITION ||
-                   rshader->output[i].name == TGSI_SEMANTIC_STENCIL)
+                   rshader->output[i].name == TGSI_SEMANTIC_STENCIL) {
                        exports_ps |= 1;
-               else if (rshader->output[i].name == TGSI_SEMANTIC_COLOR) {
-                       num_cout++;
                }
        }
+       num_cout = rshader->nr_ps_color_exports;
        exports_ps |= S_028854_EXPORT_COLORS(num_cout);
        if (!exports_ps) {
                /* always at least export 1 component per pixel */
@@ -2340,8 +2348,8 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad
                                R_028854_SQ_PGM_EXPORTS_PS,
                                exports_ps);
        /* only set some bits here, the other bits are set in the dsa state */
-       r600_pipe_state_add_reg(rstate, R_02880C_DB_SHADER_CONTROL,
-                               db_shader_control);
+       shader->db_shader_control = db_shader_control;
+       shader->ps_depth_export = z_export | stencil_export;
 
        shader->sprite_coord_enable = rctx->sprite_coord_enable;
        if (rctx->rasterizer)
@@ -2440,3 +2448,20 @@ void *r600_create_db_flush_dsa(struct r600_context *rctx)
        dsa_state->is_flush = true;
        return rstate;
 }
+
+void r600_update_dual_export_state(struct r600_context * rctx)
+{
+       unsigned dual_export = rctx->export_16bpc && rctx->nr_cbufs &&
+                              !rctx->ps_shader->current->ps_depth_export;
+       unsigned db_shader_control = rctx->ps_shader->current->db_shader_control |
+                                    S_02880C_DUAL_EXPORT_ENABLE(dual_export);
+
+       if (db_shader_control != rctx->db_shader_control) {
+               struct r600_pipe_state rstate;
+
+               rctx->db_shader_control = db_shader_control;
+               rstate.nregs = 0;
+               r600_pipe_state_add_reg(&rstate, R_02880C_DB_SHADER_CONTROL, db_shader_control);
+               r600_context_pipe_state_set(rctx, &rstate);
+       }
+}
index fb9679bed20a066a87df7135d95ab44ecb749a41..b5241a72e7341c097a57443f733f3d76102198e2 100644 (file)
@@ -559,8 +559,6 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
        rctx->ps_shader = (struct r600_pipe_shader_selector *)state;
        r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate);
 
-       rctx->cb_color_control &= C_028808_MULTIWRITE_ENABLE;
-       rctx->cb_color_control |= S_028808_MULTIWRITE_ENABLE(!!rctx->ps_shader->current->shader.fs_write_all);
 
        if (rctx->chip_class < EVERGREEN && rctx->vs_shader) {
                r600_adjust_gprs(rctx);
@@ -627,8 +625,9 @@ static void r600_update_alpha_ref(struct r600_context *rctx)
 
        alpha_ref = rctx->alpha_ref;
        rstate.nregs = 0;
-       if (rctx->export_16bpc)
+       if (rctx->export_16bpc && rctx->chip_class >= EVERGREEN) {
                alpha_ref &= ~0x1FFF;
+       }
        r600_pipe_state_add_reg(&rstate, R_028438_SX_ALPHA_REF, alpha_ref);
 
        r600_context_pipe_state_set(rctx, &rstate);
@@ -808,13 +807,17 @@ static void r600_update_derived_state(struct r600_context *rctx)
        if (ps_dirty)
                r600_context_pipe_state_set(rctx, &rctx->ps_shader->current->rstate);
                
-       if (rctx->chip_class >= EVERGREEN)
+       if (rctx->chip_class >= EVERGREEN) {
                evergreen_update_dual_export_state(rctx);
+       } else {
+               r600_update_dual_export_state(rctx);
+       }
 
-       if (rctx->dual_src_blend)
+       if (rctx->dual_src_blend) {
                rctx->cb_shader_mask = rctx->ps_shader->current->ps_cb_shader_mask | rctx->fb_cb_shader_mask;
-       else
+       } else {
                rctx->cb_shader_mask = rctx->fb_cb_shader_mask;
+       }
 }
 
 static unsigned r600_conv_prim_to_gs_out(unsigned mode)
@@ -902,8 +905,13 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
                r600_pipe_state_add_reg(&rctx->vgt, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, info.primitive_restart);
                r600_pipe_state_add_reg(&rctx->vgt, R_03CFF4_SQ_VTX_START_INST_LOC, info.start_instance);
                r600_pipe_state_add_reg(&rctx->vgt, R_028A0C_PA_SC_LINE_STIPPLE, 0);
-               if (rctx->chip_class <= R700)
+               if (rctx->chip_class <= R700) {
+                       unsigned multi_write = !!rctx->ps_shader->current->shader.fs_write_all &&
+                                              (rctx->nr_cbufs > 1);
+                       rctx->cb_color_control &= C_028808_MULTIWRITE_ENABLE;
+                       rctx->cb_color_control |= S_028808_MULTIWRITE_ENABLE(multi_write);
                        r600_pipe_state_add_reg(&rctx->vgt, R_028808_CB_COLOR_CONTROL, rctx->cb_color_control);
+               }
                r600_pipe_state_add_reg(&rctx->vgt, R_02881C_PA_CL_VS_OUT_CNTL, 0);
                r600_pipe_state_add_reg(&rctx->vgt, R_028810_PA_CL_CLIP_CNTL, 0);
        }
@@ -924,8 +932,13 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
        else if (prim == V_008958_DI_PT_LINESTRIP) 
                ls_mask = 2;
        r600_pipe_state_mod_reg(&rctx->vgt, S_028A0C_AUTO_RESET_CNTL(ls_mask) | rctx->pa_sc_line_stipple);
-       if (rctx->chip_class <= R700)
+       if (rctx->chip_class <= R700) {
+               unsigned multi_write = !!rctx->ps_shader->current->shader.fs_write_all &&
+                                      (rctx->nr_cbufs > 1);
+               rctx->cb_color_control &= C_028808_MULTIWRITE_ENABLE;
+               rctx->cb_color_control |= S_028808_MULTIWRITE_ENABLE(multi_write);
                r600_pipe_state_mod_reg(&rctx->vgt, rctx->cb_color_control);
+       }
        r600_pipe_state_mod_reg(&rctx->vgt,
                                rctx->vs_shader->current->pa_cl_vs_out_cntl |
                                (rctx->rasterizer->clip_plane_enable & rctx->vs_shader->current->shader.clip_dist_write));