intel: Use a simpler workaround for HiZ WT fast-clears
The new workaround tries to strike a balance between simplicity and functionality (for testing purposes). Instead of checking for the alignment of a specific LOD when fast-clearing, we take an all-or-nothing approach for LOD1+. I haven't found any app to clear LOD1+ except for a Dirt Rally trace some time ago. If I remember correctly, that trace clears all LODs, doesn't render to them, then clears again with a different color, incurring resolves. So, skipping LOD1+ fast clears will avoid those resolves. Other apps I tested include Synmark2, glmark2, GfxBench5, and the Vulkan games in internal our benchmarking tool. Now that we've added updated and simplified checks in the drivers themselves, we delete blorp_can_hiz_clear_depth. Reviewed-by: Rohan Garg <rohan.garg@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30250>
This commit is contained in:
@@ -498,10 +498,20 @@ can_fast_clear_depth(struct iris_context *ice,
|
||||
if (!iris_resource_level_has_hiz(devinfo, res, level))
|
||||
return false;
|
||||
|
||||
if (!blorp_can_hiz_clear_depth(devinfo, &res->surf, res->aux.usage,
|
||||
level, box->z, box->x, box->y,
|
||||
box->x + box->width,
|
||||
box->y + box->height)) {
|
||||
/* From the TGL PRM, Vol 9, "Compressed Depth Buffers" (under the
|
||||
* "Texture performant" and "ZCS" columns):
|
||||
*
|
||||
* Update with clear at either 16x8 or 8x4 granularity, based on
|
||||
* fs_clr or otherwise.
|
||||
*
|
||||
* When fast-clearing, hardware behaves in unexpected ways if the clear
|
||||
* rectangle, aligned to 16x8, could cover neighboring LODs. Fortunately,
|
||||
* ISL guarantees that LOD0 will be 8-row aligned and LOD0's height seems
|
||||
* to not matter. Also, few applications ever clear LOD1+. Only allow
|
||||
* fast-clearing upper LODs if no overlap can occur.
|
||||
*/
|
||||
if (res->aux.usage == ISL_AUX_USAGE_HIZ_CCS_WT && level >= 1 &&
|
||||
(p_res->width0 % 32 != 0 || res->surf.image_alignment_el.h % 8 != 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,12 +314,7 @@ blorp_clear_depth_stencil(struct blorp_batch *batch,
|
||||
uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1,
|
||||
bool clear_depth, float depth_value,
|
||||
uint8_t stencil_mask, uint8_t stencil_value);
|
||||
bool
|
||||
blorp_can_hiz_clear_depth(const struct intel_device_info *devinfo,
|
||||
const struct isl_surf *surf,
|
||||
enum isl_aux_usage aux_usage,
|
||||
uint32_t level, uint32_t layer,
|
||||
uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1);
|
||||
|
||||
void
|
||||
blorp_hiz_clear_depth_stencil(struct blorp_batch *batch,
|
||||
const struct blorp_surf *depth,
|
||||
|
||||
@@ -916,62 +916,6 @@ blorp_clear_depth_stencil(struct blorp_batch *batch,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
blorp_can_hiz_clear_depth(const struct intel_device_info *devinfo,
|
||||
const struct isl_surf *surf,
|
||||
enum isl_aux_usage aux_usage,
|
||||
uint32_t level, uint32_t layer,
|
||||
uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1)
|
||||
{
|
||||
/* This function currently doesn't support any gen prior to gfx8 */
|
||||
assert(devinfo->ver >= 8);
|
||||
|
||||
if (aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT && level > 0) {
|
||||
/* We have to set the WM_HZ_OP::FullSurfaceDepthandStencilClear bit
|
||||
* whenever we clear an uninitialized HIZ buffer (as some drivers
|
||||
* currently do). However, this bit seems liable to clear 16x8 pixels in
|
||||
* the ZCS on Gfx12 - greater than the slice alignments of many depth
|
||||
* buffers.
|
||||
*
|
||||
* This is the hypothesis behind some corruption that was seen with the
|
||||
* amd_vertex_shader_layer-layered-depth-texture-render piglit test.
|
||||
*
|
||||
* From the Compressed Depth Buffers section of the Bspec, under the
|
||||
* Gfx12 texture performant and ZCS columns:
|
||||
*
|
||||
* Update with clear at either 16x8 or 8x4 granularity, based on
|
||||
* fs_clr or otherwise.
|
||||
*
|
||||
* There are a number of ways to avoid full surface CCS clears that
|
||||
* overlap other slices, but for now we choose to disable fast-clears
|
||||
* when an initializing clear could hit another miplevel.
|
||||
*
|
||||
* NOTE: Because the CCS compresses the depth buffer and not a version
|
||||
* of it that has been rearranged with different alignments (like Gfx8+
|
||||
* HIZ), we have to make sure that the x0 and y0 are at least 16x8
|
||||
* aligned in the context of the entire surface.
|
||||
*/
|
||||
uint32_t slice_x0, slice_y0, slice_z0, slice_a0;
|
||||
isl_surf_get_image_offset_el(surf, level,
|
||||
surf->dim == ISL_SURF_DIM_3D ? 0 : layer,
|
||||
surf->dim == ISL_SURF_DIM_3D ? layer: 0,
|
||||
&slice_x0, &slice_y0, &slice_z0, &slice_a0);
|
||||
const bool max_x1_y1 =
|
||||
x1 == u_minify(surf->logical_level0_px.width, level) &&
|
||||
y1 == u_minify(surf->logical_level0_px.height, level);
|
||||
const uint32_t haligned_x1 = ALIGN(x1, surf->image_alignment_el.w);
|
||||
const uint32_t valigned_y1 = ALIGN(y1, surf->image_alignment_el.h);
|
||||
const bool unaligned = (slice_x0 + x0) % 16 || (slice_y0 + y0) % 8 ||
|
||||
(max_x1_y1 ? haligned_x1 % 16 || valigned_y1 % 8 :
|
||||
x1 % 16 || y1 % 8);
|
||||
|
||||
if (unaligned)
|
||||
return false;
|
||||
}
|
||||
|
||||
return isl_aux_usage_has_hiz(aux_usage);
|
||||
}
|
||||
|
||||
static bool
|
||||
blorp_can_clear_full_surface(const struct blorp_surf *depth,
|
||||
const struct blorp_surf *stencil,
|
||||
|
||||
@@ -192,17 +192,8 @@ anv_can_hiz_clear_ds_view(struct anv_device *device,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
layout, queue_flags);
|
||||
if (!blorp_can_hiz_clear_depth(device->info,
|
||||
&iview->image->planes[0].primary_surface.isl,
|
||||
clear_aux_usage,
|
||||
iview->planes[0].isl.base_level,
|
||||
iview->planes[0].isl.base_array_layer,
|
||||
render_area.offset.x,
|
||||
render_area.offset.y,
|
||||
render_area.offset.x +
|
||||
render_area.extent.width,
|
||||
render_area.offset.y +
|
||||
render_area.extent.height))
|
||||
|
||||
if (!isl_aux_usage_has_fast_clears(clear_aux_usage))
|
||||
return false;
|
||||
|
||||
if (isl_aux_usage_has_ccs(clear_aux_usage)) {
|
||||
@@ -224,6 +215,24 @@ anv_can_hiz_clear_ds_view(struct anv_device *device,
|
||||
u_minify(iview->vk.extent.height, iview->vk.base_mip_level)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* When fast-clearing, hardware behaves in unexpected ways if the clear
|
||||
* rectangle, aligned to 16x8, could cover neighboring LODs.
|
||||
* Fortunately, ISL guarantees that LOD0 will be 8-row aligned and
|
||||
* LOD0's height seems to not matter. Also, few applications ever clear
|
||||
* LOD1+. Only allow fast-clearing upper LODs if no overlap can occur.
|
||||
*/
|
||||
const struct isl_surf *surf =
|
||||
&iview->image->planes[0].primary_surface.isl;
|
||||
assert(isl_surf_usage_is_depth(surf->usage));
|
||||
assert(surf->dim_layout == ISL_DIM_LAYOUT_GFX4_2D);
|
||||
assert(surf->array_pitch_el_rows % 8 == 0);
|
||||
if (clear_aux_usage == ISL_AUX_USAGE_HIZ_CCS_WT &&
|
||||
iview->vk.base_mip_level >= 1 &&
|
||||
(iview->vk.extent.width % 32 != 0 ||
|
||||
surf->image_alignment_el.h % 8 != 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_clear_value != ANV_HZ_FC_VAL)
|
||||
|
||||
@@ -414,17 +414,7 @@ anv_can_hiz_clear_ds_view(struct anv_device *device,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
layout);
|
||||
if (!blorp_can_hiz_clear_depth(device->info,
|
||||
&iview->image->planes[0].primary_surface.isl,
|
||||
clear_aux_usage,
|
||||
iview->planes[0].isl.base_level,
|
||||
iview->planes[0].isl.base_array_layer,
|
||||
render_area.offset.x,
|
||||
render_area.offset.y,
|
||||
render_area.offset.x +
|
||||
render_area.extent.width,
|
||||
render_area.offset.y +
|
||||
render_area.extent.height))
|
||||
if (!isl_aux_usage_has_fast_clears(clear_aux_usage))
|
||||
return false;
|
||||
|
||||
assert(GFX_VER == 8);
|
||||
|
||||
Reference in New Issue
Block a user