layer = info->view.base_array_layer;
uint32_t byte_offset;
- isl_surf_get_image_offset_B_tile_sa(&info->surf,
- info->view.base_level, layer, z,
- &byte_offset,
- &info->tile_x_sa, &info->tile_y_sa);
+ isl_surf_get_image_surf(isl_dev, &info->surf,
+ info->view.base_level, layer, z,
+ &info->surf,
+ &byte_offset, &info->tile_x_sa, &info->tile_y_sa);
info->addr.offset += byte_offset;
- const uint32_t slice_width_px =
- minify(info->surf.logical_level0_px.width, info->view.base_level);
- const uint32_t slice_height_px =
- minify(info->surf.logical_level0_px.height, info->view.base_level);
-
uint32_t tile_x_px, tile_y_px;
surf_get_intratile_offset_px(info, &tile_x_px, &tile_y_px);
- /* Even for cube maps there will be only single face, therefore drop the
- * corresponding flag if present.
+ /* Instead of using the X/Y Offset fields in RENDER_SURFACE_STATE, we place
+ * the image at the tile boundary and offset our sampling or rendering.
+ * For this reason, we need to grow the image by the offset to ensure that
+ * the hardware doesn't think we've gone past the edge.
*/
- const isl_surf_usage_flags_t without_cube_map_flag =
- info->surf.usage & (~ISL_SURF_USAGE_CUBE_BIT);
-
- struct isl_surf_init_info init_info = {
- .dim = ISL_SURF_DIM_2D,
- .format = info->surf.format,
- .width = slice_width_px + tile_x_px,
- .height = slice_height_px + tile_y_px,
- .depth = 1,
- .levels = 1,
- .array_len = 1,
- .samples = info->surf.samples,
- .row_pitch = info->surf.row_pitch,
- .usage = without_cube_map_flag,
- .tiling_flags = 1 << info->surf.tiling,
- };
-
- ok = isl_surf_init_s(isl_dev, &info->surf, &init_info);
- assert(ok);
+ info->surf.logical_level0_px.w += tile_x_px;
+ info->surf.logical_level0_px.h += tile_y_px;
+ info->surf.phys_level0_sa.w += info->tile_x_sa;
+ info->surf.phys_level0_sa.h += info->tile_y_sa;
/* The view is also different now. */
info->view.base_level = 0;
}
}
+void
+isl_surf_get_image_surf(const struct isl_device *dev,
+ const struct isl_surf *surf,
+ uint32_t level,
+ uint32_t logical_array_layer,
+ uint32_t logical_z_offset_px,
+ struct isl_surf *image_surf,
+ uint32_t *offset_B,
+ uint32_t *x_offset_sa,
+ uint32_t *y_offset_sa)
+{
+ isl_surf_get_image_offset_B_tile_sa(surf,
+ level,
+ logical_array_layer,
+ logical_z_offset_px,
+ offset_B,
+ x_offset_sa,
+ y_offset_sa);
+
+ /* Even for cube maps there will be only single face, therefore drop the
+ * corresponding flag if present.
+ */
+ const isl_surf_usage_flags_t usage =
+ surf->usage & (~ISL_SURF_USAGE_CUBE_BIT);
+
+ bool ok UNUSED;
+ ok = isl_surf_init(dev, image_surf,
+ .dim = ISL_SURF_DIM_2D,
+ .format = surf->format,
+ .width = isl_minify(surf->logical_level0_px.w, level),
+ .height = isl_minify(surf->logical_level0_px.h, level),
+ .depth = 1,
+ .levels = 1,
+ .array_len = 1,
+ .samples = surf->samples,
+ .row_pitch = surf->row_pitch,
+ .usage = usage,
+ .tiling_flags = (1 << surf->tiling));
+ assert(ok);
+}
+
void
isl_tiling_get_intratile_offset_el(enum isl_tiling tiling,
uint32_t bpb,
uint32_t *x_offset_sa,
uint32_t *y_offset_sa);
+/**
+ * Create an isl_surf that represents a particular subimage in the surface.
+ *
+ * The newly created surface will have a single miplevel and array slice. The
+ * surface lives at the returned byte and intratile offsets, in samples.
+ *
+ * It is safe to call this function with surf == image_surf.
+ *
+ * @invariant level < surface levels
+ * @invariant logical_array_layer < logical array length of surface
+ * @invariant logical_z_offset_px < logical depth of surface at level
+ */
+void
+isl_surf_get_image_surf(const struct isl_device *dev,
+ const struct isl_surf *surf,
+ uint32_t level,
+ uint32_t logical_array_layer,
+ uint32_t logical_z_offset_px,
+ struct isl_surf *image_surf,
+ uint32_t *offset_B,
+ uint32_t *x_offset_sa,
+ uint32_t *y_offset_sa);
+
/**
* @brief Calculate the intratile offsets to a surface.
*