~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/freedreno/vulkan/tu_formats.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/*
3
 
 * Copyright © 2016 Red Hat.
4
 
 * Copyright © 2016 Bas Nieuwenhuizen
5
 
 *
6
 
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 
 * copy of this software and associated documentation files (the "Software"),
8
 
 * to deal in the Software without restriction, including without limitation
9
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 
 * and/or sell copies of the Software, and to permit persons to whom the
11
 
 * Software is furnished to do so, subject to the following conditions:
12
 
 *
13
 
 * The above copyright notice and this permission notice (including the next
14
 
 * paragraph) shall be included in all copies or substantial portions of the
15
 
 * Software.
16
 
 *
17
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
 
 * DEALINGS IN THE SOFTWARE.
24
 
 */
25
 
 
26
 
#include "tu_private.h"
27
 
 
28
 
#include "adreno_common.xml.h"
29
 
#include "a6xx.xml.h"
30
 
#include "fdl/fd6_format_table.h"
31
 
 
32
 
#include "vk_format.h"
33
 
#include "vk_util.h"
34
 
#include "drm-uapi/drm_fourcc.h"
35
 
 
36
 
struct tu_native_format
37
 
tu6_format_vtx(VkFormat vk_format)
38
 
{
39
 
   enum pipe_format format = vk_format_to_pipe_format(vk_format);
40
 
   struct tu_native_format fmt = {
41
 
      .fmt = fd6_vertex_format(format),
42
 
      .swap = fd6_vertex_swap(format),
43
 
   };
44
 
   assert(fmt.fmt != FMT6_NONE);
45
 
   return fmt;
46
 
}
47
 
 
48
 
bool
49
 
tu6_format_vtx_supported(VkFormat vk_format)
50
 
{
51
 
   enum pipe_format format = vk_format_to_pipe_format(vk_format);
52
 
   return fd6_vertex_format(format) != FMT6_NONE;
53
 
}
54
 
 
55
 
/* Map non-colorspace-converted YUV formats to RGB pipe formats where we can,
56
 
 * since our hardware doesn't support colorspace conversion.
57
 
 *
58
 
 * Really, we should probably be returning the RGB formats in
59
 
 * vk_format_to_pipe_format, but we don't have all the equivalent pipe formats
60
 
 * for VK RGB formats yet, and we'd have to switch all consumers of that
61
 
 * function at once.
62
 
 */
63
 
enum pipe_format
64
 
tu_vk_format_to_pipe_format(VkFormat vk_format)
65
 
{
66
 
   switch (vk_format) {
67
 
   case VK_FORMAT_G8B8G8R8_422_UNORM: /* YUYV */
68
 
      return PIPE_FORMAT_R8G8_R8B8_UNORM;
69
 
   case VK_FORMAT_B8G8R8G8_422_UNORM: /* UYVY */
70
 
      return PIPE_FORMAT_G8R8_B8R8_UNORM;
71
 
   case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
72
 
      return PIPE_FORMAT_G8_B8R8_420_UNORM;
73
 
   case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
74
 
      return PIPE_FORMAT_G8_B8_R8_420_UNORM;
75
 
   default:
76
 
      return vk_format_to_pipe_format(vk_format);
77
 
   }
78
 
}
79
 
 
80
 
static struct tu_native_format
81
 
tu6_format_color_unchecked(enum pipe_format format, enum a6xx_tile_mode tile_mode)
82
 
{
83
 
   struct tu_native_format fmt = {
84
 
      .fmt = fd6_color_format(format, tile_mode),
85
 
      .swap = fd6_color_swap(format, tile_mode),
86
 
   };
87
 
 
88
 
   switch (format) {
89
 
   case PIPE_FORMAT_Z24X8_UNORM:
90
 
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
91
 
      fmt.fmt = FMT6_8_8_8_8_UNORM;
92
 
      break;
93
 
 
94
 
   default:
95
 
      break;
96
 
   }
97
 
 
98
 
   return fmt;
99
 
}
100
 
 
101
 
bool
102
 
tu6_format_color_supported(enum pipe_format format)
103
 
{
104
 
   return tu6_format_color_unchecked(format, TILE6_LINEAR).fmt != FMT6_NONE;
105
 
}
106
 
 
107
 
