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