meson: define driver dependencies
[mesa.git] / src / gallium / drivers / r600 / r600_state_common.c
index 99ec5e7f7dc4e60ca61b1ea31687e91af60ff788..fee7a21d27dd039eca461ef43298e27f40c9eceb 100644 (file)
@@ -91,6 +91,29 @@ void r600_emit_alphatest_state(struct r600_context *rctx, struct r600_atom *atom
        radeon_set_context_reg(cs, R_028438_SX_ALPHA_REF, alpha_ref);
 }
 
+static void r600_memory_barrier(struct pipe_context *ctx, unsigned flags)
+{
+       struct r600_context *rctx = (struct r600_context *)ctx;
+       if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
+               rctx->b.flags |= R600_CONTEXT_INV_CONST_CACHE;
+
+       if (flags & (PIPE_BARRIER_VERTEX_BUFFER |
+                    PIPE_BARRIER_SHADER_BUFFER |
+                    PIPE_BARRIER_TEXTURE |
+                    PIPE_BARRIER_IMAGE |
+                    PIPE_BARRIER_STREAMOUT_BUFFER |
+                    PIPE_BARRIER_GLOBAL_BUFFER)) {
+               rctx->b.flags |= R600_CONTEXT_INV_VERTEX_CACHE|
+                       R600_CONTEXT_INV_TEX_CACHE;
+       }
+
+       if (flags & (PIPE_BARRIER_FRAMEBUFFER|
+                    PIPE_BARRIER_IMAGE))
+               rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV;
+
+       rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE;
+}
+
 static void r600_texture_barrier(struct pipe_context *ctx, unsigned flags)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
@@ -698,6 +721,58 @@ static void r600_update_compressed_colortex_mask(struct r600_samplerview_state *
        }
 }
 
+static int r600_get_hw_atomic_count(const struct pipe_context *ctx,
+                                   enum pipe_shader_type shader)
+{
+       const struct r600_context *rctx = (struct r600_context *)ctx;
+       int value = 0;
+       switch (shader) {
+       case PIPE_SHADER_FRAGMENT:
+       case PIPE_SHADER_COMPUTE:
+       default:
+               break;
+       case PIPE_SHADER_VERTEX:
+               value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC];
+               break;
+       case PIPE_SHADER_GEOMETRY:
+               value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+                       rctx->vs_shader->info.file_count[TGSI_FILE_HW_ATOMIC];
+               break;
+       case PIPE_SHADER_TESS_EVAL:
+               value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+                       rctx->vs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+                       (rctx->gs_shader ? rctx->gs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] : 0);
+               break;
+       case PIPE_SHADER_TESS_CTRL:
+               value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+                       rctx->vs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+                       (rctx->gs_shader ? rctx->gs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] : 0) +
+                       rctx->tes_shader->info.file_count[TGSI_FILE_HW_ATOMIC];
+               break;
+       }
+       return value;
+}
+
+static void r600_update_compressed_colortex_mask_images(struct r600_image_state *images)
+{
+       uint32_t mask = images->enabled_mask;
+
+       while (mask) {
+               unsigned i = u_bit_scan(&mask);
+               struct pipe_resource *res = images->views[i].base.resource;
+
+               if (res && res->target != PIPE_BUFFER) {
+                       struct r600_texture *rtex = (struct r600_texture *)res;
+
+                       if (rtex->cmask.size) {
+                               images->compressed_colortex_mask |= 1 << i;
+                       } else {
+                               images->compressed_colortex_mask &= ~(1 << i);
+                       }
+               }
+       }
+}
+
 /* Compute the key for the hw shader variant */
 static inline void r600_shader_selector_key(const struct pipe_context *ctx,
                const struct r600_pipe_shader_selector *sel,
@@ -716,11 +791,17 @@ static inline void r600_shader_selector_key(const struct pipe_context *ctx,
                        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.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_VERTEX);
                break;
        }
        case PIPE_SHADER_GEOMETRY:
