From 07e083477416d51995f48c0e5ca53304e4924541 Mon Sep 17 00:00:00 2001 From: Nanley Chery Date: Wed, 17 Jul 2024 11:55:06 -0400 Subject: [PATCH] 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 Part-of: --- src/gallium/drivers/iris/iris_clear.c | 18 ++++++-- src/intel/blorp/blorp.h | 7 +-- src/intel/blorp/blorp_clear.c | 56 ------------------------ src/intel/vulkan/anv_image_view.c | 31 ++++++++----- src/intel/vulkan_hasvk/genX_cmd_buffer.c | 12 +---- 5 files changed, 36 insertions(+), 88 deletions(-) diff --git a/src/gallium/drivers/iris/iris_clear.c b/src/gallium/drivers/iris/iris_clear.c index b4a4e346ca9..0798a754b24 100644 --- a/src/gallium/drivers/iris/iris_clear.c +++ b/src/gallium/drivers/iris/iris_clear.c @@ -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; } diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h index 31ca74cd707..0cbd36b9659 100644 --- a/src/intel/blorp/blorp.h +++ b/src/intel/blorp/blorp.h @@ -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, diff --git a/src/intel/blorp/blorp_clear.c b/src/intel/blorp/blorp_clear.c index 4444e184660..b40a501e07d 100644 --- a/src/intel/blorp/blorp_clear.c +++ b/src/intel/blorp/blorp_clear.c @@ -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, diff --git a/src/intel/vulkan/anv_image_view.c b/src/intel/vulkan/anv_image_view.c index 9ae6ec49622..e2adf60f3de 100644 --- a/src/intel/vulkan/anv_image_view.c +++ b/src/intel/vulkan/anv_image_view.c @@ -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) diff --git a/src/intel/vulkan_hasvk/genX_cmd_buffer.c b/src/intel/vulkan_hasvk/genX_cmd_buffer.c index 581d11e8f35..2f58316a86b 100644 --- a/src/intel/vulkan_hasvk/genX_cmd_buffer.c +++ b/src/intel/vulkan_hasvk/genX_cmd_buffer.c @@ -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);