- struct si_context *sctx = (struct si_context *)ctx;
- struct pipe_framebuffer_state *fb = &sctx->framebuffer.state;
- struct pipe_surface *zsbuf = fb->zsbuf;
- struct r600_texture *zstex =
- zsbuf ? (struct r600_texture*)zsbuf->texture : NULL;
-
- if (buffers & PIPE_CLEAR_COLOR) {
- si_do_fast_color_clear(sctx, &buffers, color);
- if (!buffers)
- return; /* all buffers have been fast cleared */
-
- /* These buffers cannot use fast clear, make sure to disable expansion. */
- for (unsigned i = 0; i < fb->nr_cbufs; i++) {
- struct r600_texture *tex;
-
- /* If not clearing this buffer, skip. */
- if (!(buffers & (PIPE_CLEAR_COLOR0 << i)) || !fb->cbufs[i])
- continue;
-
- tex = (struct r600_texture *)fb->cbufs[i]->texture;
- if (tex->fmask.size == 0)
- tex->dirty_level_mask &= ~(1 << fb->cbufs[i]->u.tex.level);
- }
- }
-
- if (zstex &&
- si_htile_enabled(zstex, zsbuf->u.tex.level) &&
- zsbuf->u.tex.first_layer == 0 &&
- zsbuf->u.tex.last_layer == util_max_layer(&zstex->resource.b.b, 0)) {
- /* TC-compatible HTILE only supports depth clears to 0 or 1. */
- if (buffers & PIPE_CLEAR_DEPTH &&
- (!zstex->tc_compatible_htile ||
- depth == 0 || depth == 1)) {
- /* Need to disable EXPCLEAR temporarily if clearing
- * to a new value. */
- if (!zstex->depth_cleared || zstex->depth_clear_value != depth) {
- sctx->db_depth_disable_expclear = true;
- }
-
- zstex->depth_clear_value = depth;
- sctx->framebuffer.dirty_zsbuf = true;
- si_mark_atom_dirty(sctx, &sctx->framebuffer.atom); /* updates DB_DEPTH_CLEAR */
- sctx->db_depth_clear = true;
- si_mark_atom_dirty(sctx, &sctx->db_render_state);
- }
-
- /* TC-compatible HTILE only supports stencil clears to 0. */
- if (buffers & PIPE_CLEAR_STENCIL &&
- (!zstex->tc_compatible_htile || stencil == 0)) {
- stencil &= 0xff;
-
- /* Need to disable EXPCLEAR temporarily if clearing
- * to a new value. */
- if (!zstex->stencil_cleared || zstex->stencil_clear_value != stencil) {
- sctx->db_stencil_disable_expclear = true;
- }
-
- zstex->stencil_clear_value = stencil;
- sctx->framebuffer.dirty_zsbuf = true;
- si_mark_atom_dirty(sctx, &sctx->framebuffer.atom); /* updates DB_STENCIL_CLEAR */
- sctx->db_stencil_clear = true;
- si_mark_atom_dirty(sctx, &sctx->db_render_state);
- }
-
- /* TODO: Find out what's wrong here. Fast depth clear leads to
- * corruption in ARK: Survival Evolved, but that may just be
- * a coincidence and the root cause is elsewhere.
- *
- * The corruption can be fixed by putting the DB flush before
- * or after the depth clear. (surprisingly)
- *
- * https://bugs.freedesktop.org/show_bug.cgi?id=102955 (apitrace)
- *
- * This hack decreases back-to-back ClearDepth performance.
- */
- if ((sctx->db_depth_clear || sctx->db_stencil_clear) &&
- sctx->screen->clear_db_cache_before_clear)
- sctx->flags |= SI_CONTEXT_FLUSH_AND_INV_DB;
- }
-
- si_blitter_begin(sctx, SI_CLEAR);
- util_blitter_clear(sctx->blitter, fb->width, fb->height,
- util_framebuffer_get_num_layers(fb),
- buffers, color, depth, stencil);
- si_blitter_end(sctx);
-
- if (sctx->db_depth_clear) {
- sctx->db_depth_clear = false;
- sctx->db_depth_disable_expclear = false;
- zstex->depth_cleared = true;
- si_mark_atom_dirty(sctx, &sctx->db_render_state);
- }
-
- if (sctx->db_stencil_clear) {
- sctx->db_stencil_clear = false;
- sctx->db_stencil_disable_expclear = false;
- zstex->stencil_cleared = true;
- si_mark_atom_dirty(sctx, &sctx->db_render_state);
- }
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct pipe_framebuffer_state *fb = &sctx->framebuffer.state;
+ struct pipe_surface *zsbuf = fb->zsbuf;
+ struct si_texture *zstex = zsbuf ? (struct si_texture *)zsbuf->texture : NULL;
+ bool needs_db_flush = false;
+
+ if (buffers & PIPE_CLEAR_COLOR) {
+ si_do_fast_color_clear(sctx, &buffers, color);
+ if (!buffers)
+ return; /* all buffers have been fast cleared */
+
+ /* These buffers cannot use fast clear, make sure to disable expansion. */
+ for (unsigned i = 0; i < fb->nr_cbufs; i++) {
+ struct si_texture *tex;
+
+ /* If not clearing this buffer, skip. */
+ if (!(buffers & (PIPE_CLEAR_COLOR0 << i)) || !fb->cbufs[i])
+ continue;
+
+ tex = (struct si_texture *)fb->cbufs[i]->texture;
+ if (tex->surface.fmask_size == 0)
+ tex->dirty_level_mask &= ~(1 << fb->cbufs[i]->u.tex.level);
+ }
+ }
+
+ if (zstex && zsbuf->u.tex.first_layer == 0 &&
+ zsbuf->u.tex.last_layer == util_max_layer(&zstex->buffer.b.b, 0)) {
+ /* See whether we should enable TC-compatible HTILE. */
+ if (zstex->enable_tc_compatible_htile_next_clear &&
+ !zstex->tc_compatible_htile &&
+ si_htile_enabled(zstex, zsbuf->u.tex.level, PIPE_MASK_ZS) &&
+ /* If both depth and stencil are present, they must be cleared together. */
+ ((buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL ||
+ (buffers & PIPE_CLEAR_DEPTH && (!zstex->surface.has_stencil ||
+ zstex->htile_stencil_disabled)))) {
+ /* Enable TC-compatible HTILE. */
+ zstex->enable_tc_compatible_htile_next_clear = false;
+ zstex->tc_compatible_htile = true;
+
+ /* Update the framebuffer state to reflect the change. */
+ sctx->framebuffer.DB_has_shader_readable_metadata = true;
+ sctx->framebuffer.dirty_zsbuf = true;
+ si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer);
+
+ /* Update all sampler views and shader images in all contexts. */
+ p_atomic_inc(&sctx->screen->dirty_tex_counter);
+
+ /* Re-initialize HTILE, so that it doesn't contain values incompatible
+ * with the new TC-compatible HTILE setting.
+ *
+ * 0xfffff30f = uncompressed Z + S
+ * 0xfffc000f = uncompressed Z only
+ *
+ * GFX8 always uses the Z+S HTILE format for TC-compatible HTILE even
+ * when stencil is not present.
+ */
+ uint32_t clear_value = (zstex->surface.has_stencil &&
+ !zstex->htile_stencil_disabled) ||
+ sctx->chip_class == GFX8 ? 0xfffff30f : 0xfffc000f;
+ si_clear_buffer(sctx, &zstex->buffer.b.b, zstex->surface.htile_offset,
+ zstex->surface.htile_size, &clear_value, 4,
+ SI_COHERENCY_DB_META, false);
+ }
+
+ /* TC-compatible HTILE only supports depth clears to 0 or 1. */
+ if (buffers & PIPE_CLEAR_DEPTH && si_htile_enabled(zstex, zsbuf->u.tex.level, PIPE_MASK_Z) &&
+ (!zstex->tc_compatible_htile || depth == 0 || depth == 1)) {
+ /* Need to disable EXPCLEAR temporarily if clearing
+ * to a new value. */
+ if (!zstex->depth_cleared || zstex->depth_clear_value != depth) {
+ sctx->db_depth_disable_expclear = true;
+ }
+
+ if (zstex->depth_clear_value != (float)depth) {
+ if ((zstex->depth_clear_value != 0) != (depth != 0)) {
+ /* ZRANGE_PRECISION register of a bound surface will change so we
+ * must flush the DB caches. */
+ needs_db_flush = true;
+ }
+ /* Update DB_DEPTH_CLEAR. */
+ zstex->depth_clear_value = depth;
+ sctx->framebuffer.dirty_zsbuf = true;
+ si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer);
+ }
+ sctx->db_depth_clear = true;
+ si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
+ }
+
+ /* TC-compatible HTILE only supports stencil clears to 0. */
+ if (buffers & PIPE_CLEAR_STENCIL &&
+ si_htile_enabled(zstex, zsbuf->u.tex.level, PIPE_MASK_S) &&
+ (!zstex->tc_compatible_htile || stencil == 0)) {
+ stencil &= 0xff;
+
+ /* Need to disable EXPCLEAR temporarily if clearing
+ * to a new value. */
+ if (!zstex->stencil_cleared || zstex->stencil_clear_value != stencil) {
+ sctx->db_stencil_disable_expclear = true;
+ }
+
+ if (zstex->stencil_clear_value != (uint8_t)stencil) {
+ /* Update DB_STENCIL_CLEAR. */
+ zstex->stencil_clear_value = stencil;
+ sctx->framebuffer.dirty_zsbuf = true;
+ si_mark_atom_dirty(sctx, &sctx->atoms.s.framebuffer);
+ }
+ sctx->db_stencil_clear = true;
+ si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
+ }
+
+ if (needs_db_flush)
+ sctx->flags |= SI_CONTEXT_FLUSH_AND_INV_DB;
+ }
+
+ si_blitter_begin(sctx, SI_CLEAR);
+ util_blitter_clear(sctx->blitter, fb->width, fb->height, util_framebuffer_get_num_layers(fb),
+ buffers, color, depth, stencil, sctx->framebuffer.nr_samples > 1);
+ si_blitter_end(sctx);
+
+ if (sctx->db_depth_clear) {
+ sctx->db_depth_clear = false;
+ sctx->db_depth_disable_expclear = false;
+ zstex->depth_cleared = true;
+ si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
+ }
+
+ if (sctx->db_stencil_clear) {
+ sctx->db_stencil_clear = false;
+ sctx->db_stencil_disable_expclear = false;
+ zstex->stencil_cleared = true;
+ si_mark_atom_dirty(sctx, &sctx->atoms.s.db_render_state);
+ }