From 247d11d635d2999f2f508e2cb14e91cfc2d0ae9c Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Wed, 11 Dec 2024 11:27:28 -0500 Subject: [PATCH] tu: Allow UBWC with images with swapped formats. While we're here, refactor the logic to split out the mutable and pre-mutable cases since they are now very different. The special case for NV12 is now necessary to avoid test failures, but it was always necessary and we didn't notice it before because tests didn't specify a format list. Part-of: --- src/freedreno/vulkan/tu_image.cc | 94 +++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 26 deletions(-) diff --git a/src/freedreno/vulkan/tu_image.cc b/src/freedreno/vulkan/tu_image.cc index 423f98ecbca..4ccb16db4c0 100644 --- a/src/freedreno/vulkan/tu_image.cc +++ b/src/freedreno/vulkan/tu_image.cc @@ -624,6 +624,32 @@ tu_image_update_layout(struct tu_device *device, struct tu_image *image, } TU_GENX(tu_image_update_layout); +/* Return true if all formats in the format list can support UBWC. + */ +static bool +format_list_ubwc_possible(struct tu_device *dev, + const VkImageFormatListCreateInfo *fmt_list, + const VkImageCreateInfo *create_info) +{ + /* If there is no format list, we may have to assume that a + * UBWC-incompatible format may be used. + * TODO: limit based on compatiblity class + */ + if (!fmt_list || !fmt_list->viewFormatCount) + return false; + + for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) { + if (!ubwc_possible(dev, fmt_list->pViewFormats[i], + create_info->imageType, create_info->usage, + create_info->usage, dev->physical_device->info, + create_info->samples, create_info->mipLevels, + dev->use_z24uint_s8uint)) + return false; + } + + return true; +} + static VkResult tu_image_init(struct tu_device *device, struct tu_image *image, const VkImageCreateInfo *pCreateInfo) @@ -677,7 +703,6 @@ tu_image_init(struct tu_device *device, struct tu_image *image, pCreateInfo->mipLevels, device->use_z24uint_s8uint)) image->ubwc_enabled = false; - bool fmt_list_has_swaps = 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) @@ -688,49 +713,66 @@ tu_image_init(struct tu_device *device, struct tu_image *image, * - 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); - fmt_list_has_swaps = format_list_has_swaps(fmt_list); if (!tu6_mutable_format_list_ubwc_compatible(device->physical_device->info, fmt_list)) { bool mutable_ubwc_fc = device->physical_device->info->a7xx.ubwc_all_formats_compatible; - if (image->ubwc_enabled && !mutable_ubwc_fc) { - if (fmt_list && fmt_list->viewFormatCount == 2) { + + /* NV12 uses a special compression scheme for the Y channel which + * doesn't support reinterpretation. We have to fall back to linear + * always. + */ + if (pCreateInfo->format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) { + if (image->ubwc_enabled) { 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 " + "Disabling UBWC and tiling 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; - } - - bool r8g8_r16 = format_list_reinterprets_r8g8_r16(vk_format_to_pipe_format(image->vk.format), fmt_list); - - /* A750+ TODO: Correctly handle swaps when copying mutable images. - * We should be able to support UBWC for mutable images with swaps. - */ - if ((r8g8_r16 && !mutable_ubwc_fc) || fmt_list_has_swaps) { - image->ubwc_enabled = false; image->force_linear_tile = true; - } + } else if (!mutable_ubwc_fc) { + 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; + } - image->is_mutable = image->ubwc_enabled && mutable_ubwc_fc; + bool r8g8_r16 = format_list_reinterprets_r8g8_r16(vk_format_to_pipe_format(image->vk.format), fmt_list); + bool fmt_list_has_swaps = format_list_has_swaps(fmt_list); + + if (r8g8_r16 || fmt_list_has_swaps) { + image->ubwc_enabled = false; + image->force_linear_tile = true; + } + } else { + image->is_mutable = true; + if (!format_list_ubwc_possible(device, fmt_list, pCreateInfo)) + image->ubwc_enabled = false; + } } }