[Mesa-dev] [v2 18/39] intel/isl/gen6: Add offsetting support for back-to-back layouts
Topi Pohjolainen
topi.pohjolainen at gmail.com
Wed May 3 09:22:31 UTC 2017
Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
src/intel/blorp/blorp_blit.c | 2 +-
src/intel/isl/isl.c | 29 +++++++++++++++++++++---
src/intel/isl/isl.h | 14 ++++++++++--
src/intel/isl/isl_gen6.c | 46 +++++++++++++++++++++++++++++++++++++++
src/intel/isl/isl_storage_image.c | 3 ++-
5 files changed, 87 insertions(+), 7 deletions(-)
diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
index 8e3fc31..ca42600 100644
--- a/src/intel/blorp/blorp_blit.c
+++ b/src/intel/blorp/blorp_blit.c
@@ -1398,7 +1398,7 @@ surf_convert_to_single_slice(const struct isl_device *isl_dev,
layer = info->view.base_array_layer;
uint32_t x_offset_sa, y_offset_sa;
- isl_surf_get_image_offset_sa(&info->surf, info->view.base_level,
+ isl_surf_get_image_offset_sa(isl_dev, &info->surf, info->view.base_level,
layer, z, &x_offset_sa, &y_offset_sa);
uint32_t byte_offset;
diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c
index f89f351..e06bb94 100644
--- a/src/intel/isl/isl.c
+++ b/src/intel/isl/isl.c
@@ -1295,6 +1295,20 @@ isl_apply_surface_padding(const struct isl_device *dev,
}
}
+/* On Gen6 hardware doesn't support mipmapping for stencil (W-tiled) and
+ * for HIZ. As workaround one places all slices back-to-back. Slices for
+ * level zero are back-to-back, followed by slices to level one, etc. This
+ * allows layered rendering once driver offsets the image to the first
+ * slice of particular level.
+ */
+static bool
+isl_surf_needs_back_to_back_layout(const struct isl_device *dev,
+ enum isl_tiling tiling)
+{
+ return ISL_DEV_GEN(dev) == 6 &&
+ (tiling == ISL_TILING_W || tiling == ISL_TILING_HIZ);
+}
+
bool
isl_surf_init_s(const struct isl_device *dev,
struct isl_surf *surf,
@@ -1906,7 +1920,8 @@ get_image_offset_sa_gen9_1d(const struct isl_surf *surf,
* @invariant logical_z_offset_px < logical depth of surface at level
*/
void
-isl_surf_get_image_offset_sa(const struct isl_surf *surf,
+isl_surf_get_image_offset_sa(const struct isl_device *dev,
+ const struct isl_surf *surf,
uint32_t level,
uint32_t logical_array_layer,
uint32_t logical_z_offset_px,
@@ -1918,6 +1933,13 @@ isl_surf_get_image_offset_sa(const struct isl_surf *surf,
assert(logical_z_offset_px
< isl_minify(surf->logical_level0_px.depth, level));
+ if (isl_surf_needs_back_to_back_layout(dev, surf->tiling)) {
+ get_image_offset_sa_gen6_back_to_back(surf, level, logical_array_layer,
+ logical_z_offset_px,
+ x_offset_sa, y_offset_sa);
+ return;
+ }
+
switch (surf->dim_layout) {
case ISL_DIM_LAYOUT_GEN9_1D:
get_image_offset_sa_gen9_1d(surf, level, logical_array_layer,
@@ -1939,7 +1961,8 @@ isl_surf_get_image_offset_sa(const struct isl_surf *surf,
}
void
-isl_surf_get_image_offset_el(const struct isl_surf *surf,
+isl_surf_get_image_offset_el(const struct isl_device *dev,
+ const struct isl_surf *surf,
uint32_t level,
uint32_t logical_array_layer,
uint32_t logical_z_offset_px,
@@ -1954,7 +1977,7 @@ isl_surf_get_image_offset_el(const struct isl_surf *surf,
< isl_minify(surf->logical_level0_px.depth, level));
uint32_t x_offset_sa, y_offset_sa;
- isl_surf_get_image_offset_sa(surf, level,
+ isl_surf_get_image_offset_sa(dev, surf, level,
logical_array_layer,
logical_z_offset_px,
&x_offset_sa,
diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h
index 7778551..3685ddf 100644
--- a/src/intel/isl/isl.h
+++ b/src/intel/isl/isl.h
@@ -1484,6 +1484,14 @@ isl_surf_get_array_pitch(const struct isl_surf *surf)
return isl_surf_get_array_pitch_sa_rows(surf) * surf->row_pitch;
}
+void
+get_image_offset_sa_gen6_back_to_back(const struct isl_surf *surf,
+ uint32_t level,
+ uint32_t logical_array_layer,
+ uint32_t logical_z_offset_px,
+ uint32_t *x_offset_sa,
+ uint32_t *y_offset_sa);
+
/**
* Calculate the offset, in units of surface samples, to a subimage in the
* surface.
@@ -1493,7 +1501,8 @@ isl_surf_get_array_pitch(const struct isl_surf *surf)
* @invariant logical_z_offset_px < logical depth of surface at level
*/
void
-isl_surf_get_image_offset_sa(const struct isl_surf *surf,
+isl_surf_get_image_offset_sa(const struct isl_device *dev,
+ const struct isl_surf *surf,
uint32_t level,
uint32_t logical_array_layer,
uint32_t logical_z_offset_px,
@@ -1509,7 +1518,8 @@ isl_surf_get_image_offset_sa(const struct isl_surf *surf,
* @invariant logical_z_offset_px < logical depth of surface at level
*/
void
-isl_surf_get_image_offset_el(const struct isl_surf *surf,
+isl_surf_get_image_offset_el(const struct isl_device *dev,
+ const struct isl_surf *surf,
uint32_t level,
uint32_t logical_array_layer,
uint32_t logical_z_offset_px,
diff --git a/src/intel/isl/isl_gen6.c b/src/intel/isl/isl_gen6.c
index b746903..8bd5dbc 100644
--- a/src/intel/isl/isl_gen6.c
+++ b/src/intel/isl/isl_gen6.c
@@ -145,3 +145,49 @@ isl_gen6_choose_image_alignment_el(const struct isl_device *dev,
*image_align_el = isl_extent3d(4, 2, 1);
}
+
+void
+get_image_offset_sa_gen6_back_to_back(const struct isl_surf *surf,
+ uint32_t level,
+ uint32_t logical_array_layer,
+ uint32_t logical_z_offset_px,
+ uint32_t *x_offset_sa,
+ uint32_t *y_offset_sa)
+{
+ assert(level < surf->levels);
+
+ const struct isl_extent3d image_align_sa =
+ isl_surf_get_image_alignment_sa(surf);
+
+ assert(surf->tiling == ISL_TILING_W ||
+ surf->tiling == ISL_TILING_HIZ);
+ const uint32_t tile_align_h = surf->tiling == ISL_TILING_W ? 64 : 32;
+
+ uint32_t y = 0;
+ for (unsigned i = 0; i < level; ++i) {
+ const unsigned d = surf->dim_layout == ISL_DIM_LAYOUT_GEN4_3D ?
+ isl_minify(surf->phys_level0_sa.depth, i) :
+ surf->phys_level0_sa.array_len;
+ const unsigned h = isl_minify(surf->phys_level0_sa.height, i);
+ y += d * isl_align_npot(h, image_align_sa.h);
+
+ /* Align on tile boundary so that driver can offset without intra-tile
+ * offsets.
+ */
+ y = isl_align(y, tile_align_h);
+ }
+
+ const unsigned level_h = isl_minify(surf->phys_level0_sa.height, level);
+ const unsigned aligned_level_h = isl_align_npot(level_h, image_align_sa.h);
+
+ if (surf->dim_layout == ISL_DIM_LAYOUT_GEN4_3D) {
+ assert(logical_z_offset_px < surf->logical_level0_px.depth);
+ y += logical_z_offset_px * aligned_level_h;
+ } else {
+ assert(logical_array_layer < surf->logical_level0_px.array_len);
+ y += logical_array_layer * aligned_level_h;
+ }
+
+ *x_offset_sa = 0;
+ *y_offset_sa = y;
+}
diff --git a/src/intel/isl/isl_storage_image.c b/src/intel/isl/isl_storage_image.c
index 4c56e78..9aeeede 100644
--- a/src/intel/isl/isl_storage_image.c
+++ b/src/intel/isl/isl_storage_image.c
@@ -226,7 +226,8 @@ isl_surf_fill_image_param(const struct isl_device *dev,
view->base_array_layer;
}
- isl_surf_get_image_offset_el(surf, view->base_level, view->base_array_layer,
+ isl_surf_get_image_offset_el(dev, surf,
+ view->base_level, view->base_array_layer,
0, ¶m->offset[0], ¶m->offset[1]);
const int cpp = isl_format_get_layout(surf->format)->bpb / 8;
--
2.9.3
More information about the mesa-dev
mailing list