anv/image: Add support for modifiers for WSI

This adds support for the modifiers portion of the WSI "extension".

Reviewed-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
Jason Ekstrand 2017-11-13 16:44:07 -08:00 committed by Daniel Stone
parent adca1e4a92
commit c757fd2852
4 changed files with 104 additions and 4 deletions

View File

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

View File

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

View File

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

View File

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