gallium: change pipe_sampler_view::first_element/last_element -> offset/size
[mesa.git] / src / gallium / drivers / radeonsi / si_state.c
index 0a2fdbf38ee600ddf2201aaeb874ce5f26c9c309..7e63d487377689433da9cdb7c2f637c90a7b817c 100644 (file)
@@ -88,27 +88,20 @@ static unsigned si_pack_float_12p4(float x)
 /*
  * Inferred framebuffer and blender state.
  *
- * One of the reasons CB_TARGET_MASK must be derived from the framebuffer state
- * is that:
- * - The blend state mask is 0xf most of the time.
- * - The COLOR1 format isn't INVALID because of possible dual-source blending,
- *   so COLOR1 is enabled pretty much all the time.
- * So CB_TARGET_MASK is the only register that can disable COLOR1.
- *
- * Another reason is to avoid a hang with dual source blending.
+ * CB_TARGET_MASK is emitted here to avoid a hang with dual source blending
+ * if there is not enough PS outputs.
  */
 static void si_emit_cb_render_state(struct si_context *sctx, struct r600_atom *atom)
 {
        struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
        struct si_state_blend *blend = sctx->queued.named.blend;
-       uint32_t cb_target_mask = 0, i;
-
-       for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++)
-               if (sctx->framebuffer.state.cbufs[i])
-                       cb_target_mask |= 0xf << (4*i);
+       uint32_t cb_target_mask, i;
 
+       /* CB_COLORn_INFO.FORMAT=INVALID disables empty colorbuffer slots. */
        if (blend)
-               cb_target_mask &= blend->cb_target_mask;
+               cb_target_mask = blend->cb_target_mask;
+       else
+               cb_target_mask = 0xffffffff;
 
        /* Avoid a hang that happens when dual source blending is enabled
         * but there is not enough color outputs. This is undefined behavior,
@@ -460,6 +453,20 @@ static void *si_create_blend_state_mode(struct pipe_context *ctx,
                        S_028760_COLOR_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED) |
                        S_028760_ALPHA_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED);
 
+               /* Only set dual source blending for MRT0 to avoid a hang. */
+               if (i >= 1 && blend->dual_src_blend)
+                       continue;
+
+               /* Only addition and subtraction equations are supported with
+                * dual source blending.
+                */
+               if (blend->dual_src_blend &&
+                   (eqRGB == PIPE_BLEND_MIN || eqRGB == PIPE_BLEND_MAX ||
+                    eqA == PIPE_BLEND_MIN || eqA == PIPE_BLEND_MAX)) {
+                       assert(!"Unsupported equation for dual source blending");
+                       continue;
+               }
+
                if (!state->rt[j].colormask)
                        continue;
 
@@ -572,6 +579,7 @@ static void si_bind_blend_state(struct pipe_context *ctx, void *state)
        struct si_context *sctx = (struct si_context *)ctx;
        si_pm4_bind_state(sctx, blend, (struct si_state_blend *)state);
        si_mark_atom_dirty(sctx, &sctx->cb_render_state);
+       sctx->do_update_shaders = true;
 }
 
 static void si_delete_blend_state(struct pipe_context *ctx, void *state)
@@ -856,15 +864,20 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state)
                return;
 
        if (sctx->framebuffer.nr_samples > 1 &&
-           (!old_rs || old_rs->multisample_enable != rs->multisample_enable))
+           (!old_rs || old_rs->multisample_enable != rs->multisample_enable)) {
                si_mark_atom_dirty(sctx, &sctx->db_render_state);
 
+               if (sctx->b.family >= CHIP_POLARIS10)
+                       si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs.atom);
+       }
+
        r600_set_scissor_enable(&sctx->b, rs->scissor_enable);
 
        si_pm4_bind_state(sctx, rasterizer, rs);
        si_update_poly_offset_state(sctx);
 
        si_mark_atom_dirty(sctx, &sctx->clip_regs);
