Commit d5d11b9d authored by chadversary's avatar chadversary

RFC: anv: Support VkDrmFormatModifierPropertiesListEXT

Incremental implementation of VK_EXT_image_drm_format_modifier.
parent 4b37d18c
......@@ -21,6 +21,8 @@
* IN THE SOFTWARE.
*/
#include <drm_fourcc.h>
#include "anv_private.h"
#include "drm_fourcc.h"
#include "vk_enum_to_str.h"
......@@ -426,6 +428,9 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
return unsupported;
if (aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
return unsupported;
assert(vk_format_aspects(vk_format) &
(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
return plane_format;
......@@ -436,6 +441,18 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
const struct isl_format_layout *isl_layout =
isl_format_get_layout(plane_format.isl_format);
/* For VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, the image's driver-internal
* format must be the user-facing VkFormat. Modifying the VkFormat in any
* way, including swizzling, is illegal.
*/
/* For now, for no reason other than FUD, we decline to support texture
* compression with modifiers.
*/
if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
isl_layout->txc != ISL_TXC_NONE)
return unsupported;
if (tiling == VK_IMAGE_TILING_OPTIMAL &&
!util_is_power_of_two_or_zero(isl_layout->bpb)) {
/* Tiled formats *must* be power-of-two because we need up upload
......@@ -457,7 +474,8 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
/* The B4G4R4A4 format isn't available prior to Broadwell so we have to fall
* back to a format with a more complex swizzle.
*/
if (vk_format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 && devinfo->gen < 8) {
if (tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
vk_format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 && devinfo->gen < 8) {
plane_format.isl_format = ISL_FORMAT_B4G4R4A4_UNORM;
plane_format.swizzle = ISL_SWIZZLE(GREEN, RED, ALPHA, BLUE);
}
......@@ -467,21 +485,29 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
// Format capabilities
/**
* Parameter drm_format_mod must be DRM_FORMAT_MOD_INVALID unless vk_tiling is
* VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
*/
static VkFormatFeatureFlags
get_image_format_features(const struct gen_device_info *devinfo,
VkFormat vk_format,
const struct anv_format *anv_format,
VkImageTiling vk_tiling)
VkImageTiling vk_tiling,
uint64_t drm_format_mod)
{
VkFormatFeatureFlags flags = 0;
if (vk_tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
assert(drm_format_mod == DRM_FORMAT_MOD_INVALID);
if (anv_format == NULL)
return 0;
const VkImageAspectFlags aspects = vk_format_aspects(vk_format);
if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
if (vk_tiling == VK_IMAGE_TILING_LINEAR)
if (vk_tiling != VK_IMAGE_TILING_OPTIMAL)
return 0;
flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
......@@ -507,6 +533,17 @@ get_image_format_features(const struct gen_device_info *devinfo,
if (plane_format.isl_format == ISL_FORMAT_UNSUPPORTED)
return 0;
const struct isl_format_layout *isl_layout =
isl_format_get_layout(plane_format.isl_format);
if (vk_tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
assert(isl_layout->txc == ISL_TXC_NONE);
/* For VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, the base format and
* non-base format must be the same, because the image's driver-internal
* format must be the user-facing VkFormat. Modifying the VkFormat in any
* way, including swizzling, is illegal.
*/
struct anv_format_plane base_plane_format = plane_format;
if (vk_tiling == VK_IMAGE_TILING_OPTIMAL) {
base_plane_format = anv_get_format_plane(devinfo, vk_format,
......@@ -517,8 +554,8 @@ get_image_format_features(const struct gen_device_info *devinfo,
enum isl_format base_isl_format = base_plane_format.isl_format;
/* ASTC textures must be in Y-tiled memory */
if (vk_tiling == VK_IMAGE_TILING_LINEAR &&
isl_format_get_layout(plane_format.isl_format)->txc == ISL_TXC_ASTC)
if (vk_tiling != VK_IMAGE_TILING_OPTIMAL &&
isl_layout->txc == ISL_TXC_ASTC)
return 0;
if (isl_format_supports_sampling(devinfo, plane_format.isl_format)) {
......@@ -576,6 +613,11 @@ get_image_format_features(const struct gen_device_info *devinfo,
}
if (anv_format->can_ycbcr) {
if (vk_tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
/* FINISHME(chadv): Support YUV with DRM format modifiers. */
return 0;
}
/* The sampler doesn't have support for mid point when it handles YUV on
* its own.
*/
......@@ -615,6 +657,24 @@ get_image_format_features(const struct gen_device_info *devinfo,
flags &= ~disallowed_ycbcr_image_features;
}
if (vk_tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
const struct isl_drm_modifier_info *mod_info =
isl_drm_modifier_get_info(drm_format_mod);
if (mod_info->aux_usage == ISL_AUX_USAGE_CCS_E) {
/* CCS Modifiers can only handle a single plane because the we use
* the second plane for the CCS.
*/
if (anv_format->n_planes > 1)
return 0;
/* If we have a CCS_E modifier, we must support CCS_E */
if (!isl_format_supports_ccs_e(devinfo,
anv_format->planes[0].isl_format))
return 0;
}
}
return flags;
}
......@@ -699,6 +759,69 @@ get_wsi_format_modifier_properties_list(const struct anv_physical_device *physic
}
}
/**
* Fill the VkDrmFormatModifierPropertiesEXT struct if the VkFormat supports
* the DRM format modifier, and return true. On failure, the output struct
* has undefined content.
*/
static bool
get_drm_format_modifier_properties(const struct anv_physical_device *physical_device,
VkFormat vk_format,
const struct anv_format *anv_format,
uint64_t drm_format_mod,
VkDrmFormatModifierPropertiesEXT *props)
{
const struct gen_device_info *devinfo = &physical_device->info;
VkFormatFeatureFlags features =
get_image_format_features(devinfo, vk_format, anv_format,
VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
drm_format_mod);
if (features == 0)
return false;
uint32_t plane_count = anv_format->n_planes;
if (isl_drm_modifier_has_aux(drm_format_mod))
plane_count++;
*props = (VkDrmFormatModifierPropertiesEXT) {
.drmFormatModifier = drm_format_mod,
.drmFormatModifierPlaneCount = plane_count,
.drmFormatModifierTilingFeatures = features,
};
return true;
}
static void
get_drm_format_modifier_properties_list(const struct anv_physical_device *physical_device,
VkFormat vk_format,
VkDrmFormatModifierPropertiesListEXT *drm_list)
{
const struct anv_format *anv_format = anv_get_format(vk_format);
VK_OUTARRAY_MAKE(out, drm_list->pDrmFormatModifierProperties,
&drm_list->drmFormatModifierCount);
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++) {
VkDrmFormatModifierPropertiesEXT tmp_props;
if (get_drm_format_modifier_properties(physical_device, vk_format,
anv_format, modifiers[i],
&tmp_props)) {
vk_outarray_append(&out, drm_props) {
*drm_props = tmp_props;
}
}
}
}
void anv_GetPhysicalDeviceFormatProperties(
VkPhysicalDevice physicalDevice,
VkFormat vk_format,
......@@ -711,10 +834,12 @@ void anv_GetPhysicalDeviceFormatProperties(
*pFormatProperties = (VkFormatProperties) {
.linearTilingFeatures =
get_image_format_features(devinfo, vk_format, anv_format,
VK_IMAGE_TILING_LINEAR),
VK_IMAGE_TILING_LINEAR,
DRM_FORMAT_MOD_INVALID),
.optimalTilingFeatures =
get_image_format_features(devinfo, vk_format, anv_format,
VK_IMAGE_TILING_OPTIMAL),
VK_IMAGE_TILING_OPTIMAL,
DRM_FORMAT_MOD_INVALID),
.bufferFeatures =
get_buffer_format_features(devinfo, vk_format, anv_format),
};
......@@ -736,6 +861,10 @@ void anv_GetPhysicalDeviceFormatProperties2(
get_wsi_format_modifier_properties_list(physical_device, format,
(void *)ext);
break;
case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT:
get_drm_format_modifier_properties_list(physical_device, format,
(VkDrmFormatModifierPropertiesListEXT *)ext);
break;
default:
anv_debug_ignored_stype(ext->sType);
break;
......@@ -750,7 +879,6 @@ anv_get_image_format_properties(
VkImageFormatProperties *pImageFormatProperties,
VkSamplerYcbcrConversionImageFormatPropertiesKHR *pYcbcrImageFormatProperties)
{
VkFormatFeatureFlags format_feature_flags;
VkExtent3D maxExtent;
uint32_t maxMipLevels;
uint32_t maxArraySize;
......@@ -761,8 +889,9 @@ anv_get_image_format_properties(
if (format == NULL)
goto unsupported;
format_feature_flags = get_image_format_features(devinfo, info->format,
format, info->tiling);
VkFormatFeatureFlags format_feature_flags =
get_image_format_features(devinfo, info->format, format, info->tiling,
DRM_FORMAT_MOD_INVALID);
switch (info->type) {
default:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment