nvk: Implement DRM format modifier queries

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24795>
This commit is contained in:
Faith Ekstrand 2024-02-13 15:04:53 -06:00 committed by Marge Bot
parent 4ad79bfef4
commit 224d9a514a
3 changed files with 142 additions and 15 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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,