From: Jason Ekstrand Date: Tue, 14 Nov 2017 00:44:07 +0000 (-0800) Subject: anv/image: Add support for modifiers for WSI X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c757fd2852849a5c8db92032ff66b6bbe5073f1c;p=mesa.git anv/image: Add support for modifiers for WSI This adds support for the modifiers portion of the WSI "extension". Reviewed-by: Daniel Stone --- diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_formats.c index 4075ae8e620..9c52ad5acbd 100644 --- a/src/intel/vulkan/anv_formats.c +++ b/src/intel/vulkan/anv_formats.c @@ -22,6 +22,7 @@ */ #include "anv_private.h" +#include "drm_fourcc.h" #include "vk_enum_to_str.h" #include "vk_format_info.h" #include "vk_util.h" @@ -651,6 +652,38 @@ get_buffer_format_features(const struct gen_device_info *devinfo, return flags; } +static void +get_wsi_format_modifier_properties_list(const struct anv_physical_device *physical_device, + VkFormat vk_format, + struct wsi_format_modifier_properties_list *list) +{ + const struct anv_format *anv_format = anv_get_format(vk_format); + + VK_OUTARRAY_MAKE(out, list->modifier_properties, &list->modifier_count); + + /* This is a simplified list where all the modifiers are available */ + assert(vk_format == VK_FORMAT_B8G8R8_SRGB || + vk_format == VK_FORMAT_B8G8R8_UNORM || + vk_format == VK_FORMAT_B8G8R8A8_SRGB || + vk_format == VK_FORMAT_B8G8R8A8_UNORM); + + uint64_t modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + I915_FORMAT_MOD_X_TILED, + I915_FORMAT_MOD_Y_TILED, + }; + + for (uint32_t i = 0; i < ARRAY_SIZE(modifiers); i++) { + vk_outarray_append(&out, mod_props) { + mod_props->modifier = modifiers[i]; + if (isl_drm_modifier_has_aux(modifiers[i])) + mod_props->modifier_plane_count = 2; + else + mod_props->modifier_plane_count = anv_format->n_planes; + } + } +} + void anv_GetPhysicalDeviceFormatProperties( VkPhysicalDevice physicalDevice, VkFormat vk_format, @@ -677,11 +710,16 @@ void anv_GetPhysicalDeviceFormatProperties2KHR( VkFormat format, VkFormatProperties2KHR* pFormatProperties) { + ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice); anv_GetPhysicalDeviceFormatProperties(physicalDevice, format, &pFormatProperties->formatProperties); vk_foreach_struct(ext, pFormatProperties->pNext) { switch (ext->sType) { + case VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA: + get_wsi_format_modifier_properties_list(physical_device, format, + (void *)ext); + break; default: anv_debug_ignored_stype(ext->sType); break; diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index c3d1810cee8..a2bae7b3827 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -508,6 +508,38 @@ make_surface(const struct anv_device *dev, return VK_SUCCESS; } +static uint32_t +score_drm_format_mod(uint64_t modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: return 1; + case I915_FORMAT_MOD_X_TILED: return 2; + case I915_FORMAT_MOD_Y_TILED: return 3; + default: unreachable("bad DRM format modifier"); + } +} + +static const struct isl_drm_modifier_info * +choose_drm_format_mod(const struct anv_physical_device *device, + uint32_t modifier_count, const uint64_t *modifiers) +{ + uint64_t best_mod = UINT64_MAX; + uint32_t best_score = 0; + + for (uint32_t i = 0; i < modifier_count; ++i) { + uint32_t score = score_drm_format_mod(modifiers[i]); + if (score > best_score) { + best_mod = modifiers[i]; + best_score = score; + } + } + + if (best_score > 0) + return isl_drm_modifier_get_info(best_mod); + else + return NULL; +} + VkResult anv_image_create(VkDevice _device, const struct anv_image_create_info *create_info, @@ -524,6 +556,12 @@ anv_image_create(VkDevice _device, const struct wsi_image_create_info *wsi_info = vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA); + if (wsi_info && wsi_info->modifier_count > 0) { + isl_mod_info = choose_drm_format_mod(&device->instance->physicalDevice, + wsi_info->modifier_count, + wsi_info->modifiers); + assert(isl_mod_info); + } anv_assert(pCreateInfo->mipLevels > 0); anv_assert(pCreateInfo->arrayLayers > 0); @@ -549,6 +587,8 @@ anv_image_create(VkDevice _device, image->tiling = pCreateInfo->tiling; image->disjoint = pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR; image->needs_set_tiling = wsi_info && wsi_info->scanout; + image->drm_format_mod = isl_mod_info ? isl_mod_info->modifier : + DRM_FORMAT_MOD_INVALID; const struct anv_format *format = anv_get_format(image->vk_format); assert(format != NULL); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 3d5259794bc..104b28ee5db 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2412,6 +2412,12 @@ struct anv_image { */ bool needs_set_tiling; + /** + * Must be DRM_FORMAT_MOD_INVALID unless tiling is + * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. + */ + uint64_t drm_format_mod; + VkDeviceSize size; uint32_t alignment; diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c index 6082c3dd093..8913a8022c4 100644 --- a/src/intel/vulkan/anv_wsi.c +++ b/src/intel/vulkan/anv_wsi.c @@ -33,13 +33,29 @@ anv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName) return anv_lookup_entrypoint(&physical_device->info, pName); } +static uint64_t +anv_wsi_image_get_modifier(VkImage _image) +{ + ANV_FROM_HANDLE(anv_image, image, _image); + return image->drm_format_mod; +} + VkResult anv_init_wsi(struct anv_physical_device *physical_device) { - return wsi_device_init(&physical_device->wsi_device, - anv_physical_device_to_handle(physical_device), - anv_wsi_proc_addr, - &physical_device->instance->alloc); + VkResult result; + + result = wsi_device_init(&physical_device->wsi_device, + anv_physical_device_to_handle(physical_device), + anv_wsi_proc_addr, + &physical_device->instance->alloc); + if (result != VK_SUCCESS) + return result; + + physical_device->wsi_device.supports_modifiers = true; + physical_device->wsi_device.image_get_modifier = anv_wsi_image_get_modifier; + + return VK_SUCCESS; } void