[Mesa-dev] [PATCH 13/16] anv/image: Add support for modifiers for WSI
Jason Ekstrand
jason at jlekstrand.net
Fri Feb 9 23:43:29 UTC 2018
This adds support for the modifiers portion of the WSI "extension".
---
src/intel/vulkan/anv_formats.c | 39 ++++++++++++++++++
src/intel/vulkan/anv_image.c | 93 +++++++++++++++++++++++++++++++++---------
src/intel/vulkan/anv_private.h | 6 +++
src/intel/vulkan/anv_wsi.c | 24 +++++++++--
src/vulkan/wsi/wsi_common.c | 9 ++--
5 files changed, 142 insertions(+), 29 deletions(-)
diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_formats.c
index 4075ae8..cd63879 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,39 @@ 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,
+ I915_FORMAT_MOD_Y_TILED_CCS,
+ };
+
+ 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 +711,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 355aff0..9bb0cad 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -508,6 +508,39 @@ 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;
+ case I915_FORMAT_MOD_Y_TILED_CCS: return 4;
+ 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 +557,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 +588,8 @@ anv_image_create(VkDevice _device,
image->tiling = pCreateInfo->tiling;
image->disjoint = pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR;
image->legacy_scanout = 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);
@@ -706,8 +747,13 @@ void anv_GetImageSubresourceLayout(
VkSubresourceLayout* layout)
{
ANV_FROM_HANDLE(anv_image, image, _image);
- const struct anv_surface *surface =
- get_surface(image, subresource->aspectMask);
+
+ const struct anv_surface *surface;
+ if (subresource->aspectMask == VK_IMAGE_ASPECT_PLANE_1_BIT_KHR &&
+ isl_drm_modifier_has_aux(image->drm_format_mod))
+ surface = &image->planes[0].aux_surface;
+ else
+ surface = get_surface(image, subresource->aspectMask);
assert(__builtin_popcount(subresource->aspectMask) == 1);
@@ -822,25 +868,20 @@ anv_layout_to_aux_usage(const struct gen_device_info * const devinfo,
}
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
- /* On SKL+, the render buffer can be decompressed by the presentation
- * engine. Support for this feature has not yet landed in the wider
- * ecosystem. TODO: Update this code when support lands.
- *
- * From the BDW PRM, Vol 7, Render Target Resolve:
- *
- * If the MCS is enabled on a non-multisampled render target, the
- * render target must be resolved before being used for other
- * purposes (display, texture, CPU lock) The clear value from
- * SURFACE_STATE is written into pixels in the render target
- * indicated as clear in the MCS.
- *
- * Pre-SKL, the render buffer must be resolved before being used for
- * presentation. We can infer that the auxiliary buffer is not used.
+ /* When handing the image off to the presentation engine, we need to
+ * ensure that things are properly resolved. For images with no
+ * modifier, we assume that they follow the old rules and always need
+ * a full resolve because the PE doesn't understand any form of
+ * compression. For images with modifiers, we use the aux usage from
+ * the modifier.
*/
- return ISL_AUX_USAGE_NONE;
+ const struct isl_drm_modifier_info *mod_info =
+ isl_drm_modifier_get_info(image->drm_format_mod);
+ return mod_info ? mod_info->aux_usage : ISL_AUX_USAGE_NONE;
+ }
/* Rendering Layouts */
@@ -920,8 +961,20 @@ anv_layout_to_fast_clear_type(const struct gen_device_info * const devinfo,
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
return ANV_FAST_CLEAR_ANY;
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- return ANV_FAST_CLEAR_NONE;
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
+ assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+
+ /* When handing the image off to the presentation engine, we need to
+ * ensure that things are properly resolved. For images with no
+ * modifier, we assume that they follow the old rules and always need
+ * a full resolve because the PE doesn't understand any form of
+ * compression. For images with modifiers, we use the value from the
+ * modifier.
+ */
+ const struct isl_drm_modifier_info *mod_info =
+ isl_drm_modifier_get_info(image->drm_format_mod);
+ return mod_info && mod_info->supports_clear_color;
+ }
default:
/* If the image has CCS_E enabled all the time then we can use
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 3b12ead..c4bf2d0 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2395,6 +2395,12 @@ struct anv_image {
/** True if this is a legacy scanout image */
bool legacy_scanout;
+ /**
+ * 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 6082c3d..8913a80 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
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index 4b4af78..771fbbd 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -367,13 +367,9 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
if (result != VK_SUCCESS)
goto fail;
- if (wsi->supports_modifiers)
+ if (image_modifier_count > 0) {
image->drm_modifier = wsi->image_get_modifier(image->image);
- else
- image->drm_modifier = DRM_FORMAT_MOD_INVALID;
- VkSubresourceLayout image_layout;
- if (num_modifier_lists > 0) {
for (uint32_t j = 0; j < modifier_prop_count; j++) {
if (modifier_props[j].modifier == image->drm_modifier) {
image->num_planes = modifier_props[j].modifier_plane_count;
@@ -387,6 +383,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
.mipLevel = 0,
.arrayLayer = 0,
};
+ VkSubresourceLayout image_layout;
wsi->GetImageSubresourceLayout(chain->device, image->image,
&image_subresource, &image_layout);
image->sizes[p] = image_layout.size;
@@ -410,9 +407,11 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
.mipLevel = 0,
.arrayLayer = 0,
};
+ VkSubresourceLayout image_layout;
wsi->GetImageSubresourceLayout(chain->device, image->image,
&image_subresource, &image_layout);
+ image->drm_modifier = DRM_FORMAT_MOD_INVALID;
image->num_planes = 1;
image->sizes[0] = reqs.size;
image->row_pitches[0] = image_layout.rowPitch;
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list