+               key->gs.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_GEOMETRY);
+               key->gs.tri_strip_adj_fix = rctx->gs_tri_strip_adj_fix;
                break;
        case PIPE_SHADER_FRAGMENT: {
+               if (rctx->ps_shader->info.images_declared)
+                       key->ps.image_size_const_offset = util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].views.enabled_mask);
+               key->ps.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_FRAGMENT);
                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 &&
@@ -733,9 +814,11 @@ static inline void r600_shader_selector_key(const struct pipe_context *ctx,
        }
        case PIPE_SHADER_TESS_EVAL:
                key->tes.as_es = (rctx->gs_shader != NULL);
+               key->tes.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_TESS_EVAL);
                break;
        case PIPE_SHADER_TESS_CTRL:
                key->tcs.prim_mode = rctx->tes_shader->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
+               key->tcs.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_TESS_CTRL);
                break;
        default:
                assert(0);
@@ -847,11 +930,11 @@ static void *r600_create_shader_state(struct pipe_context *ctx,
                        case TGSI_SEMANTIC_TESSOUTER:
                        case TGSI_SEMANTIC_PATCH:
                                sel->lds_patch_outputs_written_mask |=
-                                       1llu << r600_get_lds_unique_index(name, index);
+                                       1ull << r600_get_lds_unique_index(name, index);
                                break;
                        default:
                                sel->lds_outputs_written_mask |=
-                                       1llu << r600_get_lds_unique_index(name, index);
+                                       1ull << r600_get_lds_unique_index(name, index);
                        }
                }
                break;
@@ -1249,29 +1332,68 @@ static void r600_setup_buffer_constants(struct r600_context *rctx, int shader_ty
 static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type)
 {
        struct r600_textures_info *samplers = &rctx->samplers[shader_type];
-       int bits;
+       struct r600_image_state *images = NULL;
+       struct r600_image_state *buffers = NULL;
+       int bits, sview_bits, img_bits;
        uint32_t array_size;
        int i;
        uint32_t *constants;
        uint32_t base_offset;
-       if (!samplers->views.dirty_buffer_constants)
+
+       if (shader_type == PIPE_SHADER_FRAGMENT) {
+               images = &rctx->fragment_images;
+               buffers = &rctx->fragment_buffers;
+       }
+
+       if (!samplers->views.dirty_buffer_constants &&
+           (images && !images->dirty_buffer_constants) &&
+           (buffers && !buffers->dirty_buffer_constants))
                return;
 
+       if (images)
+               images->dirty_buffer_constants = FALSE;
+       if (buffers)
+               buffers->dirty_buffer_constants = FALSE;
        samplers->views.dirty_buffer_constants = FALSE;
 
-       bits = util_last_bit(samplers->views.enabled_mask);
+       bits = sview_bits = util_last_bit(samplers->views.enabled_mask);
+       if (images)
+               bits += util_last_bit(images->enabled_mask);
+       img_bits = bits;
+       if (buffers)
+               bits += util_last_bit(buffers->enabled_mask);
        array_size = bits * 2 * sizeof(uint32_t) * 4;
 
        constants = r600_alloc_buf_consts(rctx, shader_type, array_size,
                                          &base_offset);
 
-       for (i = 0; i < bits; i++) {
+       for (i = 0; i < sview_bits; i++) {
                if (samplers->views.enabled_mask & (1 << i)) {
                        uint32_t offset = (base_offset / 4) + i * 2;
                        constants[offset] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format);
                        constants[offset + 1] = samplers->views.views[i]->base.texture->array_size / 6;
                }
        }
+       if (images) {
+               for (i = sview_bits; i < img_bits; i++) {
+                       int idx = i - sview_bits;
+                       if (images->enabled_mask & (1 << idx)) {
+                               uint32_t offset = (base_offset / 4) + i * 2;
+                               constants[offset] = images->views[i].base.resource->width0 / util_format_get_blocksize(images->views[i].base.format);
+                               constants[offset + 1] = images->views[i].base.resource->array_size / 6;
+                       }
+               }
+       }
+       if (buffers) {
+               for (i = img_bits; i < bits; i++) {
+                       int idx = i - img_bits;
+                       if (buffers->enabled_mask & (1 << idx)) {
+                               uint32_t offset = (base_offset / 4) + i * 2;
+                               constants[offset] = buffers->views[i].base.resource->width0 / util_format_get_blocksize(buffers->views[i].base.format);
+                               constants[offset + 1] = 0;
+                       }
+               }
+       }
 }
 
 /* set sample xy locations as array of fragment shader constants */