struct tu_native_format
108
 
tu6_format_color(enum pipe_format format, enum a6xx_tile_mode tile_mode)
109
 
{
110
 
   struct tu_native_format fmt = tu6_format_color_unchecked(format, tile_mode);
111
 
   assert(fmt.fmt != FMT6_NONE);
112
 
   return fmt;
113
 
}
114
 
 
115
 
static struct tu_native_format
116
 
tu6_format_texture_unchecked(enum pipe_format format, enum a6xx_tile_mode tile_mode)
117
 
{
118
 
   struct tu_native_format fmt = {
119
 
      .fmt = fd6_texture_format(format, tile_mode),
120
 
      .swap = fd6_texture_swap(format, tile_mode),
121
 
   };
122
 
 
123
 
   /* No texturing support for NPOT textures yet.  See
124
 
    * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5536
125
 
    */
126
 
   if (util_format_is_plain(format) &&
127
 
       !util_is_power_of_two_nonzero(util_format_get_blocksize(format))) {
128
 
      fmt.fmt = FMT6_NONE;
129
 
   }
130
 
 
131
 
   switch (format) {
132
 
   case PIPE_FORMAT_Z24X8_UNORM:
133
 
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
134
 
      /* freedreno uses Z24_UNORM_S8_UINT (sampling) or
135
 
       * FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8 (blits) for this format, while we use
136
 
       * FMT6_8_8_8_8_UNORM or FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8
137
 
       */
138
 
      fmt.fmt = FMT6_8_8_8_8_UNORM;
139
 
      break;
140
 
 
141
 
   default:
142
 
      break;
143
 
   }
144
 
 
145
 
   return fmt;
146
 
}
147
 
 
148
 
struct tu_native_format
149
 
tu6_format_texture(enum pipe_format format, enum a6xx_tile_mode tile_mode)
150
 
{
151
 
   struct tu_native_format fmt = tu6_format_texture_unchecked(format, tile_mode);
152
 
   assert(fmt.fmt != FMT6_NONE);
153
 
   return fmt;
154
 
}
155
 
 
156
 
bool
157
 
tu6_format_texture_supported(enum pipe_format format)
158
 
{
159
 
   return tu6_format_texture_unchecked(format, TILE6_LINEAR).fmt != FMT6_NONE;
160
 
}
161
 
 
162
 
static void
163
 
tu_physical_device_get_format_properties(
164
 
   struct tu_physical_device *physical_device,
165
 
   VkFormat vk_format,
166
 
   VkFormatProperties3 *out_properties)
167
 
{
168
 
   VkFormatFeatureFlags2 linear = 0, optimal = 0, buffer = 0;
169
 
   enum pipe_format format = tu_vk_format_to_pipe_format(vk_format);
170
 
   const struct util_format_description *desc = util_format_description(format);
171
 
 
172
 
   bool supported_vtx = tu6_format_vtx_supported(vk_format);
173
 
   bool supported_color = tu6_format_color_supported(format);
174
 
   bool supported_tex = tu6_format_texture_supported(format);
175
 
 
176
 
   if (format == PIPE_FORMAT_NONE ||
177
 
       !(supported_vtx || supported_color || supported_tex)) {
178
 
      goto end;
179
 
   }
180
 
 
181
 
   buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
182
 
   if (supported_vtx)
183
 
      buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
184
 
 
185
 
   if (supported_tex) {
186
 
      optimal |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
187
 
                 VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
188
 
                 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
189
 
                 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT |
190
 
                 VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
191
 
                 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
192
 
 
193
 
      buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
194
 
 
195
 
      /* no blit src bit for YUYV/NV12/I420 formats */
196
 
      if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
197
 
          desc->layout != UTIL_FORMAT_LAYOUT_PLANAR2 &&
198
 
          desc->layout != UTIL_FORMAT_LAYOUT_PLANAR3)
199
 
         optimal |= VK_FORMAT_FEATURE_BLIT_SRC_BIT;
200
 
 
201
 
      if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED)
202
 
         optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
203
 
 
204
 
      if (!vk_format_is_int(vk_format)) {
205
 
         optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
206
 
 
207
 
         if (physical_device->vk.supported_extensions.EXT_filter_cubic)
208
 
            optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT;
209
 
      }
