From: Jason Ekstrand Date: Wed, 30 Mar 2016 23:15:54 +0000 (-0700) Subject: isl: Rework the get_intratile_offset function X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b37502b9832f02626b0caca22500b46ebbbe8007;p=mesa.git isl: Rework the get_intratile_offset function The old function tried to work in elements which isn't, strictly speaking, a valid thing to do. In the case of a non-power-of-two format, there is no guarantee that the x offset into the tile is a multiple of the format block size. This commit refactors it to work entirely in terms of a tiling (not a surface) and bytes/rows. Reviewed-by: Nanley Chery --- diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c index a36638071d5..37d8bcba078 100644 --- a/src/intel/isl/isl.c +++ b/src/intel/isl/isl.c @@ -1417,33 +1417,39 @@ isl_surf_get_image_offset_el(const struct isl_surf *surf, } void -isl_surf_get_image_intratile_offset_el_xy(const struct isl_device *dev, - const struct isl_surf *surf, - uint32_t total_x_offset_el, - uint32_t total_y_offset_el, - uint32_t *base_address_offset, - uint32_t *x_offset_el, - uint32_t *y_offset_el) +isl_tiling_get_intratile_offset_el(const struct isl_device *dev, + enum isl_tiling tiling, + uint8_t bs, + uint32_t row_pitch, + uint32_t total_x_offset_el, + uint32_t total_y_offset_el, + uint32_t *base_address_offset, + uint32_t *x_offset_el, + uint32_t *y_offset_el) { - const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); - struct isl_tile_info tile_info; - isl_surf_get_tile_info(dev, surf, &tile_info); + isl_tiling_get_info(dev, tiling, bs, &tile_info); + + /* This function only really works for power-of-two surfaces. In + * theory, we could make it work for non-power-of-two surfaces by going + * to the left until we find a block that is bs-aligned. The Vulkan + * driver doesn't use non-power-of-two tiled surfaces so we'll leave + * this unimplemented for now. + */ + assert(tiling == ISL_TILING_LINEAR || isl_is_pow2(bs)); uint32_t small_y_offset_el = total_y_offset_el % tile_info.height; uint32_t big_y_offset_el = total_y_offset_el - small_y_offset_el; - uint32_t big_y_offset_B = big_y_offset_el * surf->row_pitch; + uint32_t big_y_offset_B = big_y_offset_el * row_pitch; - uint32_t total_x_offset_B = total_x_offset_el * fmtl->bs; + uint32_t total_x_offset_B = total_x_offset_el * bs; uint32_t small_x_offset_B = total_x_offset_B % tile_info.width; - uint32_t small_x_offset_el = small_x_offset_B / fmtl->bs; + uint32_t small_x_offset_el = small_x_offset_B / bs; uint32_t big_x_offset_B = (total_x_offset_B / tile_info.width) * tile_info.size; *base_address_offset = big_y_offset_B + big_x_offset_B; *x_offset_el = small_x_offset_el; *y_offset_el = small_y_offset_el; - - } void @@ -1456,6 +1462,8 @@ isl_surf_get_image_intratile_offset_el(const struct isl_device *dev, uint32_t *x_offset_el, uint32_t *y_offset_el) { + const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); + uint32_t total_x_offset_el; uint32_t total_y_offset_el; isl_surf_get_image_offset_el(surf, level, @@ -1464,12 +1472,14 @@ isl_surf_get_image_intratile_offset_el(const struct isl_device *dev, &total_x_offset_el, &total_y_offset_el); - isl_surf_get_image_intratile_offset_el_xy(dev, surf, - total_x_offset_el, - total_y_offset_el, - base_address_offset, - x_offset_el, - y_offset_el); + + isl_tiling_get_intratile_offset_el(dev, surf->tiling, fmtl->bs, + surf->row_pitch, + total_x_offset_el, + total_y_offset_el, + base_address_offset, + x_offset_el, + y_offset_el); } uint32_t diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h index 90193ca08c1..4f796f6c6a8 100644 --- a/src/intel/isl/isl.h +++ b/src/intel/isl/isl.h @@ -1142,6 +1142,27 @@ isl_surf_get_image_offset_el(const struct isl_surf *surf, uint32_t *x_offset_el, uint32_t *y_offset_el); +/** + * @brief Calculate the intratile offsets to a surface. + * + * In @a base_address_offset return the offset from the base of the surface to + * the base address of the first tile of the subimage. In @a x_offset_B and + * @a y_offset_rows, return the offset, in units of bytes and rows, from the + * tile's base to the subimage's first surface element. The x and y offsets + * are intratile offsets; that is, they do not exceed the boundary of the + * surface's tiling format. + */ +void +isl_tiling_get_intratile_offset_el(const struct isl_device *dev, + enum isl_tiling tiling, + uint8_t bs, + uint32_t row_pitch, + uint32_t total_x_offset_B, + uint32_t total_y_offset_rows, + uint32_t *base_address_offset, + uint32_t *x_offset_B, + uint32_t *y_offset_rows); + /** * @brief Calculate the intratile offsets to a subimage in the surface. * @@ -1162,18 +1183,6 @@ isl_surf_get_image_intratile_offset_el(const struct isl_device *dev, uint32_t *x_offset_el, uint32_t *y_offset_el); -/** - * See above. - */ -void -isl_surf_get_image_intratile_offset_el_xy(const struct isl_device *dev, - const struct isl_surf *surf, - uint32_t total_x_offset_el, - uint32_t total_y_offset_el, - uint32_t *base_address_offset, - uint32_t *x_offset_el, - uint32_t *y_offset_el); - /** * @brief Get value of 3DSTATE_DEPTH_BUFFER.SurfaceFormat * diff --git a/src/intel/vulkan/anv_meta_blit2d.c b/src/intel/vulkan/anv_meta_blit2d.c index 8e63eee462d..cf2dc66597d 100644 --- a/src/intel/vulkan/anv_meta_blit2d.c +++ b/src/intel/vulkan/anv_meta_blit2d.c @@ -145,12 +145,15 @@ create_iview(struct anv_cmd_buffer *cmd_buffer, /* Create a VkImageView that starts at the tile aligned offset closest * to the provided x/y offset into the surface. */ + struct isl_surf *isl_surf = &anv_image_from_handle(*img)->color_surface.isl; + uint32_t img_o = 0; - isl_surf_get_image_intratile_offset_el_xy(&cmd_buffer->device->isl_dev, - &anv_image_from_handle(*img)-> - color_surface.isl, - *rect_x, *rect_y, - &img_o, rect_x, rect_y); + isl_tiling_get_intratile_offset_el(&cmd_buffer->device->isl_dev, + isl_surf->tiling, surf->bs, + isl_surf->row_pitch, + *rect_x * surf->bs, *rect_y, + &img_o, rect_x, rect_y); + anv_image_view_init(iview, cmd_buffer->device, &(VkImageViewCreateInfo) { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,