@@ -1362,10 +1484,12 @@ static void r600_update_clip_state(struct r600_context *rctx,
 {
        if (current->pa_cl_vs_out_cntl != rctx->clip_misc_state.pa_cl_vs_out_cntl ||
            current->shader.clip_dist_write != rctx->clip_misc_state.clip_dist_write ||
+           current->shader.cull_dist_write != rctx->clip_misc_state.cull_dist_write ||
            current->shader.vs_position_window_space != rctx->clip_misc_state.clip_disable ||
            current->shader.vs_out_viewport != rctx->clip_misc_state.vs_out_viewport) {
                rctx->clip_misc_state.pa_cl_vs_out_cntl = current->pa_cl_vs_out_cntl;
                rctx->clip_misc_state.clip_dist_write = current->shader.clip_dist_write;
+               rctx->clip_misc_state.cull_dist_write = current->shader.cull_dist_write;
                rctx->clip_misc_state.clip_disable = current->shader.vs_position_window_space;
                rctx->clip_misc_state.vs_out_viewport = current->shader.vs_out_viewport;
                r600_mark_atom_dirty(rctx, &rctx->clip_misc_state.atom);
@@ -1400,6 +1524,42 @@ static void r600_generate_fixed_func_tcs(struct r600_context *rctx)
                ureg_create_shader_and_destroy(ureg, &rctx->b.b);
 }
 
+static void r600_update_compressed_resource_state(struct r600_context *rctx)
+{
+       unsigned i;
+       unsigned counter;
+
+       counter = p_atomic_read(&rctx->screen->b.compressed_colortex_counter);
+       if (counter != rctx->b.last_compressed_colortex_counter) {
+               rctx->b.last_compressed_colortex_counter = counter;
+
+               for (i = 0; i < PIPE_SHADER_TYPES; ++i) {
+                       r600_update_compressed_colortex_mask(&rctx->samplers[i].views);
+               }
+               r600_update_compressed_colortex_mask_images(&rctx->fragment_images);
+       }
+
+       /* Decompress textures if needed. */
+       for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+               struct r600_samplerview_state *views = &rctx->samplers[i].views;
+               if (views->compressed_depthtex_mask) {
+                       r600_decompress_depth_textures(rctx, views);
+               }
+               if (views->compressed_colortex_mask) {
+                       r600_decompress_color_textures(rctx, views);
+               }
+       }
+
+       {
+               struct r600_image_state *istate;
+               istate = &rctx->fragment_images;
+               if (istate->compressed_depthtex_mask)
+                       r600_decompress_depth_images(rctx, istate);
+               if (istate->compressed_colortex_mask)
+                       r600_decompress_color_images(rctx, istate);
+       }
+}
+
 #define SELECT_SHADER_OR_FAIL(x) do {                                  \
                r600_shader_select(ctx, rctx->x##_shader, &x##_dirty);  \
                if (unlikely(!rctx->x##_shader->current))               \
@@ -1440,30 +1600,8 @@ static bool r600_update_derived_state(struct r600_context *rctx)
        bool need_buf_const;
        struct r600_pipe_shader *clip_so_current = NULL;
 
-       if (!rctx->blitter->running) {
-               unsigned i;
-               unsigned counter;
-
-               counter = p_atomic_read(&rctx->screen->b.compressed_colortex_counter);
-               if (counter != rctx->b.last_compressed_colortex_counter) {
-                       rctx->b.last_compressed_colortex_counter = counter;
-
-                       for (i = 0; i < PIPE_SHADER_TYPES; ++i) {
-                               r600_update_compressed_colortex_mask(&rctx->samplers[i].views);
-                       }
-               }
-
-               /* Decompress textures if needed. */
-               for (i = 0; i < PIPE_SHADER_TYPES; i++) {
-                       struct r600_samplerview_state *views = &rctx->samplers[i].views;
-                       if (views->compressed_depthtex_mask) {
-                               r600_decompress_depth_textures(rctx, views);
-                       }
-                       if (views->compressed_colortex_mask) {
-                               r600_decompress_color_textures(rctx, views);
-                       }
-               }
-       }
+       if (!rctx->blitter->running)
+               r600_update_compressed_resource_state(rctx);
 
        SELECT_SHADER_OR_FAIL(ps);
 
@@ -1652,7 +1790,8 @@ void r600_emit_clip_misc_state(struct r600_context *rctx, struct r600_atom *atom
                                S_028810_CLIP_DISABLE(state->clip_disable));
        radeon_set_context_reg(cs, R_02881C_PA_CL_VS_OUT_CNTL,
                               state->pa_cl_vs_out_cntl |
-                              (state->clip_plane_enable & state->clip_dist_write));
+                              (state->clip_plane_enable & state->clip_dist_write) |
+                              (state->cull_dist_write << 8));
        /* reuse needs to be set off if we write oViewport */
        if (rctx->b.chip_class >= EVERGREEN)
                radeon_set_context_reg(cs, R_028AB4_VGT_REUSE_OFF,
@@ -1696,6 +1835,8 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
        unsigned num_patches, dirty_tex_counter, index_offset = 0;
        unsigned index_size = info->index_size;
        int index_bias;
+       struct r600_shader_atomic combined_atomics[8];
+       uint8_t atomic_used_mask;
 
        if (!info->indirect && !info->count && (index_size || !info->count_from_stream_output)) {
                return;
@@ -1713,7 +1854,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
 
        /* make sure that the gfx ring is only one active */
        if (radeon_emitted(rctx->b.dma.cs, 0)) {
-               rctx->b.dma.flush(rctx, RADEON_FLUSH_ASYNC, NULL);
+               rctx->b.dma.flush(rctx, PIPE_FLUSH_ASYNC, NULL);
        }
 
        /* Re-emit the framebuffer state if needed. */
@@ -1724,6 +1865,20 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                rctx->framebuffer.do_update_surf_dirtiness = true;
        }
 
+       if (rctx->gs_shader) {
+               /* Determine whether the GS triangle strip adjacency fix should
+                * be applied. Rotate every other triangle if
+                * - triangle strips with adjacency are fed to the GS and
+                * - primitive restart is disabled (the rotation doesn't help
+                *   when the restart occurs after an odd number of triangles).
+                */
+               bool gs_tri_strip_adj_fix =
+                       !rctx->tes_shader &&
+                       info->mode == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY &&
+                       !info->primitive_restart;
+               if (gs_tri_strip_adj_fix != rctx->gs_tri_strip_adj_fix)
+                       rctx->gs_tri_strip_adj_fix = gs_tri_strip_adj_fix;
+       }
        if (!r600_update_derived_state(rctx)) {
                /* useless to render because current rendering command
                 * can't be achieved
@@ -1735,6 +1890,9 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                : (rctx->tes_shader)? rctx->tes_shader->info.properties[TGSI_PROPERTY_TES_PRIM_MODE]
                : info->mode;
 
+       if (rctx->b.chip_class >= EVERGREEN)
+               evergreen_emit_atomic_buffer_setup(rctx, combined_atomics, &atomic_used_mask);
+
        if (index_size) {
                index_offset += info->start * index_size;
 
@@ -2015,6 +2173,13 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SQ_NON_EVENT));
        }
 
+
+       if (rctx->b.chip_class >= EVERGREEN)
+               evergreen_emit_atomic_buffer_save(rctx, combined_atomics, &atomic_used_mask);
+
+       if (rctx->trace_buf)
+               eg_trace_emit(rctx);
+
        if (rctx->framebuffer.do_update_surf_dirtiness) {
                /* Set the depth buffer as dirty. */
                if (rctx->framebuffer.state.zsbuf) {
@@ -2023,7 +2188,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
 
                        rtex->dirty_level_mask |= 1 << surf->u.tex.level;
 
-                       if (rtex->surface.flags & RADEON_SURF_SBUFFER)
+                       if (rtex->surface.has_stencil)
                                rtex->stencil_dirty_level_mask |= 1 << surf->u.tex.level;
                }
                if (rctx->framebuffer.compressed_cb_mask) {
@@ -2277,6 +2442,8 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen,
                format = PIPE_FORMAT_A4R4_UNORM;
 
        desc = util_format_description(format);
+       if (!desc)
+               goto out_unknown;
 
        /* Depth and stencil swizzling is handled separately. */
        if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) {
@@ -2396,10 +2563,6 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen,
        }
 
        if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
-               if (!util_format_s3tc_enabled) {
-                       goto out_unknown;
-               }
-
                switch (format) {
                case PIPE_FORMAT_DXT1_RGB:
                case PIPE_FORMAT_DXT1_RGBA:
@@ -2643,6 +2806,8 @@ uint32_t r600_translate_colorformat(enum chip_class chip, enum pipe_format forma
        const struct util_format_description *desc = util_format_description(format);
        int channel = util_format_get_first_non_void_channel(format);
        bool is_float;
+       if (!desc)
+               return ~0U;
 
 #define HAS_SIZE(x,y,z,w) \
        (desc->channel[0].size == (x) && desc->channel[1].size == (y) && \
@@ -2881,6 +3046,24 @@ static void r600_invalidate_buffer(struct pipe_context *ctx, struct pipe_resourc
                        r600_sampler_views_dirty(rctx, state);
                }
        }
+
+       /* SSBOs */
+       struct r600_image_state *istate = &rctx->fragment_buffers;
+       {
+               uint32_t mask = istate->enabled_mask;
+               bool found = false;
+               while (mask) {
+                       unsigned i = u_bit_scan(&mask);
+                       if (istate->views[i].base.resource == &rbuffer->b.b) {
+                               found = true;
+                               istate->dirty_mask |= 1 << i;
+                       }
+               }
+               if (found) {
+                       r600_mark_atom_dirty(rctx, &istate->atom);
+               }
+       }
+
 }
 
 static void r600_set_active_query_state(struct pipe_context *ctx, boolean enable)
@@ -2903,13 +3086,6 @@ static void r600_set_active_query_state(struct pipe_context *ctx, boolean enable
        }
 }
 
-static void r600_set_occlusion_query_state(struct pipe_context *ctx, bool enable)
-{
-       struct r600_context *rctx = (struct r600_context*)ctx;
-
-       r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom);
-}
-
 static void r600_need_gfx_cs_space(struct pipe_context *ctx, unsigned num_dw,
                                    bool include_draw_vbo)
 {
@@ -2953,11 +3129,11 @@ void r600_init_common_state_functions(struct r600_context *rctx)
        rctx->b.b.set_vertex_buffers = r600_set_vertex_buffers;
        rctx->b.b.set_sampler_views = r600_set_sampler_views;
        rctx->b.b.sampler_view_destroy = r600_sampler_view_destroy;
+       rctx->b.b.memory_barrier = r600_memory_barrier;
        rctx->b.b.texture_barrier = r600_texture_barrier;
        rctx->b.b.set_stream_output_targets = r600_set_streamout_targets;
        rctx->b.b.set_active_query_state = r600_set_active_query_state;
        rctx->b.b.draw_vbo = r600_draw_vbo;
        rctx->b.invalidate_buffer = r600_invalidate_buffer;
-       rctx->b.set_occlusion_query_state = r600_set_occlusion_query_state;
        rctx->b.need_gfx_cs_space = r600_need_gfx_cs_space;
 }