void r600_decompress_depth_textures(struct r600_context *rctx, struct r600_samplerview_state *textures) { unsigned i; unsigned depth_texture_mask = textures->compressed_depthtex_mask; while (depth_texture_mask) { struct pipe_sampler_view *view; struct r600_texture *tex; i = u_bit_scan(&depth_texture_mask); view = &textures->views[i]->base; assert(view); tex = (struct r600_texture *)view->texture; assert(tex->is_depth && !tex->is_flushing_texture); if (rctx->chip_class >= EVERGREEN || r600_can_read_depth(tex)) { r600_blit_decompress_depth_in_place(rctx, tex, view->u.tex.first_level, view->u.tex.last_level, 0, u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); } else { r600_blit_decompress_depth(&rctx->context, tex, NULL, view->u.tex.first_level, view->u.tex.last_level, 0, u_max_layer(&tex->resource.b.b, view->u.tex.first_level), 0, u_max_sample(&tex->resource.b.b)); } } }
void r600_decompress_color_textures(struct r600_context *rctx, struct r600_samplerview_state *textures) { unsigned i; unsigned mask = textures->compressed_colortex_mask; /* Cayman cannot decompress an MSAA colorbuffer, * but it can read it compressed, so skip this. */ assert(rctx->chip_class != CAYMAN); if (rctx->chip_class == CAYMAN) { return; } while (mask) { struct pipe_sampler_view *view; struct r600_texture *tex; i = u_bit_scan(&mask); view = &textures->views[i]->base; assert(view); tex = (struct r600_texture *)view->texture; assert(tex->cmask_size && tex->fmask_size); r600_blit_decompress_color(&rctx->context, tex, view->u.tex.first_level, view->u.tex.last_level, 0, u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); } }
static void r600_blit_decompress_depth_in_place(struct r600_context *rctx, struct r600_texture *texture, unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer) { struct pipe_surface *zsurf, surf_tmpl = {{0}}; unsigned layer, max_layer, checked_last_layer, level; /* Enable decompression in DB_RENDER_CONTROL */ rctx->db_misc_state.flush_depthstencil_in_place = true; rctx->db_misc_state.atom.dirty = true; surf_tmpl.format = texture->resource.b.b.format; for (level = first_level; level <= last_level; level++) { if (!(texture->dirty_level_mask & (1 << level))) continue; surf_tmpl.u.tex.level = level; /* The smaller the mipmap level, the less layers there are * as far as 3D textures are concerned. */ max_layer = u_max_layer(&texture->resource.b.b, level); checked_last_layer = last_layer < max_layer ? last_layer : max_layer; for (layer = first_layer; layer <= checked_last_layer; layer++) { surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; zsurf = rctx->context.create_surface(&rctx->context, &texture->resource.b.b, &surf_tmpl); r600_blitter_begin(&rctx->context, R600_DECOMPRESS); util_blitter_custom_depth_stencil(rctx->blitter, zsurf, NULL, ~0, rctx->custom_dsa_flush, 1.0f); r600_blitter_end(&rctx->context); pipe_surface_reference(&zsurf, NULL); } /* The texture will always be dirty if some layers or samples aren't flushed. * I don't think this case occurs often though. */ if (first_layer == 0 && last_layer == max_layer) { texture->dirty_level_mask &= ~(1 << level); } } /* Disable decompression in DB_RENDER_CONTROL */ rctx->db_misc_state.flush_depthstencil_in_place = false; rctx->db_misc_state.atom.dirty = true; }
static void r600_blit_decompress_color(struct pipe_context *ctx, struct r600_texture *rtex, unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer) { struct r600_context *rctx = (struct r600_context *)ctx; unsigned layer, level, checked_last_layer, max_layer; assert(rctx->chip_class != CAYMAN); if (!rtex->dirty_level_mask) return; for (level = first_level; level <= last_level; level++) { if (!(rtex->dirty_level_mask & (1 << level))) continue; /* The smaller the mipmap level, the less layers there are * as far as 3D textures are concerned. */ max_layer = u_max_layer(&rtex->resource.b.b, level); checked_last_layer = last_layer < max_layer ? last_layer : max_layer; for (layer = first_layer; layer <= checked_last_layer; layer++) { struct pipe_surface *cbsurf, surf_tmpl; surf_tmpl.format = rtex->resource.b.b.format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; cbsurf = ctx->create_surface(ctx, &rtex->resource.b.b, &surf_tmpl); r600_blitter_begin(ctx, R600_DECOMPRESS); util_blitter_custom_color(rctx->blitter, cbsurf, rctx->custom_blend_decompress); r600_blitter_end(ctx); pipe_surface_reference(&cbsurf, NULL); } /* The texture will always be dirty if some layers or samples aren't flushed. * I don't think this case occurs often though. */ if (first_layer == 0 && last_layer == max_layer) { rtex->dirty_level_mask &= ~(1 << level); } } }
void si_flush_depth_textures(struct r600_context *rctx, struct r600_textures_info *textures) { unsigned i; for (i = 0; i < textures->n_views; ++i) { struct pipe_sampler_view *view; struct r600_resource_texture *tex; view = &textures->views[i]->base; if (!view) continue; tex = (struct r600_resource_texture *)view->texture; if (!tex->is_depth || tex->is_flushing_texture) continue; si_blit_decompress_depth_in_place(rctx, tex, view->u.tex.first_level, view->u.tex.last_level, 0, u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); } }
void r600_decompress_color_textures(struct r600_context *rctx, struct r600_samplerview_state *textures) { unsigned i; unsigned mask = textures->compressed_colortex_mask; while (mask) { struct pipe_sampler_view *view; struct r600_texture *tex; i = u_bit_scan(&mask); view = &textures->views[i]->base; assert(view); tex = (struct r600_texture *)view->texture; assert(tex->cmask_size && tex->fmask_size); r600_blit_decompress_color(&rctx->context, tex, view->u.tex.first_level, view->u.tex.last_level, 0, u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); } }
void r600_flush_depth_textures(struct r600_context *rctx, struct r600_samplerview_state *textures) { unsigned i; unsigned depth_texture_mask = textures->depth_texture_mask; while (depth_texture_mask) { struct pipe_sampler_view *view; struct r600_texture *tex; i = u_bit_scan(&depth_texture_mask); view = &textures->views[i]->base; assert(view); tex = (struct r600_texture *)view->texture; assert(tex->is_depth && !tex->is_flushing_texture); r600_blit_uncompress_depth(&rctx->context, tex, NULL, view->u.tex.first_level, view->u.tex.last_level, 0, u_max_layer(&tex->resource.b.b, view->u.tex.first_level), 0, u_max_sample(&tex->resource.b.b)); } }
void si_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture, struct r600_resource_texture *staging, unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer) { struct r600_context *rctx = (struct r600_context *)ctx; unsigned layer, level, checked_last_layer, max_layer; float depth = 1.0f; const struct util_format_description *desc; void *custom_dsa; struct r600_resource_texture *flushed_depth_texture = staging ? staging : texture->flushed_depth_texture; if (!staging && !texture->dirty_db_mask) return; desc = util_format_description(flushed_depth_texture->resource.b.b.format); switch (util_format_has_depth(desc) | util_format_has_stencil(desc) << 1) { default: assert(!"No depth or stencil to uncompress"); case 3: custom_dsa = rctx->custom_dsa_flush_depth_stencil; break; case 2: custom_dsa = rctx->custom_dsa_flush_stencil; break; case 1: custom_dsa = rctx->custom_dsa_flush_depth; break; } for (level = first_level; level <= last_level; level++) { if (!staging && !(texture->dirty_db_mask & (1 << level))) continue; /* The smaller the mipmap level, the less layers there are * as far as 3D textures are concerned. */ max_layer = u_max_layer(&texture->resource.b.b, level); checked_last_layer = last_layer < max_layer ? last_layer : max_layer; for (layer = first_layer; layer <= checked_last_layer; layer++) { struct pipe_surface *zsurf, *cbsurf, surf_tmpl; surf_tmpl.format = texture->real_format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); surf_tmpl.format = flushed_depth_texture->real_format; cbsurf = ctx->create_surface(ctx, (struct pipe_resource*)flushed_depth_texture, &surf_tmpl); r600_blitter_begin(ctx, R600_DECOMPRESS); util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, ~0, custom_dsa, depth); r600_blitter_end(ctx); pipe_surface_reference(&zsurf, NULL); pipe_surface_reference(&cbsurf, NULL); } /* The texture will always be dirty if some layers aren't flushed. * I don't think this case can occur though. */ if (!staging && first_layer == 0 && last_layer == max_layer) { texture->dirty_db_mask &= ~(1 << level); } } }
void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_texture *texture, struct r600_texture *staging, unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer, unsigned first_sample, unsigned last_sample) { struct r600_context *rctx = (struct r600_context *)ctx; unsigned layer, level, sample, checked_last_layer, max_layer, max_sample; struct r600_texture *flushed_depth_texture = staging ? staging : texture->flushed_depth_texture; const struct util_format_description *desc = util_format_description(texture->resource.b.b.format); float depth; if (!staging && !texture->dirty_db_mask) return; if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) depth = 0.0f; else depth = 1.0f; /* Enable decompression in DB_RENDER_CONTROL */ rctx->db_misc_state.flush_depthstencil_through_cb = true; rctx->db_misc_state.copy_depth = util_format_has_depth(desc); rctx->db_misc_state.copy_stencil = util_format_has_stencil(desc); rctx->db_misc_state.copy_sample = first_sample; r600_atom_dirty(rctx, &rctx->db_misc_state.atom); max_sample = u_max_sample(&texture->resource.b.b); for (level = first_level; level <= last_level; level++) { if (!staging && !(texture->dirty_db_mask & (1 << level))) continue; /* The smaller the mipmap level, the less layers there are * as far as 3D textures are concerned. */ max_layer = u_max_layer(&texture->resource.b.b, level); checked_last_layer = last_layer < max_layer ? last_layer : max_layer; for (layer = first_layer; layer <= checked_last_layer; layer++) { for (sample = first_sample; sample <= last_sample; sample++) { struct pipe_surface *zsurf, *cbsurf, surf_tmpl; if (sample != rctx->db_misc_state.copy_sample) { rctx->db_misc_state.copy_sample = sample; r600_atom_dirty(rctx, &rctx->db_misc_state.atom); } surf_tmpl.format = texture->resource.b.b.format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); surf_tmpl.format = flushed_depth_texture->resource.b.b.format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; cbsurf = ctx->create_surface(ctx, &flushed_depth_texture->resource.b.b, &surf_tmpl); r600_blitter_begin(ctx, R600_DECOMPRESS); util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, 1 << sample, rctx->custom_dsa_flush, depth); r600_blitter_end(ctx); pipe_surface_reference(&zsurf, NULL); pipe_surface_reference(&cbsurf, NULL); } } /* The texture will always be dirty if some layers or samples aren't flushed. * I don't think this case occurs often though. */ if (!staging && first_layer == 0 && last_layer == max_layer && first_sample == 0 && last_sample == max_sample) { texture->dirty_db_mask &= ~(1 << level); } } /* reenable compression in DB_RENDER_CONTROL */ rctx->db_misc_state.flush_depthstencil_through_cb = false; r600_atom_dirty(rctx, &rctx->db_misc_state.atom); }
static void r600_blit_decompress_color(struct pipe_context *ctx, struct r600_texture *rtex, unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer) { struct r600_context *rctx = (struct r600_context *)ctx; unsigned layer, level, checked_last_layer, max_layer; void *blend_decompress; if (!rtex->dirty_level_mask) return; switch (rctx->screen->msaa_texture_support) { case MSAA_TEXTURE_DECOMPRESSED: blend_decompress = rctx->custom_blend_decompress; break; case MSAA_TEXTURE_COMPRESSED: /* XXX the 2x and 4x cases are broken. */ if (rtex->resource.b.b.nr_samples == 8) blend_decompress = rctx->custom_blend_fmask_decompress; else blend_decompress = rctx->custom_blend_decompress; break; case MSAA_TEXTURE_SAMPLE_ZERO: default: /* Nothing to do. */ rtex->dirty_level_mask = 0; return; } for (level = first_level; level <= last_level; level++) { if (!(rtex->dirty_level_mask & (1 << level))) continue; /* The smaller the mipmap level, the less layers there are * as far as 3D textures are concerned. */ max_layer = u_max_layer(&rtex->resource.b.b, level); checked_last_layer = last_layer < max_layer ? last_layer : max_layer; for (layer = first_layer; layer <= checked_last_layer; layer++) { struct pipe_surface *cbsurf, surf_tmpl; surf_tmpl.format = rtex->resource.b.b.format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; cbsurf = ctx->create_surface(ctx, &rtex->resource.b.b, &surf_tmpl); r600_blitter_begin(ctx, R600_DECOMPRESS); util_blitter_custom_color(rctx->blitter, cbsurf, blend_decompress); r600_blitter_end(ctx); pipe_surface_reference(&cbsurf, NULL); } /* 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) { rtex->dirty_level_mask &= ~(1 << level); } } }