turnip: Split tu_image_init to use layout setting logic separately

Signed-off-by: tarsin <yuanqingxiang233@163.com>
[rob: improve comments about modifier taking precedence over image
create flags, and fix bogus assert]

Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Roman Stratiienko <r.stratiienko@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29090>
This commit is contained in:
tarsin 2023-09-29 17:31:07 +08:00 committed by Marge Bot
parent ecd9ece9c1
commit 4b024a15f2
2 changed files with 130 additions and 107 deletions

View file

@ -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);
}

View file

@ -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)