Module: Mesa Branch: main Commit: 65bbe58b2532f0b449eaec78b753563b5f1f1c33 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=65bbe58b2532f0b449eaec78b753563b5f1f1c33
Author: Francisco Jerez <curroje...@riseup.net> Date: Fri Sep 29 14:16:56 2023 -0700 anv/xehp: Implement TBIMR tile pass setup and pipeline bandwidth estimation. This sets up the basic parameters needed for tiled rendering based on a back-of-the-envelope estimate of the amount of memory used by the pixel pipeline during the tile pass. The actual cache footprint of a tile can vary wildly based on runtime factors which aren't easily predictable based on static analysis, so this is only intended to provide a rough approximation within the right order of magnitude. Reviewed-by: Lionel Landwerlin <lionel.g.landwer...@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25493> --- src/intel/vulkan/anv_private.h | 9 ++ src/intel/vulkan/anv_util.c | 1 + src/intel/vulkan/genX_gfx_state.c | 173 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+) diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 478e122b99b..3e5dfabecd4 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1199,6 +1199,7 @@ enum anv_gfx_state_bits { ANV_GFX_STATE_WM_DEPTH_STENCIL, ANV_GFX_STATE_PMA_FIX, /* Fake state to implement workaround */ ANV_GFX_STATE_WA_18019816803, /* Fake state to implement workaround */ + ANV_GFX_STATE_TBIMR_TILE_PASS_INFO, ANV_GFX_STATE_MAX, }; @@ -1431,6 +1432,14 @@ struct anv_gfx_dynamic_state { uint32_t BackfaceStencilTestFunction; } ds; + /* 3DSTATE_TBIMR_TILE_PASS_INFO */ + struct { + unsigned TileRectangleHeight; + unsigned TileRectangleWidth; + unsigned VerticalTileCount; + unsigned HorizontalTileCount; + unsigned TBIMRBatchSize; + } tbimr; bool use_tbimr; bool pma_fix; diff --git a/src/intel/vulkan/anv_util.c b/src/intel/vulkan/anv_util.c index de835aec937..f1573fe854a 100644 --- a/src/intel/vulkan/anv_util.c +++ b/src/intel/vulkan/anv_util.c @@ -147,6 +147,7 @@ anv_gfx_state_bit_to_str(enum anv_gfx_state_bits state) NAME(WM); NAME(WM_DEPTH_STENCIL); NAME(PMA_FIX); + NAME(TBIMR_TILE_PASS_INFO); default: unreachable("invalid state"); } } diff --git a/src/intel/vulkan/genX_gfx_state.c b/src/intel/vulkan/genX_gfx_state.c index cf760571d41..cec6177808b 100644 --- a/src/intel/vulkan/genX_gfx_state.c +++ b/src/intel/vulkan/genX_gfx_state.c @@ -32,6 +32,7 @@ #include "genxml/gen_macros.h" #include "genxml/genX_pack.h" #include "common/intel_guardband.h" +#include "common/intel_tiled_render.h" #include "compiler/brw_prim.h" const uint32_t genX(vk_to_intel_blend)[] = { @@ -288,6 +289,143 @@ genX(rasterization_mode)(VkPolygonMode raster_mode, } } +#if GFX_VERx10 == 125 +/** + * Return the dimensions of the current rendering area, defined as the + * bounding box of all present color, depth and stencil attachments. + */ +UNUSED static bool +calculate_render_area(struct anv_cmd_buffer *cmd_buffer, + unsigned *width, unsigned *height) +{ + struct anv_cmd_graphics_state *gfx = &cmd_buffer->state.gfx; + + *width = gfx->render_area.offset.x + gfx->render_area.extent.width; + *height = gfx->render_area.offset.y + gfx->render_area.extent.height; + + for (unsigned i = 0; i < gfx->color_att_count; i++) { + struct anv_attachment *att = &gfx->color_att[i]; + if (att->iview) { + *width = MAX2(*width, att->iview->vk.extent.width); + *height = MAX2(*height, att->iview->vk.extent.height); + } + } + + const struct anv_image_view *const z_view = gfx->depth_att.iview; + if (z_view) { + *width = MAX2(*width, z_view->vk.extent.width); + *height = MAX2(*height, z_view->vk.extent.height); + } + + const struct anv_image_view *const s_view = gfx->stencil_att.iview; + if (s_view) { + *width = MAX2(*width, s_view->vk.extent.width); + *height = MAX2(*height, s_view->vk.extent.height); + } + + return *width && *height; +} + +/* Calculate TBIMR tiling parameters adequate for the current pipeline + * setup. Return true if TBIMR should be enabled. + */ +UNUSED static bool +calculate_tile_dimensions(struct anv_cmd_buffer *cmd_buffer, + unsigned fb_width, unsigned fb_height, + unsigned *tile_width, unsigned *tile_height) +{ + const struct anv_device *device = cmd_buffer->device; + struct anv_cmd_graphics_state *gfx = &cmd_buffer->state.gfx; + const unsigned aux_scale = 256; + unsigned pixel_size = 0; + + /* Perform a rough calculation of the tile cache footprint of the + * pixel pipeline, approximating it as the sum of the amount of + * memory used per pixel by every render target, depth, stencil and + * auxiliary surfaces bound to the pipeline. + */ + for (uint32_t i = 0; i < gfx->color_att_count; i++) { + struct anv_attachment *att = &gfx->color_att[i]; + + if (att->iview) { + const struct anv_image *image = att->iview->image; + const unsigned p = anv_image_aspect_to_plane(image, + VK_IMAGE_ASPECT_COLOR_BIT); + const struct anv_image_plane *plane = &image->planes[p]; + + pixel_size += intel_calculate_surface_pixel_size( + &plane->primary_surface.isl); + + if (isl_aux_usage_has_mcs(att->aux_usage)) + pixel_size += intel_calculate_surface_pixel_size( + &plane->aux_surface.isl); + + /* XXX - Use proper implicit CCS surface metadata tracking + * instead of inferring pixel size from primary + * surface. + */ + if (isl_aux_usage_has_ccs(att->aux_usage)) + pixel_size += DIV_ROUND_UP(intel_calculate_surface_pixel_size( + &plane->primary_surface.isl), + aux_scale); + } + } + + const struct anv_image_view *const z_view = gfx->depth_att.iview; + if (z_view) { + const struct anv_image *image = z_view->image; + assert(image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT); + const unsigned p = anv_image_aspect_to_plane(image, + VK_IMAGE_ASPECT_DEPTH_BIT); + const struct anv_image_plane *plane = &image->planes[p]; + + pixel_size += intel_calculate_surface_pixel_size( + &plane->primary_surface.isl); + + if (isl_aux_usage_has_hiz(image->planes[p].aux_usage)) + pixel_size += intel_calculate_surface_pixel_size( + &plane->aux_surface.isl); + + /* XXX - Use proper implicit CCS surface metadata tracking + * instead of inferring pixel size from primary + * surface. + */ + if (isl_aux_usage_has_ccs(image->planes[p].aux_usage)) + pixel_size += DIV_ROUND_UP(intel_calculate_surface_pixel_size( + &plane->primary_surface.isl), + aux_scale); + } + + const struct anv_image_view *const s_view = gfx->depth_att.iview; + if (s_view && s_view != z_view) { + const struct anv_image *image = s_view->image; + assert(image->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT); + const unsigned p = anv_image_aspect_to_plane(image, + VK_IMAGE_ASPECT_STENCIL_BIT); + const struct anv_image_plane *plane = &image->planes[p]; + + pixel_size += intel_calculate_surface_pixel_size( + &plane->primary_surface.isl); + } + + if (!pixel_size) + return false; + + /* Compute a tile layout that allows reasonable utilization of the + * tile cache based on the per-pixel cache footprint estimated + * above. + */ + intel_calculate_tile_dimensions(device->info, cmd_buffer->state.current_l3_config, + 32, 32, fb_width, fb_height, + pixel_size, tile_width, tile_height); + + /* Perform TBIMR tile passes only if the framebuffer covers more + * than a single tile. + */ + return *tile_width < fb_width || *tile_height < fb_height; +} +#endif + /** * This function takes the vulkan runtime values & dirty states and updates * the values in anv_gfx_dynamic_state, flagging HW instructions for @@ -1120,6 +1258,27 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer) } } +#if GFX_VERx10 == 125 + if ((cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_RENDER_TARGETS)) { + unsigned fb_width, fb_height, tile_width, tile_height; + + if (cmd_buffer->device->physical->instance->enable_tbimr && + calculate_render_area(cmd_buffer, &fb_width, &fb_height) && + calculate_tile_dimensions(cmd_buffer, fb_width, fb_height, + &tile_width, &tile_height)) { + SET(TBIMR_TILE_PASS_INFO, tbimr.TileRectangleHeight, tile_height); + SET(TBIMR_TILE_PASS_INFO, tbimr.TileRectangleWidth, tile_width); + SET(TBIMR_TILE_PASS_INFO, tbimr.VerticalTileCount, + DIV_ROUND_UP(fb_height, tile_height)); + SET(TBIMR_TILE_PASS_INFO, tbimr.HorizontalTileCount, + DIV_ROUND_UP(fb_width, tile_width)); + SET(TBIMR_TILE_PASS_INFO, use_tbimr, true); + } else { + hw_state->use_tbimr = false; + } + } +#endif + #undef GET #undef SET #undef SET_STAGE @@ -1714,6 +1873,20 @@ genX(cmd_buffer_flush_gfx_hw_state)(struct anv_cmd_buffer *cmd_buffer) genX(cmd_buffer_enable_pma_fix)(cmd_buffer, hw_state->pma_fix); #endif +#if GFX_VERx10 >= 125 + if (hw_state->use_tbimr && + BITSET_TEST(hw_state->dirty, ANV_GFX_STATE_TBIMR_TILE_PASS_INFO)) { + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_TBIMR_TILE_PASS_INFO), + tbimr) { + SET(tbimr, tbimr, TileRectangleHeight); + SET(tbimr, tbimr, TileRectangleWidth); + SET(tbimr, tbimr, VerticalTileCount); + SET(tbimr, tbimr, HorizontalTileCount); + SET(tbimr, tbimr, TBIMRBatchSize); + } + } +#endif + #undef INIT #undef SET