210
 
   }
211
 
 
212
 
   if (supported_color) {
213
 
      assert(supported_tex);
214
 
      optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
215
 
                 VK_FORMAT_FEATURE_BLIT_DST_BIT |
216
 
                 VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
217
 
                 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
218
 
                 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR;
219
 
 
220
 
      buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT |
221
 
                VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
222
 
                VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR;
223
 
 
224
 
      /* TODO: The blob also exposes these for R16G16_UINT/R16G16_SINT, but we
225
 
       * don't have any tests for those.
226
 
       */
227
 
      if (vk_format == VK_FORMAT_R32_UINT || vk_format == VK_FORMAT_R32_SINT) {
228
 
         optimal |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
229
 
         buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
230
 
      }
231
 
 
232
 
      if (!util_format_is_pure_integer(format))
233
 
         optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
234
 
   }
235
 
 
236
 
   /* For the most part, we can do anything with a linear image that we could
237
 
    * do with a tiled image. However, we can't support sysmem rendering with a
238
 
    * linear depth texture, because we don't know if there's a bit to control
239
 
    * the tiling of the depth buffer in BYPASS mode, and the blob also
240
 
    * disables linear depth rendering, so there's no way to discover it. We
241
 
    * also can't force GMEM mode, because there are other situations where we
242
 
    * have to use sysmem rendering. So follow the blob here, and only enable
243
 
    * DEPTH_STENCIL_ATTACHMENT_BIT for the optimal features.
244
 
    */
245
 
   linear = optimal;
246
 
   if (tu6_pipe2depth(vk_format) != (enum a6xx_depth_format)~0)
247
 
      optimal |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
248
 
 
249
 
   if (!tiling_possible(vk_format) &&
250
 
       /* We don't actually support tiling for this format, but we need to
251
 
        * fake it as it's required by VK_KHR_sampler_ycbcr_conversion.
252
 
        */
253
 
       vk_format != VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) {
254
 
      optimal = 0;
255
 
   }
256
 
 
257
 
   if (vk_format == VK_FORMAT_G8B8G8R8_422_UNORM ||
258
 
       vk_format == VK_FORMAT_B8G8R8G8_422_UNORM ||
259
 
       vk_format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM ||
260
 
       vk_format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) {
261
 
      /* Disable buffer texturing of subsampled (422) and planar YUV textures.
262
 
       * The subsampling requirement comes from "If format is a block-compressed
263
 
       * format, then bufferFeatures must not support any features for the
264
 
       * format" plus the specification of subsampled as 2x1 compressed block
265
 
       * format.  I couldn't find the citation for planar, but 1D access of
266
 
       * planar YUV would be really silly.
267
 
       */
268
 
      buffer = 0;
269
 
   }
270
 
 
271
 
   /* All our depth formats support shadow comparisons. */
272
 
   if (vk_format_has_depth(vk_format) && (optimal & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
273
 
      optimal |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
274
 
      linear |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
275
 
   }
276
 
 
277
 
   /* From the Vulkan 1.3.205 spec, section 19.3 "43.3. Required Format Support":
278
 
    *
279
 
    *    Mandatory format support: depth/stencil with VkImageType
280
 
    *    VK_IMAGE_TYPE_2D
281
 
    *    [...]
282
 
    *    bufferFeatures must not support any features for these formats
283
 
    */
284
 
   if (vk_format_is_depth_or_stencil(vk_format))
285
 
      buffer = 0;
286
 
 
287
 
   /* D32_SFLOAT_S8_UINT is tiled as two images, so no linear format
288
 
    * blob enables some linear features, but its not useful, so don't bother.
289
 
    */
290
 
   if (vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT)
291
 
      linear = 0;
292
 
 
293
 
end:
294
 
   out_properties->linearTilingFeatures = linear;
295
 
   out_properties->optimalTilingFeatures = optimal;
296
 
   out_properties->bufferFeatures = buffer;
297
 
}
298
 
 
299
 
VKAPI_ATTR void VKAPI_CALL
300
 
tu_GetPhysicalDeviceFormatProperties2(
301
 
   VkPhysicalDevice physicalDevice,
302
 
   VkFormat format,
303
 
   VkFormatProperties2 *pFormatProperties)
304
 
{
305
 
   TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
306
 
 
307
 
   VkFormatProperties3 local_props3;
308
 
   VkFormatProperties3 *props3 =
309
 
      vk_find_struct(pFormatProperties->pNext, FORMAT_PROPERTIES_3);
310
 
   if (!props3)
311
 
      props3 = &local_props3;
312
 
 
313
 
   tu_physical_device_get_format_properties(
314
 
      physical_device, format, props3);
315
 
 
316
 
   pFormatProperties->formatProperties = (VkFormatProperties) {
317
 
      .linearTilingFeatures = props3->linearTilingFeatures,
318
 
      .optimalTilingFeatures = props3->optimalTilingFeatures,
319
 
      .bufferFeatures = props3->bufferFeatures,
320
 
   };
321
 
 
322
 
   VkDrmFormatModifierPropertiesListEXT *list =
323
 
      vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
324
 
   if (list) {
325
 
      VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
326
 
                             list->pDrmFormatModifierProperties,
327
 
                             &list->drmFormatModifierCount);
328
 
 
329
 
      if (pFormatProperties->formatProperties.linearTilingFeatures) {
330
 
         vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) {
331
 
            mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
332
 
            mod_props->drmFormatModifierPlaneCount = 1;
333
 
            mod_props->drmFormatModifierTilingFeatures =
334
 
               pFormatProperties->formatProperties.linearTilingFeatures;
335
 
         }
336
 
      }
337
 
 
338
 
      /* note: ubwc_possible() argument values to be ignored except for format */
339
 
      if (pFormatProperties->formatProperties.optimalTilingFeatures &&
340
 
          tiling_possible(format) &&
341
 
          ubwc_possible(format, VK_IMAGE_TYPE_2D, 0, 0, physical_device->info, VK_SAMPLE_COUNT_1_BIT)) {
342
 
         vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) {
343
 
            mod_props->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
344
 
            mod_props->drmFormatModifierPlaneCount = 1;
345
 
            mod_props->drmFormatModifierTilingFeatures =
346
 
               pFormatProperties->formatProperties.optimalTilingFeatures;
347
 
         }
348
 
      }
349
 
   }
350
 
}
351
 
 
352
 
static VkResult
353
 
tu_get_image_format_properties(
354
 
   struct tu_physical_device *physical_device,
355
 
   const VkPhysicalDeviceImageFormatInfo2 *info,
356
 
   VkImageFormatProperties *pImageFormatProperties,
357
 
   VkFormatFeatureFlags *p_feature_flags)
358
 
{
359
 
   VkFormatProperties3 format_props;
360
 
   VkFormatFeatureFlags format_feature_flags;
361
 
   VkExtent3D maxExtent;
362
 
   uint32_t maxMipLevels;
363
 
   uint32_t maxArraySize;
364
 
   VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
365
 
 
366
 
   tu_physical_device_get_format_properties(physical_device, info->format,
367
 
                                            &format_props);
368
 
 
369
 
   switch (info->tiling) {
370
 
   case VK_IMAGE_TILING_LINEAR:
371
 
      format_feature_flags = format_props.linearTilingFeatures;
372
 
      break;
373
 
 
374
 
   case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: {
375
 
      const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_info =
376
 
         vk_find_struct_const(info->pNext, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT);
377
 
 
378
 
      switch (drm_info->drmFormatModifier) {
379
 
      case DRM_FORMAT_MOD_QCOM_COMPRESSED:
380
 
         /* falling back to linear/non-UBWC isn't possible with explicit modifier */
381
 
 
382
 
         /* formats which don't support tiling */
383
 
         if (!format_props.optimalTilingFeatures ||
384
 
             !tiling_possible(info->format))
385
 
            return VK_ERROR_FORMAT_NOT_SUPPORTED;
386
 
 
387
 
         /* for mutable formats, its very unlikely to be possible to use UBWC */
388
 
         if (info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)
389
 
            return VK_ERROR_FORMAT_NOT_SUPPORTED;
390
 
 
391
 
 
392
 
         if (!ubwc_possible(info->format, info->type, info->usage, info->usage, physical_device->info, sampleCounts))
393
 
            return VK_ERROR_FORMAT_NOT_SUPPORTED;
394
 
 
395
 
         format_feature_flags = format_props.optimalTilingFeatures;
396
 
         break;
397
 
      case DRM_FORMAT_MOD_LINEAR:
398
 
         format_feature_flags = format_props.linearTilingFeatures;
399
 
         break;
400
 
      default:
401
 
         return VK_ERROR_FORMAT_NOT_SUPPORTED;
402
 
      }
403
 
   } break;
404
 
   case VK_IMAGE_TILING_OPTIMAL:
405
 
      format_feature_flags = format_props.optimalTilingFeatures;
406
 
      break;
407
 
   default:
408
 
      unreachable("bad VkPhysicalDeviceImageFormatInfo2");
409
 
   }
410
 
 
411
 
   if (format_feature_flags == 0)
412
 
      goto unsupported;
413
 
 
414
 
   if (info->type != VK_IMAGE_TYPE_2D &&
415
 
       vk_format_is_depth_or_stencil(info->format))
416
 
      goto unsupported;
417
 
 
418
 
   switch (info->type) {
419
 
   default:
420
 
      unreachable("bad vkimage type\n");
421
 
   case VK_IMAGE_TYPE_1D:
422
 
      maxExtent.width = 16384;
423
 
      maxExtent.height = 1;
424
 
      maxExtent.depth = 1;
425
 
      maxMipLevels = 15; /* log2(maxWidth) + 1 */
426
 
      maxArraySize = 2048;
427
 
      break;
428
 
   case VK_IMAGE_TYPE_2D:
429
 
      maxExtent.width = 16384;
430
 
      maxExtent.height = 16384;
431
 
      maxExtent.depth = 1;
432
 
      maxMipLevels = 15; /* log2(maxWidth) + 1 */
433
 
      maxArraySize = 2048;
434
 
      break;
435
 
   case VK_IMAGE_TYPE_3D:
436
 
      maxExtent.width = 2048;
437
 
      maxExtent.height = 2048;
438
 
      maxExtent.depth = 2048;
439
 
      maxMipLevels = 12; /* log2(maxWidth) + 1 */
440
 
      maxArraySize = 1;
441
 
      break;
442
 
   }
443
 
 
444
 
   if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
445
 
       info->type == VK_IMAGE_TYPE_2D &&
446
 
       (format_feature_flags &
447
 
        (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
448
 
         VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
449
 
       !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
450
 
       !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
451
 
      sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
452
 
      /* note: most operations support 8 samples (GMEM render/resolve do at least)
453
 
       * but some do not (which ones?), just disable 8 samples completely,
454
 
       * (no 8x msaa matches the blob driver behavior)
455
 
       */
456
 
   }
457
 
 
458
 
   /* From the Vulkan 1.3.206 spec:
459
 
    *
460
 
    * "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be
461
 
    * created with usage flags that are not supported for the format the image
462
 
    * is created with but are supported for at least one format a VkImageView
463
 
    * created from the image can have."
464
 
    *
465
 
    * This means we should relax checks that only depend on the
466
 
    * format_feature_flags, to allow the user to create images that may be
467
 
    * e.g. reinterpreted as storage when the original format doesn't allow it.
468
 
    * The user will have to check against the format features anyway.
469
 
    * Otherwise we'd unnecessarily disallow it.
470
 
    */
471
 
 
472
 
   VkImageUsageFlags image_usage = info->usage;
473
 
   if (info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
474
 
      image_usage = 0;
475
 
 
476
 
   if (image_usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
477
 
      if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
478
 
         goto unsupported;
479
 
      }
480
 
   }
481
 
 
482
 
   if (image_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
483
 
      if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
484
 
         goto unsupported;
485
 
      }
486
 
   }
487
 
 
488
 
   if (image_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
489
 
      if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
490
 
         goto unsupported;
491
 
      }
492
 
   }
493
 
 
494
 
   if (image_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
495
 
      if (!(format_feature_flags &
496
 
            VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
497
 
         goto unsupported;
498
 
      }
499
 
   }
500
 
 
501
 
   *pImageFormatProperties = (VkImageFormatProperties) {
502
 
      .maxExtent = maxExtent,
503
 
      .maxMipLevels = maxMipLevels,
504
 
      .maxArrayLayers = maxArraySize,
505
 
      .sampleCounts = sampleCounts,
506
 
 
507
 
      /* FINISHME: Accurately calculate
508
 
       * VkImageFormatProperties::maxResourceSize.
509
 
       */
510
 
      .maxResourceSize = UINT32_MAX,
511
 
   };
512
 
 
513
 
   if (p_feature_flags)
514
 
      *p_feature_flags = format_feature_flags;
515
 
 
516
 
   return VK_SUCCESS;
517
 
unsupported:
518
 
   *pImageFormatProperties = (VkImageFormatProperties) {
519
 
      .maxExtent = { 0, 0, 0 },
520
 
      .maxMipLevels = 0,
521
 
      .maxArrayLayers = 0,
522
 
      .sampleCounts = 0,
523
 
      .maxResourceSize = 0,
524
 
   };
525
 
 
526
 
   return VK_ERROR_FORMAT_NOT_SUPPORTED;
527
 
}
528
 
 
529
 
static VkResult
530
 
tu_get_external_image_format_properties(
531
 
   const struct tu_physical_device *physical_device,
532
 
   const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
533
 
   VkExternalMemoryHandleTypeFlagBits handleType,
534
 
   VkExternalImageFormatProperties *external_properties)
535
 
{
536
 
   VkExternalMemoryFeatureFlagBits flags = 0;
537
 
   VkExternalMemoryHandleTypeFlags export_flags = 0;
538
 
   VkExternalMemoryHandleTypeFlags compat_flags = 0;
539
 
 
540
 
   /* From the Vulkan 1.1.98 spec:
541
 
    *
542
 
    *    If handleType is not compatible with the format, type, tiling,
543
 
    *    usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
544
 
    *    then vkGetPhysicalDeviceImageFormatProperties2 returns
545
 
    *    VK_ERROR_FORMAT_NOT_SUPPORTED.
546
 
    */
547
 
 
548
 
   switch (handleType) {
549
 
   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
550
 
   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
551
 
      switch (pImageFormatInfo->type) {
552
 
      case VK_IMAGE_TYPE_2D:
553
 
         flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
554
 
                 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
555
 
                 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
556
 
         compat_flags = export_flags =
557
 
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
558
 
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
559
 
         break;
560
 
      default:
561
 
         return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
562
 
                          "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
563
 
                          handleType, pImageFormatInfo->type);
564
 
      }
565
 
      break;
566
 
   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
567
 
      flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
568
 
      compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
569
 
      break;
570
 
   default:
571
 
      return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
572
 
                       "VkExternalMemoryTypeFlagBits(0x%x) unsupported",
573
 
                       handleType);
574
 
   }
575
 
 
576
 
   if (external_properties) {
577
 
      external_properties->externalMemoryProperties =
578
 
         (VkExternalMemoryProperties) {
579
 
            .externalMemoryFeatures = flags,
580
 
            .exportFromImportedHandleTypes = export_flags,
581
 
            .compatibleHandleTypes = compat_flags,
582
 
         };
583
 
   }
584
 
 
585
 
   return VK_SUCCESS;
586
 
}
587
 
 
588
 
VKAPI_ATTR VkResult VKAPI_CALL
589
 
tu_GetPhysicalDeviceImageFormatProperties2(
590
 
   VkPhysicalDevice physicalDevice,
591
 
   const VkPhysicalDeviceImageFormatInfo2 *base_info,
592
 
   VkImageFormatProperties2 *base_props)
593
 
{
594
 
   TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
595
 
   const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
596
 
   const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL;
597
 
   VkExternalImageFormatProperties *external_props = NULL;
598
 
   VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL;
599
 
   VkFormatFeatureFlags format_feature_flags;
600
 
   VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
601
 
   VkResult result;
602
 
 
603
 
   result = tu_get_image_format_properties(physical_device,
604
 
      base_info, &base_props->imageFormatProperties, &format_feature_flags);
605
 
   if (result != VK_SUCCESS)
606
 
      return result;
607
 
 
608
 
   /* Extract input structs */
609
 
   vk_foreach_struct_const(s, base_info->pNext)
610
 
   {
611
 
      switch (s->sType) {
612
 
      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
613
 
         external_info = (const void *) s;
614
 
         break;
615
 
      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:
616
 
         image_view_info = (const void *) s;
617
 
         break;
618
 
      default:
619
 
         break;
620
 
      }
621
 
   }
622
 
 
623
 
   /* Extract output structs */
624
 
   vk_foreach_struct(s, base_props->pNext)
625
 
   {
626
 
      switch (s->sType) {
627
 
      case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
628
 
         external_props = (void *) s;
629
 
         break;
630
 
      case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:
631
 
         cubic_props = (void *) s;
632
 
         break;
633
 
      case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
634
 
         ycbcr_props = (void *) s;
635
 
         break;
636
 
      default:
637
 
         break;
638
 
      }
639
 
   }
640
 
 
641
 
   /* From the Vulkan 1.0.42 spec:
642
 
    *
643
 
    *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
644
 
    *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
645
 
    *    present and VkExternalImageFormatProperties will be ignored.
646
 
    */
647
 
   if (external_info && external_info->handleType != 0) {
648
 
      result = tu_get_external_image_format_properties(
649
 
         physical_device, base_info, external_info->handleType,
650
 
         external_props);
651
 
      if (result != VK_SUCCESS)
652
 
         goto fail;
653
 
   }
654
 
 
655
 
   if (cubic_props) {
656
 
      /* note: blob only allows cubic filtering for 2D and 2D array views
657
 
       * its likely we can enable it for 1D and CUBE, needs testing however
658
 
       */
659
 
      if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D ||
660
 
           image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) &&
661
 
          (format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
662
 
         cubic_props->filterCubic = true;
663
 
         cubic_props->filterCubicMinmax = true;
664
 
      } else {
665
 
         cubic_props->filterCubic = false;
666
 
         cubic_props->filterCubicMinmax = false;
667
 
      }
668
 
   }
669
 
 
670
 
   if (ycbcr_props)
671
 
      ycbcr_props->combinedImageSamplerDescriptorCount = 1;
672
 
 
673
 
   return VK_SUCCESS;
674
 
 
675
 
fail:
676
 
   if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
677
 
      /* From the Vulkan 1.0.42 spec:
678
 
       *
679
 
       *    If the combination of parameters to
680
 
       *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by
681
 
       *    the implementation for use in vkCreateImage, then all members of
682
 
       *    imageFormatProperties will be filled with zero.
683
 
       */
684
 
      base_props->imageFormatProperties = (VkImageFormatProperties) {};
685
 
   }
686
 
 
687
 
   return result;
688
 
}
689
 
 
690
 
VKAPI_ATTR void VKAPI_CALL
691
 
tu_GetPhysicalDeviceSparseImageFormatProperties2(
692
 
   VkPhysicalDevice physicalDevice,
693
 
   const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
694
 
   uint32_t *pPropertyCount,
695
 
   VkSparseImageFormatProperties2 *pProperties)
696
 
{
697
 
   /* Sparse images are not yet supported. */
698
 
   *pPropertyCount = 0;
699
 
}
700
 
 
701
 
VKAPI_ATTR void VKAPI_CALL
702
 
tu_GetPhysicalDeviceExternalBufferProperties(
703
 
   VkPhysicalDevice physicalDevice,
704
 
   const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
705
 
   VkExternalBufferProperties *pExternalBufferProperties)
706
 
{
707
 
   VkExternalMemoryFeatureFlagBits flags = 0;
708
 
   VkExternalMemoryHandleTypeFlags export_flags = 0;
709
 
   VkExternalMemoryHandleTypeFlags compat_flags = 0;
710
 
   switch (pExternalBufferInfo->handleType) {
711
 
   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
712
 
   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
713
 
      flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
714
 
              VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
715
 
      compat_flags = export_flags =
716
 
         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
717
 
         VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
718
 
      break;
719
 
   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
720
 
      flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
721
 
      compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
722
 
      break;
723
 
   default:
724
 
      break;
725
 
   }
726
 
   pExternalBufferProperties->externalMemoryProperties =
727
 
      (VkExternalMemoryProperties) {
728
 
         .externalMemoryFeatures = flags,
729
 
         .exportFromImportedHandleTypes = export_flags,
730
 
         .compatibleHandleTypes = compat_flags,
731
 
      };
732
 
}