1 /*
2 * Copyright 2024 Valve Corporation
3 * Copyright 2024 Alyssa Rosenzweig
4 * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5 * Copyright 2024 Valve Corporation
6 * Copyright 2024 Alyssa Rosenzweig
7 * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
8 * SPDX-License-Identifier: MIT
9 */
10 #include "drm-uapi/drm_fourcc.h"
11 #include "vulkan/vulkan_core.h"
12
13 #include "hk_buffer_view.h"
14 #include "hk_entrypoints.h"
15 #include "hk_image.h"
16 #include "hk_physical_device.h"
17
18 #include "vk_enum_defines.h"
19 #include "vk_format.h"
20
21 uint64_t agx_best_modifiers[] = {
22 DRM_FORMAT_MOD_APPLE_TWIDDLED_COMPRESSED,
23 DRM_FORMAT_MOD_APPLE_TWIDDLED,
24 DRM_FORMAT_MOD_LINEAR,
25 };
26
27 static VkFormatFeatureFlags2
hk_modifier_features(const struct agx_device * dev,uint64_t mod,VkFormat vk_format,const VkFormatProperties * props)28 hk_modifier_features(const struct agx_device *dev, uint64_t mod,
29 VkFormat vk_format, const VkFormatProperties *props)
30 {
31 /* There's no corresponding fourcc, so don't advertise modifiers */
32 if (vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32 ||
33 vk_format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
34 return 0;
35 }
36
37 /* Don't advertise compression for the uncompressable */
38 if (mod == DRM_FORMAT_MOD_APPLE_TWIDDLED_COMPRESSED &&
39 !hk_can_compress_format(dev, vk_format))
40 return 0;
41
42 if (mod == DRM_FORMAT_MOD_LINEAR)
43 return props->linearTilingFeatures;
44 else
45 return props->optimalTilingFeatures;
46 }
47
48 static void
get_drm_format_modifier_properties_list(const struct hk_physical_device * physical_device,VkFormat vk_format,VkDrmFormatModifierPropertiesListEXT * list,const VkFormatProperties * props)49 get_drm_format_modifier_properties_list(
50 const struct hk_physical_device *physical_device, VkFormat vk_format,
51 VkDrmFormatModifierPropertiesListEXT *list, const VkFormatProperties *props)
52 {
53 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
54 list->pDrmFormatModifierProperties,
55 &list->drmFormatModifierCount);
56
57 for (unsigned i = 0; i < ARRAY_SIZE(agx_best_modifiers); ++i) {
58 uint64_t mod = agx_best_modifiers[i];
59 VkFormatFeatureFlags2 flags =
60 hk_modifier_features(&physical_device->dev, mod, vk_format, props);
61
62 if (!flags)
63 continue;
64
65 vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out,
66 out_props)
67 {
68 *out_props = (VkDrmFormatModifierPropertiesEXT){
69 .drmFormatModifier = mod,
70 .drmFormatModifierPlaneCount = 1 /* no planar mods */,
71 .drmFormatModifierTilingFeatures = flags,
72 };
73 };
74 }
75 }
76
77 static void
get_drm_format_modifier_properties_list_2(const struct hk_physical_device * physical_device,VkFormat vk_format,VkDrmFormatModifierPropertiesList2EXT * list,const VkFormatProperties * props)78 get_drm_format_modifier_properties_list_2(
79 const struct hk_physical_device *physical_device, VkFormat vk_format,
80 VkDrmFormatModifierPropertiesList2EXT *list, const VkFormatProperties *props)
81 {
82 VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierProperties2EXT, out,
83 list->pDrmFormatModifierProperties,
84 &list->drmFormatModifierCount);
85
86 for (unsigned i = 0; i < ARRAY_SIZE(agx_best_modifiers); ++i) {
87 uint64_t mod = agx_best_modifiers[i];
88 VkFormatFeatureFlags2 flags =
89 hk_modifier_features(&physical_device->dev, mod, vk_format, props);
90
91 if (!flags)
92 continue;
93
94 vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT, &out,
95 out_props)
96 {
97 *out_props = (VkDrmFormatModifierProperties2EXT){
98 .drmFormatModifier = mod,
99 .drmFormatModifierPlaneCount = 1, /* no planar mods */
100 .drmFormatModifierTilingFeatures = flags,
101 };
102 };
103 }
104 }
105
106 VKAPI_ATTR void VKAPI_CALL
hk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)107 hk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
108 VkFormat format,
109 VkFormatProperties2 *pFormatProperties)
110 {
111 VK_FROM_HANDLE(hk_physical_device, pdevice, physicalDevice);
112
113 VkFormatFeatureFlags2 linear2, optimal2, buffer2;
114 linear2 =
115 hk_get_image_format_features(pdevice, format, VK_IMAGE_TILING_LINEAR);
116 optimal2 =
117 hk_get_image_format_features(pdevice, format, VK_IMAGE_TILING_OPTIMAL);
118 buffer2 = hk_get_buffer_format_features(pdevice, format);
119
120 pFormatProperties->formatProperties = (VkFormatProperties){
121 .linearTilingFeatures = vk_format_features2_to_features(linear2),
122 .optimalTilingFeatures = vk_format_features2_to_features(optimal2),
123 .bufferFeatures = vk_format_features2_to_features(buffer2),
124 };
125
126 vk_foreach_struct(ext, pFormatProperties->pNext) {
127 switch (ext->sType) {
128 case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3: {
129 VkFormatProperties3 *p = (void *)ext;
130 p->linearTilingFeatures = linear2;
131 p->optimalTilingFeatures = optimal2;
132 p->bufferFeatures = buffer2;
133 break;
134 }
135
136 case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT:
137 get_drm_format_modifier_properties_list(
138 pdevice, format, (void *)ext, &pFormatProperties->formatProperties);
139 break;
140
141 case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT:
142 get_drm_format_modifier_properties_list_2(
143 pdevice, format, (void *)ext, &pFormatProperties->formatProperties);
144 break;
145
146 default:
147 vk_debug_ignored_stype(ext->sType);
148 break;
149 }
150 }
151 }
152