mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 13:30:12 +01:00
intel/isl: Add more cases to isl_surf_get_uncompressed_surf
We can actually create array surfaces instead of requiring single-slice in a few cases. This does require us to be very careful about our checks, though. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11647>
This commit is contained in:
parent
2001a26309
commit
9946120d2b
4 changed files with 78 additions and 33 deletions
|
|
@ -2621,14 +2621,18 @@ blorp_surf_convert_to_uncompressed(const struct isl_device *isl_dev,
|
|||
}
|
||||
|
||||
uint32_t offset_B;
|
||||
isl_surf_get_uncompressed_surf(isl_dev, &info->surf, &info->view,
|
||||
&info->surf, &info->view, &offset_B,
|
||||
&info->tile_x_sa, &info->tile_y_sa);
|
||||
ASSERTED bool ok =
|
||||
isl_surf_get_uncompressed_surf(isl_dev, &info->surf, &info->view,
|
||||
&info->surf, &info->view, &offset_B,
|
||||
&info->tile_x_sa, &info->tile_y_sa);
|
||||
assert(ok);
|
||||
info->addr.offset += offset_B;
|
||||
|
||||
/* BLORP doesn't use the actual intratile offsets. Instead, it needs the
|
||||
* surface to be a bit bigger and we offset the vertices instead.
|
||||
*/
|
||||
assert(info->surf.dim == ISL_SURF_DIM_2D);
|
||||
assert(info->surf.logical_level0_px.array_len == 1);
|
||||
info->surf.logical_level0_px.w += info->tile_x_sa;
|
||||
info->surf.logical_level0_px.h += info->tile_y_sa;
|
||||
info->surf.phys_level0_sa.w += info->tile_x_sa;
|
||||
|
|
|
|||
|
|
@ -2827,7 +2827,7 @@ isl_surf_get_image_surf(const struct isl_device *dev,
|
|||
assert(ok);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
isl_surf_get_uncompressed_surf(const struct isl_device *dev,
|
||||
const struct isl_surf *surf,
|
||||
const struct isl_view *view,
|
||||
|
|
@ -2839,6 +2839,7 @@ isl_surf_get_uncompressed_surf(const struct isl_device *dev,
|
|||
{
|
||||
const struct isl_format_layout *fmtl =
|
||||
isl_format_get_layout(surf->format);
|
||||
const enum isl_format view_format = view->format;
|
||||
|
||||
assert(fmtl->bw > 1 || fmtl->bh > 1 || fmtl->bd > 1);
|
||||
assert(isl_format_is_compressed(surf->format));
|
||||
|
|
@ -2854,46 +2855,84 @@ isl_surf_get_uncompressed_surf(const struct isl_device *dev,
|
|||
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);
|
||||
|
||||
/* Due to hardware restrictions with intratile offsets, we can only
|
||||
* handle a single slice.
|
||||
*/
|
||||
assert(view->array_len == 1);
|
||||
/* If we ever enable 3D block formats, we'll need to re-think this */
|
||||
assert(fmtl->bd == 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);
|
||||
uint32_t x_offset_sa = 0, y_offset_sa = 0;
|
||||
if (view->array_len > 1) {
|
||||
/* The Skylake PRM Vol. 2d, "RENDER_SURFACE_STATE::X Offset" says:
|
||||
*
|
||||
* "If Surface Array is enabled, this field must be zero."
|
||||
*
|
||||
* The PRMs for other hardware have similar text. This is also tricky
|
||||
* to handle with things like BLORP's SW offsetting because the
|
||||
* increased surface size required for the offset may result in an image
|
||||
* height greater than qpitch.
|
||||
*/
|
||||
if (view->base_level > 0)
|
||||
return false;
|
||||
|
||||
ucompr_surf->format = view->format;
|
||||
/* On Haswell and earlier, RENDER_SURFACE_STATE doesn't have a QPitch
|
||||
* field; it only has "array pitch span" which means the QPitch is
|
||||
* automatically calculated. Since we're smashing the surface format
|
||||
* (block formats are subtly different) and the number of miplevels,
|
||||
* that calculation will get thrown off. This means we can't do arrays
|
||||
* even at LOD0
|
||||
*
|
||||
* On Broadwell, we do have a QPitch field which we can control.
|
||||
* However, HALIGN and VALIGN are specified in pixels and are
|
||||
* hard-coded to align to exactly the block size of the compressed
|
||||
* texture. This means that, when reinterpreted as a non-compressed
|
||||
* the QPitch may be anything but the HW requires it to be properly
|
||||
* aligned.
|
||||
*/
|
||||
if (ISL_GFX_VER(dev) < 9)
|
||||
return false;
|
||||
|
||||
*ucompr_surf = *surf;
|
||||
ucompr_surf->levels = 1;
|
||||
|
||||
/* The view remains the same */
|
||||
*ucompr_view = *view;
|
||||
} else {
|
||||
/* If only one array slice is requested, directly offset to that slice.
|
||||
* We could, in theory, still use arrays in some cases but BLORP isn't
|
||||
* prepared for this and everyone who calls this function should be
|
||||
* prepared to handle an X/Y offset.
|
||||
*/
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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.depth == 1);
|
||||
assert(ucompr_surf->phys_level0_sa.array_len == 1);
|
||||
ucompr_surf->phys_level0_sa = isl_surf_get_phys_level0_el(surf);
|
||||
|
||||
*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;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -2664,7 +2664,7 @@ isl_surf_get_image_surf(const struct isl_device *dev,
|
|||
* It is safe to call this function with surf == uncompressed_surf and
|
||||
* view == uncompressed_view.
|
||||
*/
|
||||
void
|
||||
bool MUST_CHECK
|
||||
isl_surf_get_uncompressed_surf(const struct isl_device *dev,
|
||||
const struct isl_surf *surf,
|
||||
const struct isl_view *view,
|
||||
|
|
|
|||
|
|
@ -2570,9 +2570,11 @@ anv_image_fill_surface_state(struct anv_device *device,
|
|||
assert(view.levels == 1);
|
||||
assert(view.array_len == 1);
|
||||
|
||||
isl_surf_get_uncompressed_surf(&device->isl_dev, isl_surf, &view,
|
||||
&tmp_surf, &view,
|
||||
&offset_B, &tile_x_sa, &tile_y_sa);
|
||||
ASSERTED bool ok =
|
||||
isl_surf_get_uncompressed_surf(&device->isl_dev, isl_surf, &view,
|
||||
&tmp_surf, &view,
|
||||
&offset_B, &tile_x_sa, &tile_y_sa);
|
||||
assert(ok);
|
||||
isl_surf = &tmp_surf;
|
||||
|
||||
if (device->info.ver <= 8) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue