1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat.
3bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22bf215546Sopenharmony_ci * IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#include "radv_debug.h"
26bf215546Sopenharmony_ci#include "radv_private.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "sid.h"
29bf215546Sopenharmony_ci#include "vk_format.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "vk_util.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "ac_drm_fourcc.h"
34bf215546Sopenharmony_ci#include "util/format_r11g11b10f.h"
35bf215546Sopenharmony_ci#include "util/format_rgb9e5.h"
36bf215546Sopenharmony_ci#include "util/format_srgb.h"
37bf215546Sopenharmony_ci#include "util/half_float.h"
38bf215546Sopenharmony_ci#include "vulkan/util/vk_format.h"
39bf215546Sopenharmony_ci#include "vulkan/util/vk_enum_defines.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ciuint32_t
42bf215546Sopenharmony_ciradv_translate_buffer_dataformat(const struct util_format_description *desc, int first_non_void)
43bf215546Sopenharmony_ci{
44bf215546Sopenharmony_ci   unsigned type;
45bf215546Sopenharmony_ci   int i;
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci   assert(util_format_get_num_planes(desc->format) == 1);
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT)
50bf215546Sopenharmony_ci      return V_008F0C_BUF_DATA_FORMAT_10_11_11;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   if (first_non_void < 0)
53bf215546Sopenharmony_ci      return V_008F0C_BUF_DATA_FORMAT_INVALID;
54bf215546Sopenharmony_ci   type = desc->channel[first_non_void].type;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   if (type == UTIL_FORMAT_TYPE_FIXED)
57bf215546Sopenharmony_ci      return V_008F0C_BUF_DATA_FORMAT_INVALID;
58bf215546Sopenharmony_ci   if (desc->nr_channels == 4 && desc->channel[0].size == 10 && desc->channel[1].size == 10 &&
59bf215546Sopenharmony_ci       desc->channel[2].size == 10 && desc->channel[3].size == 2)
60bf215546Sopenharmony_ci      return V_008F0C_BUF_DATA_FORMAT_2_10_10_10;
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   /* See whether the components are of the same size. */
63bf215546Sopenharmony_ci   for (i = 0; i < desc->nr_channels; i++) {
64bf215546Sopenharmony_ci      if (desc->channel[first_non_void].size != desc->channel[i].size)
65bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_INVALID;
66bf215546Sopenharmony_ci   }
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   switch (desc->channel[first_non_void].size) {
69bf215546Sopenharmony_ci   case 8:
70bf215546Sopenharmony_ci      switch (desc->nr_channels) {
71bf215546Sopenharmony_ci      case 1:
72bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_8;
73bf215546Sopenharmony_ci      case 2:
74bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_8_8;
75bf215546Sopenharmony_ci      case 4:
76bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_8_8_8_8;
77bf215546Sopenharmony_ci      }
78bf215546Sopenharmony_ci      break;
79bf215546Sopenharmony_ci   case 16:
80bf215546Sopenharmony_ci      switch (desc->nr_channels) {
81bf215546Sopenharmony_ci      case 1:
82bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_16;
83bf215546Sopenharmony_ci      case 2:
84bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_16_16;
85bf215546Sopenharmony_ci      case 4:
86bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_16_16_16_16;
87bf215546Sopenharmony_ci      }
88bf215546Sopenharmony_ci      break;
89bf215546Sopenharmony_ci   case 32:
90bf215546Sopenharmony_ci      /* From the Southern Islands ISA documentation about MTBUF:
91bf215546Sopenharmony_ci       * 'Memory reads of data in memory that is 32 or 64 bits do not
92bf215546Sopenharmony_ci       * undergo any format conversion.'
93bf215546Sopenharmony_ci       */
94bf215546Sopenharmony_ci      if (type != UTIL_FORMAT_TYPE_FLOAT && !desc->channel[first_non_void].pure_integer)
95bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_INVALID;
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci      switch (desc->nr_channels) {
98bf215546Sopenharmony_ci      case 1:
99bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_32;
100bf215546Sopenharmony_ci      case 2:
101bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_32_32;
102bf215546Sopenharmony_ci      case 3:
103bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_32_32_32;
104bf215546Sopenharmony_ci      case 4:
105bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_32_32_32_32;
106bf215546Sopenharmony_ci      }
107bf215546Sopenharmony_ci      break;
108bf215546Sopenharmony_ci   case 64:
109bf215546Sopenharmony_ci      if (type != UTIL_FORMAT_TYPE_FLOAT && desc->nr_channels == 1)
110bf215546Sopenharmony_ci         return V_008F0C_BUF_DATA_FORMAT_32_32;
111bf215546Sopenharmony_ci   }
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   return V_008F0C_BUF_DATA_FORMAT_INVALID;
114bf215546Sopenharmony_ci}
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ciuint32_t
117bf215546Sopenharmony_ciradv_translate_buffer_numformat(const struct util_format_description *desc, int first_non_void)
118bf215546Sopenharmony_ci{
119bf215546Sopenharmony_ci   assert(util_format_get_num_planes(desc->format) == 1);
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   if (desc->format == PIPE_FORMAT_R11G11B10_FLOAT)
122bf215546Sopenharmony_ci      return V_008F0C_BUF_NUM_FORMAT_FLOAT;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   if (first_non_void < 0)
125bf215546Sopenharmony_ci      return ~0;
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci   switch (desc->channel[first_non_void].type) {
128bf215546Sopenharmony_ci   case UTIL_FORMAT_TYPE_SIGNED:
129bf215546Sopenharmony_ci      if (desc->channel[first_non_void].normalized)
130bf215546Sopenharmony_ci         return V_008F0C_BUF_NUM_FORMAT_SNORM;
131bf215546Sopenharmony_ci      else if (desc->channel[first_non_void].pure_integer)
132bf215546Sopenharmony_ci         return V_008F0C_BUF_NUM_FORMAT_SINT;
133bf215546Sopenharmony_ci      else
134bf215546Sopenharmony_ci         return V_008F0C_BUF_NUM_FORMAT_SSCALED;
135bf215546Sopenharmony_ci      break;
136bf215546Sopenharmony_ci   case UTIL_FORMAT_TYPE_UNSIGNED:
137bf215546Sopenharmony_ci      if (desc->channel[first_non_void].normalized)
138bf215546Sopenharmony_ci         return V_008F0C_BUF_NUM_FORMAT_UNORM;
139bf215546Sopenharmony_ci      else if (desc->channel[first_non_void].pure_integer)
140bf215546Sopenharmony_ci         return V_008F0C_BUF_NUM_FORMAT_UINT;
141bf215546Sopenharmony_ci      else
142bf215546Sopenharmony_ci         return V_008F0C_BUF_NUM_FORMAT_USCALED;
143bf215546Sopenharmony_ci      break;
144bf215546Sopenharmony_ci   case UTIL_FORMAT_TYPE_FLOAT:
145bf215546Sopenharmony_ci   default:
146bf215546Sopenharmony_ci      return V_008F0C_BUF_NUM_FORMAT_FLOAT;
147bf215546Sopenharmony_ci   }
148bf215546Sopenharmony_ci}
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_civoid
151bf215546Sopenharmony_ciradv_translate_vertex_format(const struct radv_physical_device *pdevice, VkFormat format,
152bf215546Sopenharmony_ci                             const struct util_format_description *desc, unsigned *dfmt,
153bf215546Sopenharmony_ci                             unsigned *nfmt, bool *post_shuffle,
154bf215546Sopenharmony_ci                             enum radv_vs_input_alpha_adjust *alpha_adjust)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci   assert(desc->channel[0].type != UTIL_FORMAT_TYPE_VOID);
157bf215546Sopenharmony_ci   *nfmt = radv_translate_buffer_numformat(desc, 0);
158bf215546Sopenharmony_ci   *dfmt = radv_translate_buffer_dataformat(desc, 0);
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   *alpha_adjust = ALPHA_ADJUST_NONE;
161bf215546Sopenharmony_ci   if (pdevice->rad_info.gfx_level <= GFX8 && pdevice->rad_info.family != CHIP_STONEY) {
162bf215546Sopenharmony_ci      switch (format) {
163bf215546Sopenharmony_ci      case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
164bf215546Sopenharmony_ci      case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
165bf215546Sopenharmony_ci         *alpha_adjust = ALPHA_ADJUST_SNORM;
166bf215546Sopenharmony_ci         break;
167bf215546Sopenharmony_ci      case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
168bf215546Sopenharmony_ci      case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
169bf215546Sopenharmony_ci         *alpha_adjust = ALPHA_ADJUST_SSCALED;
170bf215546Sopenharmony_ci         break;
171bf215546Sopenharmony_ci      case VK_FORMAT_A2R10G10B10_SINT_PACK32:
172bf215546Sopenharmony_ci      case VK_FORMAT_A2B10G10R10_SINT_PACK32:
173bf215546Sopenharmony_ci         *alpha_adjust = ALPHA_ADJUST_SINT;
174bf215546Sopenharmony_ci         break;
175bf215546Sopenharmony_ci      default:
176bf215546Sopenharmony_ci         break;
177bf215546Sopenharmony_ci      }
178bf215546Sopenharmony_ci   }
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   switch (format) {
181bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_UNORM:
182bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_SNORM:
183bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_USCALED:
184bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_SSCALED:
185bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_UINT:
186bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_SINT:
187bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_SRGB:
188bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
189bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
190bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
191bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
192bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_UINT_PACK32:
193bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_SINT_PACK32:
194bf215546Sopenharmony_ci      *post_shuffle = true;
195bf215546Sopenharmony_ci      break;
196bf215546Sopenharmony_ci   default:
197bf215546Sopenharmony_ci      *post_shuffle = false;
198bf215546Sopenharmony_ci      break;
199bf215546Sopenharmony_ci   }
200bf215546Sopenharmony_ci}
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ciuint32_t
203bf215546Sopenharmony_ciradv_translate_tex_dataformat(VkFormat format, const struct util_format_description *desc,
204bf215546Sopenharmony_ci                              int first_non_void)
205bf215546Sopenharmony_ci{
206bf215546Sopenharmony_ci   bool uniform = true;
207bf215546Sopenharmony_ci   int i;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   assert(vk_format_get_plane_count(format) == 1);
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   /* Colorspace (return non-RGB formats directly). */
212bf215546Sopenharmony_ci   switch (desc->colorspace) {
213bf215546Sopenharmony_ci      /* Depth stencil formats */
214bf215546Sopenharmony_ci   case UTIL_FORMAT_COLORSPACE_ZS:
215bf215546Sopenharmony_ci      switch (format) {
216bf215546Sopenharmony_ci      case VK_FORMAT_D16_UNORM:
217bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_16;
218bf215546Sopenharmony_ci      case VK_FORMAT_D24_UNORM_S8_UINT:
219bf215546Sopenharmony_ci      case VK_FORMAT_X8_D24_UNORM_PACK32:
220bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_8_24;
221bf215546Sopenharmony_ci      case VK_FORMAT_S8_UINT:
222bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_8;
223bf215546Sopenharmony_ci      case VK_FORMAT_D32_SFLOAT:
224bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_32;
225bf215546Sopenharmony_ci      case VK_FORMAT_D32_SFLOAT_S8_UINT:
226bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_X24_8_32;
227bf215546Sopenharmony_ci      default:
228bf215546Sopenharmony_ci         goto out_unknown;
229bf215546Sopenharmony_ci      }
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   case UTIL_FORMAT_COLORSPACE_YUV:
232bf215546Sopenharmony_ci      goto out_unknown; /* TODO */
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   default:
235bf215546Sopenharmony_ci      break;
236bf215546Sopenharmony_ci   }
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
239bf215546Sopenharmony_ci      switch (format) {
240bf215546Sopenharmony_ci      /* Don't ask me why this looks inverted. PAL does the same. */
241bf215546Sopenharmony_ci      case VK_FORMAT_G8B8G8R8_422_UNORM:
242bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BG_RG;
243bf215546Sopenharmony_ci      case VK_FORMAT_B8G8R8G8_422_UNORM:
244bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_GB_GR;
245bf215546Sopenharmony_ci      default:
246bf215546Sopenharmony_ci         goto out_unknown;
247bf215546Sopenharmony_ci      }
248bf215546Sopenharmony_ci   }
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
251bf215546Sopenharmony_ci      switch (format) {
252bf215546Sopenharmony_ci      case VK_FORMAT_BC4_UNORM_BLOCK:
253bf215546Sopenharmony_ci      case VK_FORMAT_BC4_SNORM_BLOCK:
254bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BC4;
255bf215546Sopenharmony_ci      case VK_FORMAT_BC5_UNORM_BLOCK:
256bf215546Sopenharmony_ci      case VK_FORMAT_BC5_SNORM_BLOCK:
257bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BC5;
258bf215546Sopenharmony_ci      default:
259bf215546Sopenharmony_ci         break;
260bf215546Sopenharmony_ci      }
261bf215546Sopenharmony_ci   }
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
264bf215546Sopenharmony_ci      switch (format) {
265bf215546Sopenharmony_ci      case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
266bf215546Sopenharmony_ci      case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
267bf215546Sopenharmony_ci      case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
268bf215546Sopenharmony_ci      case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
269bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BC1;
270bf215546Sopenharmony_ci      case VK_FORMAT_BC2_UNORM_BLOCK:
271bf215546Sopenharmony_ci      case VK_FORMAT_BC2_SRGB_BLOCK:
272bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BC2;
273bf215546Sopenharmony_ci      case VK_FORMAT_BC3_UNORM_BLOCK:
274bf215546Sopenharmony_ci      case VK_FORMAT_BC3_SRGB_BLOCK:
275bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BC3;
276bf215546Sopenharmony_ci      default:
277bf215546Sopenharmony_ci         break;
278bf215546Sopenharmony_ci      }
279bf215546Sopenharmony_ci   }
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_BPTC) {
282bf215546Sopenharmony_ci      switch (format) {
283bf215546Sopenharmony_ci      case VK_FORMAT_BC6H_UFLOAT_BLOCK:
284bf215546Sopenharmony_ci      case VK_FORMAT_BC6H_SFLOAT_BLOCK:
285bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BC6;
286bf215546Sopenharmony_ci      case VK_FORMAT_BC7_UNORM_BLOCK:
287bf215546Sopenharmony_ci      case VK_FORMAT_BC7_SRGB_BLOCK:
288bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_BC7;
289bf215546Sopenharmony_ci      default:
290bf215546Sopenharmony_ci         break;
291bf215546Sopenharmony_ci      }
292bf215546Sopenharmony_ci   }
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_ETC) {
295bf215546Sopenharmony_ci      switch (format) {
296bf215546Sopenharmony_ci      case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
297bf215546Sopenharmony_ci      case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
298bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_ETC2_RGB;
299bf215546Sopenharmony_ci      case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
300bf215546Sopenharmony_ci      case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
301bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA1;
302bf215546Sopenharmony_ci      case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
303bf215546Sopenharmony_ci      case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
304bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA;
305bf215546Sopenharmony_ci      case VK_FORMAT_EAC_R11_UNORM_BLOCK:
306bf215546Sopenharmony_ci      case VK_FORMAT_EAC_R11_SNORM_BLOCK:
307bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_ETC2_R;
308bf215546Sopenharmony_ci      case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
309bf215546Sopenharmony_ci      case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
310bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_ETC2_RG;
311bf215546Sopenharmony_ci      default:
312bf215546Sopenharmony_ci         break;
313bf215546Sopenharmony_ci      }
314bf215546Sopenharmony_ci   }
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci   if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
317bf215546Sopenharmony_ci      return V_008F14_IMG_DATA_FORMAT_5_9_9_9;
318bf215546Sopenharmony_ci   } else if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
319bf215546Sopenharmony_ci      return V_008F14_IMG_DATA_FORMAT_10_11_11;
320bf215546Sopenharmony_ci   }
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   /* R8G8Bx_SNORM - TODO CxV8U8 */
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci   /* hw cannot support mixed formats (except depth/stencil, since only
325bf215546Sopenharmony_ci    * depth is read).*/
326bf215546Sopenharmony_ci   if (desc->is_mixed && desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
327bf215546Sopenharmony_ci      goto out_unknown;
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   /* See whether the components are of the same size. */
330bf215546Sopenharmony_ci   for (i = 1; i < desc->nr_channels; i++) {
331bf215546Sopenharmony_ci      uniform = uniform && desc->channel[0].size == desc->channel[i].size;
332bf215546Sopenharmony_ci   }
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   /* Non-uniform formats. */
335bf215546Sopenharmony_ci   if (!uniform) {
336bf215546Sopenharmony_ci      switch (desc->nr_channels) {
337bf215546Sopenharmony_ci      case 3:
338bf215546Sopenharmony_ci         if (desc->channel[0].size == 5 && desc->channel[1].size == 6 &&
339bf215546Sopenharmony_ci             desc->channel[2].size == 5) {
340bf215546Sopenharmony_ci            return V_008F14_IMG_DATA_FORMAT_5_6_5;
341bf215546Sopenharmony_ci         }
342bf215546Sopenharmony_ci         goto out_unknown;
343bf215546Sopenharmony_ci      case 4:
344bf215546Sopenharmony_ci         if (desc->channel[0].size == 5 && desc->channel[1].size == 5 &&
345bf215546Sopenharmony_ci             desc->channel[2].size == 5 && desc->channel[3].size == 1) {
346bf215546Sopenharmony_ci            return V_008F14_IMG_DATA_FORMAT_1_5_5_5;
347bf215546Sopenharmony_ci         }
348bf215546Sopenharmony_ci         if (desc->channel[0].size == 1 && desc->channel[1].size == 5 &&
349bf215546Sopenharmony_ci             desc->channel[2].size == 5 && desc->channel[3].size == 5) {
350bf215546Sopenharmony_ci            return V_008F14_IMG_DATA_FORMAT_5_5_5_1;
351bf215546Sopenharmony_ci         }
352bf215546Sopenharmony_ci         if (desc->channel[0].size == 10 && desc->channel[1].size == 10 &&
353bf215546Sopenharmony_ci             desc->channel[2].size == 10 && desc->channel[3].size == 2) {
354bf215546Sopenharmony_ci            /* Closed VK driver does this also no 2/10/10/10 snorm */
355bf215546Sopenharmony_ci            if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[0].normalized)
356bf215546Sopenharmony_ci               goto out_unknown;
357bf215546Sopenharmony_ci            return V_008F14_IMG_DATA_FORMAT_2_10_10_10;
358bf215546Sopenharmony_ci         }
359bf215546Sopenharmony_ci         goto out_unknown;
360bf215546Sopenharmony_ci      }
361bf215546Sopenharmony_ci      goto out_unknown;
362bf215546Sopenharmony_ci   }
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   if (first_non_void < 0 || first_non_void > 3)
365bf215546Sopenharmony_ci      goto out_unknown;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   /* uniform formats */
368bf215546Sopenharmony_ci   switch (desc->channel[first_non_void].size) {
369bf215546Sopenharmony_ci   case 4:
370bf215546Sopenharmony_ci      switch (desc->nr_channels) {
371bf215546Sopenharmony_ci#if 0 /* Not supported for render targets */
372bf215546Sopenharmony_ci		case 2:
373bf215546Sopenharmony_ci			return V_008F14_IMG_DATA_FORMAT_4_4;
374bf215546Sopenharmony_ci#endif
375bf215546Sopenharmony_ci      case 4:
376bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_4_4_4_4;
377bf215546Sopenharmony_ci      }
378bf215546Sopenharmony_ci      break;
379bf215546Sopenharmony_ci   case 8:
380bf215546Sopenharmony_ci      switch (desc->nr_channels) {
381bf215546Sopenharmony_ci      case 1:
382bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_8;
383bf215546Sopenharmony_ci      case 2:
384bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_8_8;
385bf215546Sopenharmony_ci      case 4:
386bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_8_8_8_8;
387bf215546Sopenharmony_ci      }
388bf215546Sopenharmony_ci      break;
389bf215546Sopenharmony_ci   case 16:
390bf215546Sopenharmony_ci      switch (desc->nr_channels) {
391bf215546Sopenharmony_ci      case 1:
392bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_16;
393bf215546Sopenharmony_ci      case 2:
394bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_16_16;
395bf215546Sopenharmony_ci      case 4:
396bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_16_16_16_16;
397bf215546Sopenharmony_ci      }
398bf215546Sopenharmony_ci      break;
399bf215546Sopenharmony_ci   case 32:
400bf215546Sopenharmony_ci      switch (desc->nr_channels) {
401bf215546Sopenharmony_ci      case 1:
402bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_32;
403bf215546Sopenharmony_ci      case 2:
404bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_32_32;
405bf215546Sopenharmony_ci      case 3:
406bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_32_32_32;
407bf215546Sopenharmony_ci      case 4:
408bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_32_32_32_32;
409bf215546Sopenharmony_ci      }
410bf215546Sopenharmony_ci      break;
411bf215546Sopenharmony_ci   case 64:
412bf215546Sopenharmony_ci      if (desc->channel[0].type != UTIL_FORMAT_TYPE_FLOAT && desc->nr_channels == 1)
413bf215546Sopenharmony_ci         return V_008F14_IMG_DATA_FORMAT_32_32;
414bf215546Sopenharmony_ci      break;
415bf215546Sopenharmony_ci   }
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_ciout_unknown:
418bf215546Sopenharmony_ci   /* R600_ERR("Unable to handle texformat %d %s\n", format, vk_format_name(format)); */
419bf215546Sopenharmony_ci   return ~0;
420bf215546Sopenharmony_ci}
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ciuint32_t
423bf215546Sopenharmony_ciradv_translate_tex_numformat(VkFormat format, const struct util_format_description *desc,
424bf215546Sopenharmony_ci                             int first_non_void)
425bf215546Sopenharmony_ci{
426bf215546Sopenharmony_ci   assert(vk_format_get_plane_count(format) == 1);
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   switch (format) {
429bf215546Sopenharmony_ci   case VK_FORMAT_D24_UNORM_S8_UINT:
430bf215546Sopenharmony_ci      return V_008F14_IMG_NUM_FORMAT_UNORM;
431bf215546Sopenharmony_ci   default:
432bf215546Sopenharmony_ci      if (first_non_void < 0) {
433bf215546Sopenharmony_ci         if (vk_format_is_compressed(format)) {
434bf215546Sopenharmony_ci            switch (format) {
435bf215546Sopenharmony_ci            case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
436bf215546Sopenharmony_ci            case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
437bf215546Sopenharmony_ci            case VK_FORMAT_BC2_SRGB_BLOCK:
438bf215546Sopenharmony_ci            case VK_FORMAT_BC3_SRGB_BLOCK:
439bf215546Sopenharmony_ci            case VK_FORMAT_BC7_SRGB_BLOCK:
440bf215546Sopenharmony_ci            case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
441bf215546Sopenharmony_ci            case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
442bf215546Sopenharmony_ci            case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
443bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_SRGB;
444bf215546Sopenharmony_ci            case VK_FORMAT_BC4_SNORM_BLOCK:
445bf215546Sopenharmony_ci            case VK_FORMAT_BC5_SNORM_BLOCK:
446bf215546Sopenharmony_ci            case VK_FORMAT_BC6H_SFLOAT_BLOCK:
447bf215546Sopenharmony_ci            case VK_FORMAT_EAC_R11_SNORM_BLOCK:
448bf215546Sopenharmony_ci            case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
449bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_SNORM;
450bf215546Sopenharmony_ci            default:
451bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_UNORM;
452bf215546Sopenharmony_ci            }
453bf215546Sopenharmony_ci         } else if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
454bf215546Sopenharmony_ci            return V_008F14_IMG_NUM_FORMAT_UNORM;
455bf215546Sopenharmony_ci         } else {
456bf215546Sopenharmony_ci            return V_008F14_IMG_NUM_FORMAT_FLOAT;
457bf215546Sopenharmony_ci         }
458bf215546Sopenharmony_ci      } else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
459bf215546Sopenharmony_ci         return V_008F14_IMG_NUM_FORMAT_SRGB;
460bf215546Sopenharmony_ci      } else {
461bf215546Sopenharmony_ci         switch (desc->channel[first_non_void].type) {
462bf215546Sopenharmony_ci         case UTIL_FORMAT_TYPE_FLOAT:
463bf215546Sopenharmony_ci            return V_008F14_IMG_NUM_FORMAT_FLOAT;
464bf215546Sopenharmony_ci         case UTIL_FORMAT_TYPE_SIGNED:
465bf215546Sopenharmony_ci            if (desc->channel[first_non_void].normalized)
466bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_SNORM;
467bf215546Sopenharmony_ci            else if (desc->channel[first_non_void].pure_integer)
468bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_SINT;
469bf215546Sopenharmony_ci            else
470bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_SSCALED;
471bf215546Sopenharmony_ci         case UTIL_FORMAT_TYPE_UNSIGNED:
472bf215546Sopenharmony_ci            if (desc->channel[first_non_void].normalized)
473bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_UNORM;
474bf215546Sopenharmony_ci            else if (desc->channel[first_non_void].pure_integer)
475bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_UINT;
476bf215546Sopenharmony_ci            else
477bf215546Sopenharmony_ci               return V_008F14_IMG_NUM_FORMAT_USCALED;
478bf215546Sopenharmony_ci         default:
479bf215546Sopenharmony_ci            return V_008F14_IMG_NUM_FORMAT_UNORM;
480bf215546Sopenharmony_ci         }
481bf215546Sopenharmony_ci      }
482bf215546Sopenharmony_ci   }
483bf215546Sopenharmony_ci}
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ciuint32_t
486bf215546Sopenharmony_ciradv_translate_color_numformat(VkFormat format, const struct util_format_description *desc,
487bf215546Sopenharmony_ci                               int first_non_void)
488bf215546Sopenharmony_ci{
489bf215546Sopenharmony_ci   unsigned ntype;
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   assert(vk_format_get_plane_count(format) == 1);
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   if (first_non_void == -1 || desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_FLOAT)
494bf215546Sopenharmony_ci      ntype = V_028C70_NUMBER_FLOAT;
495bf215546Sopenharmony_ci   else {
496bf215546Sopenharmony_ci      ntype = V_028C70_NUMBER_UNORM;
497bf215546Sopenharmony_ci      if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
498bf215546Sopenharmony_ci         ntype = V_028C70_NUMBER_SRGB;
499bf215546Sopenharmony_ci      else if (desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_SIGNED) {
500bf215546Sopenharmony_ci         if (desc->channel[first_non_void].pure_integer) {
501bf215546Sopenharmony_ci            ntype = V_028C70_NUMBER_SINT;
502bf215546Sopenharmony_ci         } else if (desc->channel[first_non_void].normalized) {
503bf215546Sopenharmony_ci            ntype = V_028C70_NUMBER_SNORM;
504bf215546Sopenharmony_ci         } else
505bf215546Sopenharmony_ci            ntype = ~0u;
506bf215546Sopenharmony_ci      } else if (desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_UNSIGNED) {
507bf215546Sopenharmony_ci         if (desc->channel[first_non_void].pure_integer) {
508bf215546Sopenharmony_ci            ntype = V_028C70_NUMBER_UINT;
509bf215546Sopenharmony_ci         } else if (desc->channel[first_non_void].normalized) {
510bf215546Sopenharmony_ci            ntype = V_028C70_NUMBER_UNORM;
511bf215546Sopenharmony_ci         } else
512bf215546Sopenharmony_ci            ntype = ~0u;
513bf215546Sopenharmony_ci      }
514bf215546Sopenharmony_ci   }
515bf215546Sopenharmony_ci   return ntype;
516bf215546Sopenharmony_ci}
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_cistatic bool
519bf215546Sopenharmony_ciradv_is_sampler_format_supported(VkFormat format, bool *linear_sampling)
520bf215546Sopenharmony_ci{
521bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
522bf215546Sopenharmony_ci   uint32_t num_format;
523bf215546Sopenharmony_ci   if (format == VK_FORMAT_UNDEFINED || format == VK_FORMAT_R64_UINT ||
524bf215546Sopenharmony_ci       format == VK_FORMAT_R64_SINT)
525bf215546Sopenharmony_ci      return false;
526bf215546Sopenharmony_ci   num_format =
527bf215546Sopenharmony_ci      radv_translate_tex_numformat(format, desc, vk_format_get_first_non_void_channel(format));
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_ci   if (num_format == V_008F14_IMG_NUM_FORMAT_USCALED ||
530bf215546Sopenharmony_ci       num_format == V_008F14_IMG_NUM_FORMAT_SSCALED)
531bf215546Sopenharmony_ci      return false;
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci   if (num_format == V_008F14_IMG_NUM_FORMAT_UNORM || num_format == V_008F14_IMG_NUM_FORMAT_SNORM ||
534bf215546Sopenharmony_ci       num_format == V_008F14_IMG_NUM_FORMAT_FLOAT || num_format == V_008F14_IMG_NUM_FORMAT_SRGB)
535bf215546Sopenharmony_ci      *linear_sampling = true;
536bf215546Sopenharmony_ci   else
537bf215546Sopenharmony_ci      *linear_sampling = false;
538bf215546Sopenharmony_ci   return radv_translate_tex_dataformat(format, vk_format_description(format),
539bf215546Sopenharmony_ci                                        vk_format_get_first_non_void_channel(format)) != ~0U;
540bf215546Sopenharmony_ci}
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_cibool
543bf215546Sopenharmony_ciradv_is_atomic_format_supported(VkFormat format)
544bf215546Sopenharmony_ci{
545bf215546Sopenharmony_ci   return format == VK_FORMAT_R32_UINT || format == VK_FORMAT_R32_SINT ||
546bf215546Sopenharmony_ci          format == VK_FORMAT_R32_SFLOAT || format == VK_FORMAT_R64_UINT ||
547bf215546Sopenharmony_ci          format == VK_FORMAT_R64_SINT;
548bf215546Sopenharmony_ci}
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_cibool
551bf215546Sopenharmony_ciradv_is_storage_image_format_supported(struct radv_physical_device *physical_device,
552bf215546Sopenharmony_ci                                       VkFormat format)
553bf215546Sopenharmony_ci{
554bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
555bf215546Sopenharmony_ci   unsigned data_format, num_format;
556bf215546Sopenharmony_ci   if (format == VK_FORMAT_UNDEFINED)
557bf215546Sopenharmony_ci      return false;
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci   data_format =
560bf215546Sopenharmony_ci      radv_translate_tex_dataformat(format, desc, vk_format_get_first_non_void_channel(format));
561bf215546Sopenharmony_ci   num_format =
562bf215546Sopenharmony_ci      radv_translate_tex_numformat(format, desc, vk_format_get_first_non_void_channel(format));
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci   if (data_format == ~0 || num_format == ~0)
565bf215546Sopenharmony_ci      return false;
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   /* Extracted from the GCN3 ISA document. */
568bf215546Sopenharmony_ci   switch (num_format) {
569bf215546Sopenharmony_ci   case V_008F14_IMG_NUM_FORMAT_UNORM:
570bf215546Sopenharmony_ci   case V_008F14_IMG_NUM_FORMAT_SNORM:
571bf215546Sopenharmony_ci   case V_008F14_IMG_NUM_FORMAT_UINT:
572bf215546Sopenharmony_ci   case V_008F14_IMG_NUM_FORMAT_SINT:
573bf215546Sopenharmony_ci   case V_008F14_IMG_NUM_FORMAT_FLOAT:
574bf215546Sopenharmony_ci      break;
575bf215546Sopenharmony_ci   default:
576bf215546Sopenharmony_ci      return false;
577bf215546Sopenharmony_ci   }
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   switch (data_format) {
580bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_8:
581bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_16:
582bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_8_8:
583bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_32:
584bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_16_16:
585bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_10_11_11:
586bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_11_11_10:
587bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_10_10_10_2:
588bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_2_10_10_10:
589bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_8_8_8_8:
590bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_32_32:
591bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_16_16_16_16:
592bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_32_32_32_32:
593bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_5_6_5:
594bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_1_5_5_5:
595bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_5_5_5_1:
596bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_4_4_4_4:
597bf215546Sopenharmony_ci      /* TODO: FMASK formats. */
598bf215546Sopenharmony_ci      return true;
599bf215546Sopenharmony_ci   case V_008F14_IMG_DATA_FORMAT_5_9_9_9:
600bf215546Sopenharmony_ci      return physical_device->rad_info.gfx_level >= GFX10_3;
601bf215546Sopenharmony_ci   default:
602bf215546Sopenharmony_ci      return false;
603bf215546Sopenharmony_ci   }
604bf215546Sopenharmony_ci}
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_cibool
607bf215546Sopenharmony_ciradv_is_buffer_format_supported(VkFormat format, bool *scaled)
608bf215546Sopenharmony_ci{
609bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
610bf215546Sopenharmony_ci   unsigned data_format, num_format;
611bf215546Sopenharmony_ci   if (format == VK_FORMAT_UNDEFINED)
612bf215546Sopenharmony_ci      return false;
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_ci   data_format =
615bf215546Sopenharmony_ci      radv_translate_buffer_dataformat(desc, vk_format_get_first_non_void_channel(format));
616bf215546Sopenharmony_ci   num_format = radv_translate_buffer_numformat(desc, vk_format_get_first_non_void_channel(format));
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci   if (scaled)
619bf215546Sopenharmony_ci      *scaled = (num_format == V_008F0C_BUF_NUM_FORMAT_SSCALED) ||
620bf215546Sopenharmony_ci                (num_format == V_008F0C_BUF_NUM_FORMAT_USCALED);
621bf215546Sopenharmony_ci   return data_format != V_008F0C_BUF_DATA_FORMAT_INVALID && num_format != ~0;
622bf215546Sopenharmony_ci}
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_cibool
625bf215546Sopenharmony_ciradv_is_colorbuffer_format_supported(const struct radv_physical_device *pdevice, VkFormat format,
626bf215546Sopenharmony_ci                                     bool *blendable)
627bf215546Sopenharmony_ci{
628bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
629bf215546Sopenharmony_ci   uint32_t color_format = radv_translate_colorformat(format);
630bf215546Sopenharmony_ci   uint32_t color_swap = radv_translate_colorswap(format, false);
631bf215546Sopenharmony_ci   uint32_t color_num_format =
632bf215546Sopenharmony_ci      radv_translate_color_numformat(format, desc, vk_format_get_first_non_void_channel(format));
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci   if (color_num_format == V_028C70_NUMBER_UINT || color_num_format == V_028C70_NUMBER_SINT ||
635bf215546Sopenharmony_ci       color_format == V_028C70_COLOR_8_24 || color_format == V_028C70_COLOR_24_8 ||
636bf215546Sopenharmony_ci       color_format == V_028C70_COLOR_X24_8_32_FLOAT) {
637bf215546Sopenharmony_ci      *blendable = false;
638bf215546Sopenharmony_ci   } else
639bf215546Sopenharmony_ci      *blendable = true;
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci   if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 && pdevice->rad_info.gfx_level < GFX10_3)
642bf215546Sopenharmony_ci      return false;
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci   return color_format != V_028C70_COLOR_INVALID && color_swap != ~0U && color_num_format != ~0;
645bf215546Sopenharmony_ci}
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_cistatic bool
648bf215546Sopenharmony_ciradv_is_zs_format_supported(VkFormat format)
649bf215546Sopenharmony_ci{
650bf215546Sopenharmony_ci   return radv_translate_dbformat(format) != V_028040_Z_INVALID || format == VK_FORMAT_S8_UINT;
651bf215546Sopenharmony_ci}
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_cistatic bool
654bf215546Sopenharmony_ciradv_is_filter_minmax_format_supported(VkFormat format)
655bf215546Sopenharmony_ci{
656bf215546Sopenharmony_ci   /* From the Vulkan spec 1.1.71:
657bf215546Sopenharmony_ci    *
658bf215546Sopenharmony_ci    * "The following formats must support the
659bf215546Sopenharmony_ci    *  VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT feature with
660bf215546Sopenharmony_ci    *  VK_IMAGE_TILING_OPTIMAL, if they support
661bf215546Sopenharmony_ci    *  VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT."
662bf215546Sopenharmony_ci    */
663bf215546Sopenharmony_ci   /* TODO: enable more formats. */
664bf215546Sopenharmony_ci   switch (format) {
665bf215546Sopenharmony_ci   case VK_FORMAT_R8_UNORM:
666bf215546Sopenharmony_ci   case VK_FORMAT_R8_SNORM:
667bf215546Sopenharmony_ci   case VK_FORMAT_R16_UNORM:
668bf215546Sopenharmony_ci   case VK_FORMAT_R16_SNORM:
669bf215546Sopenharmony_ci   case VK_FORMAT_R16_SFLOAT:
670bf215546Sopenharmony_ci   case VK_FORMAT_R32_SFLOAT:
671bf215546Sopenharmony_ci   case VK_FORMAT_D16_UNORM:
672bf215546Sopenharmony_ci   case VK_FORMAT_X8_D24_UNORM_PACK32:
673bf215546Sopenharmony_ci   case VK_FORMAT_D32_SFLOAT:
674bf215546Sopenharmony_ci   case VK_FORMAT_D16_UNORM_S8_UINT:
675bf215546Sopenharmony_ci   case VK_FORMAT_D24_UNORM_S8_UINT:
676bf215546Sopenharmony_ci   case VK_FORMAT_D32_SFLOAT_S8_UINT:
677bf215546Sopenharmony_ci      return true;
678bf215546Sopenharmony_ci   default:
679bf215546Sopenharmony_ci      return false;
680bf215546Sopenharmony_ci   }
681bf215546Sopenharmony_ci}
682bf215546Sopenharmony_ci
683bf215546Sopenharmony_cibool
684bf215546Sopenharmony_ciradv_device_supports_etc(struct radv_physical_device *physical_device)
685bf215546Sopenharmony_ci{
686bf215546Sopenharmony_ci   return physical_device->rad_info.family == CHIP_VEGA10 ||
687bf215546Sopenharmony_ci          physical_device->rad_info.family == CHIP_RAVEN ||
688bf215546Sopenharmony_ci          physical_device->rad_info.family == CHIP_RAVEN2 ||
689bf215546Sopenharmony_ci          physical_device->rad_info.family == CHIP_STONEY;
690bf215546Sopenharmony_ci}
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_cistatic void
693bf215546Sopenharmony_ciradv_physical_device_get_format_properties(struct radv_physical_device *physical_device,
694bf215546Sopenharmony_ci                                           VkFormat format, VkFormatProperties3 *out_properties)
695bf215546Sopenharmony_ci{
696bf215546Sopenharmony_ci   VkFormatFeatureFlags2 linear = 0, tiled = 0, buffer = 0;
697bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
698bf215546Sopenharmony_ci   bool blendable;
699bf215546Sopenharmony_ci   bool scaled = false;
700bf215546Sopenharmony_ci   /* TODO: implement some software emulation of SUBSAMPLED formats. */
701bf215546Sopenharmony_ci   if (desc->format == PIPE_FORMAT_NONE || desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
702bf215546Sopenharmony_ci      out_properties->linearTilingFeatures = linear;
703bf215546Sopenharmony_ci      out_properties->optimalTilingFeatures = tiled;
704bf215546Sopenharmony_ci      out_properties->bufferFeatures = buffer;
705bf215546Sopenharmony_ci      return;
706bf215546Sopenharmony_ci   }
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_ETC && !radv_device_supports_etc(physical_device) &&
709bf215546Sopenharmony_ci       !physical_device->emulate_etc2) {
710bf215546Sopenharmony_ci      out_properties->linearTilingFeatures = linear;
711bf215546Sopenharmony_ci      out_properties->optimalTilingFeatures = tiled;
712bf215546Sopenharmony_ci      out_properties->bufferFeatures = buffer;
713bf215546Sopenharmony_ci      return;
714bf215546Sopenharmony_ci   }
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci   const bool multiplanar = vk_format_get_plane_count(format) > 1;
717bf215546Sopenharmony_ci   if (multiplanar || desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
718bf215546Sopenharmony_ci      uint64_t tiling = VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
719bf215546Sopenharmony_ci                        VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
720bf215546Sopenharmony_ci                        VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
721bf215546Sopenharmony_ci                        VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT |
722bf215546Sopenharmony_ci                        VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci      /* The subsampled formats have no support for linear filters. */
725bf215546Sopenharmony_ci      if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
726bf215546Sopenharmony_ci         tiling |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
727bf215546Sopenharmony_ci      }
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci      if (multiplanar)
730bf215546Sopenharmony_ci         tiling |= VK_FORMAT_FEATURE_2_DISJOINT_BIT;
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_ci      /* Fails for unknown reasons with linear tiling & subsampled formats. */
733bf215546Sopenharmony_ci      out_properties->linearTilingFeatures =
734bf215546Sopenharmony_ci         desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED ? 0 : tiling;
735bf215546Sopenharmony_ci      out_properties->optimalTilingFeatures = tiling;
736bf215546Sopenharmony_ci      out_properties->bufferFeatures = 0;
737bf215546Sopenharmony_ci      return;
738bf215546Sopenharmony_ci   }
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_ci   if (radv_is_storage_image_format_supported(physical_device, format)) {
741bf215546Sopenharmony_ci      tiled |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
742bf215546Sopenharmony_ci               VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
743bf215546Sopenharmony_ci               VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
744bf215546Sopenharmony_ci      linear |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
745bf215546Sopenharmony_ci                VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
746bf215546Sopenharmony_ci                VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
747bf215546Sopenharmony_ci   }
748bf215546Sopenharmony_ci
749bf215546Sopenharmony_ci   if (radv_is_buffer_format_supported(format, &scaled)) {
750bf215546Sopenharmony_ci      if (format != VK_FORMAT_R64_UINT && format != VK_FORMAT_R64_SINT &&
751bf215546Sopenharmony_ci          !vk_format_is_srgb(format)) {
752bf215546Sopenharmony_ci         buffer |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT;
753bf215546Sopenharmony_ci         if (!scaled)
754bf215546Sopenharmony_ci            buffer |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT;
755bf215546Sopenharmony_ci      }
756bf215546Sopenharmony_ci      buffer |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT |
757bf215546Sopenharmony_ci                VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
758bf215546Sopenharmony_ci                VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
759bf215546Sopenharmony_ci   }
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_ci   if (vk_format_is_depth_or_stencil(format)) {
762bf215546Sopenharmony_ci      if (radv_is_zs_format_supported(format)) {
763bf215546Sopenharmony_ci         tiled |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
764bf215546Sopenharmony_ci         tiled |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT;
765bf215546Sopenharmony_ci         tiled |= VK_FORMAT_FEATURE_2_BLIT_SRC_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
766bf215546Sopenharmony_ci         tiled |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci         if (radv_is_filter_minmax_format_supported(format))
769bf215546Sopenharmony_ci            tiled |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
770bf215546Sopenharmony_ci
771bf215546Sopenharmony_ci         if (vk_format_has_depth(format)) {
772bf215546Sopenharmony_ci            tiled |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
773bf215546Sopenharmony_ci                     VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
774bf215546Sopenharmony_ci         }
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci         /* Don't support blitting surfaces with depth/stencil. */
777bf215546Sopenharmony_ci         if (vk_format_has_depth(format) && vk_format_has_stencil(format))
778bf215546Sopenharmony_ci            tiled &= ~VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci         /* Don't support linear depth surfaces */
781bf215546Sopenharmony_ci         linear = 0;
782bf215546Sopenharmony_ci      }
783bf215546Sopenharmony_ci   } else {
784bf215546Sopenharmony_ci      bool linear_sampling;
785bf215546Sopenharmony_ci      if (radv_is_sampler_format_supported(format, &linear_sampling)) {
786bf215546Sopenharmony_ci         linear |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
787bf215546Sopenharmony_ci         tiled |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
788bf215546Sopenharmony_ci
789bf215546Sopenharmony_ci         if (radv_is_filter_minmax_format_supported(format))
790bf215546Sopenharmony_ci            tiled |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
791bf215546Sopenharmony_ci
792bf215546Sopenharmony_ci         if (linear_sampling) {
793bf215546Sopenharmony_ci            linear |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
794bf215546Sopenharmony_ci            tiled |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
795bf215546Sopenharmony_ci         }
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci         /* Don't support blitting for R32G32B32 formats. */
798bf215546Sopenharmony_ci         if (format == VK_FORMAT_R32G32B32_SFLOAT || format == VK_FORMAT_R32G32B32_UINT ||
799bf215546Sopenharmony_ci             format == VK_FORMAT_R32G32B32_SINT) {
800bf215546Sopenharmony_ci            linear &= ~VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
801bf215546Sopenharmony_ci         }
802bf215546Sopenharmony_ci      }
803bf215546Sopenharmony_ci      if (radv_is_colorbuffer_format_supported(physical_device, format, &blendable)) {
804bf215546Sopenharmony_ci         linear |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
805bf215546Sopenharmony_ci         tiled |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
806bf215546Sopenharmony_ci         if (blendable) {
807bf215546Sopenharmony_ci            linear |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
808bf215546Sopenharmony_ci            tiled |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
809bf215546Sopenharmony_ci         }
810bf215546Sopenharmony_ci      }
811bf215546Sopenharmony_ci      if (tiled && !scaled) {
812bf215546Sopenharmony_ci         tiled |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
813bf215546Sopenharmony_ci      }
814bf215546Sopenharmony_ci
815bf215546Sopenharmony_ci      /* Tiled formatting does not support NPOT pixel sizes */
816bf215546Sopenharmony_ci      if (!util_is_power_of_two_or_zero(vk_format_get_blocksize(format)))
817bf215546Sopenharmony_ci         tiled = 0;
818bf215546Sopenharmony_ci   }
819bf215546Sopenharmony_ci
820bf215546Sopenharmony_ci   if (linear && !scaled) {
821bf215546Sopenharmony_ci      linear |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
822bf215546Sopenharmony_ci   }
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_ci   if (radv_is_atomic_format_supported(format)) {
825bf215546Sopenharmony_ci      buffer |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
826bf215546Sopenharmony_ci      linear |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
827bf215546Sopenharmony_ci      tiled |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
828bf215546Sopenharmony_ci   }
829bf215546Sopenharmony_ci
830bf215546Sopenharmony_ci   switch (format) {
831bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
832bf215546Sopenharmony_ci   case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
833bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
834bf215546Sopenharmony_ci   case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
835bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_SINT_PACK32:
836bf215546Sopenharmony_ci   case VK_FORMAT_A2B10G10R10_SINT_PACK32:
837bf215546Sopenharmony_ci      buffer &=
838bf215546Sopenharmony_ci         ~(VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT);
839bf215546Sopenharmony_ci      linear = 0;
840bf215546Sopenharmony_ci      tiled = 0;
841bf215546Sopenharmony_ci      break;
842bf215546Sopenharmony_ci   default:
843bf215546Sopenharmony_ci      break;
844bf215546Sopenharmony_ci   }
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ci   switch (format) {
847bf215546Sopenharmony_ci   case VK_FORMAT_R32G32_SFLOAT:
848bf215546Sopenharmony_ci   case VK_FORMAT_R32G32B32_SFLOAT:
849bf215546Sopenharmony_ci   case VK_FORMAT_R32G32B32A32_SFLOAT:
850bf215546Sopenharmony_ci   case VK_FORMAT_R16G16_SFLOAT:
851bf215546Sopenharmony_ci   case VK_FORMAT_R16G16B16_SFLOAT:
852bf215546Sopenharmony_ci   case VK_FORMAT_R16G16B16A16_SFLOAT:
853bf215546Sopenharmony_ci   case VK_FORMAT_R16G16_SNORM:
854bf215546Sopenharmony_ci   case VK_FORMAT_R16G16_UNORM:
855bf215546Sopenharmony_ci   case VK_FORMAT_R16G16B16A16_SNORM:
856bf215546Sopenharmony_ci   case VK_FORMAT_R16G16B16A16_UNORM:
857bf215546Sopenharmony_ci   case VK_FORMAT_R8G8_SNORM:
858bf215546Sopenharmony_ci   case VK_FORMAT_R8G8_UNORM:
859bf215546Sopenharmony_ci   case VK_FORMAT_R8G8B8A8_SNORM:
860bf215546Sopenharmony_ci   case VK_FORMAT_R8G8B8A8_UNORM:
861bf215546Sopenharmony_ci   case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
862bf215546Sopenharmony_ci      buffer |= VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR;
863bf215546Sopenharmony_ci      break;
864bf215546Sopenharmony_ci   default:
865bf215546Sopenharmony_ci      break;
866bf215546Sopenharmony_ci   }
867bf215546Sopenharmony_ci   /* addrlib does not support linear compressed textures. */
868bf215546Sopenharmony_ci   if (vk_format_is_compressed(format))
869bf215546Sopenharmony_ci      linear = 0;
870bf215546Sopenharmony_ci
871bf215546Sopenharmony_ci   /* From the Vulkan spec 1.2.163:
872bf215546Sopenharmony_ci    *
873bf215546Sopenharmony_ci    * "VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT must be supported for the
874bf215546Sopenharmony_ci    *  following formats if the attachmentFragmentShadingRate feature is supported:"
875bf215546Sopenharmony_ci    *
876bf215546Sopenharmony_ci    * - VK_FORMAT_R8_UINT
877bf215546Sopenharmony_ci    */
878bf215546Sopenharmony_ci   if (format == VK_FORMAT_R8_UINT) {
879bf215546Sopenharmony_ci      tiled |= VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
880bf215546Sopenharmony_ci   }
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci   /* It's invalid to expose buffer features with depth/stencil formats. */
883bf215546Sopenharmony_ci   if (vk_format_is_depth_or_stencil(format)) {
884bf215546Sopenharmony_ci      buffer = 0;
885bf215546Sopenharmony_ci   }
886bf215546Sopenharmony_ci
887bf215546Sopenharmony_ci   out_properties->linearTilingFeatures = linear;
888bf215546Sopenharmony_ci   out_properties->optimalTilingFeatures = tiled;
889bf215546Sopenharmony_ci   out_properties->bufferFeatures = buffer;
890bf215546Sopenharmony_ci}
891bf215546Sopenharmony_ci
892bf215546Sopenharmony_ciuint32_t
893bf215546Sopenharmony_ciradv_translate_colorformat(VkFormat format)
894bf215546Sopenharmony_ci{
895bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_ci#define HAS_SIZE(x, y, z, w)                                                                       \
898bf215546Sopenharmony_ci   (desc->channel[0].size == (x) && desc->channel[1].size == (y) &&                                \
899bf215546Sopenharmony_ci    desc->channel[2].size == (z) && desc->channel[3].size == (w))
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci   if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) /* isn't plain */
902bf215546Sopenharmony_ci      return V_028C70_COLOR_10_11_11;
903bf215546Sopenharmony_ci
904bf215546Sopenharmony_ci   if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)
905bf215546Sopenharmony_ci      return V_028C70_COLOR_5_9_9_9;
906bf215546Sopenharmony_ci
907bf215546Sopenharmony_ci   if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)
908bf215546Sopenharmony_ci      return V_028C70_COLOR_INVALID;
909bf215546Sopenharmony_ci
910bf215546Sopenharmony_ci   /* hw cannot support mixed formats (except depth/stencil, since
911bf215546Sopenharmony_ci    * stencil is not written to). */
912bf215546Sopenharmony_ci   if (desc->is_mixed && desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
913bf215546Sopenharmony_ci      return V_028C70_COLOR_INVALID;
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ci   switch (desc->nr_channels) {
916bf215546Sopenharmony_ci   case 1:
917bf215546Sopenharmony_ci      switch (desc->channel[0].size) {
918bf215546Sopenharmony_ci      case 8:
919bf215546Sopenharmony_ci         return V_028C70_COLOR_8;
920bf215546Sopenharmony_ci      case 16:
921bf215546Sopenharmony_ci         return V_028C70_COLOR_16;
922bf215546Sopenharmony_ci      case 32:
923bf215546Sopenharmony_ci         return V_028C70_COLOR_32;
924bf215546Sopenharmony_ci      }
925bf215546Sopenharmony_ci      break;
926bf215546Sopenharmony_ci   case 2:
927bf215546Sopenharmony_ci      if (desc->channel[0].size == desc->channel[1].size) {
928bf215546Sopenharmony_ci         switch (desc->channel[0].size) {
929bf215546Sopenharmony_ci         case 8:
930bf215546Sopenharmony_ci            return V_028C70_COLOR_8_8;
931bf215546Sopenharmony_ci         case 16:
932bf215546Sopenharmony_ci            return V_028C70_COLOR_16_16;
933bf215546Sopenharmony_ci         case 32:
934bf215546Sopenharmony_ci            return V_028C70_COLOR_32_32;
935bf215546Sopenharmony_ci         }
936bf215546Sopenharmony_ci      } else if (HAS_SIZE(8, 24, 0, 0)) {
937bf215546Sopenharmony_ci         return V_028C70_COLOR_24_8;
938bf215546Sopenharmony_ci      } else if (HAS_SIZE(24, 8, 0, 0)) {
939bf215546Sopenharmony_ci         return V_028C70_COLOR_8_24;
940bf215546Sopenharmony_ci      }
941bf215546Sopenharmony_ci      break;
942bf215546Sopenharmony_ci   case 3:
943bf215546Sopenharmony_ci      if (HAS_SIZE(5, 6, 5, 0)) {
944bf215546Sopenharmony_ci         return V_028C70_COLOR_5_6_5;
945bf215546Sopenharmony_ci      } else if (HAS_SIZE(32, 8, 24, 0)) {
946bf215546Sopenharmony_ci         return V_028C70_COLOR_X24_8_32_FLOAT;
947bf215546Sopenharmony_ci      }
948bf215546Sopenharmony_ci      break;
949bf215546Sopenharmony_ci   case 4:
950bf215546Sopenharmony_ci      if (desc->channel[0].size == desc->channel[1].size &&
951bf215546Sopenharmony_ci          desc->channel[0].size == desc->channel[2].size &&
952bf215546Sopenharmony_ci          desc->channel[0].size == desc->channel[3].size) {
953bf215546Sopenharmony_ci         switch (desc->channel[0].size) {
954bf215546Sopenharmony_ci         case 4:
955bf215546Sopenharmony_ci            return V_028C70_COLOR_4_4_4_4;
956bf215546Sopenharmony_ci         case 8:
957bf215546Sopenharmony_ci            return V_028C70_COLOR_8_8_8_8;
958bf215546Sopenharmony_ci         case 16:
959bf215546Sopenharmony_ci            return V_028C70_COLOR_16_16_16_16;
960bf215546Sopenharmony_ci         case 32:
961bf215546Sopenharmony_ci            return V_028C70_COLOR_32_32_32_32;
962bf215546Sopenharmony_ci         }
963bf215546Sopenharmony_ci      } else if (HAS_SIZE(5, 5, 5, 1)) {
964bf215546Sopenharmony_ci         return V_028C70_COLOR_1_5_5_5;
965bf215546Sopenharmony_ci      } else if (HAS_SIZE(1, 5, 5, 5)) {
966bf215546Sopenharmony_ci         return V_028C70_COLOR_5_5_5_1;
967bf215546Sopenharmony_ci      } else if (HAS_SIZE(10, 10, 10, 2)) {
968bf215546Sopenharmony_ci         return V_028C70_COLOR_2_10_10_10;
969bf215546Sopenharmony_ci      }
970bf215546Sopenharmony_ci      break;
971bf215546Sopenharmony_ci   }
972bf215546Sopenharmony_ci   return V_028C70_COLOR_INVALID;
973bf215546Sopenharmony_ci}
974bf215546Sopenharmony_ci
975bf215546Sopenharmony_ciuint32_t
976bf215546Sopenharmony_ciradv_colorformat_endian_swap(uint32_t colorformat)
977bf215546Sopenharmony_ci{
978bf215546Sopenharmony_ci   if (0 /*SI_BIG_ENDIAN*/) {
979bf215546Sopenharmony_ci      switch (colorformat) {
980bf215546Sopenharmony_ci         /* 8-bit buffers. */
981bf215546Sopenharmony_ci      case V_028C70_COLOR_8:
982bf215546Sopenharmony_ci         return V_028C70_ENDIAN_NONE;
983bf215546Sopenharmony_ci
984bf215546Sopenharmony_ci         /* 16-bit buffers. */
985bf215546Sopenharmony_ci      case V_028C70_COLOR_5_6_5:
986bf215546Sopenharmony_ci      case V_028C70_COLOR_1_5_5_5:
987bf215546Sopenharmony_ci      case V_028C70_COLOR_4_4_4_4:
988bf215546Sopenharmony_ci      case V_028C70_COLOR_16:
989bf215546Sopenharmony_ci      case V_028C70_COLOR_8_8:
990bf215546Sopenharmony_ci         return V_028C70_ENDIAN_8IN16;
991bf215546Sopenharmony_ci
992bf215546Sopenharmony_ci         /* 32-bit buffers. */
993bf215546Sopenharmony_ci      case V_028C70_COLOR_8_8_8_8:
994bf215546Sopenharmony_ci      case V_028C70_COLOR_2_10_10_10:
995bf215546Sopenharmony_ci      case V_028C70_COLOR_8_24:
996bf215546Sopenharmony_ci      case V_028C70_COLOR_24_8:
997bf215546Sopenharmony_ci      case V_028C70_COLOR_16_16:
998bf215546Sopenharmony_ci         return V_028C70_ENDIAN_8IN32;
999bf215546Sopenharmony_ci
1000bf215546Sopenharmony_ci         /* 64-bit buffers. */
1001bf215546Sopenharmony_ci      case V_028C70_COLOR_16_16_16_16:
1002bf215546Sopenharmony_ci         return V_028C70_ENDIAN_8IN16;
1003bf215546Sopenharmony_ci
1004bf215546Sopenharmony_ci      case V_028C70_COLOR_32_32:
1005bf215546Sopenharmony_ci         return V_028C70_ENDIAN_8IN32;
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_ci         /* 128-bit buffers. */
1008bf215546Sopenharmony_ci      case V_028C70_COLOR_32_32_32_32:
1009bf215546Sopenharmony_ci         return V_028C70_ENDIAN_8IN32;
1010bf215546Sopenharmony_ci      default:
1011bf215546Sopenharmony_ci         return V_028C70_ENDIAN_NONE; /* Unsupported. */
1012bf215546Sopenharmony_ci      }
1013bf215546Sopenharmony_ci   } else {
1014bf215546Sopenharmony_ci      return V_028C70_ENDIAN_NONE;
1015bf215546Sopenharmony_ci   }
1016bf215546Sopenharmony_ci}
1017bf215546Sopenharmony_ci
1018bf215546Sopenharmony_ciuint32_t
1019bf215546Sopenharmony_ciradv_translate_dbformat(VkFormat format)
1020bf215546Sopenharmony_ci{
1021bf215546Sopenharmony_ci   switch (format) {
1022bf215546Sopenharmony_ci   case VK_FORMAT_D16_UNORM:
1023bf215546Sopenharmony_ci   case VK_FORMAT_D16_UNORM_S8_UINT:
1024bf215546Sopenharmony_ci      return V_028040_Z_16;
1025bf215546Sopenharmony_ci   case VK_FORMAT_D32_SFLOAT:
1026bf215546Sopenharmony_ci   case VK_FORMAT_D32_SFLOAT_S8_UINT:
1027bf215546Sopenharmony_ci      return V_028040_Z_32_FLOAT;
1028bf215546Sopenharmony_ci   default:
1029bf215546Sopenharmony_ci      return V_028040_Z_INVALID;
1030bf215546Sopenharmony_ci   }
1031bf215546Sopenharmony_ci}
1032bf215546Sopenharmony_ci
1033bf215546Sopenharmony_ciunsigned
1034bf215546Sopenharmony_ciradv_translate_colorswap(VkFormat format, bool do_endian_swap)
1035bf215546Sopenharmony_ci{
1036bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci#define HAS_SWIZZLE(chan, swz) (desc->swizzle[chan] == PIPE_SWIZZLE_##swz)
1039bf215546Sopenharmony_ci
1040bf215546Sopenharmony_ci   if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
1041bf215546Sopenharmony_ci      return V_028C70_SWAP_STD;
1042bf215546Sopenharmony_ci
1043bf215546Sopenharmony_ci   if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)
1044bf215546Sopenharmony_ci      return V_028C70_SWAP_STD;
1045bf215546Sopenharmony_ci
1046bf215546Sopenharmony_ci   if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN)
1047bf215546Sopenharmony_ci      return ~0U;
1048bf215546Sopenharmony_ci
1049bf215546Sopenharmony_ci   switch (desc->nr_channels) {
1050bf215546Sopenharmony_ci   case 1:
1051bf215546Sopenharmony_ci      if (HAS_SWIZZLE(0, X))
1052bf215546Sopenharmony_ci         return V_028C70_SWAP_STD; /* X___ */
1053bf215546Sopenharmony_ci      else if (HAS_SWIZZLE(3, X))
1054bf215546Sopenharmony_ci         return V_028C70_SWAP_ALT_REV; /* ___X */
1055bf215546Sopenharmony_ci      break;
1056bf215546Sopenharmony_ci   case 2:
1057bf215546Sopenharmony_ci      if ((HAS_SWIZZLE(0, X) && HAS_SWIZZLE(1, Y)) || (HAS_SWIZZLE(0, X) && HAS_SWIZZLE(1, NONE)) ||
1058bf215546Sopenharmony_ci          (HAS_SWIZZLE(0, NONE) && HAS_SWIZZLE(1, Y)))
1059bf215546Sopenharmony_ci         return V_028C70_SWAP_STD; /* XY__ */
1060bf215546Sopenharmony_ci      else if ((HAS_SWIZZLE(0, Y) && HAS_SWIZZLE(1, X)) ||
1061bf215546Sopenharmony_ci               (HAS_SWIZZLE(0, Y) && HAS_SWIZZLE(1, NONE)) ||
1062bf215546Sopenharmony_ci               (HAS_SWIZZLE(0, NONE) && HAS_SWIZZLE(1, X)))
1063bf215546Sopenharmony_ci         /* YX__ */
1064bf215546Sopenharmony_ci         return (do_endian_swap ? V_028C70_SWAP_STD : V_028C70_SWAP_STD_REV);
1065bf215546Sopenharmony_ci      else if (HAS_SWIZZLE(0, X) && HAS_SWIZZLE(3, Y))
1066bf215546Sopenharmony_ci         return V_028C70_SWAP_ALT; /* X__Y */
1067bf215546Sopenharmony_ci      else if (HAS_SWIZZLE(0, Y) && HAS_SWIZZLE(3, X))
1068bf215546Sopenharmony_ci         return V_028C70_SWAP_ALT_REV; /* Y__X */
1069bf215546Sopenharmony_ci      break;
1070bf215546Sopenharmony_ci   case 3:
1071bf215546Sopenharmony_ci      if (HAS_SWIZZLE(0, X))
1072bf215546Sopenharmony_ci         return (do_endian_swap ? V_028C70_SWAP_STD_REV : V_028C70_SWAP_STD);
1073bf215546Sopenharmony_ci      else if (HAS_SWIZZLE(0, Z))
1074bf215546Sopenharmony_ci         return V_028C70_SWAP_STD_REV; /* ZYX */
1075bf215546Sopenharmony_ci      break;
1076bf215546Sopenharmony_ci   case 4:
1077bf215546Sopenharmony_ci      /* check the middle channels, the 1st and 4th channel can be NONE */
1078bf215546Sopenharmony_ci      if (HAS_SWIZZLE(1, Y) && HAS_SWIZZLE(2, Z)) {
1079bf215546Sopenharmony_ci         return V_028C70_SWAP_STD; /* XYZW */
1080bf215546Sopenharmony_ci      } else if (HAS_SWIZZLE(1, Z) && HAS_SWIZZLE(2, Y)) {
1081bf215546Sopenharmony_ci         return V_028C70_SWAP_STD_REV; /* WZYX */
1082bf215546Sopenharmony_ci      } else if (HAS_SWIZZLE(1, Y) && HAS_SWIZZLE(2, X)) {
1083bf215546Sopenharmony_ci         return V_028C70_SWAP_ALT; /* ZYXW */
1084bf215546Sopenharmony_ci      } else if (HAS_SWIZZLE(1, Z) && HAS_SWIZZLE(2, W)) {
1085bf215546Sopenharmony_ci         /* YZWX */
1086bf215546Sopenharmony_ci         if (desc->is_array)
1087bf215546Sopenharmony_ci            return V_028C70_SWAP_ALT_REV;
1088bf215546Sopenharmony_ci         else
1089bf215546Sopenharmony_ci            return (do_endian_swap ? V_028C70_SWAP_ALT : V_028C70_SWAP_ALT_REV);
1090bf215546Sopenharmony_ci      }
1091bf215546Sopenharmony_ci      break;
1092bf215546Sopenharmony_ci   }
1093bf215546Sopenharmony_ci   return ~0U;
1094bf215546Sopenharmony_ci}
1095bf215546Sopenharmony_ci
1096bf215546Sopenharmony_cibool
1097bf215546Sopenharmony_ciradv_format_pack_clear_color(VkFormat format, uint32_t clear_vals[2], VkClearColorValue *value)
1098bf215546Sopenharmony_ci{
1099bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
1100bf215546Sopenharmony_ci
1101bf215546Sopenharmony_ci   if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
1102bf215546Sopenharmony_ci      clear_vals[0] = float3_to_r11g11b10f(value->float32);
1103bf215546Sopenharmony_ci      clear_vals[1] = 0;
1104bf215546Sopenharmony_ci      return true;
1105bf215546Sopenharmony_ci   } else if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
1106bf215546Sopenharmony_ci      clear_vals[0] = float3_to_rgb9e5(value->float32);
1107bf215546Sopenharmony_ci      clear_vals[1] = 0;
1108bf215546Sopenharmony_ci      return true;
1109bf215546Sopenharmony_ci   }
1110bf215546Sopenharmony_ci
1111bf215546Sopenharmony_ci   if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
1112bf215546Sopenharmony_ci      fprintf(stderr, "failed to fast clear for non-plain format %d\n", format);
1113bf215546Sopenharmony_ci      return false;
1114bf215546Sopenharmony_ci   }
1115bf215546Sopenharmony_ci
1116bf215546Sopenharmony_ci   if (!util_is_power_of_two_or_zero(desc->block.bits)) {
1117bf215546Sopenharmony_ci      fprintf(stderr, "failed to fast clear for NPOT format %d\n", format);
1118bf215546Sopenharmony_ci      return false;
1119bf215546Sopenharmony_ci   }
1120bf215546Sopenharmony_ci
1121bf215546Sopenharmony_ci   if (desc->block.bits > 64) {
1122bf215546Sopenharmony_ci      /*
1123bf215546Sopenharmony_ci       * We have a 128 bits format, check if the first 3 components are the same.
1124bf215546Sopenharmony_ci       * Every elements has to be 32 bits since we don't support 64-bit formats,
1125bf215546Sopenharmony_ci       * and we can skip swizzling checks as alpha always comes last for these and
1126bf215546Sopenharmony_ci       * we do not care about the rest as they have to be the same.
1127bf215546Sopenharmony_ci       */
1128bf215546Sopenharmony_ci      if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
1129bf215546Sopenharmony_ci         if (value->float32[0] != value->float32[1] || value->float32[0] != value->float32[2])
1130bf215546Sopenharmony_ci            return false;
1131bf215546Sopenharmony_ci      } else {
1132bf215546Sopenharmony_ci         if (value->uint32[0] != value->uint32[1] || value->uint32[0] != value->uint32[2])
1133bf215546Sopenharmony_ci            return false;
1134bf215546Sopenharmony_ci      }
1135bf215546Sopenharmony_ci      clear_vals[0] = value->uint32[0];
1136bf215546Sopenharmony_ci      clear_vals[1] = value->uint32[3];
1137bf215546Sopenharmony_ci      return true;
1138bf215546Sopenharmony_ci   }
1139bf215546Sopenharmony_ci   uint64_t clear_val = 0;
1140bf215546Sopenharmony_ci
1141bf215546Sopenharmony_ci   for (unsigned c = 0; c < 4; ++c) {
1142bf215546Sopenharmony_ci      if (desc->swizzle[c] >= 4)
1143bf215546Sopenharmony_ci         continue;
1144bf215546Sopenharmony_ci
1145bf215546Sopenharmony_ci      const struct util_format_channel_description *channel = &desc->channel[desc->swizzle[c]];
1146bf215546Sopenharmony_ci      assert(channel->size);
1147bf215546Sopenharmony_ci
1148bf215546Sopenharmony_ci      uint64_t v = 0;
1149bf215546Sopenharmony_ci      if (channel->pure_integer) {
1150bf215546Sopenharmony_ci         v = value->uint32[c] & ((1ULL << channel->size) - 1);
1151bf215546Sopenharmony_ci      } else if (channel->normalized) {
1152bf215546Sopenharmony_ci         if (channel->type == UTIL_FORMAT_TYPE_UNSIGNED && desc->swizzle[c] < 3 &&
1153bf215546Sopenharmony_ci             desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
1154bf215546Sopenharmony_ci            assert(channel->size == 8);
1155bf215546Sopenharmony_ci
1156bf215546Sopenharmony_ci            v = util_format_linear_float_to_srgb_8unorm(value->float32[c]);
1157bf215546Sopenharmony_ci         } else {
1158bf215546Sopenharmony_ci            float f = MIN2(value->float32[c], 1.0f);
1159bf215546Sopenharmony_ci
1160bf215546Sopenharmony_ci            if (channel->type == UTIL_FORMAT_TYPE_UNSIGNED) {
1161bf215546Sopenharmony_ci               f = MAX2(f, 0.0f) * ((1ULL << channel->size) - 1);
1162bf215546Sopenharmony_ci            } else {
1163bf215546Sopenharmony_ci               f = MAX2(f, -1.0f) * ((1ULL << (channel->size - 1)) - 1);
1164bf215546Sopenharmony_ci            }
1165bf215546Sopenharmony_ci
1166bf215546Sopenharmony_ci            /* The hardware rounds before conversion. */
1167bf215546Sopenharmony_ci            if (f > 0)
1168bf215546Sopenharmony_ci               f += 0.5f;
1169bf215546Sopenharmony_ci            else
1170bf215546Sopenharmony_ci               f -= 0.5f;
1171bf215546Sopenharmony_ci
1172bf215546Sopenharmony_ci            v = (uint64_t)f;
1173bf215546Sopenharmony_ci         }
1174bf215546Sopenharmony_ci      } else if (channel->type == UTIL_FORMAT_TYPE_FLOAT) {
1175bf215546Sopenharmony_ci         if (channel->size == 32) {
1176bf215546Sopenharmony_ci            memcpy(&v, &value->float32[c], 4);
1177bf215546Sopenharmony_ci         } else if (channel->size == 16) {
1178bf215546Sopenharmony_ci            v = _mesa_float_to_float16_rtz(value->float32[c]);
1179bf215546Sopenharmony_ci         } else {
1180bf215546Sopenharmony_ci            fprintf(stderr, "failed to fast clear for unhandled float size in format %d\n", format);
1181bf215546Sopenharmony_ci            return false;
1182bf215546Sopenharmony_ci         }
1183bf215546Sopenharmony_ci      } else {
1184bf215546Sopenharmony_ci         fprintf(stderr, "failed to fast clear for unhandled component type in format %d\n",
1185bf215546Sopenharmony_ci                 format);
1186bf215546Sopenharmony_ci         return false;
1187bf215546Sopenharmony_ci      }
1188bf215546Sopenharmony_ci      clear_val |= (v & ((1ULL << channel->size) - 1)) << channel->shift;
1189bf215546Sopenharmony_ci   }
1190bf215546Sopenharmony_ci
1191bf215546Sopenharmony_ci   clear_vals[0] = clear_val;
1192bf215546Sopenharmony_ci   clear_vals[1] = clear_val >> 32;
1193bf215546Sopenharmony_ci
1194bf215546Sopenharmony_ci   return true;
1195bf215546Sopenharmony_ci}
1196bf215546Sopenharmony_ci
1197bf215546Sopenharmony_cistatic const struct ac_modifier_options radv_modifier_options = {
1198bf215546Sopenharmony_ci   .dcc = true,
1199bf215546Sopenharmony_ci   .dcc_retile = true,
1200bf215546Sopenharmony_ci};
1201bf215546Sopenharmony_ci
1202bf215546Sopenharmony_cistatic VkFormatFeatureFlags2
1203bf215546Sopenharmony_ciradv_get_modifier_flags(struct radv_physical_device *dev, VkFormat format, uint64_t modifier,
1204bf215546Sopenharmony_ci                        const VkFormatProperties3 *props)
1205bf215546Sopenharmony_ci{
1206bf215546Sopenharmony_ci   VkFormatFeatureFlags2 features;
1207bf215546Sopenharmony_ci
1208bf215546Sopenharmony_ci   if (vk_format_is_compressed(format) || vk_format_is_depth_or_stencil(format))
1209bf215546Sopenharmony_ci      return 0;
1210bf215546Sopenharmony_ci
1211bf215546Sopenharmony_ci   if (modifier == DRM_FORMAT_MOD_LINEAR)
1212bf215546Sopenharmony_ci      features = props->linearTilingFeatures;
1213bf215546Sopenharmony_ci   else
1214bf215546Sopenharmony_ci      features = props->optimalTilingFeatures;
1215bf215546Sopenharmony_ci
1216bf215546Sopenharmony_ci   /* Unconditionally disable DISJOINT support for modifiers for now */
1217bf215546Sopenharmony_ci   features &= ~VK_FORMAT_FEATURE_2_DISJOINT_BIT;
1218bf215546Sopenharmony_ci
1219bf215546Sopenharmony_ci   if (ac_modifier_has_dcc(modifier)) {
1220bf215546Sopenharmony_ci      /* Only disable support for STORAGE_IMAGE on modifiers that
1221bf215546Sopenharmony_ci       * do not support DCC image stores.
1222bf215546Sopenharmony_ci       */
1223bf215546Sopenharmony_ci      if (!ac_modifier_supports_dcc_image_stores(modifier) || radv_is_atomic_format_supported(format))
1224bf215546Sopenharmony_ci         features &= ~VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
1225bf215546Sopenharmony_ci
1226bf215546Sopenharmony_ci      if (dev->instance->debug_flags & (RADV_DEBUG_NO_DCC | RADV_DEBUG_NO_DISPLAY_DCC))
1227bf215546Sopenharmony_ci         return 0;
1228bf215546Sopenharmony_ci   }
1229bf215546Sopenharmony_ci
1230bf215546Sopenharmony_ci   return features;
1231bf215546Sopenharmony_ci}
1232bf215546Sopenharmony_ci
1233bf215546Sopenharmony_cistatic VkFormatFeatureFlags
1234bf215546Sopenharmony_cifeatures2_to_features(VkFormatFeatureFlags2 features2)
1235bf215546Sopenharmony_ci{
1236bf215546Sopenharmony_ci   return features2 & VK_ALL_FORMAT_FEATURE_FLAG_BITS;
1237bf215546Sopenharmony_ci}
1238bf215546Sopenharmony_ci
1239bf215546Sopenharmony_cistatic void
1240bf215546Sopenharmony_ciradv_list_drm_format_modifiers(struct radv_physical_device *dev, VkFormat format,
1241bf215546Sopenharmony_ci                               const VkFormatProperties3 *format_props,
1242bf215546Sopenharmony_ci                               VkDrmFormatModifierPropertiesListEXT *mod_list)
1243bf215546Sopenharmony_ci{
1244bf215546Sopenharmony_ci   unsigned mod_count;
1245bf215546Sopenharmony_ci
1246bf215546Sopenharmony_ci   if (!mod_list)
1247bf215546Sopenharmony_ci      return;
1248bf215546Sopenharmony_ci
1249bf215546Sopenharmony_ci   if (vk_format_is_compressed(format) || vk_format_is_depth_or_stencil(format)) {
1250bf215546Sopenharmony_ci      mod_list->drmFormatModifierCount = 0;
1251bf215546Sopenharmony_ci      return;
1252bf215546Sopenharmony_ci   }
1253bf215546Sopenharmony_ci
1254bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
1255bf215546Sopenharmony_ci                          mod_list->pDrmFormatModifierProperties,
1256bf215546Sopenharmony_ci                          &mod_list->drmFormatModifierCount);
1257bf215546Sopenharmony_ci
1258bf215546Sopenharmony_ci   ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,
1259bf215546Sopenharmony_ci                              vk_format_to_pipe_format(format), &mod_count, NULL);
1260bf215546Sopenharmony_ci
1261bf215546Sopenharmony_ci   uint64_t *mods = malloc(mod_count * sizeof(uint64_t));
1262bf215546Sopenharmony_ci   if (!mods) {
1263bf215546Sopenharmony_ci      /* We can't return an error here ... */
1264bf215546Sopenharmony_ci      mod_list->drmFormatModifierCount = 0;
1265bf215546Sopenharmony_ci      return;
1266bf215546Sopenharmony_ci   }
1267bf215546Sopenharmony_ci   ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,
1268bf215546Sopenharmony_ci                              vk_format_to_pipe_format(format), &mod_count, mods);
1269bf215546Sopenharmony_ci
1270bf215546Sopenharmony_ci   for (unsigned i = 0; i < mod_count; ++i) {
1271bf215546Sopenharmony_ci      VkFormatFeatureFlags2 features =
1272bf215546Sopenharmony_ci         radv_get_modifier_flags(dev, format, mods[i], format_props);
1273bf215546Sopenharmony_ci      unsigned planes = vk_format_get_plane_count(format);
1274bf215546Sopenharmony_ci      if (planes == 1) {
1275bf215546Sopenharmony_ci         if (ac_modifier_has_dcc_retile(mods[i]))
1276bf215546Sopenharmony_ci            planes = 3;
1277bf215546Sopenharmony_ci         else if (ac_modifier_has_dcc(mods[i]))
1278bf215546Sopenharmony_ci            planes = 2;
1279bf215546Sopenharmony_ci      }
1280bf215546Sopenharmony_ci
1281bf215546Sopenharmony_ci      if (!features)
1282bf215546Sopenharmony_ci         continue;
1283bf215546Sopenharmony_ci
1284bf215546Sopenharmony_ci      vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, out_props) {
1285bf215546Sopenharmony_ci         *out_props = (VkDrmFormatModifierPropertiesEXT) {
1286bf215546Sopenharmony_ci            .drmFormatModifier = mods[i],
1287bf215546Sopenharmony_ci            .drmFormatModifierPlaneCount = planes,
1288bf215546Sopenharmony_ci            .drmFormatModifierTilingFeatures = features2_to_features(features),
1289bf215546Sopenharmony_ci         };
1290bf215546Sopenharmony_ci      };
1291bf215546Sopenharmony_ci   }
1292bf215546Sopenharmony_ci
1293bf215546Sopenharmony_ci   free(mods);
1294bf215546Sopenharmony_ci}
1295bf215546Sopenharmony_ci
1296bf215546Sopenharmony_cistatic void
1297bf215546Sopenharmony_ciradv_list_drm_format_modifiers_2(struct radv_physical_device *dev, VkFormat format,
1298bf215546Sopenharmony_ci                                 const VkFormatProperties3 *format_props,
1299bf215546Sopenharmony_ci                                 VkDrmFormatModifierPropertiesList2EXT *mod_list)
1300bf215546Sopenharmony_ci{
1301bf215546Sopenharmony_ci   unsigned mod_count;
1302bf215546Sopenharmony_ci
1303bf215546Sopenharmony_ci   if (!mod_list)
1304bf215546Sopenharmony_ci      return;
1305bf215546Sopenharmony_ci
1306bf215546Sopenharmony_ci   if (vk_format_is_compressed(format) || vk_format_is_depth_or_stencil(format)) {
1307bf215546Sopenharmony_ci      mod_list->drmFormatModifierCount = 0;
1308bf215546Sopenharmony_ci      return;
1309bf215546Sopenharmony_ci   }
1310bf215546Sopenharmony_ci
1311bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierProperties2EXT, out,
1312bf215546Sopenharmony_ci                          mod_list->pDrmFormatModifierProperties,
1313bf215546Sopenharmony_ci                          &mod_list->drmFormatModifierCount);
1314bf215546Sopenharmony_ci
1315bf215546Sopenharmony_ci   ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,
1316bf215546Sopenharmony_ci                              vk_format_to_pipe_format(format), &mod_count, NULL);
1317bf215546Sopenharmony_ci
1318bf215546Sopenharmony_ci   uint64_t *mods = malloc(mod_count * sizeof(uint64_t));
1319bf215546Sopenharmony_ci   if (!mods) {
1320bf215546Sopenharmony_ci      /* We can't return an error here ... */
1321bf215546Sopenharmony_ci      mod_list->drmFormatModifierCount = 0;
1322bf215546Sopenharmony_ci      return;
1323bf215546Sopenharmony_ci   }
1324bf215546Sopenharmony_ci   ac_get_supported_modifiers(&dev->rad_info, &radv_modifier_options,
1325bf215546Sopenharmony_ci                              vk_format_to_pipe_format(format), &mod_count, mods);
1326bf215546Sopenharmony_ci
1327bf215546Sopenharmony_ci   for (unsigned i = 0; i < mod_count; ++i) {
1328bf215546Sopenharmony_ci      VkFormatFeatureFlags2 features =
1329bf215546Sopenharmony_ci         radv_get_modifier_flags(dev, format, mods[i], format_props);
1330bf215546Sopenharmony_ci      unsigned planes = vk_format_get_plane_count(format);
1331bf215546Sopenharmony_ci      if (planes == 1) {
1332bf215546Sopenharmony_ci         if (ac_modifier_has_dcc_retile(mods[i]))
1333bf215546Sopenharmony_ci            planes = 3;
1334bf215546Sopenharmony_ci         else if (ac_modifier_has_dcc(mods[i]))
1335bf215546Sopenharmony_ci            planes = 2;
1336bf215546Sopenharmony_ci      }
1337bf215546Sopenharmony_ci
1338bf215546Sopenharmony_ci      if (!features)
1339bf215546Sopenharmony_ci         continue;
1340bf215546Sopenharmony_ci
1341bf215546Sopenharmony_ci      vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT, &out, out_props) {
1342bf215546Sopenharmony_ci         *out_props = (VkDrmFormatModifierProperties2EXT) {
1343bf215546Sopenharmony_ci            .drmFormatModifier = mods[i],
1344bf215546Sopenharmony_ci            .drmFormatModifierPlaneCount = planes,
1345bf215546Sopenharmony_ci            .drmFormatModifierTilingFeatures = features,
1346bf215546Sopenharmony_ci         };
1347bf215546Sopenharmony_ci      };
1348bf215546Sopenharmony_ci   }
1349bf215546Sopenharmony_ci
1350bf215546Sopenharmony_ci   free(mods);
1351bf215546Sopenharmony_ci}
1352bf215546Sopenharmony_ci
1353bf215546Sopenharmony_cistatic VkResult
1354bf215546Sopenharmony_ciradv_check_modifier_support(struct radv_physical_device *dev,
1355bf215546Sopenharmony_ci                            const VkPhysicalDeviceImageFormatInfo2 *info,
1356bf215546Sopenharmony_ci                            VkImageFormatProperties *props, VkFormat format, uint64_t modifier)
1357bf215546Sopenharmony_ci{
1358bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
1359bf215546Sopenharmony_ci   uint32_t max_width, max_height;
1360bf215546Sopenharmony_ci
1361bf215546Sopenharmony_ci   if (info->type != VK_IMAGE_TYPE_2D)
1362bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
1363bf215546Sopenharmony_ci
1364bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_ETC && dev->emulate_etc2)
1365bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
1366bf215546Sopenharmony_ci
1367bf215546Sopenharmony_ci   /* We did not add modifiers for sparse textures. */
1368bf215546Sopenharmony_ci   if (info->flags & (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |
1369bf215546Sopenharmony_ci                      VK_IMAGE_CREATE_SPARSE_ALIASED_BIT))
1370bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
1371bf215546Sopenharmony_ci
1372bf215546Sopenharmony_ci   /*
1373bf215546Sopenharmony_ci    * Need to check the modifier is supported in general:
1374bf215546Sopenharmony_ci    * "If the drmFormatModifier is incompatible with the parameters specified
1375bf215546Sopenharmony_ci    * in VkPhysicalDeviceImageFormatInfo2 and its pNext chain, then
1376bf215546Sopenharmony_ci    * vkGetPhysicalDeviceImageFormatProperties2 returns VK_ERROR_FORMAT_NOT_SUPPORTED.
1377bf215546Sopenharmony_ci    * The implementation must support the query of any drmFormatModifier,
1378bf215546Sopenharmony_ci    * including unknown and invalid modifier values."
1379bf215546Sopenharmony_ci    */
1380bf215546Sopenharmony_ci   VkDrmFormatModifierPropertiesListEXT mod_list = {
1381bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
1382bf215546Sopenharmony_ci   };
1383bf215546Sopenharmony_ci
1384bf215546Sopenharmony_ci   VkFormatProperties2 format_props2 = {.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
1385bf215546Sopenharmony_ci                                        .pNext = &mod_list};
1386bf215546Sopenharmony_ci
1387bf215546Sopenharmony_ci   radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(dev), format,
1388bf215546Sopenharmony_ci                                           &format_props2);
1389bf215546Sopenharmony_ci
1390bf215546Sopenharmony_ci   if (!mod_list.drmFormatModifierCount)
1391bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
1392bf215546Sopenharmony_ci
1393bf215546Sopenharmony_ci   mod_list.pDrmFormatModifierProperties =
1394bf215546Sopenharmony_ci      calloc(mod_list.drmFormatModifierCount, sizeof(*mod_list.pDrmFormatModifierProperties));
1395bf215546Sopenharmony_ci   if (!mod_list.pDrmFormatModifierProperties)
1396bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
1397bf215546Sopenharmony_ci
1398bf215546Sopenharmony_ci   radv_GetPhysicalDeviceFormatProperties2(radv_physical_device_to_handle(dev), format,
1399bf215546Sopenharmony_ci                                           &format_props2);
1400bf215546Sopenharmony_ci
1401bf215546Sopenharmony_ci   bool found = false;
1402bf215546Sopenharmony_ci   for (uint32_t i = 0; i < mod_list.drmFormatModifierCount && !found; ++i)
1403bf215546Sopenharmony_ci      if (mod_list.pDrmFormatModifierProperties[i].drmFormatModifier == modifier)
1404bf215546Sopenharmony_ci         found = true;
1405bf215546Sopenharmony_ci
1406bf215546Sopenharmony_ci   free(mod_list.pDrmFormatModifierProperties);
1407bf215546Sopenharmony_ci
1408bf215546Sopenharmony_ci   if (!found)
1409bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
1410bf215546Sopenharmony_ci
1411bf215546Sopenharmony_ci   bool need_dcc_sign_reinterpret = false;
1412bf215546Sopenharmony_ci   if (ac_modifier_has_dcc(modifier) &&
1413bf215546Sopenharmony_ci       !radv_are_formats_dcc_compatible(dev, info->pNext, format, info->flags,
1414bf215546Sopenharmony_ci                                        &need_dcc_sign_reinterpret) &&
1415bf215546Sopenharmony_ci       !need_dcc_sign_reinterpret)
1416bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
1417bf215546Sopenharmony_ci
1418bf215546Sopenharmony_ci   /* We can expand this as needed and implemented but there is not much demand
1419bf215546Sopenharmony_ci    * for more. */
1420bf215546Sopenharmony_ci   if (ac_modifier_has_dcc(modifier)) {
1421bf215546Sopenharmony_ci      props->maxMipLevels = 1;
1422bf215546Sopenharmony_ci      props->maxArrayLayers = 1;
1423bf215546Sopenharmony_ci   }
1424bf215546Sopenharmony_ci
1425bf215546Sopenharmony_ci   ac_modifier_max_extent(&dev->rad_info, modifier, &max_width, &max_height);
1426bf215546Sopenharmony_ci   props->maxExtent.width = MIN2(props->maxExtent.width, max_width);
1427bf215546Sopenharmony_ci   props->maxExtent.height = MIN2(props->maxExtent.width, max_height);
1428bf215546Sopenharmony_ci
1429bf215546Sopenharmony_ci   /* We don't support MSAA for modifiers */
1430bf215546Sopenharmony_ci   props->sampleCounts &= VK_SAMPLE_COUNT_1_BIT;
1431bf215546Sopenharmony_ci   return VK_SUCCESS;
1432bf215546Sopenharmony_ci}
1433bf215546Sopenharmony_ci
1434bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1435bf215546Sopenharmony_ciradv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format,
1436bf215546Sopenharmony_ci                                        VkFormatProperties2 *pFormatProperties)
1437bf215546Sopenharmony_ci{
1438bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
1439bf215546Sopenharmony_ci   VkFormatProperties3 format_props;
1440bf215546Sopenharmony_ci
1441bf215546Sopenharmony_ci   radv_physical_device_get_format_properties(physical_device, format, &format_props);
1442bf215546Sopenharmony_ci
1443bf215546Sopenharmony_ci   pFormatProperties->formatProperties.linearTilingFeatures =
1444bf215546Sopenharmony_ci      features2_to_features(format_props.linearTilingFeatures);
1445bf215546Sopenharmony_ci   pFormatProperties->formatProperties.optimalTilingFeatures =
1446bf215546Sopenharmony_ci      features2_to_features(format_props.optimalTilingFeatures);
1447bf215546Sopenharmony_ci   pFormatProperties->formatProperties.bufferFeatures =
1448bf215546Sopenharmony_ci      features2_to_features(format_props.bufferFeatures);
1449bf215546Sopenharmony_ci
1450bf215546Sopenharmony_ci   VkFormatProperties3 *format_props_extended =
1451bf215546Sopenharmony_ci      vk_find_struct(pFormatProperties, FORMAT_PROPERTIES_3);
1452bf215546Sopenharmony_ci   if (format_props_extended) {
1453bf215546Sopenharmony_ci      format_props_extended->linearTilingFeatures = format_props.linearTilingFeatures;
1454bf215546Sopenharmony_ci      format_props_extended->optimalTilingFeatures = format_props.optimalTilingFeatures;
1455bf215546Sopenharmony_ci      format_props_extended->bufferFeatures = format_props.bufferFeatures;
1456bf215546Sopenharmony_ci   }
1457bf215546Sopenharmony_ci
1458bf215546Sopenharmony_ci   radv_list_drm_format_modifiers(
1459bf215546Sopenharmony_ci      physical_device, format, &format_props,
1460bf215546Sopenharmony_ci      vk_find_struct(pFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT));
1461bf215546Sopenharmony_ci   radv_list_drm_format_modifiers_2(
1462bf215546Sopenharmony_ci      physical_device, format, &format_props,
1463bf215546Sopenharmony_ci      vk_find_struct(pFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT));
1464bf215546Sopenharmony_ci}
1465bf215546Sopenharmony_ci
1466bf215546Sopenharmony_cistatic VkResult
1467bf215546Sopenharmony_ciradv_get_image_format_properties(struct radv_physical_device *physical_device,
1468bf215546Sopenharmony_ci                                 const VkPhysicalDeviceImageFormatInfo2 *info, VkFormat format,
1469bf215546Sopenharmony_ci                                 VkImageFormatProperties *pImageFormatProperties)
1470bf215546Sopenharmony_ci
1471bf215546Sopenharmony_ci{
1472bf215546Sopenharmony_ci   VkFormatProperties3 format_props;
1473bf215546Sopenharmony_ci   VkFormatFeatureFlags2 format_feature_flags;
1474bf215546Sopenharmony_ci   VkExtent3D maxExtent;
1475bf215546Sopenharmony_ci   uint32_t maxMipLevels;
1476bf215546Sopenharmony_ci   uint32_t maxArraySize;
1477bf215546Sopenharmony_ci   VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
1478bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(format);
1479bf215546Sopenharmony_ci   enum amd_gfx_level gfx_level = physical_device->rad_info.gfx_level;
1480bf215546Sopenharmony_ci   VkImageTiling tiling = info->tiling;
1481bf215546Sopenharmony_ci   const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *mod_info =
1482bf215546Sopenharmony_ci      vk_find_struct_const(info->pNext, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT);
1483bf215546Sopenharmony_ci   VkResult result = VK_ERROR_FORMAT_NOT_SUPPORTED;
1484bf215546Sopenharmony_ci
1485bf215546Sopenharmony_ci   radv_physical_device_get_format_properties(physical_device, format, &format_props);
1486bf215546Sopenharmony_ci   if (tiling == VK_IMAGE_TILING_LINEAR) {
1487bf215546Sopenharmony_ci      format_feature_flags = format_props.linearTilingFeatures;
1488bf215546Sopenharmony_ci   } else if (tiling == VK_IMAGE_TILING_OPTIMAL) {
1489bf215546Sopenharmony_ci      format_feature_flags = format_props.optimalTilingFeatures;
1490bf215546Sopenharmony_ci   } else if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1491bf215546Sopenharmony_ci      format_feature_flags = radv_get_modifier_flags(physical_device, format,
1492bf215546Sopenharmony_ci                                                     mod_info->drmFormatModifier, &format_props);
1493bf215546Sopenharmony_ci   } else {
1494bf215546Sopenharmony_ci      unreachable("bad VkImageTiling");
1495bf215546Sopenharmony_ci   }
1496bf215546Sopenharmony_ci
1497bf215546Sopenharmony_ci   if (format_feature_flags == 0)
1498bf215546Sopenharmony_ci      goto unsupported;
1499bf215546Sopenharmony_ci
1500bf215546Sopenharmony_ci   if (info->type != VK_IMAGE_TYPE_2D && vk_format_is_depth_or_stencil(format))
1501bf215546Sopenharmony_ci      goto unsupported;
1502bf215546Sopenharmony_ci
1503bf215546Sopenharmony_ci   switch (info->type) {
1504bf215546Sopenharmony_ci   default:
1505bf215546Sopenharmony_ci      unreachable("bad vkimage type\n");
1506bf215546Sopenharmony_ci   case VK_IMAGE_TYPE_1D:
1507bf215546Sopenharmony_ci      maxExtent.width = 16384;
1508bf215546Sopenharmony_ci      maxExtent.height = 1;
1509bf215546Sopenharmony_ci      maxExtent.depth = 1;
1510bf215546Sopenharmony_ci      maxMipLevels = 15; /* log2(maxWidth) + 1 */
1511bf215546Sopenharmony_ci      maxArraySize = gfx_level >= GFX10 ? 8192 : 2048;
1512bf215546Sopenharmony_ci      break;
1513bf215546Sopenharmony_ci   case VK_IMAGE_TYPE_2D:
1514bf215546Sopenharmony_ci      maxExtent.width = 16384;
1515bf215546Sopenharmony_ci      maxExtent.height = 16384;
1516bf215546Sopenharmony_ci      maxExtent.depth = 1;
1517bf215546Sopenharmony_ci      maxMipLevels = 15; /* log2(maxWidth) + 1 */
1518bf215546Sopenharmony_ci      maxArraySize = gfx_level >= GFX10 ? 8192 : 2048;
1519bf215546Sopenharmony_ci      break;
1520bf215546Sopenharmony_ci   case VK_IMAGE_TYPE_3D:
1521bf215546Sopenharmony_ci      if (gfx_level >= GFX10) {
1522bf215546Sopenharmony_ci         maxExtent.width = 8192;
1523bf215546Sopenharmony_ci         maxExtent.height = 8192;
1524bf215546Sopenharmony_ci         maxExtent.depth = 8192;
1525bf215546Sopenharmony_ci      } else {
1526bf215546Sopenharmony_ci         maxExtent.width = 2048;
1527bf215546Sopenharmony_ci         maxExtent.height = 2048;
1528bf215546Sopenharmony_ci         maxExtent.depth = 2048;
1529bf215546Sopenharmony_ci      }
1530bf215546Sopenharmony_ci      maxMipLevels = util_logbase2(maxExtent.width) + 1;
1531bf215546Sopenharmony_ci      maxArraySize = 1;
1532bf215546Sopenharmony_ci      break;
1533bf215546Sopenharmony_ci   }
1534bf215546Sopenharmony_ci
1535bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
1536bf215546Sopenharmony_ci      /* Might be able to support but the entire format support is
1537bf215546Sopenharmony_ci       * messy, so taking the lazy way out. */
1538bf215546Sopenharmony_ci      maxArraySize = 1;
1539bf215546Sopenharmony_ci   }
1540bf215546Sopenharmony_ci
1541bf215546Sopenharmony_ci   if (tiling == VK_IMAGE_TILING_OPTIMAL && info->type == VK_IMAGE_TYPE_2D &&
1542bf215546Sopenharmony_ci       (format_feature_flags & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
1543bf215546Sopenharmony_ci                                VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
1544bf215546Sopenharmony_ci       !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
1545bf215546Sopenharmony_ci       !(info->usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)) {
1546bf215546Sopenharmony_ci      sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT;
1547bf215546Sopenharmony_ci   }
1548bf215546Sopenharmony_ci
1549bf215546Sopenharmony_ci   if (tiling == VK_IMAGE_TILING_LINEAR &&
1550bf215546Sopenharmony_ci       (format == VK_FORMAT_R32G32B32_SFLOAT || format == VK_FORMAT_R32G32B32_SINT ||
1551bf215546Sopenharmony_ci        format == VK_FORMAT_R32G32B32_UINT)) {
1552bf215546Sopenharmony_ci      /* R32G32B32 is a weird format and the driver currently only
1553bf215546Sopenharmony_ci       * supports the barely minimum.
1554bf215546Sopenharmony_ci       * TODO: Implement more if we really need to.
1555bf215546Sopenharmony_ci       */
1556bf215546Sopenharmony_ci      if (info->type == VK_IMAGE_TYPE_3D)
1557bf215546Sopenharmony_ci         goto unsupported;
1558bf215546Sopenharmony_ci      maxArraySize = 1;
1559bf215546Sopenharmony_ci      maxMipLevels = 1;
1560bf215546Sopenharmony_ci   }
1561bf215546Sopenharmony_ci
1562bf215546Sopenharmony_ci   /* We can't create 3d compressed 128bpp images that can be rendered to on GFX9 */
1563bf215546Sopenharmony_ci   if (physical_device->rad_info.gfx_level >= GFX9 && info->type == VK_IMAGE_TYPE_3D &&
1564bf215546Sopenharmony_ci       vk_format_get_blocksizebits(format) == 128 && vk_format_is_compressed(format) &&
1565bf215546Sopenharmony_ci       (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) &&
1566bf215546Sopenharmony_ci       ((info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) ||
1567bf215546Sopenharmony_ci        (info->usage & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT))) {
1568bf215546Sopenharmony_ci      goto unsupported;
1569bf215546Sopenharmony_ci   }
1570bf215546Sopenharmony_ci
1571bf215546Sopenharmony_ci   /* From the Vulkan 1.3.206 spec:
1572bf215546Sopenharmony_ci    *
1573bf215546Sopenharmony_ci    * "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be created with usage flags
1574bf215546Sopenharmony_ci    * that are not supported for the format the image is created with but are supported for at least
1575bf215546Sopenharmony_ci    * one format a VkImageView created from the image can have."
1576bf215546Sopenharmony_ci    */
1577bf215546Sopenharmony_ci   VkImageUsageFlags image_usage = info->usage;
1578bf215546Sopenharmony_ci   if (info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
1579bf215546Sopenharmony_ci      image_usage = 0;
1580bf215546Sopenharmony_ci
1581bf215546Sopenharmony_ci   if (image_usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
1582bf215546Sopenharmony_ci      if (!(format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
1583bf215546Sopenharmony_ci         goto unsupported;
1584bf215546Sopenharmony_ci      }
1585bf215546Sopenharmony_ci   }
1586bf215546Sopenharmony_ci
1587bf215546Sopenharmony_ci   if (image_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
1588bf215546Sopenharmony_ci      if (!(format_feature_flags & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) {
1589bf215546Sopenharmony_ci         goto unsupported;
1590bf215546Sopenharmony_ci      }
1591bf215546Sopenharmony_ci   }
1592bf215546Sopenharmony_ci
1593bf215546Sopenharmony_ci   if (image_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
1594bf215546Sopenharmony_ci      if (!(format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) {
1595bf215546Sopenharmony_ci         goto unsupported;
1596bf215546Sopenharmony_ci      }
1597bf215546Sopenharmony_ci   }
1598bf215546Sopenharmony_ci
1599bf215546Sopenharmony_ci   if (image_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1600bf215546Sopenharmony_ci      if (!(format_feature_flags & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
1601bf215546Sopenharmony_ci         goto unsupported;
1602bf215546Sopenharmony_ci      }
1603bf215546Sopenharmony_ci   }
1604bf215546Sopenharmony_ci
1605bf215546Sopenharmony_ci   if (image_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
1606bf215546Sopenharmony_ci      if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT)) {
1607bf215546Sopenharmony_ci         goto unsupported;
1608bf215546Sopenharmony_ci      }
1609bf215546Sopenharmony_ci   }
1610bf215546Sopenharmony_ci
1611bf215546Sopenharmony_ci   if (image_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
1612bf215546Sopenharmony_ci      if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT)) {
1613bf215546Sopenharmony_ci         goto unsupported;
1614bf215546Sopenharmony_ci      }
1615bf215546Sopenharmony_ci   }
1616bf215546Sopenharmony_ci
1617bf215546Sopenharmony_ci   if (image_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
1618bf215546Sopenharmony_ci      if (!(format_feature_flags & (VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
1619bf215546Sopenharmony_ci                                    VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT))) {
1620bf215546Sopenharmony_ci         goto unsupported;
1621bf215546Sopenharmony_ci      }
1622bf215546Sopenharmony_ci   }
1623bf215546Sopenharmony_ci
1624bf215546Sopenharmony_ci   /* Sparse resources with multi-planar formats are unsupported. */
1625bf215546Sopenharmony_ci   if (info->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
1626bf215546Sopenharmony_ci      if (vk_format_get_plane_count(format) > 1)
1627bf215546Sopenharmony_ci         goto unsupported;
1628bf215546Sopenharmony_ci   }
1629bf215546Sopenharmony_ci
1630bf215546Sopenharmony_ci   if (info->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {
1631bf215546Sopenharmony_ci      /* Sparse textures are only supported on GFX8+. */
1632bf215546Sopenharmony_ci      if (physical_device->rad_info.gfx_level < GFX8)
1633bf215546Sopenharmony_ci         goto unsupported;
1634bf215546Sopenharmony_ci
1635bf215546Sopenharmony_ci      if (vk_format_get_plane_count(format) > 1 || info->type != VK_IMAGE_TYPE_2D ||
1636bf215546Sopenharmony_ci          info->tiling != VK_IMAGE_TILING_OPTIMAL || vk_format_is_depth_or_stencil(format))
1637bf215546Sopenharmony_ci         goto unsupported;
1638bf215546Sopenharmony_ci   }
1639bf215546Sopenharmony_ci
1640bf215546Sopenharmony_ci   if ((info->flags &
1641bf215546Sopenharmony_ci        (VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)) &&
1642bf215546Sopenharmony_ci       (desc->layout == UTIL_FORMAT_LAYOUT_ETC && physical_device->emulate_etc2)) {
1643bf215546Sopenharmony_ci      goto unsupported;
1644bf215546Sopenharmony_ci   }
1645bf215546Sopenharmony_ci
1646bf215546Sopenharmony_ci   *pImageFormatProperties = (VkImageFormatProperties){
1647bf215546Sopenharmony_ci      .maxExtent = maxExtent,
1648bf215546Sopenharmony_ci      .maxMipLevels = maxMipLevels,
1649bf215546Sopenharmony_ci      .maxArrayLayers = maxArraySize,
1650bf215546Sopenharmony_ci      .sampleCounts = sampleCounts,
1651bf215546Sopenharmony_ci
1652bf215546Sopenharmony_ci      /* FINISHME: Accurately calculate
1653bf215546Sopenharmony_ci       * VkImageFormatProperties::maxResourceSize.
1654bf215546Sopenharmony_ci       */
1655bf215546Sopenharmony_ci      .maxResourceSize = UINT32_MAX,
1656bf215546Sopenharmony_ci   };
1657bf215546Sopenharmony_ci
1658bf215546Sopenharmony_ci   if (mod_info) {
1659bf215546Sopenharmony_ci      result = radv_check_modifier_support(physical_device, info, pImageFormatProperties, format,
1660bf215546Sopenharmony_ci                                           mod_info->drmFormatModifier);
1661bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1662bf215546Sopenharmony_ci         goto unsupported;
1663bf215546Sopenharmony_ci   }
1664bf215546Sopenharmony_ci
1665bf215546Sopenharmony_ci   return VK_SUCCESS;
1666bf215546Sopenharmony_ciunsupported:
1667bf215546Sopenharmony_ci   *pImageFormatProperties = (VkImageFormatProperties){
1668bf215546Sopenharmony_ci      .maxExtent = {0, 0, 0},
1669bf215546Sopenharmony_ci      .maxMipLevels = 0,
1670bf215546Sopenharmony_ci      .maxArrayLayers = 0,
1671bf215546Sopenharmony_ci      .sampleCounts = 0,
1672bf215546Sopenharmony_ci      .maxResourceSize = 0,
1673bf215546Sopenharmony_ci   };
1674bf215546Sopenharmony_ci
1675bf215546Sopenharmony_ci   return result;
1676bf215546Sopenharmony_ci}
1677bf215546Sopenharmony_ci
1678bf215546Sopenharmony_cistatic void
1679bf215546Sopenharmony_ciget_external_image_format_properties(struct radv_physical_device *physical_device,
1680bf215546Sopenharmony_ci                                     const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
1681bf215546Sopenharmony_ci                                     VkExternalMemoryHandleTypeFlagBits handleType,
1682bf215546Sopenharmony_ci                                     VkExternalMemoryProperties *external_properties,
1683bf215546Sopenharmony_ci                                     VkImageFormatProperties *format_properties)
1684bf215546Sopenharmony_ci{
1685bf215546Sopenharmony_ci   VkExternalMemoryFeatureFlagBits flags = 0;
1686bf215546Sopenharmony_ci   VkExternalMemoryHandleTypeFlags export_flags = 0;
1687bf215546Sopenharmony_ci   VkExternalMemoryHandleTypeFlags compat_flags = 0;
1688bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(pImageFormatInfo->format);
1689bf215546Sopenharmony_ci
1690bf215546Sopenharmony_ci   if (desc->layout == UTIL_FORMAT_LAYOUT_ETC && physical_device->emulate_etc2)
1691bf215546Sopenharmony_ci      return;
1692bf215546Sopenharmony_ci
1693bf215546Sopenharmony_ci   if (pImageFormatInfo->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)
1694bf215546Sopenharmony_ci      return;
1695bf215546Sopenharmony_ci
1696bf215546Sopenharmony_ci   switch (handleType) {
1697bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1698bf215546Sopenharmony_ci      if (pImageFormatInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1699bf215546Sopenharmony_ci         break;
1700bf215546Sopenharmony_ci
1701bf215546Sopenharmony_ci      switch (pImageFormatInfo->type) {
1702bf215546Sopenharmony_ci      case VK_IMAGE_TYPE_2D:
1703bf215546Sopenharmony_ci         flags =
1704bf215546Sopenharmony_ci            VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1705bf215546Sopenharmony_ci
1706bf215546Sopenharmony_ci         compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1707bf215546Sopenharmony_ci         break;
1708bf215546Sopenharmony_ci      default:
1709bf215546Sopenharmony_ci         break;
1710bf215546Sopenharmony_ci      }
1711bf215546Sopenharmony_ci      break;
1712bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1713bf215546Sopenharmony_ci      switch (pImageFormatInfo->type) {
1714bf215546Sopenharmony_ci      case VK_IMAGE_TYPE_2D:
1715bf215546Sopenharmony_ci         flags =
1716bf215546Sopenharmony_ci            VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1717bf215546Sopenharmony_ci         if (pImageFormatInfo->tiling != VK_IMAGE_TILING_LINEAR)
1718bf215546Sopenharmony_ci            flags |= VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT;
1719bf215546Sopenharmony_ci
1720bf215546Sopenharmony_ci         compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
1721bf215546Sopenharmony_ci         break;
1722bf215546Sopenharmony_ci      default:
1723bf215546Sopenharmony_ci         break;
1724bf215546Sopenharmony_ci      }
1725bf215546Sopenharmony_ci      break;
1726bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
1727bf215546Sopenharmony_ci      if (!physical_device->vk.supported_extensions.ANDROID_external_memory_android_hardware_buffer)
1728bf215546Sopenharmony_ci         break;
1729bf215546Sopenharmony_ci
1730bf215546Sopenharmony_ci      if (!radv_android_gralloc_supports_format(pImageFormatInfo->format, pImageFormatInfo->usage))
1731bf215546Sopenharmony_ci         break;
1732bf215546Sopenharmony_ci
1733bf215546Sopenharmony_ci      if (pImageFormatInfo->type != VK_IMAGE_TYPE_2D)
1734bf215546Sopenharmony_ci         break;
1735bf215546Sopenharmony_ci
1736bf215546Sopenharmony_ci      format_properties->maxMipLevels = MIN2(1, format_properties->maxMipLevels);
1737bf215546Sopenharmony_ci      format_properties->maxArrayLayers = MIN2(1, format_properties->maxArrayLayers);
1738bf215546Sopenharmony_ci      format_properties->sampleCounts &= VK_SAMPLE_COUNT_1_BIT;
1739bf215546Sopenharmony_ci
1740bf215546Sopenharmony_ci      flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1741bf215546Sopenharmony_ci      if (pImageFormatInfo->tiling != VK_IMAGE_TILING_LINEAR)
1742bf215546Sopenharmony_ci         flags |= VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT;
1743bf215546Sopenharmony_ci
1744bf215546Sopenharmony_ci      compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
1745bf215546Sopenharmony_ci      break;
1746bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1747bf215546Sopenharmony_ci      flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1748bf215546Sopenharmony_ci      compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
1749bf215546Sopenharmony_ci      break;
1750bf215546Sopenharmony_ci   default:
1751bf215546Sopenharmony_ci      break;
1752bf215546Sopenharmony_ci   }
1753bf215546Sopenharmony_ci
1754bf215546Sopenharmony_ci   *external_properties = (VkExternalMemoryProperties){
1755bf215546Sopenharmony_ci      .externalMemoryFeatures = flags,
1756bf215546Sopenharmony_ci      .exportFromImportedHandleTypes = export_flags,
1757bf215546Sopenharmony_ci      .compatibleHandleTypes = compat_flags,
1758bf215546Sopenharmony_ci   };
1759bf215546Sopenharmony_ci}
1760bf215546Sopenharmony_ci
1761bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1762bf215546Sopenharmony_ciradv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
1763bf215546Sopenharmony_ci                                             const VkPhysicalDeviceImageFormatInfo2 *base_info,
1764bf215546Sopenharmony_ci                                             VkImageFormatProperties2 *base_props)
1765bf215546Sopenharmony_ci{
1766bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
1767bf215546Sopenharmony_ci   const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
1768bf215546Sopenharmony_ci   VkExternalImageFormatProperties *external_props = NULL;
1769bf215546Sopenharmony_ci   struct VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;
1770bf215546Sopenharmony_ci   VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
1771bf215546Sopenharmony_ci   VkTextureLODGatherFormatPropertiesAMD *texture_lod_props = NULL;
1772bf215546Sopenharmony_ci   VkResult result;
1773bf215546Sopenharmony_ci   VkFormat format = radv_select_android_external_format(base_info->pNext, base_info->format);
1774bf215546Sopenharmony_ci
1775bf215546Sopenharmony_ci   result = radv_get_image_format_properties(physical_device, base_info, format,
1776bf215546Sopenharmony_ci                                             &base_props->imageFormatProperties);
1777bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1778bf215546Sopenharmony_ci      return result;
1779bf215546Sopenharmony_ci
1780bf215546Sopenharmony_ci   /* Extract input structs */
1781bf215546Sopenharmony_ci   vk_foreach_struct_const(s, base_info->pNext)
1782bf215546Sopenharmony_ci   {
1783bf215546Sopenharmony_ci      switch (s->sType) {
1784bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
1785bf215546Sopenharmony_ci         external_info = (const void *)s;
1786bf215546Sopenharmony_ci         break;
1787bf215546Sopenharmony_ci      default:
1788bf215546Sopenharmony_ci         break;
1789bf215546Sopenharmony_ci      }
1790bf215546Sopenharmony_ci   }
1791bf215546Sopenharmony_ci
1792bf215546Sopenharmony_ci   /* Extract output structs */
1793bf215546Sopenharmony_ci   vk_foreach_struct(s, base_props->pNext)
1794bf215546Sopenharmony_ci   {
1795bf215546Sopenharmony_ci      switch (s->sType) {
1796bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
1797bf215546Sopenharmony_ci         external_props = (void *)s;
1798bf215546Sopenharmony_ci         break;
1799bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
1800bf215546Sopenharmony_ci         ycbcr_props = (void *)s;
1801bf215546Sopenharmony_ci         break;
1802bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
1803bf215546Sopenharmony_ci         android_usage = (void *)s;
1804bf215546Sopenharmony_ci         break;
1805bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD:
1806bf215546Sopenharmony_ci         texture_lod_props = (void *)s;
1807bf215546Sopenharmony_ci         break;
1808bf215546Sopenharmony_ci      default:
1809bf215546Sopenharmony_ci         break;
1810bf215546Sopenharmony_ci      }
1811bf215546Sopenharmony_ci   }
1812bf215546Sopenharmony_ci
1813bf215546Sopenharmony_ci   bool ahb_supported =
1814bf215546Sopenharmony_ci      physical_device->vk.supported_extensions.ANDROID_external_memory_android_hardware_buffer;
1815bf215546Sopenharmony_ci   if (android_usage && ahb_supported) {
1816bf215546Sopenharmony_ci#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
1817bf215546Sopenharmony_ci      android_usage->androidHardwareBufferUsage =
1818bf215546Sopenharmony_ci         radv_ahb_usage_from_vk_usage(base_info->flags, base_info->usage);
1819bf215546Sopenharmony_ci#endif
1820bf215546Sopenharmony_ci   }
1821bf215546Sopenharmony_ci
1822bf215546Sopenharmony_ci   /* From the Vulkan 1.0.97 spec:
1823bf215546Sopenharmony_ci    *
1824bf215546Sopenharmony_ci    *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
1825bf215546Sopenharmony_ci    *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
1826bf215546Sopenharmony_ci    *    present and VkExternalImageFormatProperties will be ignored.
1827bf215546Sopenharmony_ci    */
1828bf215546Sopenharmony_ci   if (external_info && external_info->handleType != 0) {
1829bf215546Sopenharmony_ci      VkExternalImageFormatProperties fallback_external_props;
1830bf215546Sopenharmony_ci
1831bf215546Sopenharmony_ci      if (!external_props) {
1832bf215546Sopenharmony_ci         memset(&fallback_external_props, 0, sizeof(fallback_external_props));
1833bf215546Sopenharmony_ci         external_props = &fallback_external_props;
1834bf215546Sopenharmony_ci      }
1835bf215546Sopenharmony_ci
1836bf215546Sopenharmony_ci      get_external_image_format_properties(physical_device, base_info, external_info->handleType,
1837bf215546Sopenharmony_ci                                           &external_props->externalMemoryProperties,
1838bf215546Sopenharmony_ci                                           &base_props->imageFormatProperties);
1839bf215546Sopenharmony_ci      if (!external_props->externalMemoryProperties.externalMemoryFeatures) {
1840bf215546Sopenharmony_ci         /* From the Vulkan 1.0.97 spec:
1841bf215546Sopenharmony_ci          *
1842bf215546Sopenharmony_ci          *    If handleType is not compatible with the [parameters] specified
1843bf215546Sopenharmony_ci          *    in VkPhysicalDeviceImageFormatInfo2, then
1844bf215546Sopenharmony_ci          *    vkGetPhysicalDeviceImageFormatProperties2 returns
1845bf215546Sopenharmony_ci          *    VK_ERROR_FORMAT_NOT_SUPPORTED.
1846bf215546Sopenharmony_ci          */
1847bf215546Sopenharmony_ci         result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
1848bf215546Sopenharmony_ci                            "unsupported VkExternalMemoryTypeFlagBitsKHR 0x%x",
1849bf215546Sopenharmony_ci                            external_info->handleType);
1850bf215546Sopenharmony_ci         goto fail;
1851bf215546Sopenharmony_ci      }
1852bf215546Sopenharmony_ci   }
1853bf215546Sopenharmony_ci
1854bf215546Sopenharmony_ci   if (ycbcr_props) {
1855bf215546Sopenharmony_ci      ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(format);
1856bf215546Sopenharmony_ci   }
1857bf215546Sopenharmony_ci
1858bf215546Sopenharmony_ci   if (texture_lod_props) {
1859bf215546Sopenharmony_ci      if (physical_device->rad_info.gfx_level >= GFX9) {
1860bf215546Sopenharmony_ci         texture_lod_props->supportsTextureGatherLODBiasAMD = true;
1861bf215546Sopenharmony_ci      } else {
1862bf215546Sopenharmony_ci         texture_lod_props->supportsTextureGatherLODBiasAMD = !vk_format_is_int(format);
1863bf215546Sopenharmony_ci      }
1864bf215546Sopenharmony_ci   }
1865bf215546Sopenharmony_ci
1866bf215546Sopenharmony_ci   return VK_SUCCESS;
1867bf215546Sopenharmony_ci
1868bf215546Sopenharmony_cifail:
1869bf215546Sopenharmony_ci   if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
1870bf215546Sopenharmony_ci      /* From the Vulkan 1.0.97 spec:
1871bf215546Sopenharmony_ci       *
1872bf215546Sopenharmony_ci       *    If the combination of parameters to
1873bf215546Sopenharmony_ci       *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by
1874bf215546Sopenharmony_ci       *    the implementation for use in vkCreateImage, then all members of
1875bf215546Sopenharmony_ci       *    imageFormatProperties will be filled with zero.
1876bf215546Sopenharmony_ci       */
1877bf215546Sopenharmony_ci      base_props->imageFormatProperties = (VkImageFormatProperties){0};
1878bf215546Sopenharmony_ci   }
1879bf215546Sopenharmony_ci
1880bf215546Sopenharmony_ci   return result;
1881bf215546Sopenharmony_ci}
1882bf215546Sopenharmony_ci
1883bf215546Sopenharmony_cistatic void
1884bf215546Sopenharmony_cifill_sparse_image_format_properties(struct radv_physical_device *pdev, VkFormat format,
1885bf215546Sopenharmony_ci                                    VkSparseImageFormatProperties *prop)
1886bf215546Sopenharmony_ci{
1887bf215546Sopenharmony_ci   prop->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1888bf215546Sopenharmony_ci   prop->flags = 0;
1889bf215546Sopenharmony_ci
1890bf215546Sopenharmony_ci   /* On GFX8 we first subdivide by level and then layer, leading to a single
1891bf215546Sopenharmony_ci    * miptail. On GFX9+ we first subdivide by layer and then level which results
1892bf215546Sopenharmony_ci    * in a miptail per layer. */
1893bf215546Sopenharmony_ci   if (pdev->rad_info.gfx_level < GFX9)
1894bf215546Sopenharmony_ci      prop->flags |= VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT;
1895bf215546Sopenharmony_ci
1896bf215546Sopenharmony_ci   /* This assumes the sparse image tile size is always 64 KiB (1 << 16) */
1897bf215546Sopenharmony_ci   unsigned l2_size = 16 - util_logbase2(vk_format_get_blocksize(format));
1898bf215546Sopenharmony_ci   unsigned w = (1u << ((l2_size + 1) / 2)) * vk_format_get_blockwidth(format);
1899bf215546Sopenharmony_ci   unsigned h = (1u << (l2_size / 2)) * vk_format_get_blockheight(format);
1900bf215546Sopenharmony_ci
1901bf215546Sopenharmony_ci   prop->imageGranularity = (VkExtent3D){w, h, 1};
1902bf215546Sopenharmony_ci}
1903bf215546Sopenharmony_ci
1904bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1905bf215546Sopenharmony_ciradv_GetPhysicalDeviceSparseImageFormatProperties2(
1906bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
1907bf215546Sopenharmony_ci   uint32_t *pPropertyCount, VkSparseImageFormatProperties2 *pProperties)
1908bf215546Sopenharmony_ci{
1909bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_physical_device, pdev, physicalDevice);
1910bf215546Sopenharmony_ci   VkResult result;
1911bf215546Sopenharmony_ci
1912bf215546Sopenharmony_ci   if (pFormatInfo->samples > VK_SAMPLE_COUNT_1_BIT) {
1913bf215546Sopenharmony_ci      *pPropertyCount = 0;
1914bf215546Sopenharmony_ci      return;
1915bf215546Sopenharmony_ci   }
1916bf215546Sopenharmony_ci
1917bf215546Sopenharmony_ci   const VkPhysicalDeviceImageFormatInfo2 fmt_info = {
1918bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
1919bf215546Sopenharmony_ci      .format = pFormatInfo->format,
1920bf215546Sopenharmony_ci      .type = pFormatInfo->type,
1921bf215546Sopenharmony_ci      .tiling = pFormatInfo->tiling,
1922bf215546Sopenharmony_ci      .usage = pFormatInfo->usage,
1923bf215546Sopenharmony_ci      .flags = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT};
1924bf215546Sopenharmony_ci
1925bf215546Sopenharmony_ci   VkImageFormatProperties fmt_props;
1926bf215546Sopenharmony_ci   result = radv_get_image_format_properties(pdev, &fmt_info, pFormatInfo->format, &fmt_props);
1927bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
1928bf215546Sopenharmony_ci      *pPropertyCount = 0;
1929bf215546Sopenharmony_ci      return;
1930bf215546Sopenharmony_ci   }
1931bf215546Sopenharmony_ci
1932bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkSparseImageFormatProperties2, out, pProperties, pPropertyCount);
1933bf215546Sopenharmony_ci
1934bf215546Sopenharmony_ci   vk_outarray_append_typed(VkSparseImageFormatProperties2, &out, prop)
1935bf215546Sopenharmony_ci   {
1936bf215546Sopenharmony_ci      fill_sparse_image_format_properties(pdev, pFormatInfo->format, &prop->properties);
1937bf215546Sopenharmony_ci   };
1938bf215546Sopenharmony_ci}
1939bf215546Sopenharmony_ci
1940bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1941bf215546Sopenharmony_ciradv_GetImageSparseMemoryRequirements2(VkDevice _device,
1942bf215546Sopenharmony_ci                                       const VkImageSparseMemoryRequirementsInfo2 *pInfo,
1943bf215546Sopenharmony_ci                                       uint32_t *pSparseMemoryRequirementCount,
1944bf215546Sopenharmony_ci                                       VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1945bf215546Sopenharmony_ci{
1946bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_device, device, _device);
1947bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_image, image, pInfo->image);
1948bf215546Sopenharmony_ci
1949bf215546Sopenharmony_ci   if (!(image->vk.create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
1950bf215546Sopenharmony_ci      *pSparseMemoryRequirementCount = 0;
1951bf215546Sopenharmony_ci      return;
1952bf215546Sopenharmony_ci   }
1953bf215546Sopenharmony_ci
1954bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkSparseImageMemoryRequirements2, out, pSparseMemoryRequirements,
1955bf215546Sopenharmony_ci                          pSparseMemoryRequirementCount);
1956bf215546Sopenharmony_ci
1957bf215546Sopenharmony_ci   vk_outarray_append_typed(VkSparseImageMemoryRequirements2, &out, req)
1958bf215546Sopenharmony_ci   {
1959bf215546Sopenharmony_ci      fill_sparse_image_format_properties(device->physical_device, image->vk.format,
1960bf215546Sopenharmony_ci                                          &req->memoryRequirements.formatProperties);
1961bf215546Sopenharmony_ci      req->memoryRequirements.imageMipTailFirstLod = image->planes[0].surface.first_mip_tail_level;
1962bf215546Sopenharmony_ci
1963bf215546Sopenharmony_ci      if (req->memoryRequirements.imageMipTailFirstLod < image->info.levels) {
1964bf215546Sopenharmony_ci         if (device->physical_device->rad_info.gfx_level >= GFX9) {
1965bf215546Sopenharmony_ci            /* The tail is always a single tile per layer. */
1966bf215546Sopenharmony_ci            req->memoryRequirements.imageMipTailSize = 65536;
1967bf215546Sopenharmony_ci            req->memoryRequirements.imageMipTailOffset =
1968bf215546Sopenharmony_ci               image->planes[0]
1969bf215546Sopenharmony_ci                  .surface.u.gfx9.prt_level_offset[req->memoryRequirements.imageMipTailFirstLod] &
1970bf215546Sopenharmony_ci               ~65535;
1971bf215546Sopenharmony_ci            req->memoryRequirements.imageMipTailStride =
1972bf215546Sopenharmony_ci               image->planes[0].surface.u.gfx9.surf_slice_size;
1973bf215546Sopenharmony_ci         } else {
1974bf215546Sopenharmony_ci            req->memoryRequirements.imageMipTailOffset =
1975bf215546Sopenharmony_ci               (uint64_t)image->planes[0]
1976bf215546Sopenharmony_ci                  .surface.u.legacy.level[req->memoryRequirements.imageMipTailFirstLod]
1977bf215546Sopenharmony_ci                  .offset_256B * 256;
1978bf215546Sopenharmony_ci            req->memoryRequirements.imageMipTailSize =
1979bf215546Sopenharmony_ci               image->size - req->memoryRequirements.imageMipTailOffset;
1980bf215546Sopenharmony_ci            req->memoryRequirements.imageMipTailStride = 0;
1981bf215546Sopenharmony_ci         }
1982bf215546Sopenharmony_ci      } else {
1983bf215546Sopenharmony_ci         req->memoryRequirements.imageMipTailSize = 0;
1984bf215546Sopenharmony_ci         req->memoryRequirements.imageMipTailOffset = 0;
1985bf215546Sopenharmony_ci         req->memoryRequirements.imageMipTailStride = 0;
1986bf215546Sopenharmony_ci      }
1987bf215546Sopenharmony_ci   };
1988bf215546Sopenharmony_ci}
1989bf215546Sopenharmony_ci
1990bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1991bf215546Sopenharmony_ciradv_GetDeviceImageSparseMemoryRequirements(VkDevice device,
1992bf215546Sopenharmony_ci                                            const VkDeviceImageMemoryRequirements* pInfo,
1993bf215546Sopenharmony_ci                                            uint32_t *pSparseMemoryRequirementCount,
1994bf215546Sopenharmony_ci                                            VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1995bf215546Sopenharmony_ci{
1996bf215546Sopenharmony_ci   UNUSED VkResult result;
1997bf215546Sopenharmony_ci   VkImage image;
1998bf215546Sopenharmony_ci
1999bf215546Sopenharmony_ci   /* Determining the image size/alignment require to create a surface, which is complicated without
2000bf215546Sopenharmony_ci    * creating an image.
2001bf215546Sopenharmony_ci    * TODO: Avoid creating an image.
2002bf215546Sopenharmony_ci    */
2003bf215546Sopenharmony_ci   result = radv_CreateImage(device, pInfo->pCreateInfo, NULL, &image);
2004bf215546Sopenharmony_ci   assert(result == VK_SUCCESS);
2005bf215546Sopenharmony_ci
2006bf215546Sopenharmony_ci   VkImageSparseMemoryRequirementsInfo2 info2 = {
2007bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2,
2008bf215546Sopenharmony_ci      .image = image,
2009bf215546Sopenharmony_ci   };
2010bf215546Sopenharmony_ci
2011bf215546Sopenharmony_ci   radv_GetImageSparseMemoryRequirements2(device, &info2, pSparseMemoryRequirementCount,
2012bf215546Sopenharmony_ci                                          pSparseMemoryRequirements);
2013bf215546Sopenharmony_ci
2014bf215546Sopenharmony_ci   radv_DestroyImage(device, image, NULL);
2015bf215546Sopenharmony_ci}
2016bf215546Sopenharmony_ci
2017bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2018bf215546Sopenharmony_ciradv_GetPhysicalDeviceExternalBufferProperties(
2019bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
2020bf215546Sopenharmony_ci   VkExternalBufferProperties *pExternalBufferProperties)
2021bf215546Sopenharmony_ci{
2022bf215546Sopenharmony_ci   VkExternalMemoryFeatureFlagBits flags = 0;
2023bf215546Sopenharmony_ci   VkExternalMemoryHandleTypeFlags export_flags = 0;
2024bf215546Sopenharmony_ci   VkExternalMemoryHandleTypeFlags compat_flags = 0;
2025bf215546Sopenharmony_ci   switch (pExternalBufferInfo->handleType) {
2026bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
2027bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
2028bf215546Sopenharmony_ci      flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
2029bf215546Sopenharmony_ci      compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
2030bf215546Sopenharmony_ci                                    VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
2031bf215546Sopenharmony_ci      break;
2032bf215546Sopenharmony_ci   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
2033bf215546Sopenharmony_ci      flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
2034bf215546Sopenharmony_ci      compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
2035bf215546Sopenharmony_ci      break;
2036bf215546Sopenharmony_ci   default:
2037bf215546Sopenharmony_ci      break;
2038bf215546Sopenharmony_ci   }
2039bf215546Sopenharmony_ci   pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties){
2040bf215546Sopenharmony_ci      .externalMemoryFeatures = flags,
2041bf215546Sopenharmony_ci      .exportFromImportedHandleTypes = export_flags,
2042bf215546Sopenharmony_ci      .compatibleHandleTypes = compat_flags,
2043bf215546Sopenharmony_ci   };
2044bf215546Sopenharmony_ci}
2045bf215546Sopenharmony_ci
2046bf215546Sopenharmony_ci/* DCC channel type categories within which formats can be reinterpreted
2047bf215546Sopenharmony_ci * while keeping the same DCC encoding. The swizzle must also match. */
2048bf215546Sopenharmony_cienum dcc_channel_type {
2049bf215546Sopenharmony_ci   dcc_channel_float,
2050bf215546Sopenharmony_ci   dcc_channel_uint,
2051bf215546Sopenharmony_ci   dcc_channel_sint,
2052bf215546Sopenharmony_ci   dcc_channel_incompatible,
2053bf215546Sopenharmony_ci};
2054bf215546Sopenharmony_ci
2055bf215546Sopenharmony_ci/* Return the type of DCC encoding. */
2056bf215546Sopenharmony_cistatic void
2057bf215546Sopenharmony_ciradv_get_dcc_channel_type(const struct util_format_description *desc, enum dcc_channel_type *type,
2058bf215546Sopenharmony_ci                          unsigned *size)
2059bf215546Sopenharmony_ci{
2060bf215546Sopenharmony_ci   int i;
2061bf215546Sopenharmony_ci
2062bf215546Sopenharmony_ci   /* Find the first non-void channel. */
2063bf215546Sopenharmony_ci   for (i = 0; i < desc->nr_channels; i++)
2064bf215546Sopenharmony_ci      if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
2065bf215546Sopenharmony_ci         break;
2066bf215546Sopenharmony_ci   if (i == desc->nr_channels) {
2067bf215546Sopenharmony_ci      *type = dcc_channel_incompatible;
2068bf215546Sopenharmony_ci      return;
2069bf215546Sopenharmony_ci   }
2070bf215546Sopenharmony_ci
2071bf215546Sopenharmony_ci   switch (desc->channel[i].size) {
2072bf215546Sopenharmony_ci   case 32:
2073bf215546Sopenharmony_ci   case 16:
2074bf215546Sopenharmony_ci   case 10:
2075bf215546Sopenharmony_ci   case 8:
2076bf215546Sopenharmony_ci      *size = desc->channel[i].size;
2077bf215546Sopenharmony_ci      if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
2078bf215546Sopenharmony_ci         *type = dcc_channel_float;
2079bf215546Sopenharmony_ci      else if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED)
2080bf215546Sopenharmony_ci         *type = dcc_channel_uint;
2081bf215546Sopenharmony_ci      else
2082bf215546Sopenharmony_ci         *type = dcc_channel_sint;
2083bf215546Sopenharmony_ci      break;
2084bf215546Sopenharmony_ci   default:
2085bf215546Sopenharmony_ci      *type = dcc_channel_incompatible;
2086bf215546Sopenharmony_ci      break;
2087bf215546Sopenharmony_ci   }
2088bf215546Sopenharmony_ci}
2089bf215546Sopenharmony_ci
2090bf215546Sopenharmony_ci/* Return if it's allowed to reinterpret one format as another with DCC enabled. */
2091bf215546Sopenharmony_cibool
2092bf215546Sopenharmony_ciradv_dcc_formats_compatible(enum amd_gfx_level gfx_level, VkFormat format1, VkFormat format2,
2093bf215546Sopenharmony_ci                            bool *sign_reinterpret)
2094bf215546Sopenharmony_ci{
2095bf215546Sopenharmony_ci   const struct util_format_description *desc1, *desc2;
2096bf215546Sopenharmony_ci   enum dcc_channel_type type1, type2;
2097bf215546Sopenharmony_ci   unsigned size1, size2;
2098bf215546Sopenharmony_ci   int i;
2099bf215546Sopenharmony_ci
2100bf215546Sopenharmony_ci   /* All formats are compatible on GFX11. */
2101bf215546Sopenharmony_ci   if (gfx_level >= GFX11)
2102bf215546Sopenharmony_ci      return true;
2103bf215546Sopenharmony_ci
2104bf215546Sopenharmony_ci   if (format1 == format2)
2105bf215546Sopenharmony_ci      return true;
2106bf215546Sopenharmony_ci
2107bf215546Sopenharmony_ci   desc1 = vk_format_description(format1);
2108bf215546Sopenharmony_ci   desc2 = vk_format_description(format2);
2109bf215546Sopenharmony_ci
2110bf215546Sopenharmony_ci   if (desc1->nr_channels != desc2->nr_channels)
2111bf215546Sopenharmony_ci      return false;
2112bf215546Sopenharmony_ci
2113bf215546Sopenharmony_ci   /* Swizzles must be the same. */
2114bf215546Sopenharmony_ci   for (i = 0; i < desc1->nr_channels; i++)
2115bf215546Sopenharmony_ci      if (desc1->swizzle[i] <= PIPE_SWIZZLE_W && desc2->swizzle[i] <= PIPE_SWIZZLE_W &&
2116bf215546Sopenharmony_ci          desc1->swizzle[i] != desc2->swizzle[i])
2117bf215546Sopenharmony_ci         return false;
2118bf215546Sopenharmony_ci
2119bf215546Sopenharmony_ci   radv_get_dcc_channel_type(desc1, &type1, &size1);
2120bf215546Sopenharmony_ci   radv_get_dcc_channel_type(desc2, &type2, &size2);
2121bf215546Sopenharmony_ci
2122bf215546Sopenharmony_ci   if (type1 == dcc_channel_incompatible || type2 == dcc_channel_incompatible ||
2123bf215546Sopenharmony_ci       (type1 == dcc_channel_float) != (type2 == dcc_channel_float) || size1 != size2)
2124bf215546Sopenharmony_ci      return false;
2125bf215546Sopenharmony_ci
2126bf215546Sopenharmony_ci   if (type1 != type2)
2127bf215546Sopenharmony_ci      *sign_reinterpret = true;
2128bf215546Sopenharmony_ci
2129bf215546Sopenharmony_ci   return true;
2130bf215546Sopenharmony_ci}
2131