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