This adds a helper isl_surf_get_uncompressed_surf for creating a surface which provides an uncompressed view into a compressed surface. The code is basically a direct port of the uncompressed surface code from the Vulkan driver which, in turn, was a port from BLORP.
Reviewed-by: Topi Pohjolainen <topi.pohjolai...@intel.com> --- src/intel/isl/isl.c | 75 ++++++++++++++++++++++++++++++++++++ src/intel/isl/isl.h | 29 ++++++++++++++ src/intel/vulkan/anv_image.c | 34 ++-------------- 3 files changed, 107 insertions(+), 31 deletions(-) diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c index a118da56c17..b8af8ad1176 100644 --- a/src/intel/isl/isl.c +++ b/src/intel/isl/isl.c @@ -2414,6 +2414,81 @@ isl_surf_get_image_surf(const struct isl_device *dev, assert(ok); } +void +isl_surf_get_uncompressed_surf(const struct isl_device *dev, + const struct isl_surf *surf, + const struct isl_view *view, + struct isl_surf *ucompr_surf, + struct isl_view *ucompr_view, + uint32_t *offset_B, + uint32_t *x_offset_el, + uint32_t *y_offset_el) +{ + const struct isl_format_layout *fmtl = + isl_format_get_layout(surf->format); + + assert(fmtl->bw > 1 || fmtl->bh > 1 || fmtl->bd > 1); + assert(isl_format_is_compressed(surf->format)); + assert(!isl_format_is_compressed(view->format)); + assert(isl_format_get_layout(view->format)->bpb == fmtl->bpb); + assert(view->levels == 1); + + const uint32_t view_width = + isl_minify(surf->logical_level0_px.width, view->base_level); + const uint32_t view_height = + isl_minify(surf->logical_level0_px.height, view->base_level); + + const uint32_t ucompr_width = isl_align_div_npot(view_width, fmtl->bw); + const uint32_t ucompr_height = isl_align_div_npot(view_height, fmtl->bh); + + { + /* For legacy tilings, we just make a new 2D surface which represents + * the single slice of the main surface. Due to hardware restrictions + * with intratile offsets, we can only handle a single slice. + */ + assert(view->array_len == 1); + + uint32_t x_offset_sa, y_offset_sa; + isl_surf_get_image_surf(dev, surf, + view->base_level, + surf->dim == ISL_SURF_DIM_3D ? + 0 : view->base_array_layer, + surf->dim == ISL_SURF_DIM_3D ? + view->base_array_layer : 0, + ucompr_surf, + offset_B, &x_offset_sa, &y_offset_sa); + + ucompr_surf->format = view->format; + + /* We're making an uncompressed view here. The image dimensions + * need to be scaled down by the block size. + */ + assert(ucompr_surf->logical_level0_px.width == view_width); + assert(ucompr_surf->logical_level0_px.height == view_height); + assert(ucompr_surf->logical_level0_px.depth == 1); + assert(ucompr_surf->logical_level0_px.array_len = 1); + ucompr_surf->logical_level0_px.width = ucompr_width; + ucompr_surf->logical_level0_px.height = ucompr_height; + + assert(ucompr_surf->phys_level0_sa.width % fmtl->bw == 0); + assert(ucompr_surf->phys_level0_sa.height % fmtl->bh == 0); + assert(ucompr_surf->phys_level0_sa.depth == 1); + assert(ucompr_surf->phys_level0_sa.array_len == 1); + ucompr_surf->phys_level0_sa.width /= fmtl->bw; + ucompr_surf->phys_level0_sa.height /= fmtl->bh; + + *x_offset_el = isl_assert_div(x_offset_sa, fmtl->bw); + *y_offset_el = isl_assert_div(y_offset_sa, fmtl->bh); + + /* The newly created image represents the one subimage we're referencing + * with this view so it only has one array slice and miplevel. + */ + *ucompr_view = *view; + ucompr_view->base_array_layer = 0; + ucompr_view->base_level = 0; + } +} + void isl_tiling_get_intratile_offset_el(enum isl_tiling tiling, enum isl_surf_dim dim, diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h index 200bfbfa85b..213f5b408e2 100644 --- a/src/intel/isl/isl.h +++ b/src/intel/isl/isl.h @@ -2045,6 +2045,35 @@ isl_surf_get_image_surf(const struct isl_device *dev, uint32_t *x_offset_sa, uint32_t *y_offset_sa); +/** + * Create an isl_surf that is an uncompressed view of a compressed isl_surf + * + * The incoming surface must have a compressed format. The incoming view must + * be a valid view for the given surface with the exception that it's format + * is an umcompressed format with the same bpb as the surface format. The + * incoming view must have isl_view::levels == 1. + * + * When the function returns, the resulting combination of uncompressed_surf + * and uncompressed_view will be a valid view giving an uncompressed view of + * the incoming surface. Depending on tiling, uncompressed_surf may have a + * different isl_surf::dim from surf and uncompressed_view may or may not have + * a zero base_array_layer. For legacy tiling (not Yf or Ys), an intratile + * offset is returned in x_offset_sa and y_offset_sa. For standard Y tilings + * (Yf and Ys), x_offset_sa and y_offset_sa will be set to zero. + * + * It is safe to call this function with surf == uncompressed_surf and + * view == uncompressed_view. + */ +void +isl_surf_get_uncompressed_surf(const struct isl_device *dev, + const struct isl_surf *surf, + const struct isl_view *view, + struct isl_surf *uncompressed_surf, + struct isl_view *uncompressed_view, + uint32_t *offset_B, + uint32_t *x_offset_el, + uint32_t *y_offset_el); + /** * @brief Calculate the intratile offsets to a surface. * diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index e89ce012be7..388f9410564 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -1129,37 +1129,9 @@ anv_image_fill_surface_state(struct anv_device *device, assert(view.levels == 1); assert(view.array_len == 1); - isl_surf_get_image_surf(&device->isl_dev, isl_surf, - view.base_level, - surface->isl.dim == ISL_SURF_DIM_3D ? - 0 : view.base_array_layer, - surface->isl.dim == ISL_SURF_DIM_3D ? - view.base_array_layer : 0, - &tmp_surf, - &offset_B, &tile_x_sa, &tile_y_sa); - - /* The newly created image represents the one subimage we're - * referencing with this view so it only has one array slice and - * miplevel. - */ - view.base_array_layer = 0; - view.base_level = 0; - - /* We're making an uncompressed view here. The image dimensions need - * to be scaled down by the block size. - */ - const struct isl_format_layout *fmtl = - isl_format_get_layout(surface->isl.format); - tmp_surf.format = view.format; - tmp_surf.logical_level0_px.width = - DIV_ROUND_UP(tmp_surf.logical_level0_px.width, fmtl->bw); - tmp_surf.logical_level0_px.height = - DIV_ROUND_UP(tmp_surf.logical_level0_px.height, fmtl->bh); - tmp_surf.phys_level0_sa.width /= fmtl->bw; - tmp_surf.phys_level0_sa.height /= fmtl->bh; - tile_x_sa /= fmtl->bw; - tile_y_sa /= fmtl->bh; - + isl_surf_get_uncompressed_surf(&device->isl_dev, isl_surf, &view, + &tmp_surf, &view, + &offset_B, &tile_x_sa, &tile_y_sa); isl_surf = &tmp_surf; if (device->info.gen <= 8) { -- 2.19.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev