Mesa (master): radv: Add format modifier format queries.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Feb 2 01:01:33 UTC 2021


Module: Mesa
Branch: master
Commit: 6c83e3ea98b7e2c8972e9897c5971f78c69a7138
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6c83e3ea98b7e2c8972e9897c5971f78c69a7138

Author: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Date:   Mon Nov 16 04:00:29 2020 +0100

radv: Add format modifier format queries.

Reviewed-By: Chad Versace <chad at kiwitree.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7667>

---

 src/amd/vulkan/radv_formats.c | 217 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 208 insertions(+), 9 deletions(-)

diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c
index 25d147adfe3..450846f76dd 100644
--- a/src/amd/vulkan/radv_formats.c
+++ b/src/amd/vulkan/radv_formats.c
@@ -23,16 +23,19 @@
  */
 
 #include "radv_private.h"
+#include "radv_debug.h"
 
 #include "vk_format.h"
 #include "sid.h"
 
 #include "vk_util.h"
 
+#include "drm-uapi/drm_fourcc.h"
 #include "util/half_float.h"
 #include "util/format_srgb.h"
 #include "util/format_r11g11b10f.h"
 #include "util/format_rgb9e5.h"
+#include "vulkan/util/vk_format.h"
 
 uint32_t radv_translate_buffer_dataformat(const struct vk_format_description *desc,
 					  int first_non_void)
@@ -1119,6 +1122,167 @@ void radv_GetPhysicalDeviceFormatProperties(
 						   pFormatProperties);
 }
 
