From: Bas Nieuwenhuizen Date: Tue, 17 Nov 2020 04:10:20 +0000 (+0100) Subject: radv: Add image layout with drm format modifiers. X-Git-Tag: upstream/21.2.3~8572 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7f7da82dbb7839593f454d92e57b0aff15b65a07;p=platform%2Fupstream%2Fmesa.git radv: Add image layout with drm format modifiers. Half of it is passing the right modifier to ac_surface, the other half is applying the offset/strides. Reviewed-By: Chad Versace Part-of: --- diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index a7b2cdb..fad1f46 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -5323,7 +5323,8 @@ static VkResult radv_alloc_memory(struct radv_device *device, /* This gives a basic ability to import radeonsi images * that don't have DCC. This is not guaranteed by any * spec and can be removed after we support modifiers. */ - result = radv_image_create_layout(device, create_info, mem->image); + result = radv_image_create_layout(device, create_info, NULL, + mem->image); if (result != VK_SUCCESS) { device->ws->buffer_destroy(mem->bo); goto fail; diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c index 60934cb..6a0c667 100644 --- a/src/amd/vulkan/radv_image.c +++ b/src/amd/vulkan/radv_image.c @@ -1349,6 +1349,7 @@ radv_image_reset_layout(struct radv_image *image) VkResult radv_image_create_layout(struct radv_device *device, struct radv_image_create_info create_info, + const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info, struct radv_image *image) { /* Clear the pCreateInfo pointer so we catch issues in the delayed case when we test in the @@ -1360,11 +1361,14 @@ radv_image_create_layout(struct radv_device *device, if (result != VK_SUCCESS) return result; + assert(!mod_info || mod_info->drmFormatModifierPlaneCount == image->plane_count); + radv_image_reset_layout(image); for (unsigned plane = 0; plane < image->plane_count; ++plane) { struct ac_surf_info info = image_info; uint64_t offset; + unsigned stride; if (plane) { const struct vk_format_description *desc = vk_format_description(image->vk_format); @@ -1383,15 +1387,42 @@ radv_image_create_layout(struct radv_device *device, device->ws->surface_init(device->ws, &info, &image->planes[plane].surface); - if (!create_info.no_metadata_planes && image->plane_count == 1) + if (!create_info.no_metadata_planes && image->plane_count == 1 && + !mod_info) radv_image_alloc_single_sample_cmask(device, image, &image->planes[plane].surface); - offset = align(image->size, image->planes[plane].surface.alignment); - ac_surface_override_offset_stride(&device->physical_device->rad_info, - &image->planes[plane].surface, - image->info.levels, - offset, - 0); + if (mod_info) { + if (mod_info->pPlaneLayouts[plane].rowPitch % image->planes[plane].surface.bpe || + !mod_info->pPlaneLayouts[plane].rowPitch) + return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT; + + offset = mod_info->pPlaneLayouts[plane].offset; + stride = mod_info->pPlaneLayouts[plane].rowPitch / image->planes[plane].surface.bpe; + } else { + offset = align(image->size, image->planes[plane].surface.alignment); + stride = 0; /* 0 means no override */ + } + + if (!ac_surface_override_offset_stride(&device->physical_device->rad_info, + &image->planes[plane].surface, + image->info.levels, + offset, + stride)) + return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT; + + /* Validate DCC offsets in modifier layout. */ + if (image->plane_count == 1 && mod_info) { + unsigned mem_planes = ac_surface_get_nplanes(&image->planes[plane].surface); + if (mod_info->drmFormatModifierPlaneCount != mem_planes) + return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT; + + for (unsigned i = 1; i < mem_planes; ++i) { + if (ac_surface_get_plane_offset(device->physical_device->rad_info.chip_class, + &image->planes[plane].surface, i, 0) != + mod_info->pPlaneLayouts[i].offset) + return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT; + } + } image->size = MAX2(image->size, offset + image->planes[plane].surface.total_size); image->alignment = MAX2(image->alignment, image->planes[plane].surface.alignment); @@ -1405,6 +1436,8 @@ radv_image_create_layout(struct radv_device *device, radv_image_alloc_values(device, image); assert(image->planes[0].surface.surf_size); + assert(ac_modifier_has_dcc(image->planes[0].surface.modifier) == + radv_image_has_dcc(image)); return VK_SUCCESS; } @@ -1482,6 +1515,46 @@ radv_image_can_fast_clear(const struct radv_device *device, return true; } +static uint64_t +radv_select_modifier(const struct radv_device *dev, + VkFormat format, + const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list) +{ + const struct radv_physical_device *pdev = dev->physical_device; + unsigned mod_count; + + assert(mod_list->drmFormatModifierCount); + + /* We can allow everything here as it does not affect order and the application + * is only allowed to specify modifiers that we support. */ + const struct ac_modifier_options modifier_options = { + .dcc = true, + .dcc_retile = true, + }; + + ac_get_supported_modifiers(&pdev->rad_info, &modifier_options, + vk_format_to_pipe_format(format), &mod_count, NULL); + + uint64_t *mods = calloc(mod_count, sizeof(*mods)); + + /* If allocations fail, fall back to a dumber solution. */ + if (!mods) + return mod_list->pDrmFormatModifiers[0]; + + ac_get_supported_modifiers(&pdev->rad_info, &modifier_options, + vk_format_to_pipe_format(format), &mod_count, mods); + + for (unsigned i = 0; i < mod_count; ++i) { + for (uint32_t j = 0; j < mod_list->drmFormatModifierCount; ++j) { + if (mods[i] == mod_list->pDrmFormatModifiers[j]) { + free(mods); + return mod_list->pDrmFormatModifiers[j]; + } + } + } + unreachable("App specified an invalid modifier"); +} + VkResult radv_image_create(VkDevice _device, const struct radv_image_create_info *create_info, @@ -1490,9 +1563,14 @@ radv_image_create(VkDevice _device, { RADV_FROM_HANDLE(radv_device, device, _device); const VkImageCreateInfo *pCreateInfo = create_info->vk_info; + uint64_t modifier = DRM_FORMAT_MOD_INVALID; struct radv_image *image = NULL; VkFormat format = radv_select_android_external_format(pCreateInfo->pNext, pCreateInfo->format); + const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list = + vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); + const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod = + vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); const unsigned plane_count = vk_format_get_plane_count(format); @@ -1544,14 +1622,20 @@ radv_image_create(VkDevice _device, image->shareable = external_info; if (!vk_format_is_depth_or_stencil(format) && !image->shareable && - !(image->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT)) { + !(image->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) && + pCreateInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { image->info.surf_index = &device->image_mrt_offset_counter; } + if (mod_list) + modifier = radv_select_modifier(device, format, mod_list); + else if (explicit_mod) + modifier = explicit_mod->drmFormatModifier; + for (unsigned plane = 0; plane < image->plane_count; ++plane) { image->planes[plane].surface.flags = radv_get_surface_flags(device, image, plane, pCreateInfo, format); - image->planes[plane].surface.modifier = DRM_FORMAT_MOD_INVALID; + image->planes[plane].surface.modifier = modifier; } bool delay_layout = external_info && @@ -1563,7 +1647,7 @@ radv_image_create(VkDevice _device, return VK_SUCCESS; } - ASSERTED VkResult result = radv_image_create_layout(device, *create_info, image); + ASSERTED VkResult result = radv_image_create_layout(device, *create_info, explicit_mod, image); assert(result == VK_SUCCESS); if (image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) { diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index f28e616..56c281b 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -2175,6 +2175,7 @@ struct radv_image_create_info { VkResult radv_image_create_layout(struct radv_device *device, struct radv_image_create_info create_info, + const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info, struct radv_image *image); VkResult radv_image_create(VkDevice _device,