+       sctx->do_update_shaders = true;
 }
 
 static void si_delete_rs_state(struct pipe_context *ctx, void *state)
@@ -1014,6 +1027,7 @@ static void si_bind_dsa_state(struct pipe_context *ctx, void *state)
                sctx->stencil_ref.dsa_part = dsa->stencil_ref;
                si_mark_atom_dirty(sctx, &sctx->stencil_ref.atom);
        }
+       sctx->do_update_shaders = true;
 }
 
 static void si_delete_dsa_state(struct pipe_context *ctx, void *state)
@@ -1779,6 +1793,9 @@ static boolean si_is_format_supported(struct pipe_screen *screen,
                if (!screen->get_param(screen, PIPE_CAP_TEXTURE_MULTISAMPLE))
                        return false;
 
+               if (usage & PIPE_BIND_SHADER_IMAGE)
+                       return false;
+
                switch (sample_count) {
                case 2:
                case 4:
@@ -2042,6 +2059,12 @@ static void si_initialize_color_surface(struct si_context *sctx,
                S_028C70_COMP_SWAP(swap) |
                S_028C70_BLEND_CLAMP(blend_clamp) |
                S_028C70_BLEND_BYPASS(blend_bypass) |
+               S_028C70_SIMPLE_FLOAT(1) |
+               S_028C70_ROUND_MODE(ntype != V_028C70_NUMBER_UNORM &&
+                                   ntype != V_028C70_NUMBER_SNORM &&
+                                   ntype != V_028C70_NUMBER_SRGB &&
+                                   format != V_028C70_COLOR_8_24 &&
+                                   format != V_028C70_COLOR_24_8) |
                S_028C70_NUMBER_TYPE(ntype) |
                S_028C70_ENDIAN(endian);
 
@@ -2206,7 +2229,7 @@ static void si_init_depth_surface(struct si_context *sctx,
        surf->depth_initialized = true;
 }
 
-void si_dec_framebuffer_counters(const struct pipe_framebuffer_state *state)
+static void si_dec_framebuffer_counters(const struct pipe_framebuffer_state *state)
 {
        for (int i = 0; i < state->nr_cbufs; ++i) {
                struct r600_surface *surf = NULL;
@@ -2233,6 +2256,15 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
        unsigned old_nr_samples = sctx->framebuffer.nr_samples;
        int i;
 
+       for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++) {
+               if (!sctx->framebuffer.state.cbufs[i])
+                       continue;
+
+               rtex = (struct r600_texture*)sctx->framebuffer.state.cbufs[i]->texture;
+               if (rtex->dcc_gather_statistics)
+                       vi_separate_dcc_stop_query(ctx, rtex);
+       }
+
        /* Only flush TC when changing the framebuffer state, because
         * the only client not using TC that can change textures is
         * the framebuffer.
@@ -2304,17 +2336,12 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
                r600_context_add_resource_size(ctx, surf->base.texture);
 
                p_atomic_inc(&rtex->framebuffers_bound);
-       }
-       /* Set the second SPI format for possible dual-src blending. */
-       if (i == 1 && surf) {
-               sctx->framebuffer.spi_shader_col_format |=
-                       surf->spi_shader_col_format << (i * 4);
-               sctx->framebuffer.spi_shader_col_format_alpha |=
-                       surf->spi_shader_col_format_alpha << (i * 4);
-               sctx->framebuffer.spi_shader_col_format_blend |=
-                       surf->spi_shader_col_format_blend << (i * 4);
-               sctx->framebuffer.spi_shader_col_format_blend_alpha |=
-                       surf->spi_shader_col_format_blend_alpha << (i * 4);
+
+               if (rtex->dcc_gather_statistics) {
+                       /* Dirty tracking must be enabled for DCC usage analysis. */
+                       sctx->framebuffer.compressed_cb_mask |= 1 << i;
+                       vi_separate_dcc_start_query(ctx, rtex);
+               }
        }
 
        if (state->zsbuf) {
@@ -2362,21 +2389,11 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
                constbuf.buffer_size = sctx->framebuffer.nr_samples * 2 * 4;
                si_set_rw_buffer(sctx, SI_PS_CONST_SAMPLE_POSITIONS, &constbuf);
 
-               /* Smoothing (only possible with nr_samples == 1) uses the same
-                * sample locations as the MSAA it simulates.
-                *
-                * Therefore, don't update the sample locations when
-                * transitioning from no AA to smoothing-equivalent AA, and
-                * vice versa.
-                */
-               if ((sctx->framebuffer.nr_samples != 1 ||
-                    old_nr_samples != SI_NUM_SMOOTH_AA_SAMPLES) &&
-                   (sctx->framebuffer.nr_samples != SI_NUM_SMOOTH_AA_SAMPLES ||
-                    old_nr_samples != 1))
-                       si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs);
+               si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs.atom);
        }
 
        sctx->need_check_render_feedback = true;
+       sctx->do_update_shaders = true;
 }
 
 static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom *atom)
