diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_blit.c | 101 |
1 files changed, 73 insertions, 28 deletions
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c index 5882f7dcb2a..e044538d40c 100644 --- a/src/gallium/drivers/radeonsi/si_blit.c +++ b/src/gallium/drivers/radeonsi/si_blit.c @@ -179,31 +179,24 @@ static void si_blit_decompress_depth(struct pipe_context *ctx, si_mark_atom_dirty(sctx, &sctx->db_render_state); } -static void si_blit_decompress_depth_in_place(struct si_context *sctx, - struct r600_texture *texture, - bool is_stencil_sampler, - unsigned first_level, unsigned last_level, - unsigned first_layer, unsigned last_layer) +/* Helper function for si_blit_decompress_zs_in_place. + */ +static void +si_blit_decompress_zs_planes_in_place(struct si_context *sctx, + struct r600_texture *texture, + unsigned planes, unsigned level_mask, + unsigned first_layer, unsigned last_layer) { struct pipe_surface *zsurf, surf_tmpl = {{0}}; unsigned layer, max_layer, checked_last_layer; - unsigned *dirty_level_mask; - unsigned level_mask = - u_bit_consecutive(first_level, last_level - first_level + 1); + unsigned fully_decompressed_mask = 0; - if (is_stencil_sampler) { - dirty_level_mask = &texture->stencil_dirty_level_mask; - } else { - dirty_level_mask = &texture->dirty_level_mask; - } - - level_mask &= *dirty_level_mask; if (!level_mask) return; - if (is_stencil_sampler) + if (planes & PIPE_MASK_S) sctx->db_flush_stencil_inplace = true; - else + if (planes & PIPE_MASK_Z) sctx->db_flush_depth_inplace = true; si_mark_atom_dirty(sctx, &sctx->db_render_state); @@ -237,15 +230,65 @@ static void si_blit_decompress_depth_in_place(struct si_context *sctx, /* The texture will always be dirty if some layers aren't flushed. * I don't think this case occurs often though. */ if (first_layer == 0 && last_layer == max_layer) { - *dirty_level_mask &= ~(1 << level); + fully_decompressed_mask |= 1u << level; } } + if (planes & PIPE_MASK_Z) + texture->dirty_level_mask &= ~fully_decompressed_mask; + if (planes & PIPE_MASK_S) + texture->stencil_dirty_level_mask &= ~fully_decompressed_mask; + sctx->db_flush_depth_inplace = false; sctx->db_flush_stencil_inplace = false; si_mark_atom_dirty(sctx, &sctx->db_render_state); } +/* Decompress Z and/or S planes in place, depending on mask. + */ +static void +si_blit_decompress_zs_in_place(struct si_context *sctx, + struct r600_texture *texture, + unsigned planes, + unsigned first_level, unsigned last_level, + unsigned first_layer, unsigned last_layer) +{ + unsigned level_mask = + u_bit_consecutive(first_level, last_level - first_level + 1); + unsigned cur_level_mask; + + /* First, do combined Z & S decompresses for levels that need it. */ + if (planes == (PIPE_MASK_Z | PIPE_MASK_S)) { + cur_level_mask = + level_mask & + texture->dirty_level_mask & + texture->stencil_dirty_level_mask; + si_blit_decompress_zs_planes_in_place( + sctx, texture, PIPE_MASK_Z | PIPE_MASK_S, + cur_level_mask, + first_layer, last_layer); + level_mask &= ~cur_level_mask; + } + + /* Now do separate Z and S decompresses. */ + if (planes & PIPE_MASK_Z) { + cur_level_mask = level_mask & texture->dirty_level_mask; + si_blit_decompress_zs_planes_in_place( + sctx, texture, PIPE_MASK_Z, + cur_level_mask, + first_layer, last_layer); + level_mask &= ~cur_level_mask; + } + + if (planes & PIPE_MASK_S) { + cur_level_mask = level_mask & texture->stencil_dirty_level_mask; + si_blit_decompress_zs_planes_in_place( + sctx, texture, PIPE_MASK_S, + cur_level_mask, + first_layer, last_layer); + } +} + static void si_flush_depth_textures(struct si_context *sctx, struct si_textures_info *textures) @@ -267,10 +310,11 @@ si_flush_depth_textures(struct si_context *sctx, tex = (struct r600_texture *)view->texture; assert(tex->is_depth && !tex->is_flushing_texture); - si_blit_decompress_depth_in_place(sctx, tex, - sview->is_stencil_sampler, - view->u.tex.first_level, view->u.tex.last_level, - 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level)); + si_blit_decompress_zs_in_place(sctx, tex, + sview->is_stencil_sampler ? PIPE_MASK_S + : PIPE_MASK_Z, + view->u.tex.first_level, view->u.tex.last_level, + 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level)); } } @@ -559,13 +603,14 @@ static void si_decompress_subresource(struct pipe_context *ctx, struct r600_texture *rtex = (struct r600_texture*)tex; if (rtex->is_depth && !rtex->is_flushing_texture) { - si_blit_decompress_depth_in_place(sctx, rtex, false, - level, level, - first_layer, last_layer); + unsigned planes = PIPE_MASK_Z; + if (rtex->surface.flags & RADEON_SURF_SBUFFER) - si_blit_decompress_depth_in_place(sctx, rtex, true, - level, level, - first_layer, last_layer); + planes |= PIPE_MASK_S; + + si_blit_decompress_zs_in_place(sctx, rtex, planes, + level, level, + first_layer, last_layer); } else if (rtex->fmask.size || rtex->cmask.size || rtex->dcc_offset) { si_blit_decompress_color(ctx, rtex, level, level, first_layer, last_layer, false); |