1 /*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <stdbool.h>
25
26 #include "pvr_formats.h"
27 #include "pvr_private.h"
28 #include "vk_enum_to_str.h"
29 #include "vk_format.h"
30 #include "vk_log.h"
31 #include "vk_util.h"
32
33 #define FORMAT(vk, tex_fmt, pack_mode) \
34 [VK_FORMAT_##vk] = { \
35 .vk_format = VK_FORMAT_##vk, \
36 .tex_format = ROGUE_TEXSTATE_FORMAT_##tex_fmt, \
37 .pbe_packmode = ROGUE_PBESTATE_PACKMODE_##pack_mode, \
38 .supported = true, \
39 }
40
41 struct pvr_format {
42 VkFormat vk_format;
43 uint32_t tex_format;
44 uint32_t pbe_packmode;
45 bool supported;
46 };
47
48 /* TODO: add all supported core formats */
49 static const struct pvr_format pvr_format_table[] = {
50 /* VK_FORMAT_R8_UINT = 13. */
51 FORMAT(R8_UINT, U8, U8),
52 /* VK_FORMAT_B8G8R8A8_UNORM = 44. */
53 FORMAT(B8G8R8A8_UNORM, U8U8U8U8, U8U8U8U8),
54 /* VK_FORMAT_R32_UINT = 98. */
55 FORMAT(R32_UINT, U32, U32),
56 /* VK_FORMAT_R32G32B32A32_UINT = 107. */
57 FORMAT(R32G32B32A32_UINT, U32U32U32U32, U32U32U32U32),
58 /* VK_FORMAT_R32G32B32A32_SFLOAT = 109. */
59 FORMAT(R32G32B32A32_SFLOAT, F32F32F32F32, F32F32F32F32),
60 /* VK_FORMAT_D32_SFLOAT = 126. */
61 FORMAT(D32_SFLOAT, F32, F32),
62 };
63
64 #undef FORMAT
65
pvr_get_format(VkFormat vk_format)66 static inline const struct pvr_format *pvr_get_format(VkFormat vk_format)
67 {
68 if (vk_format < ARRAY_SIZE(pvr_format_table) &&
69 pvr_format_table[vk_format].supported) {
70 return &pvr_format_table[vk_format];
71 }
72
73 mesa_logd("Format %s(%d) not supported\n",
74 vk_Format_to_str(vk_format),
75 vk_format);
76
77 return NULL;
78 }
79
pvr_get_tex_format(VkFormat vk_format)80 uint32_t pvr_get_tex_format(VkFormat vk_format)
81 {
82 const struct pvr_format *pvr_format = pvr_get_format(vk_format);
83 if (pvr_format) {
84 return pvr_format->tex_format;
85 }
86
87 return ROGUE_TEXSTATE_FORMAT_INVALID;
88 }
89
pvr_get_pbe_packmode(VkFormat vk_format)90 uint32_t pvr_get_pbe_packmode(VkFormat vk_format)
91 {
92 const struct pvr_format *pvr_format = pvr_get_format(vk_format);
93 if (pvr_format)
94 return pvr_format->pbe_packmode;
95
96 return ROGUE_PBESTATE_PACKMODE_INVALID;
97 }
98
99 static VkFormatFeatureFlags
pvr_get_image_format_features(const struct pvr_format * pvr_format,VkImageTiling vk_tiling)100 pvr_get_image_format_features(const struct pvr_format *pvr_format,
101 VkImageTiling vk_tiling)
102 {
103 VkFormatFeatureFlags flags = 0;
104 VkImageAspectFlags aspects;
105
106 if (!pvr_format)
107 return 0;
108
109 aspects = vk_format_aspects(pvr_format->vk_format);
110 if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
111 flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
112 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
113 VK_FORMAT_FEATURE_BLIT_SRC_BIT;
114 }
115
116 return flags;
117 }
118
pvr_get_format_swizzle(VkFormat vk_format)119 const uint8_t *pvr_get_format_swizzle(VkFormat vk_format)
120 {
121 const struct util_format_description *vf = vk_format_description(vk_format);
122
123 return vf->swizzle;
124 }
125
126 static VkFormatFeatureFlags
pvr_get_buffer_format_features(const struct pvr_format * pvr_format)127 pvr_get_buffer_format_features(const struct pvr_format *pvr_format)
128 {
129 VkFormatFeatureFlags flags = 0;
130
131 if (!pvr_format)
132 return 0;
133
134 return flags;
135 }
136
pvr_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)137 void pvr_GetPhysicalDeviceFormatProperties2(
138 VkPhysicalDevice physicalDevice,
139 VkFormat format,
140 VkFormatProperties2 *pFormatProperties)
141 {
142 const struct pvr_format *pvr_format = pvr_get_format(format);
143
144 pFormatProperties->formatProperties = (VkFormatProperties){
145 .linearTilingFeatures =
146 pvr_get_image_format_features(pvr_format, VK_IMAGE_TILING_LINEAR),
147 .optimalTilingFeatures =
148 pvr_get_image_format_features(pvr_format, VK_IMAGE_TILING_OPTIMAL),
149 .bufferFeatures = pvr_get_buffer_format_features(pvr_format),
150 };
151
152 vk_foreach_struct (ext, pFormatProperties->pNext) {
153 pvr_debug_ignored_stype(ext->sType);
154 }
155 }
156
157 static VkResult
pvr_get_image_format_properties(struct pvr_physical_device * pdevice,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties)158 pvr_get_image_format_properties(struct pvr_physical_device *pdevice,
159 const VkPhysicalDeviceImageFormatInfo2 *info,
160 VkImageFormatProperties *pImageFormatProperties)
161 {
162 assert(!"Unimplemented");
163 return VK_SUCCESS;
164 }
165
pvr_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkImageFormatProperties2 * pImageFormatProperties)166 VkResult pvr_GetPhysicalDeviceImageFormatProperties2(
167 VkPhysicalDevice physicalDevice,
168 const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
169 VkImageFormatProperties2 *pImageFormatProperties)
170 {
171 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
172 PVR_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice);
173 VkExternalImageFormatProperties *external_props = NULL;
174 VkResult result;
175
176 result = pvr_get_image_format_properties(
177 pdevice,
178 pImageFormatInfo,
179 &pImageFormatProperties->imageFormatProperties);
180 if (result != VK_SUCCESS)
181 return result;
182
183 /* Extract input structs */
184 vk_foreach_struct_const (ext, pImageFormatInfo->pNext) {
185 switch (ext->sType) {
186 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
187 external_info = (const void *)ext;
188 break;
189 default:
190 pvr_debug_ignored_stype(ext->sType);
191 break;
192 }
193 }
194
195 /* Extract output structs */
196 vk_foreach_struct (ext, pImageFormatProperties->pNext) {
197 switch (ext->sType) {
198 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
199 external_props = (void *)ext;
200 break;
201 default:
202 pvr_debug_ignored_stype(ext->sType);
203 break;
204 }
205 }
206
207 /* From the Vulkan 1.0.42 spec:
208 *
209 * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
210 * behave as if VkPhysicalDeviceExternalImageFormatInfo was not
211 * present and VkExternalImageFormatProperties will be ignored.
212 */
213 if (external_info && external_info->handleType != 0) {
214 switch (external_info->handleType) {
215 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
216 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
217 if (!external_props)
218 break;
219
220 external_props->externalMemoryProperties.externalMemoryFeatures =
221 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
222 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
223 external_props->externalMemoryProperties.compatibleHandleTypes =
224 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
225 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
226 external_props->externalMemoryProperties.exportFromImportedHandleTypes =
227 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
228 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
229 break;
230 default:
231 return vk_error(pdevice, VK_ERROR_FORMAT_NOT_SUPPORTED);
232 }
233 }
234
235 return VK_SUCCESS;
236 }
237
pvr_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,uint32_t samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pNumProperties,VkSparseImageFormatProperties * pProperties)238 void pvr_GetPhysicalDeviceSparseImageFormatProperties(
239 VkPhysicalDevice physicalDevice,
240 VkFormat format,
241 VkImageType type,
242 uint32_t samples,
243 VkImageUsageFlags usage,
244 VkImageTiling tiling,
245 uint32_t *pNumProperties,
246 VkSparseImageFormatProperties *pProperties)
247 {
248 /* Sparse images are not yet supported. */
249 *pNumProperties = 0;
250 }
251
pvr_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)252 void pvr_GetPhysicalDeviceSparseImageFormatProperties2(
253 VkPhysicalDevice physicalDevice,
254 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
255 uint32_t *pPropertyCount,
256 VkSparseImageFormatProperties2 *pProperties)
257 {
258 /* Sparse images are not yet supported. */
259 *pPropertyCount = 0;
260 }
261
pvr_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)262 void pvr_GetPhysicalDeviceExternalBufferProperties(
263 VkPhysicalDevice physicalDevice,
264 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
265 VkExternalBufferProperties *pExternalBufferProperties)
266 {
267 /* The Vulkan 1.0.42 spec says "handleType must be a valid
268 * VkExternalMemoryHandleTypeFlagBits value" in
269 * VkPhysicalDeviceExternalBufferInfo. This differs from
270 * VkPhysicalDeviceExternalImageFormatInfo, which surprisingly permits
271 * handleType == 0.
272 */
273 assert(pExternalBufferInfo->handleType != 0);
274
275 /* All of the current flags are for sparse which we don't support. */
276 if (pExternalBufferInfo->flags)
277 goto unsupported;
278
279 switch (pExternalBufferInfo->handleType) {
280 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
281 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
282 /* clang-format off */
283 pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures =
284 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
285 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
286 pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes =
287 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
288 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
289 pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes =
290 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
291 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
292 /* clang-format on */
293 return;
294 default:
295 break;
296 }
297
298 unsupported:
299 /* From the Vulkan 1.1.113 spec:
300 *
301 * compatibleHandleTypes must include at least handleType.
302 */
303 pExternalBufferProperties->externalMemoryProperties =
304 (VkExternalMemoryProperties){
305 .compatibleHandleTypes = pExternalBufferInfo->handleType,
306 };
307 }
308
pvr_format_is_pbe_downscalable(VkFormat vk_format)309 bool pvr_format_is_pbe_downscalable(VkFormat vk_format)
310 {
311 if (vk_format_is_int(vk_format)) {
312 /* PBE downscale behavior for integer formats does not match Vulkan
313 * spec. Vulkan requires a single sample to be chosen instead of
314 * taking the average sample color.
315 */
316 return false;
317 }
318
319 switch (pvr_get_pbe_packmode(vk_format)) {
320 default:
321 return true;
322
323 case ROGUE_PBESTATE_PACKMODE_U16U16U16U16:
324 case ROGUE_PBESTATE_PACKMODE_S16S16S16S16:
325 case ROGUE_PBESTATE_PACKMODE_U32U32U32U32:
326 case ROGUE_PBESTATE_PACKMODE_S32S32S32S32:
327 case ROGUE_PBESTATE_PACKMODE_F32F32F32F32:
328 case ROGUE_PBESTATE_PACKMODE_U16U16U16:
329 case ROGUE_PBESTATE_PACKMODE_S16S16S16:
330 case ROGUE_PBESTATE_PACKMODE_U32U32U32:
331 case ROGUE_PBESTATE_PACKMODE_S32S32S32:
332 case ROGUE_PBESTATE_PACKMODE_F32F32F32:
333 case ROGUE_PBESTATE_PACKMODE_U16U16:
334 case ROGUE_PBESTATE_PACKMODE_S16S16:
335 case ROGUE_PBESTATE_PACKMODE_U32U32:
336 case ROGUE_PBESTATE_PACKMODE_S32S32:
337 case ROGUE_PBESTATE_PACKMODE_F32F32:
338 case ROGUE_PBESTATE_PACKMODE_U24ST8:
339 case ROGUE_PBESTATE_PACKMODE_ST8U24:
340 case ROGUE_PBESTATE_PACKMODE_U16:
341 case ROGUE_PBESTATE_PACKMODE_S16:
342 case ROGUE_PBESTATE_PACKMODE_U32:
343 case ROGUE_PBESTATE_PACKMODE_S32:
344 case ROGUE_PBESTATE_PACKMODE_F32:
345 case ROGUE_PBESTATE_PACKMODE_X24U8F32:
346 case ROGUE_PBESTATE_PACKMODE_X24X8F32:
347 case ROGUE_PBESTATE_PACKMODE_X24G8X32:
348 case ROGUE_PBESTATE_PACKMODE_X8U24:
349 case ROGUE_PBESTATE_PACKMODE_U8X24:
350 case ROGUE_PBESTATE_PACKMODE_PBYTE:
351 case ROGUE_PBESTATE_PACKMODE_PWORD:
352 case ROGUE_PBESTATE_PACKMODE_INVALID:
353 return false;
354 }
355 }
356