+static const struct ac_modifier_options radv_modifier_options = {
+	.dcc = false,
+	.dcc_retile = false,
+};
+
+static VkFormatFeatureFlags
+radv_get_modifier_flags(struct radv_physical_device *dev,
+                        VkFormat format, uint64_t modifier,
+                        const VkFormatProperties *props)
+{
+	VkFormatFeatureFlags features;
+
+	if (vk_format_is_compressed(format) || vk_format_is_depth_or_stencil(format))
+		return 0;
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		features = props->linearTilingFeatures;
+	else
+		features = props->optimalTilingFeatures;
+
+	if (modifier != DRM_FORMAT_MOD_LINEAR && vk_format_get_plane_count(format) > 1)
+		return 0;
+
+	if (ac_modifier_has_dcc(modifier)) {
+		features &= ~VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
+
+		if (dev->instance->debug_flags & RADV_DEBUG_NO_DCC)
+			return 0;
+	}
+
+	return features;
+}
+
+static void radv_list_drm_format_modifiers(struct radv_physical_device *dev,
+                                           VkFormat format,
+                                           VkFormatProperties2 *pFormatProperties)
+{
+	VkDrmFormatModifierPropertiesListEXT *mod_list =
+		vk_find_struct(pFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
+	unsigned mod_count;
+
+	if (!mod_list)
+		return;
+
+	if (vk_format_is_compressed(format) || vk_format_is_depth_or_stencil(format)) {
+		mod_list->drmFormatModifierCount = 0;
+		return;
+	}
+
+	ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,
+	                           vk_format_to_pipe_format(format), &mod_count, NULL);
+	if (!mod_list->pDrmFormatModifierProperties) {
+		mod_list->drmFormatModifierCount = mod_count;
+		return;
+	}
+
+	mod_count = MIN2(mod_count, mod_list->drmFormatModifierCount);
+
+	uint64_t *mods = malloc(mod_count * sizeof(uint64_t));
+	if (!mods) {
+		/* We can't return an error here ... */
+		mod_list->drmFormatModifierCount = 0;
+		return;
+	}
+	ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,
+	                           vk_format_to_pipe_format(format), &mod_count, mods);
+
+	mod_list->drmFormatModifierCount = 0;
+	for (unsigned i = 0; i < mod_count; ++i) {
+		VkFormatFeatureFlags features =
+			radv_get_modifier_flags(dev, format, mods[i], &pFormatProperties->formatProperties);
+		unsigned planes = vk_format_get_plane_count(format);
+		if (planes == 1) {
+			if (ac_modifier_has_dcc_retile(mods[i]))
+				planes = 3;
+			else if (ac_modifier_has_dcc(mods[i]))
+				planes = 2;
+		}
+
+		if (!features)
+			continue;
+
+		mod_list->pDrmFormatModifierProperties[mod_list->drmFormatModifierCount].drmFormatModifier = mods[i];
+		mod_list->pDrmFormatModifierProperties[mod_list->drmFormatModifierCount].drmFormatModifierPlaneCount = planes;
+		mod_list->pDrmFormatModifierProperties[mod_list->drmFormatModifierCount].drmFormatModifierTilingFeatures = features;
+
+		++mod_list->drmFormatModifierCount;
+	}
+
+	free(mods);
+}
+
+
+static VkResult radv_check_modifier_support(struct radv_physical_device *dev,
+                                       const VkPhysicalDeviceImageFormatInfo2 *info,
+                                       VkImageFormatProperties *props,
+                                       VkFormat format,
+                                       uint64_t modifier)
+{
+	if (info->type != VK_IMAGE_TYPE_2D)
+		return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+	/* We did not add modifiers for sparse textures. */
+	if (info->flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
+	                   VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |
+	                   VK_IMAGE_CREATE_SPARSE_ALIASED_BIT))
+		return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+	/*
+	 * Need to check the modifier is supported in general:
+	 * "If the drmFormatModifier is incompatible with the parameters specified
+	 * in VkPhysicalDeviceImageFormatInfo2 and its pNext chain, then
+	 * vkGetPhysicalDeviceImageFormatProperties2 returns VK_ERROR_FORMAT_NOT_SUPPORTED.
+	 * The implementation must support the query of any drmFormatModifier,
+	 * including unknown and invalid modifier values."
+	 */
+	VkDrmFormatModifierPropertiesListEXT mod_list = {
+		.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
+	};
+
+	VkFormatProperties2 format_props2 = {
+		.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+		.pNext = &mod_list
+	};
+
+	radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(dev), format,  &format_props2);
+
+	if (!mod_list.drmFormatModifierCount)
+		return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+	mod_list.pDrmFormatModifierProperties = calloc(mod_list.drmFormatModifierCount, sizeof(*mod_list.pDrmFormatModifierProperties));
+	if (!mod_list.pDrmFormatModifierProperties)
+		return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+	radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(dev), format,  &format_props2);
+
+	bool found = false;
+	for (uint32_t i = 0; i < mod_list.drmFormatModifierCount && !found; ++i)
+		if (mod_list.pDrmFormatModifierProperties[i].drmFormatModifier == modifier)
+			found = true;
+
+	free(mod_list.pDrmFormatModifierProperties);
+
+	if (!found)
+		return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+	if (ac_modifier_has_dcc(modifier) &&
+	    !radv_are_formats_dcc_compatible(dev, info->pNext, format, info->flags))
+		return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+	/* We can expand this as needed and implemented but there is not much demand
+	 * for more. */
+	if (ac_modifier_has_dcc(modifier)) {
+		props->maxMipLevels = 1;
+		props->maxArrayLayers = 1;
+	}
+	/* We don't support MSAA for modifiers */
+	props->sampleCounts &= VK_SAMPLE_COUNT_1_BIT;
+	return VK_SUCCESS;
+}
+
 void radv_GetPhysicalDeviceFormatProperties2(
 	VkPhysicalDevice                            physicalDevice,
 	VkFormat                                    format,
@@ -1129,6 +1293,8 @@ void radv_GetPhysicalDeviceFormatProperties2(
 	radv_physical_device_get_format_properties(physical_device,
 						   format,
 						   &pFormatProperties->formatProperties);
+
+	radv_list_drm_format_modifiers(physical_device, format, pFormatProperties);
 }
 
 static VkResult radv_get_image_format_properties(struct radv_physical_device *physical_device,
@@ -1145,13 +1311,26 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph
 	VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
 	const struct vk_format_description *desc = vk_format_description(format);
 	enum chip_class chip_class = physical_device->rad_info.chip_class;
+	VkImageTiling tiling = info->tiling;
+	const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *mod_info =
+		vk_find_struct_const(info->pNext, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT);
+	VkResult result = VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+	if (mod_info) {
+		tiling = mod_info->drmFormatModifier == DRM_FORMAT_MOD_LINEAR ?
+			VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
+	}
 
 	radv_physical_device_get_format_properties(physical_device, format,
 						   &format_props);
-	if (info->tiling == VK_IMAGE_TILING_LINEAR) {
+	if (tiling == VK_IMAGE_TILING_LINEAR) {
 		format_feature_flags = format_props.linearTilingFeatures;
-	} else if (info->tiling == VK_IMAGE_TILING_OPTIMAL) {
+	} else if (tiling == VK_IMAGE_TILING_OPTIMAL) {
 		format_feature_flags = format_props.optimalTilingFeatures;
+	} else if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
+		format_feature_flags = radv_get_modifier_flags(physical_device, format,
+		                                               mod_info->drmFormatModifier,
+		                                               &format_props);
 	} else {
 		unreachable("bad VkImageTiling");
 	}
@@ -1200,7 +1379,7 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph
 		maxArraySize = 1;
 	}
 
-	if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
+	if (tiling == VK_IMAGE_TILING_OPTIMAL &&
 	    info->type == VK_IMAGE_TYPE_2D &&
 	    (format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
 				     VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
@@ -1208,7 +1387,7 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph
 		sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT;
 	}
 
-	if (info->tiling == VK_IMAGE_TILING_LINEAR &&
+	if (tiling == VK_IMAGE_TILING_LINEAR &&
 	    (format == VK_FORMAT_R32G32B32_SFLOAT ||
 	     format == VK_FORMAT_R32G32B32_SINT ||
 	     format == VK_FORMAT_R32G32B32_UINT)) {
@@ -1306,6 +1485,14 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph
 		.maxResourceSize = UINT32_MAX,
 	};
 
+	if (mod_info) {
+		result = radv_check_modifier_support(physical_device, info,
+		                                     pImageFormatProperties,
+		                                     format, mod_info->drmFormatModifier);
+		if (result != VK_SUCCESS)
+			goto unsupported;
+	}
+
 	return VK_SUCCESS;
 unsupported:
 	*pImageFormatProperties = (VkImageFormatProperties) {
@@ -1316,7 +1503,7 @@ unsupported:
 		.maxResourceSize = 0,
 	};
 
-	return VK_ERROR_FORMAT_NOT_SUPPORTED;
+	return result;
 }
 
 VkResult radv_GetPhysicalDeviceImageFormatProperties(
@@ -1359,16 +1546,28 @@ get_external_image_format_properties(struct radv_physical_device *physical_devic
 		return;
 
 	switch (handleType) {
-	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
 	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
+		if (pImageFormatInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+			break;
+
+		switch (pImageFormatInfo->type) {
+		case VK_IMAGE_TYPE_2D:
+			flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
+
+			compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+			break;
+		default:
+			break;
+		}
+		break;
+	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
 		switch (pImageFormatInfo->type) {
 		case VK_IMAGE_TYPE_2D:
-			flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
+			flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
 			if (pImageFormatInfo->tiling != VK_IMAGE_TILING_LINEAR)
 				flags |= VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT;
 
-			compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
-						      VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
+			compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
 			break;
 		default:
 			break;



More information about the mesa-commit mailing list