diff --git a/src/freedreno/fdl/fd6_layout.c b/src/freedreno/fdl/fd6_layout.c index 9fb7a8cefd6..f55ea19d7ea 100644 --- a/src/freedreno/fdl/fd6_layout.c +++ b/src/freedreno/fdl/fd6_layout.c @@ -175,6 +175,11 @@ fdl6_layout_image(struct fdl_layout *layout, const struct fd_dev_info *info, if (layout->ubwc && !info->props.has_ubwc_linear_mipmap_fallback) layout->tile_all = true; + if (layout->tile_mode != TILE6_LINEAR && + params->force_disable_linear_fallback) { + layout->tile_all = true; + } + /* in layer_first layout, the level (slice) contains just one * layer (since in fact the layer contains the slices) */ diff --git a/src/freedreno/fdl/freedreno_layout.h b/src/freedreno/fdl/freedreno_layout.h index 1e1814890de..f436069e110 100644 --- a/src/freedreno/fdl/freedreno_layout.h +++ b/src/freedreno/fdl/freedreno_layout.h @@ -109,6 +109,8 @@ struct fdl_image_params { * standard sparse tiling. */ bool sparse; + + bool force_disable_linear_fallback; }; /** diff --git a/src/freedreno/vulkan/tu_image.cc b/src/freedreno/vulkan/tu_image.cc index dc6c3868fbf..168b0eea455 100644 --- a/src/freedreno/vulkan/tu_image.cc +++ b/src/freedreno/vulkan/tu_image.cc @@ -475,6 +475,20 @@ format_list_has_swaps(const VkImageFormatListCreateInfo *fmt_list) return false; } +static bool +format_list_has_uncompressed_format( + const VkImageFormatListCreateInfo *fmt_list) +{ + if (!fmt_list || !fmt_list->viewFormatCount) + return true; + + for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) { + if (!vk_format_is_compressed(fmt_list->pViewFormats[i])) + return true; + } + return false; +} + template VkResult tu_image_update_layout(struct tu_device *device, struct tu_image *image, @@ -564,6 +578,7 @@ tu_image_update_layout(struct tu_device *device, struct tu_image *image, .is_mutable = image->is_mutable, .sparse = image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT, + .force_disable_linear_fallback = image->force_disable_linear_fallback, }; if (!fdl6_layout_image(layout, &device->physical_device->dev_info, @@ -780,6 +795,23 @@ tu_image_init(struct tu_device *device, struct tu_image *image, if (!format_list_ubwc_possible(device, fmt_list, pCreateInfo)) image->ubwc_enabled = false; } + + /* If the threshold of the linear mipmap fallback for compressed + * format is reached at a different mipmap level than the + * size-compatible non-compressed formats the image can be viewed as, + * then we have to disable the fallback. Otherwise, for some levels, + * texels would be read from the wrong locations due to the tiling + * mismatch. + * NOTE: Prop driver falls back to LINEAR in this case. + */ + if (!device->physical_device->info->props + .supports_linear_mipmap_threshold_in_blocks && + vk_format_is_compressed(image->vk.format) && + pCreateInfo->usage & + VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT && + format_list_has_uncompressed_format(fmt_list)) { + image->force_disable_linear_fallback = true; + } } } diff --git a/src/freedreno/vulkan/tu_image.h b/src/freedreno/vulkan/tu_image.h index ed47b89aca4..df4ce5b6088 100644 --- a/src/freedreno/vulkan/tu_image.h +++ b/src/freedreno/vulkan/tu_image.h @@ -58,6 +58,8 @@ struct tu_image bool ubwc_enabled; bool force_linear_tile; bool is_mutable; + /* Force to either use tiled layout or linear for all mip layers. */ + bool force_disable_linear_fallback; }; VK_DEFINE_NONDISP_HANDLE_CASTS(tu_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE)