Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_formats.c
4560 views
1
/*
2
* Copyright © 2021 Collabora Ltd.
3
*
4
* Derived from tu_formats.c which is:
5
* Copyright © 2016 Red Hat.
6
* Copyright © 2016 Bas Nieuwenhuizen
7
*
8
* Permission is hereby granted, free of charge, to any person obtaining a
9
* copy of this software and associated documentation files (the "Software"),
10
* to deal in the Software without restriction, including without limitation
11
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
* and/or sell copies of the Software, and to permit persons to whom the
13
* Software is furnished to do so, subject to the following conditions:
14
*
15
* The above copyright notice and this permission notice (including the next
16
* paragraph) shall be included in all copies or substantial portions of the
17
* Software.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
* DEALINGS IN THE SOFTWARE.
26
*/
27
28
#include "panvk_private.h"
29
30
#include "util/format_r11g11b10f.h"
31
#include "util/format_srgb.h"
32
#include "util/half_float.h"
33
#include "vulkan/util/vk_format.h"
34
#include "vk_format.h"
35
#include "vk_util.h"
36
#include "panfrost/lib/pan_texture.h"
37
38
static void
39
get_format_properties(struct panvk_physical_device *physical_device,
40
VkFormat format,
41
VkFormatProperties *out_properties)
42
{
43
struct panfrost_device *pdev = &physical_device->pdev;
44
VkFormatFeatureFlags tex = 0, buffer = 0;
45
enum pipe_format pfmt = vk_format_to_pipe_format(format);
46
const struct panfrost_format fmt = pdev->formats[pfmt];
47
48
if (!pfmt || !fmt.hw)
49
goto end;
50
51
/* 3byte formats are not supported by the buffer <-> image copy helpers. */
52
if (util_format_get_blocksize(pfmt) == 3)
53
goto end;
54
55
/* We don't support compressed formats yet: this is causing trouble when
56
* doing a vkCmdCopyImage() between a compressed and a non-compressed format
57
* on a tiled/AFBC resource.
58
*/
59
if (util_format_is_compressed(pfmt))
60
goto end;
61
62
buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
63
VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
64
65
if (fmt.bind & PIPE_BIND_VERTEX_BUFFER)
66
buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
67
68
if (fmt.bind & PIPE_BIND_SAMPLER_VIEW) {
69
tex |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
70
VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
71
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
72
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
73
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT |
74
VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
75
VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
76
77
buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
78
79
tex |= VK_FORMAT_FEATURE_BLIT_SRC_BIT;
80
}
81
82
if (fmt.bind & PIPE_BIND_RENDER_TARGET) {
83
tex |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
84
VK_FORMAT_FEATURE_BLIT_DST_BIT;
85
86
tex |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
87
buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
88
89
/* Can always blend via blend shaders */
90
tex |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
91
}
92
93
if (fmt.bind & PIPE_BIND_DEPTH_STENCIL)
94
tex |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
95
96
end:
97
out_properties->linearTilingFeatures = tex;
98
out_properties->optimalTilingFeatures = tex;
99
out_properties->bufferFeatures = buffer;
100
}
101
102
void
103
panvk_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
104
VkFormat format,
105
VkFormatProperties *pFormatProperties)
106
{
107
VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
108
109
get_format_properties(physical_device, format, pFormatProperties);
110
}
111
112
void
113
panvk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
114
VkFormat format,
115
VkFormatProperties2 *pFormatProperties)
116
{
117
VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
118
119
get_format_properties(physical_device, format,
120
&pFormatProperties->formatProperties);
121
122
VkDrmFormatModifierPropertiesListEXT *list =
123
vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
124
if (list) {
125
VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,
126
&list->drmFormatModifierCount);
127
128
vk_outarray_append(&out, mod_props) {
129
mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
130
mod_props->drmFormatModifierPlaneCount = 1;
131
}
132
}
133
}
134
135
static VkResult
136
get_image_format_properties(struct panvk_physical_device *physical_device,
137
const VkPhysicalDeviceImageFormatInfo2 *info,
138
VkImageFormatProperties *pImageFormatProperties,
139
VkFormatFeatureFlags *p_feature_flags)
140
{
141
VkFormatProperties format_props;
142
VkFormatFeatureFlags format_feature_flags;
143
VkExtent3D maxExtent;
144
uint32_t maxMipLevels;
145
uint32_t maxArraySize;
146
VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
147
enum pipe_format format = vk_format_to_pipe_format(info->format);
148
149
get_format_properties(physical_device, info->format, &format_props);
150
151
switch (info->tiling) {
152
case VK_IMAGE_TILING_LINEAR:
153
format_feature_flags = format_props.linearTilingFeatures;
154
break;
155
156
case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
157
/* The only difference between optimal and linear is currently whether
158
* depth/stencil attachments are allowed on depth/stencil formats.
159
* There's no reason to allow importing depth/stencil textures, so just
160
* disallow it and then this annoying edge case goes away.
161
*
162
* TODO: If anyone cares, we could enable this by looking at the
163
* modifier and checking if it's LINEAR or not.
164
*/
165
if (util_format_is_depth_or_stencil(format))
166
goto unsupported;
167
168
assert(format_props.optimalTilingFeatures == format_props.linearTilingFeatures);
169
/* fallthrough */
170
case VK_IMAGE_TILING_OPTIMAL:
171
format_feature_flags = format_props.optimalTilingFeatures;
172
break;
173
default:
174
unreachable("bad VkPhysicalDeviceImageFormatInfo2");
175
}
176
177
if (format_feature_flags == 0)
178
goto unsupported;
179
180
if (info->type != VK_IMAGE_TYPE_2D &&
181
util_format_is_depth_or_stencil(format))
182
goto unsupported;
183
184
switch (info->type) {
185
default:
186
unreachable("bad vkimage type");
187
case VK_IMAGE_TYPE_1D:
188
maxExtent.width = 16384;
189
maxExtent.height = 1;
190
maxExtent.depth = 1;
191
maxMipLevels = 15; /* log2(maxWidth) + 1 */
192
maxArraySize = 2048;
193
break;
194
case VK_IMAGE_TYPE_2D:
195
maxExtent.width = 16384;
196
maxExtent.height = 16384;
197
maxExtent.depth = 1;
198
maxMipLevels = 15; /* log2(maxWidth) + 1 */
199
maxArraySize = 2048;
200
break;
201
case VK_IMAGE_TYPE_3D:
202
maxExtent.width = 2048;
203
maxExtent.height = 2048;
204
maxExtent.depth = 2048;
205
maxMipLevels = 12; /* log2(maxWidth) + 1 */
206
maxArraySize = 1;
207
break;
208
}
209
210
if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
211
info->type == VK_IMAGE_TYPE_2D &&
212
(format_feature_flags &
213
(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
214
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
215
!(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
216
!(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
217
sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
218
}
219
220
if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
221
if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
222
goto unsupported;
223
}
224
}
225
226
if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
227
if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
228
goto unsupported;
229
}
230
}
231
232
if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
233
if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
234
goto unsupported;
235
}
236
}
237
238
if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
239
if (!(format_feature_flags &
240
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
241
goto unsupported;
242
}
243
}
244
245
*pImageFormatProperties = (VkImageFormatProperties) {
246
.maxExtent = maxExtent,
247
.maxMipLevels = maxMipLevels,
248
.maxArrayLayers = maxArraySize,
249
.sampleCounts = sampleCounts,
250
251
/* FINISHME: Accurately calculate
252
* VkImageFormatProperties::maxResourceSize.
253
*/
254
.maxResourceSize = UINT32_MAX,
255
};
256
257
if (p_feature_flags)
258
*p_feature_flags = format_feature_flags;
259
260
return VK_SUCCESS;
261
unsupported:
262
*pImageFormatProperties = (VkImageFormatProperties) {
263
.maxExtent = { 0, 0, 0 },
264
.maxMipLevels = 0,
265
.maxArrayLayers = 0,
266
.sampleCounts = 0,
267
.maxResourceSize = 0,
268
};
269
270
return VK_ERROR_FORMAT_NOT_SUPPORTED;
271
}
272
273
274
VkResult
275
panvk_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,
276
VkFormat format,
277
VkImageType type,
278
VkImageTiling tiling,
279
VkImageUsageFlags usage,
280
VkImageCreateFlags createFlags,
281
VkImageFormatProperties *pImageFormatProperties)
282
{
283
VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
284
285
const VkPhysicalDeviceImageFormatInfo2 info = {
286
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
287
.pNext = NULL,
288
.format = format,
289
.type = type,
290
.tiling = tiling,
291
.usage = usage,
292
.flags = createFlags,
293
};
294
295
return get_image_format_properties(physical_device, &info,
296
pImageFormatProperties, NULL);
297
}
298
299
static VkResult
300
panvk_get_external_image_format_properties(const struct panvk_physical_device *physical_device,
301
const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
302
VkExternalMemoryHandleTypeFlagBits handleType,
303
VkExternalMemoryProperties *external_properties)
304
{
305
VkExternalMemoryFeatureFlagBits flags = 0;
306
VkExternalMemoryHandleTypeFlags export_flags = 0;
307
VkExternalMemoryHandleTypeFlags compat_flags = 0;
308
309
/* From the Vulkan 1.1.98 spec:
310
*
311
* If handleType is not compatible with the format, type, tiling,
312
* usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
313
* then vkGetPhysicalDeviceImageFormatProperties2 returns
314
* VK_ERROR_FORMAT_NOT_SUPPORTED.
315
*/
316
switch (handleType) {
317
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
318
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
319
switch (pImageFormatInfo->type) {
320
case VK_IMAGE_TYPE_2D:
321
flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
322
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
323
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
324
compat_flags = export_flags =
325
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
326
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
327
break;
328
default:
329
return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
330
"VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
331
handleType, pImageFormatInfo->type);
332
}
333
break;
334
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
335
flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
336
compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
337
break;
338
default:
339
return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
340
"VkExternalMemoryTypeFlagBits(0x%x) unsupported",
341
handleType);
342
}
343
344
*external_properties = (VkExternalMemoryProperties) {
345
.externalMemoryFeatures = flags,
346
.exportFromImportedHandleTypes = export_flags,
347
.compatibleHandleTypes = compat_flags,
348
};
349
350
return VK_SUCCESS;
351
}
352
353
VkResult
354
panvk_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
355
const VkPhysicalDeviceImageFormatInfo2 *base_info,
356
VkImageFormatProperties2 *base_props)
357
{
358
VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
359
const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
360
const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL;
361
VkExternalImageFormatProperties *external_props = NULL;
362
VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL;
363
VkFormatFeatureFlags format_feature_flags;
364
VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
365
VkResult result;
366
367
result = get_image_format_properties(physical_device, base_info,
368
&base_props->imageFormatProperties,
369
&format_feature_flags);
370
if (result != VK_SUCCESS)
371
return result;
372
373
/* Extract input structs */
374
vk_foreach_struct_const(s, base_info->pNext)
375
{
376
switch (s->sType) {
377
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
378
external_info = (const void *) s;
379
break;
380
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:
381
image_view_info = (const void *) s;
382
break;
383
default:
384
break;
385
}
386
}
387
388
/* Extract output structs */
389
vk_foreach_struct(s, base_props->pNext)
390
{
391
switch (s->sType) {
392
case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
393
external_props = (void *) s;
394
break;
395
case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:
396
cubic_props = (void *) s;
397
break;
398
case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
399
ycbcr_props = (void *) s;
400
break;
401
default:
402
break;
403
}
404
}
405
406
/* From the Vulkan 1.0.42 spec:
407
*
408
* If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
409
* behave as if VkPhysicalDeviceExternalImageFormatInfo was not
410
* present and VkExternalImageFormatProperties will be ignored.
411
*/
412
if (external_info && external_info->handleType != 0) {
413
result = panvk_get_external_image_format_properties(physical_device,
414
base_info,
415
external_info->handleType,
416
&external_props->externalMemoryProperties);
417
if (result != VK_SUCCESS)
418
goto fail;
419
}
420
421
if (cubic_props) {
422
/* note: blob only allows cubic filtering for 2D and 2D array views
423
* its likely we can enable it for 1D and CUBE, needs testing however
424
*/
425
if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D ||
426
image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) &&
427
(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
428
cubic_props->filterCubic = true;
429
cubic_props->filterCubicMinmax = true;
430
} else {
431
cubic_props->filterCubic = false;
432
cubic_props->filterCubicMinmax = false;
433
}
434
}
435
436
if (ycbcr_props)
437
ycbcr_props->combinedImageSamplerDescriptorCount = 1;
438
439
return VK_SUCCESS;
440
441
fail:
442
if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
443
/* From the Vulkan 1.0.42 spec:
444
*
445
* If the combination of parameters to
446
* vkGetPhysicalDeviceImageFormatProperties2 is not supported by
447
* the implementation for use in vkCreateImage, then all members of
448
* imageFormatProperties will be filled with zero.
449
*/
450
base_props->imageFormatProperties = (VkImageFormatProperties) {};
451
}
452
453
return result;
454
}
455
456
void
457
panvk_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,
458
VkFormat format,
459
VkImageType type,
460
uint32_t samples,
461
VkImageUsageFlags usage,
462
VkImageTiling tiling,
463
uint32_t *pNumProperties,
464
VkSparseImageFormatProperties *pProperties)
465
{
466
panvk_stub();
467
}
468
469
void
470
panvk_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,
471
const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
472
uint32_t *pPropertyCount,
473
VkSparseImageFormatProperties2 *pProperties)
474
{
475
panvk_stub();
476
}
477
478
void
479
panvk_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,
480
const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
481
VkExternalBufferProperties *pExternalBufferProperties)
482
{
483
panvk_stub();
484
}
485
486