isl: Rework the get_intratile_offset function
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 30 Mar 2016 23:15:54 +0000 (16:15 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 8 Apr 2016 22:57:58 +0000 (15:57 -0700)
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 <nanley.g.chery@intel.com>
src/intel/isl/isl.c
src/intel/isl/isl.h
src/intel/vulkan/anv_meta_blit2d.c

index a36638071d5927014fde2515a5adb4fcc3f58a32..37d8bcba0789a5191f0b4bf9a30e18ad982a2f9c 100644 (file)
@@ -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
index 90193ca08c1b1f03f13ae3b67f771e7684ed1cc8..4f796f6c6a80bcf12122ab583e780505ff2cf8a7 100644 (file)
@@ -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
  *
index 8e63eee462df9706f97e1447af874c247166f783..cf2dc66597d5cd185cfd320d2fc5ebc5b0625b15 100644 (file)
@@ -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,