From 4b024a15f2660886f868c33470ba83677edd24c4 Mon Sep 17 00:00:00 2001 From: tarsin Date: Fri, 29 Sep 2023 17:31:07 +0800 Subject: [PATCH] turnip: Split tu_image_init to use layout setting logic separately Signed-off-by: tarsin [rob: improve comments about modifier taking precedence over image create flags, and fix bogus assert] Signed-off-by: Rob Clark Reviewed-by: Roman Stratiienko Part-of: --- src/freedreno/vulkan/tu_image.cc | 234 +++++++++++++++++-------------- src/freedreno/vulkan/tu_image.h | 3 + 2 files changed, 130 insertions(+), 107 deletions(-) diff --git a/src/freedreno/vulkan/tu_image.cc b/src/freedreno/vulkan/tu_image.cc index b89cd8a1559..92837226940 100644 --- a/src/freedreno/vulkan/tu_image.cc +++ b/src/freedreno/vulkan/tu_image.cc @@ -429,121 +429,48 @@ format_list_has_swaps(const VkImageFormatListCreateInfo *fmt_list) return false; } -static VkResult -tu_image_init(struct tu_device *device, struct tu_image *image, - const VkImageCreateInfo *pCreateInfo, uint64_t modifier, - const VkSubresourceLayout *plane_layouts) +VkResult +tu_image_update_layout(struct tu_device *device, struct tu_image *image, + uint64_t modifier, const VkSubresourceLayout *plane_layouts) { + enum a6xx_tile_mode tile_mode = TILE6_3; image->vk.drm_format_mod = modifier; - enum a6xx_tile_mode tile_mode = TILE6_3; - bool ubwc_enabled = true; - - /* use linear tiling if requested */ - if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR || modifier == DRM_FORMAT_MOD_LINEAR) { - tile_mode = TILE6_LINEAR; - ubwc_enabled = false; + if (modifier == DRM_FORMAT_MOD_LINEAR) { + image->force_linear_tile = true; } - /* Force linear tiling for formats with "fake" optimalTilingFeatures */ - if (!tiling_possible(image->vk.format)) { + if (image->force_linear_tile) { tile_mode = TILE6_LINEAR; - ubwc_enabled = false; + image->ubwc_enabled = false; } - /* No sense in tiling a 1D image, you'd just waste space and cache locality. */ - if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) { - tile_mode = TILE6_LINEAR; - ubwc_enabled = false; - } - - /* Fragment density maps are sampled on the CPU and we don't support - * sampling tiled images on the CPU or UBWC at the moment. - */ - if (pCreateInfo->usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) { - tile_mode = TILE6_LINEAR; - ubwc_enabled = false; - } - - enum pipe_format format = - tu_vk_format_to_pipe_format(image->vk.format); /* Whether a view of the image with an R8G8 format could be made. */ - bool has_r8g8 = tu_is_r8g8(format); + bool has_r8g8 = tu_is_r8g8(tu_vk_format_to_pipe_format(image->vk.format)); - if (ubwc_enabled && - !ubwc_possible(device, image->vk.format, pCreateInfo->imageType, - pCreateInfo->usage, image->vk.stencil_usage, - device->physical_device->info, pCreateInfo->samples, - device->use_z24uint_s8uint)) - ubwc_enabled = false; - - /* Mutable images can be reinterpreted as any other compatible format. - * This is a problem with UBWC (compression for different formats is different), - * but also tiling ("swap" affects how tiled formats are stored in memory) - * Depth and stencil formats cannot be reintepreted as another format, and - * cannot be linear with sysmem rendering, so don't fall back for those. - * - * TODO: - * - if the fmt_list contains only formats which are swapped, but compatible - * with each other (B8G8R8A8_UNORM and B8G8R8A8_UINT for example), then - * tiling is still possible - * - figure out which UBWC compressions are compatible to keep it enabled + /* With AHB, we could be asked to create an image with VK_IMAGE_TILING_LINEAR + * but gralloc doesn't know this. So if we are explicitly told that it is + * UBWC, then override how the image was created. */ - if ((pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && - !vk_format_is_depth_or_stencil(image->vk.format)) { - const VkImageFormatListCreateInfo *fmt_list = - vk_find_struct_const(pCreateInfo->pNext, IMAGE_FORMAT_LIST_CREATE_INFO); - if (!tu6_mutable_format_list_ubwc_compatible(device->physical_device->info, - fmt_list)) { - if (ubwc_enabled) { - if (fmt_list && fmt_list->viewFormatCount == 2) { - perf_debug( - device, - "Disabling UBWC on %dx%d %s resource due to mutable formats " - "(fmt list %s, %s)", - image->vk.extent.width, image->vk.extent.height, - util_format_name(vk_format_to_pipe_format(image->vk.format)), - util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[0])), - util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[1]))); - } else { - perf_debug( - device, - "Disabling UBWC on %dx%d %s resource due to mutable formats " - "(fmt list %s)", - image->vk.extent.width, image->vk.extent.height, - util_format_name(vk_format_to_pipe_format(image->vk.format)), - fmt_list ? "present" : "missing"); - } - ubwc_enabled = false; - } - - if (format_list_reinterprets_r8g8_r16(format, fmt_list) || - format_list_has_swaps(fmt_list)) { - tile_mode = TILE6_LINEAR; - } - } + if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) { + assert(!image->force_linear_tile); + image->ubwc_enabled = true; } - /* expect UBWC enabled if we asked for it */ - if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) - assert(ubwc_enabled); - else if (TU_DEBUG(NOUBWC)) - ubwc_enabled = false; - /* Non-UBWC tiled R8G8 is probably buggy since media formats are always * either linear or UBWC. There is no simple test to reproduce the bug. * However it was observed in the wild leading to an unrecoverable hang * on a650/a660. */ - if (has_r8g8 && tile_mode == TILE6_3 && !ubwc_enabled) { + if (has_r8g8 && tile_mode == TILE6_3 && !image->ubwc_enabled) { tile_mode = TILE6_LINEAR; } for (uint32_t i = 0; i < tu6_plane_count(image->vk.format); i++) { struct fdl_layout *layout = &image->layout[i]; enum pipe_format format = tu6_plane_format(image->vk.format, i); - uint32_t width0 = pCreateInfo->extent.width; - uint32_t height0 = pCreateInfo->extent.height; + uint32_t width0 = image->vk.extent.width; + uint32_t height0 = image->vk.extent.height; if (i > 0) { switch (image->vk.format) { @@ -555,7 +482,7 @@ tu_image_init(struct tu_device *device, struct tu_image *image, break; case VK_FORMAT_D32_SFLOAT_S8_UINT: /* no UBWC for separate stencil */ - ubwc_enabled = false; + image->ubwc_enabled = false; break; default: break; @@ -566,9 +493,9 @@ tu_image_init(struct tu_device *device, struct tu_image *image, if (plane_layouts) { /* only expect simple 2D images for now */ - if (pCreateInfo->mipLevels != 1 || - pCreateInfo->arrayLayers != 1 || - pCreateInfo->extent.depth != 1) + if (image->vk.mip_levels != 1 || + image->vk.array_layers != 1 || + image->vk.extent.depth != 1) return vk_error(device, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT); plane_layout.offset = plane_layouts[i].offset; @@ -577,15 +504,15 @@ tu_image_init(struct tu_device *device, struct tu_image *image, } layout->tile_mode = tile_mode; - layout->ubwc = ubwc_enabled; + layout->ubwc = image->ubwc_enabled; if (!fdl6_layout(layout, format, - pCreateInfo->samples, + image->vk.samples, width0, height0, - pCreateInfo->extent.depth, - pCreateInfo->mipLevels, - pCreateInfo->arrayLayers, - pCreateInfo->imageType == VK_IMAGE_TYPE_3D, + image->vk.extent.depth, + image->vk.mip_levels, + image->vk.array_layers, + image->vk.image_type == VK_IMAGE_TYPE_3D, plane_layouts ? &plane_layout : NULL)) { assert(plane_layouts); /* can only fail with explicit layout */ return vk_error(device, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT); @@ -599,7 +526,7 @@ tu_image_init(struct tu_device *device, struct tu_image *image, */ if (!plane_layouts && i > 0) { uint32_t offset = ALIGN_POT(image->total_size, 4096); - for (int i = 0; i < pCreateInfo->mipLevels; i++) { + for (int i = 0; i < image->vk.mip_levels; i++) { layout->slices[i].offset += offset; layout->ubwc_slices[i].offset += offset; } @@ -670,6 +597,95 @@ tu_image_init(struct tu_device *device, struct tu_image *image, return VK_SUCCESS; } +static VkResult +tu_image_init(struct tu_device *device, struct tu_image *image, + const VkImageCreateInfo *pCreateInfo) +{ + image->ubwc_enabled = true; + + /* use linear tiling if requested */ + if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) { + image->force_linear_tile = true; + } + + /* Force linear tiling for formats with "fake" optimalTilingFeatures */ + if (!tiling_possible(image->vk.format)) { + image->force_linear_tile = true; + } + + /* No sense in tiling a 1D image, you'd just waste space and cache locality. */ + if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) { + image->force_linear_tile = true; + } + + /* Fragment density maps are sampled on the CPU and we don't support + * sampling tiled images on the CPU or UBWC at the moment. + */ + if (pCreateInfo->usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) { + image->force_linear_tile = true; + } + + if (image->force_linear_tile || + !ubwc_possible(device, image->vk.format, pCreateInfo->imageType, + pCreateInfo->usage, image->vk.stencil_usage, + device->physical_device->info, pCreateInfo->samples, + device->use_z24uint_s8uint)) + image->ubwc_enabled = false; + + /* Mutable images can be reinterpreted as any other compatible format. + * This is a problem with UBWC (compression for different formats is different), + * but also tiling ("swap" affects how tiled formats are stored in memory) + * Depth and stencil formats cannot be reintepreted as another format, and + * cannot be linear with sysmem rendering, so don't fall back for those. + * + * TODO: + * - if the fmt_list contains only formats which are swapped, but compatible + * with each other (B8G8R8A8_UNORM and B8G8R8A8_UINT for example), then + * tiling is still possible + * - figure out which UBWC compressions are compatible to keep it enabled + */ + if ((pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && + !vk_format_is_depth_or_stencil(image->vk.format)) { + const VkImageFormatListCreateInfo *fmt_list = + vk_find_struct_const(pCreateInfo->pNext, IMAGE_FORMAT_LIST_CREATE_INFO); + if (!tu6_mutable_format_list_ubwc_compatible(device->physical_device->info, + fmt_list)) { + if (image->ubwc_enabled) { + if (fmt_list && fmt_list->viewFormatCount == 2) { + perf_debug( + device, + "Disabling UBWC on %dx%d %s resource due to mutable formats " + "(fmt list %s, %s)", + image->vk.extent.width, image->vk.extent.height, + util_format_name(vk_format_to_pipe_format(image->vk.format)), + util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[0])), + util_format_name(vk_format_to_pipe_format(fmt_list->pViewFormats[1]))); + } else { + perf_debug( + device, + "Disabling UBWC on %dx%d %s resource due to mutable formats " + "(fmt list %s)", + image->vk.extent.width, image->vk.extent.height, + util_format_name(vk_format_to_pipe_format(image->vk.format)), + fmt_list ? "present" : "missing"); + } + image->ubwc_enabled = false; + } + + if (format_list_reinterprets_r8g8_r16(tu_vk_format_to_pipe_format(image->vk.format), fmt_list) || + format_list_has_swaps(fmt_list)) { + image->force_linear_tile = true; + } + } + } + + if (TU_DEBUG(NOUBWC)) { + image->ubwc_enabled = false; + } + + return VK_SUCCESS; +} + VKAPI_ATTR VkResult VKAPI_CALL tu_CreateImage(VkDevice _device, const VkImageCreateInfo *pCreateInfo, @@ -745,7 +761,11 @@ tu_CreateImage(VkDevice _device, modifier = eci.drmFormatModifier; } - result = tu_image_init(device, image, pCreateInfo, modifier, + result = tu_image_init(device, image, pCreateInfo); + if (result != VK_SUCCESS) + goto fail; + + result = tu_image_update_layout(device, image, modifier, plane_layouts); if (result != VK_SUCCESS) goto fail; @@ -908,8 +928,8 @@ tu_GetDeviceImageMemoryRequirements( struct tu_image image = {0}; vk_image_init(&device->vk, &image.vk, pInfo->pCreateInfo); - tu_image_init(device, &image, pInfo->pCreateInfo, DRM_FORMAT_MOD_INVALID, - NULL); + tu_image_init(device, &image, pInfo->pCreateInfo); + tu_image_update_layout(device, &image, DRM_FORMAT_MOD_INVALID, NULL); tu_get_image_memory_requirements(device, &image, pMemoryRequirements); } @@ -974,8 +994,8 @@ tu_GetDeviceImageSubresourceLayoutKHR(VkDevice _device, struct tu_image image = {0}; vk_image_init(&device->vk, &image.vk, pInfo->pCreateInfo); - tu_image_init(device, &image, pInfo->pCreateInfo, DRM_FORMAT_MOD_INVALID, - NULL); + tu_image_init(device, &image, pInfo->pCreateInfo); + tu_image_update_layout(device, &image, DRM_FORMAT_MOD_INVALID, NULL); tu_get_image_subresource_layout(&image, pInfo->pSubresource, pLayout); } diff --git a/src/freedreno/vulkan/tu_image.h b/src/freedreno/vulkan/tu_image.h index cc8e5ac5dbe..3ade6f8852d 100644 --- a/src/freedreno/vulkan/tu_image.h +++ b/src/freedreno/vulkan/tu_image.h @@ -39,6 +39,9 @@ struct tu_image uint32_t lrz_offset; uint32_t lrz_fc_offset; uint32_t lrz_fc_size; + + bool ubwc_enabled; + bool force_linear_tile; }; VK_DEFINE_NONDISP_HANDLE_CASTS(tu_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE)