diff --git a/src/nouveau/vulkan/nvk_format.c b/src/nouveau/vulkan/nvk_format.c index beaeac898d4dc..35aeb8db52b79 100644 --- a/src/nouveau/vulkan/nvk_format.c +++ b/src/nouveau/vulkan/nvk_format.c @@ -161,9 +161,9 @@ nvk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormatFeatureFlags2 linear2, optimal2, buffer2; linear2 = nvk_get_image_format_features(pdevice, format, - VK_IMAGE_TILING_LINEAR); + VK_IMAGE_TILING_LINEAR, 0); optimal2 = nvk_get_image_format_features(pdevice, format, - VK_IMAGE_TILING_OPTIMAL); + VK_IMAGE_TILING_OPTIMAL, 0); buffer2 = nvk_get_buffer_format_features(pdevice, format); pFormatProperties->formatProperties = (VkFormatProperties) { @@ -182,6 +182,11 @@ nvk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, break; } + case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: + case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: + nvk_get_drm_format_modifier_properties_list(pdevice, format, ext); + break; + default: vk_debug_ignored_stype(ext->sType); break; diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index 07008201dd372..4031f1d33a331 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -12,6 +12,9 @@ #include "vk_enum_to_str.h" #include "vk_format.h" +#include "nil.h" +#include "vk_enum_defines.h" +#include "vk_format.h" #include "clb097.h" #include "clb197.h" @@ -19,10 +22,16 @@ static VkFormatFeatureFlags2 nvk_get_image_plane_format_features(struct nvk_physical_device *pdev, - VkFormat vk_format, VkImageTiling tiling) + VkFormat vk_format, VkImageTiling tiling, + uint64_t drm_format_mod) { VkFormatFeatureFlags2 features = 0; + if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && + drm_format_mod != DRM_FORMAT_MOD_LINEAR && + !fourcc_mod_is_vendor(drm_format_mod, NVIDIA)) + return 0; + enum pipe_format p_format = vk_format_to_pipe_format(vk_format); if (p_format == PIPE_FORMAT_NONE) return 0; @@ -84,12 +93,15 @@ nvk_get_image_plane_format_features(struct nvk_physical_device *pdev, VkFormatFeatureFlags2 nvk_get_image_format_features(struct nvk_physical_device *pdev, - VkFormat vk_format, VkImageTiling tiling) + VkFormat vk_format, VkImageTiling tiling, + uint64_t drm_format_mod) { const struct vk_format_ycbcr_info *ycbcr_info = vk_format_get_ycbcr_info(vk_format); - if (ycbcr_info == NULL) - return nvk_get_image_plane_format_features(pdev, vk_format, tiling); + if (ycbcr_info == NULL) { + return nvk_get_image_plane_format_features(pdev, vk_format, tiling, + drm_format_mod); + } /* For multi-plane, we get the feature flags of each plane separately, * then take their intersection as the overall format feature flags @@ -99,7 +111,7 @@ nvk_get_image_format_features(struct nvk_physical_device *pdev, for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) { const struct vk_format_ycbcr_plane *plane_info = &ycbcr_info->planes[plane]; features &= nvk_get_image_plane_format_features(pdev, plane_info->format, - tiling); + tiling, drm_format_mod); if (plane_info->denominator_scales[0] > 1 || plane_info->denominator_scales[1] > 1) cosited_chroma = true; @@ -143,6 +155,98 @@ nvk_get_image_format_features(struct nvk_physical_device *pdev, return features; } +void +nvk_get_drm_format_modifier_properties_list(struct nvk_physical_device *pdev, + VkFormat vk_format, + VkBaseOutStructure *ext) +{ + assert(ext->sType == VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT || + ext->sType == VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT); + + /* The two top-level data structures are the same. It's only when + * you get to walking the actual list of modifier properties that + * they differ. + */ + VkDrmFormatModifierPropertiesListEXT *p = (void *)ext; + + /* We don't support modifiers for YCbCr images */ + if (vk_format_get_ycbcr_info(vk_format) != NULL) { + p->drmFormatModifierCount = 0; + return; + } + + /* Check that we actually support the format so we don't try to query + * modifiers for formats NIL doesn't support. + */ + const VkFormatFeatureFlags2 tiled_features = + nvk_get_image_plane_format_features(pdev, vk_format, + VK_IMAGE_TILING_OPTIMAL, + DRM_FORMAT_MOD_INVALID); + if (tiled_features == 0) { + p->drmFormatModifierCount = 0; + return; + } + + uint64_t mods[NIL_MAX_DRM_FORMAT_MODS]; + size_t mod_count = NIL_MAX_DRM_FORMAT_MODS; + enum pipe_format p_format = vk_format_to_pipe_format(vk_format); + nil_drm_format_mods_for_format(&pdev->info, nil_format(p_format), + &mod_count, &mods); + if (mod_count == 0) { + p->drmFormatModifierCount = 0; + return; + } + + switch (ext->sType) { + case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: { + VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out, + p->pDrmFormatModifierProperties, + &p->drmFormatModifierCount); + + for (uint32_t i = 0; i < mod_count; i++) { + const VkFormatFeatureFlags2 features2 = + nvk_get_image_format_features(pdev, vk_format, + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, + mods[i]); + if (features2 != 0) { + vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mp) { + mp->drmFormatModifier = mods[i]; + mp->drmFormatModifierPlaneCount = 1; + mp->drmFormatModifierTilingFeatures = + vk_format_features2_to_features(features2); + } + } + } + break; + } + + case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: { + VkDrmFormatModifierPropertiesList2EXT *p2 = (void *)p; + VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierProperties2EXT, out, + p2->pDrmFormatModifierProperties, + &p2->drmFormatModifierCount); + + for (uint32_t i = 0; i < mod_count; i++) { + const VkFormatFeatureFlags2 features2 = + nvk_get_image_format_features(pdev, vk_format, + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, + mods[i]); + if (features2 != 0) { + vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT, &out, mp) { + mp->drmFormatModifier = mods[i]; + mp->drmFormatModifierPlaneCount = 1; + mp->drmFormatModifierTilingFeatures = features2; + } + } + } + break; + } + + default: + unreachable("Invalid structure type"); + } +} + static VkFormatFeatureFlags2 vk_image_usage_to_format_features(VkImageUsageFlagBits usage_flag) { @@ -182,6 +286,18 @@ nvk_image_max_dimension(const struct nv_device_info *info, } } +static uint64_t +get_explicit_drm_format_mod(const void *pNext) +{ + const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = + vk_find_struct_const(pNext, + PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT); + if (drm_format_mod_info) + return drm_format_mod_info->drmFormatModifier; + else + return DRM_FORMAT_MOD_INVALID; +} + VKAPI_ATTR VkResult VKAPI_CALL nvk_GetPhysicalDeviceImageFormatProperties2( VkPhysicalDevice physicalDevice, @@ -198,6 +314,8 @@ nvk_GetPhysicalDeviceImageFormatProperties2( memset(&pImageFormatProperties->imageFormatProperties, 0, sizeof(pImageFormatProperties->imageFormatProperties)); + uint64_t drm_format_mod = + get_explicit_drm_format_mod(pImageFormatInfo->pNext); const struct vk_format_ycbcr_info *ycbcr_info = vk_format_get_ycbcr_info(pImageFormatInfo->format); @@ -208,16 +326,18 @@ nvk_GetPhysicalDeviceImageFormatProperties2( VkFormatFeatureFlags2 features; if (ycbcr_info == NULL) { features = nvk_get_image_plane_format_features( - pdev, pImageFormatInfo->format, pImageFormatInfo->tiling); + pdev, pImageFormatInfo->format, pImageFormatInfo->tiling, + drm_format_mod); } else { features = ~0ull; assert(ycbcr_info->n_planes > 0); for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) { const VkFormat plane_format = ycbcr_info->planes[plane].format; features &= nvk_get_image_plane_format_features( - pdev, plane_format, pImageFormatInfo->tiling); + pdev, plane_format, pImageFormatInfo->tiling, drm_format_mod); } } + if (features == 0) return VK_ERROR_FORMAT_NOT_SUPPORTED; @@ -624,7 +744,7 @@ nvk_image_init(struct nvk_device *dev, struct nil_image_init_info nil_info = { .dim = vk_image_type_to_nil_dim(pCreateInfo->imageType), .format = nil_format(vk_format_to_pipe_format(format)), - .modifier = DRM_FORMAT_MOD_INVALID, + .modifier = image->vk.drm_format_mod, .extent_px = { .width = pCreateInfo->extent.width / width_scale, .height = pCreateInfo->extent.height / height_scale, diff --git a/src/nouveau/vulkan/nvk_image.h b/src/nouveau/vulkan/nvk_image.h index cca869266b449..7f86924b192ef 100644 --- a/src/nouveau/vulkan/nvk_image.h +++ b/src/nouveau/vulkan/nvk_image.h @@ -37,13 +37,15 @@ struct nvk_device_memory; struct nvk_physical_device; -static VkFormatFeatureFlags2 -nvk_get_image_plane_format_features(struct nvk_physical_device *pdev, - VkFormat vk_format, VkImageTiling tiling); - VkFormatFeatureFlags2 nvk_get_image_format_features(struct nvk_physical_device *pdevice, - VkFormat format, VkImageTiling tiling); + VkFormat format, VkImageTiling tiling, + uint64_t drm_format_mod); + +void +nvk_get_drm_format_modifier_properties_list(struct nvk_physical_device *pdev, + VkFormat vk_format, + VkBaseOutStructure *ext); uint32_t nvk_image_max_dimension(const struct nv_device_info *info,