@@ -2417,6 +2434,12 @@ static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom
                                RADEON_PRIO_CMASK);
                }
 
+               if (tex->dcc_separate_buffer)
+                       radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
+                                                 tex->dcc_separate_buffer,
+                                                 RADEON_USAGE_READWRITE,
+                                                 RADEON_PRIO_DCC);
+
                /* Compute mutable surface parameters. */
                pitch_tile_max = cb->level_info->nblk_x / 8 - 1;
                slice_tile_max = cb->level_info->nblk_x *
@@ -2473,17 +2496,10 @@ static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom
                radeon_emit(cs, tex->color_clear_value[1]);     /* R_028C90_CB_COLOR0_CLEAR_WORD1 */
 
                if (sctx->b.chip_class >= VI) /* R_028C94_CB_COLOR0_DCC_BASE */
-                       radeon_emit(cs, (tex->resource.gpu_address +
+                       radeon_emit(cs, ((!tex->dcc_separate_buffer ? tex->resource.gpu_address : 0) +
                                         tex->dcc_offset +
                                         tex->surface.level[cb->base.u.tex.level].dcc_offset) >> 8);
        }
-       /* set CB_COLOR1_INFO for possible dual-src blending */
-       if (i == 1 && state->cbufs[0] &&
-           sctx->framebuffer.dirty_cbufs & (1 << 0)) {
-               radeon_set_context_reg(cs, R_028C70_CB_COLOR0_INFO + 1 * 0x3C,
-                                      cb_color_info);
-               i++;
-       }
        for (; i < 8 ; i++)
                if (sctx->framebuffer.dirty_cbufs & (1 << i))
                        radeon_set_context_reg(cs, R_028C70_CB_COLOR0_INFO + i * 0x3C, 0);
@@ -2546,8 +2562,37 @@ static void si_emit_msaa_sample_locs(struct si_context *sctx,
        struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
        unsigned nr_samples = sctx->framebuffer.nr_samples;
 
-       cayman_emit_msaa_sample_locs(cs, nr_samples > 1 ? nr_samples :
-                                               SI_NUM_SMOOTH_AA_SAMPLES);
+       /* Smoothing (only possible with nr_samples == 1) uses the same
+        * sample locations as the MSAA it simulates.
+        */
+       if (nr_samples <= 1 && sctx->smoothing_enabled)
+               nr_samples = SI_NUM_SMOOTH_AA_SAMPLES;
+
+       /* On Polaris, the small primitive filter uses the sample locations
+        * even when MSAA is off, so we need to make sure they're set to 0.
+        */
+       if ((nr_samples > 1 || sctx->b.family >= CHIP_POLARIS10) &&
+           (nr_samples != sctx->msaa_sample_locs.nr_samples)) {
+               sctx->msaa_sample_locs.nr_samples = nr_samples;
+               cayman_emit_msaa_sample_locs(cs, nr_samples);
+       }
+
+       if (sctx->b.family >= CHIP_POLARIS10) {
+               struct si_state_rasterizer *rs = sctx->queued.named.rasterizer;
+               unsigned small_prim_filter_cntl =
+                       S_028830_SMALL_PRIM_FILTER_ENABLE(1) |
+                       S_028830_LINE_FILTER_DISABLE(1); /* line bug */
+
+               /* The alternative of setting sample locations to 0 would
+                * require a DB flush to avoid Z errors, see
+                * https://bugs.freedesktop.org/show_bug.cgi?id=96908
+                */
+               if (sctx->framebuffer.nr_samples > 1 && rs && !rs->multisample_enable)
+                       small_prim_filter_cntl &= C_028830_SMALL_PRIM_FILTER_ENABLE;
+
+               radeon_set_context_reg(cs, R_028830_PA_SU_SMALL_PRIM_FILTER_CNTL,
+                                      small_prim_filter_cntl);
+       }
 }
 
 static void si_emit_msaa_config(struct si_context *sctx, struct r600_atom *atom)
@@ -2582,6 +2627,7 @@ static void si_set_min_samples(struct pipe_context *ctx, unsigned min_samples)
                return;
 
        sctx->ps_iter_samples = min_samples;
+       sctx->do_update_shaders = true;
 
        if (sctx->framebuffer.nr_samples > 1)
                si_mark_atom_dirty(sctx, &sctx->msaa_config);
@@ -2598,7 +2644,7 @@ static void si_set_min_samples(struct pipe_context *ctx, unsigned min_samples)
 void
 si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
                          enum pipe_format format,
-                         unsigned first_element, unsigned last_element,
+                         unsigned offset, unsigned size,
                          uint32_t *state)
 {
        const struct util_format_description *desc;
@@ -2611,11 +2657,11 @@ si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
        desc = util_format_description(format);
        first_non_void = util_format_get_first_non_void_channel(format);
        stride = desc->block.bits / 8;
-       va = buf->gpu_address + first_element * stride;
+       va = buf->gpu_address + offset;
        num_format = si_translate_buffer_numformat(&screen->b.b, desc, first_non_void);
        data_format = si_translate_buffer_dataformat(&screen->b.b, desc, first_non_void);
 
-       num_records = last_element + 1 - first_element;
+       num_records = size / stride;
        num_records = MIN2(num_records, buf->b.b.width0 / stride);
 
        if (screen->b.chip_class >= VI)
@@ -2914,8 +2960,8 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
                si_make_buffer_descriptor(sctx->screen,
                                          (struct r600_resource *)texture,
                                          state->format,
-                                         state->u.buf.first_element,
-                                         state->u.buf.last_element,
+                                         state->u.buf.offset,
+                                         state->u.buf.size,
                                          view->state);
 
                LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
@@ -2954,16 +3000,39 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
 
        /* Texturing with separate depth and stencil. */
        pipe_format = state->format;
+
+       /* Depth/stencil texturing sometimes needs separate texture. */
+       if (tmp->is_depth && !r600_can_sample_zs(tmp, view->is_stencil_sampler)) {
+               if (!tmp->flushed_depth_texture &&
+                   !r600_init_flushed_depth_texture(ctx, texture, NULL)) {
+                       pipe_resource_reference(&view->base.texture, NULL);
+                       FREE(view);
+                       return NULL;
+               }
+
+               assert(tmp->flushed_depth_texture);
+
+               /* Override format for the case where the flushed texture
+                * contains only Z or only S.
+                */
+               if (tmp->flushed_depth_texture->resource.b.b.format != tmp->resource.b.b.format)
+                       pipe_format = tmp->flushed_depth_texture->resource.b.b.format;
+
+               tmp = tmp->flushed_depth_texture;
+       }
+
        surflevel = tmp->surface.level;
 
-       if (tmp->is_depth && !tmp->is_flushing_texture) {
+       if (tmp->db_compatible) {
                switch (pipe_format) {
                case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
                        pipe_format = PIPE_FORMAT_Z32_FLOAT;
                        break;
                case PIPE_FORMAT_X8Z24_UNORM:
                case PIPE_FORMAT_S8_UINT_Z24_UNORM:
-                       /* Z24 is always stored like this. */
+                       /* Z24 is always stored like this for DB
+                        * compatibility.
+                        */
                        pipe_format = PIPE_FORMAT_Z24X8_UNORM;
                        break;
                case PIPE_FORMAT_X24S8_UINT:
@@ -3135,6 +3204,13 @@ static void si_emit_sample_mask(struct si_context *sctx, struct r600_atom *atom)
        struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
        unsigned mask = sctx->sample_mask.sample_mask;
 
+       /* Needed for line and polygon smoothing as well as for the Polaris
+        * small primitive filter. We expect the state tracker to take care of
+        * this for us.
+        */
+       assert(mask == 0xffff || sctx->framebuffer.nr_samples > 1 ||
+              (mask & 1 && sctx->blitter->running));
+
        radeon_set_context_reg_seq(cs, R_028C38_PA_SC_AA_MASK_X0Y0_X1Y0, 2);
        radeon_emit(cs, mask | (mask << 16));
        radeon_emit(cs, mask | (mask << 16));
@@ -3191,6 +3267,7 @@ static void si_bind_vertex_elements(struct pipe_context *ctx, void *state)
 
        sctx->vertex_elements = v;
        sctx->vertex_buffers_dirty = true;
+       sctx->do_update_shaders = true;
 }
 
 static void si_delete_vertex_element(struct pipe_context *ctx, void *state)
@@ -3357,7 +3434,7 @@ void si_init_state_functions(struct si_context *sctx)
 
        si_init_atom(sctx, &sctx->cache_flush, &sctx->atoms.s.cache_flush, si_emit_cache_flush);
        si_init_atom(sctx, &sctx->framebuffer.atom, &sctx->atoms.s.framebuffer, si_emit_framebuffer_state);
-       si_init_atom(sctx, &sctx->msaa_sample_locs, &sctx->atoms.s.msaa_sample_locs, si_emit_msaa_sample_locs);
+       si_init_atom(sctx, &sctx->msaa_sample_locs.atom, &sctx->atoms.s.msaa_sample_locs, si_emit_msaa_sample_locs);
        si_init_atom(sctx, &sctx->db_render_state, &sctx->atoms.s.db_render_state, si_emit_db_render_state);
        si_init_atom(sctx, &sctx->msaa_config, &sctx->atoms.s.msaa_config, si_emit_msaa_config);
        si_init_atom(sctx, &sctx->sample_mask.atom, &sctx->atoms.s.sample_mask, si_emit_sample_mask);
@@ -3444,6 +3521,7 @@ static void si_query_opaque_metadata(struct r600_common_screen *rscreen,
        if (rscreen->info.drm_major != 3)
                return;
 
+       assert(rtex->dcc_separate_buffer == NULL);
        assert(rtex->fmask.size == 0);
 
        /* Metadata image format format version 1:
@@ -3805,7 +3883,15 @@ static void si_init_config(struct si_context *sctx)
                       S_028034_BR_X(16384) | S_028034_BR_Y(16384));
 
        si_pm4_set_reg(pm4, R_02820C_PA_SC_CLIPRECT_RULE, 0xFFFF);
-       si_pm4_set_reg(pm4, R_028230_PA_SC_EDGERULE, 0xAAAAAAAA);
+       si_pm4_set_reg(pm4, R_028230_PA_SC_EDGERULE,
+                      S_028230_ER_TRI(0xA) |
+                      S_028230_ER_POINT(0xA) |
+                      S_028230_ER_RECT(0xA) |
+                      /* Required by DX10_DIAMOND_TEST_ENA: */
+                      S_028230_ER_LINE_LR(0x1A) |
+                      S_028230_ER_LINE_RL(0x26) |
+                      S_028230_ER_LINE_TB(0xA) |
+                      S_028230_ER_LINE_BT(0xA));
        /* PA_SU_HARDWARE_SCREEN_OFFSET must be 0 due to hw bug on SI */
        si_pm4_set_reg(pm4, R_028234_PA_SU_HARDWARE_SCREEN_OFFSET, 0);
        si_pm4_set_reg(pm4, R_028820_PA_CL_NANINF_CNTL, 0);
@@ -3821,6 +3907,7 @@ static void si_init_config(struct si_context *sctx)
        si_pm4_set_reg(pm4, R_028408_VGT_INDX_OFFSET, 0);
 
        if (sctx->b.chip_class >= CIK) {
+               si_pm4_set_reg(pm4, R_00B51C_SPI_SHADER_PGM_RSRC3_LS, S_00B51C_CU_EN(0xffff));
                si_pm4_set_reg(pm4, R_00B41C_SPI_SHADER_PGM_RSRC3_HS, 0);
                si_pm4_set_reg(pm4, R_00B31C_SPI_SHADER_PGM_RSRC3_ES, S_00B31C_CU_EN(0xffff));
                si_pm4_set_reg(pm4, R_00B21C_SPI_SHADER_PGM_RSRC3_GS, S_00B21C_CU_EN(0xffff));
@@ -3833,7 +3920,6 @@ static void si_init_config(struct si_context *sctx)
                         *
                         * LATE_ALLOC_VS = 2 is the highest safe number.
                         */
-                       si_pm4_set_reg(pm4, R_00B51C_SPI_SHADER_PGM_RSRC3_LS, S_00B51C_CU_EN(0xffff));
                        si_pm4_set_reg(pm4, R_00B118_SPI_SHADER_PGM_RSRC3_VS, S_00B118_CU_EN(0xffff));
                        si_pm4_set_reg(pm4, R_00B11C_SPI_SHADER_LATE_ALLOC_VS, S_00B11C_LIMIT(2));
                } else {
@@ -3842,7 +3928,6 @@ static void si_init_config(struct si_context *sctx)
                         * - VS can't execute on CU0.
                         * - If HS writes outputs to LDS, LS can't execute on CU0.
                         */
-                       si_pm4_set_reg(pm4, R_00B51C_SPI_SHADER_PGM_RSRC3_LS, S_00B51C_CU_EN(0xfffe));
                        si_pm4_set_reg(pm4, R_00B118_SPI_SHADER_PGM_RSRC3_VS, S_00B118_CU_EN(0xfffe));
                        si_pm4_set_reg(pm4, R_00B11C_SPI_SHADER_LATE_ALLOC_VS, S_00B11C_LIMIT(31));
                }
@@ -3882,11 +3967,6 @@ static void si_init_config(struct si_context *sctx)
        if (sctx->b.family == CHIP_STONEY)
                si_pm4_set_reg(pm4, R_028C40_PA_SC_SHADER_CONTROL, 0);
 
-       if (sctx->b.family >= CHIP_POLARIS10)
-               si_pm4_set_reg(pm4, R_028830_PA_SU_SMALL_PRIM_FILTER_CNTL,
-                              S_028830_SMALL_PRIM_FILTER_ENABLE(1) |
-                              S_028830_LINE_FILTER_DISABLE(1)); /* line bug */
-
        si_pm4_set_reg(pm4, R_028080_TA_BC_BASE_ADDR, border_color_va >> 8);
        if (sctx->b.chip_class >= CIK)
                si_pm4_set_reg(pm4, R_028084_TA_BC_BASE_ADDR_HI, border_color_va >> 40);