1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2016 Red Hat.
3b8e80941Smrg * Copyright © 2016 Bas Nieuwenhuizen
4b8e80941Smrg *
5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
7b8e80941Smrg * to deal in the Software without restriction, including without limitation
8b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
10b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
11b8e80941Smrg *
12b8e80941Smrg * The above copyright notice and this permission notice (including the next
13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
14b8e80941Smrg * Software.
15b8e80941Smrg *
16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22b8e80941Smrg * IN THE SOFTWARE.
23b8e80941Smrg */
24b8e80941Smrg
25b8e80941Smrg#include "radv_private.h"
26b8e80941Smrg
27b8e80941Smrg#include "vk_format.h"
28b8e80941Smrg#include "sid.h"
29b8e80941Smrg
30b8e80941Smrg#include "vk_util.h"
31b8e80941Smrg
32b8e80941Smrg#include "util/u_half.h"
33b8e80941Smrg#include "util/format_srgb.h"
34b8e80941Smrg#include "util/format_r11g11b10f.h"
35b8e80941Smrg
36b8e80941Smrguint32_t radv_translate_buffer_dataformat(const struct vk_format_description *desc,
37b8e80941Smrg					  int first_non_void)
38b8e80941Smrg{
39b8e80941Smrg	unsigned type;
40b8e80941Smrg	int i;
41b8e80941Smrg
42b8e80941Smrg	assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE);
43b8e80941Smrg
44b8e80941Smrg	if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
45b8e80941Smrg		return V_008F0C_BUF_DATA_FORMAT_10_11_11;
46b8e80941Smrg
47b8e80941Smrg	if (first_non_void < 0)
48b8e80941Smrg		return V_008F0C_BUF_DATA_FORMAT_INVALID;
49b8e80941Smrg	type = desc->channel[first_non_void].type;
50b8e80941Smrg
51b8e80941Smrg	if (type == VK_FORMAT_TYPE_FIXED)
52b8e80941Smrg		return V_008F0C_BUF_DATA_FORMAT_INVALID;
53b8e80941Smrg	if (desc->nr_channels == 4 &&
54b8e80941Smrg	    desc->channel[0].size == 10 &&
55b8e80941Smrg	    desc->channel[1].size == 10 &&
56b8e80941Smrg	    desc->channel[2].size == 10 &&
57b8e80941Smrg	    desc->channel[3].size == 2)
58b8e80941Smrg		return V_008F0C_BUF_DATA_FORMAT_2_10_10_10;
59b8e80941Smrg
60b8e80941Smrg	/* See whether the components are of the same size. */
61b8e80941Smrg	for (i = 0; i < desc->nr_channels; i++) {
62b8e80941Smrg		if (desc->channel[first_non_void].size != desc->channel[i].size)
63b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_INVALID;
64b8e80941Smrg	}
65b8e80941Smrg
66b8e80941Smrg	switch (desc->channel[first_non_void].size) {
67b8e80941Smrg	case 8:
68b8e80941Smrg		switch (desc->nr_channels) {
69b8e80941Smrg		case 1:
70b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_8;
71b8e80941Smrg		case 2:
72b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_8_8;
73b8e80941Smrg		case 4:
74b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_8_8_8_8;
75b8e80941Smrg		}
76b8e80941Smrg		break;
77b8e80941Smrg	case 16:
78b8e80941Smrg		switch (desc->nr_channels) {
79b8e80941Smrg		case 1:
80b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_16;
81b8e80941Smrg		case 2:
82b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_16_16;
83b8e80941Smrg		case 4:
84b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_16_16_16_16;
85b8e80941Smrg		}
86b8e80941Smrg		break;
87b8e80941Smrg	case 32:
88b8e80941Smrg		/* From the Southern Islands ISA documentation about MTBUF:
89b8e80941Smrg		 * 'Memory reads of data in memory that is 32 or 64 bits do not
90b8e80941Smrg		 * undergo any format conversion.'
91b8e80941Smrg		 */
92b8e80941Smrg		if (type != VK_FORMAT_TYPE_FLOAT &&
93b8e80941Smrg		    !desc->channel[first_non_void].pure_integer)
94b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_INVALID;
95b8e80941Smrg
96b8e80941Smrg		switch (desc->nr_channels) {
97b8e80941Smrg		case 1:
98b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_32;
99b8e80941Smrg		case 2:
100b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_32_32;
101b8e80941Smrg		case 3:
102b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_32_32_32;
103b8e80941Smrg		case 4:
104b8e80941Smrg			return V_008F0C_BUF_DATA_FORMAT_32_32_32_32;
105b8e80941Smrg		}
106b8e80941Smrg		break;
107b8e80941Smrg	}
108b8e80941Smrg
109b8e80941Smrg	return V_008F0C_BUF_DATA_FORMAT_INVALID;
110b8e80941Smrg}
111b8e80941Smrg
112b8e80941Smrguint32_t radv_translate_buffer_numformat(const struct vk_format_description *desc,
113b8e80941Smrg					 int first_non_void)
114b8e80941Smrg{
115b8e80941Smrg	assert(desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE);
116b8e80941Smrg
117b8e80941Smrg	if (desc->format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
118b8e80941Smrg		return V_008F0C_BUF_NUM_FORMAT_FLOAT;
119b8e80941Smrg
120b8e80941Smrg	if (first_non_void < 0)
121b8e80941Smrg		return ~0;
122b8e80941Smrg
123b8e80941Smrg	switch (desc->channel[first_non_void].type) {
124b8e80941Smrg	case VK_FORMAT_TYPE_SIGNED:
125b8e80941Smrg		if (desc->channel[first_non_void].normalized)
126b8e80941Smrg			return V_008F0C_BUF_NUM_FORMAT_SNORM;
127b8e80941Smrg		else if (desc->channel[first_non_void].pure_integer)
128b8e80941Smrg			return V_008F0C_BUF_NUM_FORMAT_SINT;
129b8e80941Smrg		else
130b8e80941Smrg			return V_008F0C_BUF_NUM_FORMAT_SSCALED;
131b8e80941Smrg		break;
132b8e80941Smrg	case VK_FORMAT_TYPE_UNSIGNED:
133b8e80941Smrg		if (desc->channel[first_non_void].normalized)
134b8e80941Smrg			return V_008F0C_BUF_NUM_FORMAT_UNORM;
135b8e80941Smrg		else if (desc->channel[first_non_void].pure_integer)
136b8e80941Smrg			return V_008F0C_BUF_NUM_FORMAT_UINT;
137b8e80941Smrg		else
138b8e80941Smrg			return V_008F0C_BUF_NUM_FORMAT_USCALED;
139b8e80941Smrg		break;
140b8e80941Smrg	case VK_FORMAT_TYPE_FLOAT:
141b8e80941Smrg	default:
142b8e80941Smrg		return V_008F0C_BUF_NUM_FORMAT_FLOAT;
143b8e80941Smrg	}
144b8e80941Smrg}
145b8e80941Smrg
146b8e80941Smrguint32_t radv_translate_tex_dataformat(VkFormat format,
147b8e80941Smrg				       const struct vk_format_description *desc,
148b8e80941Smrg				       int first_non_void)
149b8e80941Smrg{
150b8e80941Smrg	bool uniform = true;
151b8e80941Smrg	int i;
152b8e80941Smrg
153b8e80941Smrg	assert(vk_format_get_plane_count(format) == 1);
154b8e80941Smrg
155b8e80941Smrg	if (!desc)
156b8e80941Smrg		return ~0;
157b8e80941Smrg	/* Colorspace (return non-RGB formats directly). */
158b8e80941Smrg	switch (desc->colorspace) {
159b8e80941Smrg		/* Depth stencil formats */
160b8e80941Smrg	case VK_FORMAT_COLORSPACE_ZS:
161b8e80941Smrg		switch (format) {
162b8e80941Smrg		case VK_FORMAT_D16_UNORM:
163b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_16;
164b8e80941Smrg		case VK_FORMAT_D24_UNORM_S8_UINT:
165b8e80941Smrg		case VK_FORMAT_X8_D24_UNORM_PACK32:
166b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_8_24;
167b8e80941Smrg		case VK_FORMAT_S8_UINT:
168b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_8;
169b8e80941Smrg		case VK_FORMAT_D32_SFLOAT:
170b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_32;
171b8e80941Smrg		case VK_FORMAT_D32_SFLOAT_S8_UINT:
172b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_X24_8_32;
173b8e80941Smrg		default:
174b8e80941Smrg			goto out_unknown;
175b8e80941Smrg		}
176b8e80941Smrg
177b8e80941Smrg	case VK_FORMAT_COLORSPACE_YUV:
178b8e80941Smrg		goto out_unknown; /* TODO */
179b8e80941Smrg
180b8e80941Smrg	case VK_FORMAT_COLORSPACE_SRGB:
181b8e80941Smrg		if (desc->nr_channels != 4 && desc->nr_channels != 1)
182b8e80941Smrg			goto out_unknown;
183b8e80941Smrg		break;
184b8e80941Smrg
185b8e80941Smrg	default:
186b8e80941Smrg		break;
187b8e80941Smrg	}
188b8e80941Smrg
189b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
190b8e80941Smrg		switch(format) {
191b8e80941Smrg		/* Don't ask me why this looks inverted. PAL does the same. */
192b8e80941Smrg		case VK_FORMAT_G8B8G8R8_422_UNORM:
193b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BG_RG;
194b8e80941Smrg		case VK_FORMAT_B8G8R8G8_422_UNORM:
195b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_GB_GR;
196b8e80941Smrg		default:
197b8e80941Smrg			goto out_unknown;
198b8e80941Smrg		}
199b8e80941Smrg	}
200b8e80941Smrg
201b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_RGTC) {
202b8e80941Smrg		switch(format) {
203b8e80941Smrg		case VK_FORMAT_BC4_UNORM_BLOCK:
204b8e80941Smrg		case VK_FORMAT_BC4_SNORM_BLOCK:
205b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BC4;
206b8e80941Smrg		case VK_FORMAT_BC5_UNORM_BLOCK:
207b8e80941Smrg		case VK_FORMAT_BC5_SNORM_BLOCK:
208b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BC5;
209b8e80941Smrg		default:
210b8e80941Smrg			break;
211b8e80941Smrg		}
212b8e80941Smrg	}
213b8e80941Smrg
214b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_S3TC) {
215b8e80941Smrg		switch(format) {
216b8e80941Smrg		case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
217b8e80941Smrg		case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
218b8e80941Smrg		case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
219b8e80941Smrg		case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
220b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BC1;
221b8e80941Smrg		case VK_FORMAT_BC2_UNORM_BLOCK:
222b8e80941Smrg		case VK_FORMAT_BC2_SRGB_BLOCK:
223b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BC2;
224b8e80941Smrg		case VK_FORMAT_BC3_UNORM_BLOCK:
225b8e80941Smrg		case VK_FORMAT_BC3_SRGB_BLOCK:
226b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BC3;
227b8e80941Smrg		default:
228b8e80941Smrg			break;
229b8e80941Smrg		}
230b8e80941Smrg	}
231b8e80941Smrg
232b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_BPTC) {
233b8e80941Smrg		switch(format) {
234b8e80941Smrg		case VK_FORMAT_BC6H_UFLOAT_BLOCK:
235b8e80941Smrg		case VK_FORMAT_BC6H_SFLOAT_BLOCK:
236b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BC6;
237b8e80941Smrg		case VK_FORMAT_BC7_UNORM_BLOCK:
238b8e80941Smrg		case VK_FORMAT_BC7_SRGB_BLOCK:
239b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_BC7;
240b8e80941Smrg		default:
241b8e80941Smrg			break;
242b8e80941Smrg		}
243b8e80941Smrg	}
244b8e80941Smrg
245b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_ETC) {
246b8e80941Smrg		switch (format) {
247b8e80941Smrg		case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
248b8e80941Smrg		case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
249b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_ETC2_RGB;
250b8e80941Smrg		case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
251b8e80941Smrg		case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
252b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA1;
253b8e80941Smrg		case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
254b8e80941Smrg		case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
255b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA;
256b8e80941Smrg		case VK_FORMAT_EAC_R11_UNORM_BLOCK:
257b8e80941Smrg		case VK_FORMAT_EAC_R11_SNORM_BLOCK:
258b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_ETC2_R;
259b8e80941Smrg		case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
260b8e80941Smrg		case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
261b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_ETC2_RG;
262b8e80941Smrg		default:
263b8e80941Smrg			break;
264b8e80941Smrg		}
265b8e80941Smrg	}
266b8e80941Smrg
267b8e80941Smrg	if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
268b8e80941Smrg		return V_008F14_IMG_DATA_FORMAT_5_9_9_9;
269b8e80941Smrg	} else if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
270b8e80941Smrg		return V_008F14_IMG_DATA_FORMAT_10_11_11;
271b8e80941Smrg	}
272b8e80941Smrg
273b8e80941Smrg	/* R8G8Bx_SNORM - TODO CxV8U8 */
274b8e80941Smrg
275b8e80941Smrg	/* hw cannot support mixed formats (except depth/stencil, since only
276b8e80941Smrg	 * depth is read).*/
277b8e80941Smrg	if (desc->is_mixed && desc->colorspace != VK_FORMAT_COLORSPACE_ZS)
278b8e80941Smrg		goto out_unknown;
279b8e80941Smrg
280b8e80941Smrg	/* See whether the components are of the same size. */
281b8e80941Smrg	for (i = 1; i < desc->nr_channels; i++) {
282b8e80941Smrg		uniform = uniform && desc->channel[0].size == desc->channel[i].size;
283b8e80941Smrg	}
284b8e80941Smrg
285b8e80941Smrg	/* Non-uniform formats. */
286b8e80941Smrg	if (!uniform) {
287b8e80941Smrg		switch(desc->nr_channels) {
288b8e80941Smrg		case 3:
289b8e80941Smrg			if (desc->channel[0].size == 5 &&
290b8e80941Smrg			    desc->channel[1].size == 6 &&
291b8e80941Smrg			    desc->channel[2].size == 5) {
292b8e80941Smrg				return V_008F14_IMG_DATA_FORMAT_5_6_5;
293b8e80941Smrg			}
294b8e80941Smrg			goto out_unknown;
295b8e80941Smrg		case 4:
296b8e80941Smrg			if (desc->channel[0].size == 5 &&
297b8e80941Smrg			    desc->channel[1].size == 5 &&
298b8e80941Smrg			    desc->channel[2].size == 5 &&
299b8e80941Smrg			    desc->channel[3].size == 1) {
300b8e80941Smrg				return V_008F14_IMG_DATA_FORMAT_1_5_5_5;
301b8e80941Smrg			}
302b8e80941Smrg			if (desc->channel[0].size == 1 &&
303b8e80941Smrg			    desc->channel[1].size == 5 &&
304b8e80941Smrg			    desc->channel[2].size == 5 &&
305b8e80941Smrg			    desc->channel[3].size == 5) {
306b8e80941Smrg				return V_008F14_IMG_DATA_FORMAT_5_5_5_1;
307b8e80941Smrg			}
308b8e80941Smrg			if (desc->channel[0].size == 10 &&
309b8e80941Smrg			    desc->channel[1].size == 10 &&
310b8e80941Smrg			    desc->channel[2].size == 10 &&
311b8e80941Smrg			    desc->channel[3].size == 2) {
312b8e80941Smrg				/* Closed VK driver does this also no 2/10/10/10 snorm */
313b8e80941Smrg				if (desc->channel[0].type == VK_FORMAT_TYPE_SIGNED &&
314b8e80941Smrg				    desc->channel[0].normalized)
315b8e80941Smrg					goto out_unknown;
316b8e80941Smrg				return V_008F14_IMG_DATA_FORMAT_2_10_10_10;
317b8e80941Smrg			}
318b8e80941Smrg			goto out_unknown;
319b8e80941Smrg		}
320b8e80941Smrg		goto out_unknown;
321b8e80941Smrg	}
322b8e80941Smrg
323b8e80941Smrg	if (first_non_void < 0 || first_non_void > 3)
324b8e80941Smrg		goto out_unknown;
325b8e80941Smrg
326b8e80941Smrg	/* uniform formats */
327b8e80941Smrg	switch (desc->channel[first_non_void].size) {
328b8e80941Smrg	case 4:
329b8e80941Smrg		switch (desc->nr_channels) {
330b8e80941Smrg#if 0 /* Not supported for render targets */
331b8e80941Smrg		case 2:
332b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_4_4;
333b8e80941Smrg#endif
334b8e80941Smrg		case 4:
335b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_4_4_4_4;
336b8e80941Smrg		}
337b8e80941Smrg		break;
338b8e80941Smrg	case 8:
339b8e80941Smrg		switch (desc->nr_channels) {
340b8e80941Smrg		case 1:
341b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_8;
342b8e80941Smrg		case 2:
343b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_8_8;
344b8e80941Smrg		case 4:
345b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_8_8_8_8;
346b8e80941Smrg		}
347b8e80941Smrg		break;
348b8e80941Smrg	case 16:
349b8e80941Smrg		switch (desc->nr_channels) {
350b8e80941Smrg		case 1:
351b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_16;
352b8e80941Smrg		case 2:
353b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_16_16;
354b8e80941Smrg		case 4:
355b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_16_16_16_16;
356b8e80941Smrg		}
357b8e80941Smrg		break;
358b8e80941Smrg	case 32:
359b8e80941Smrg		switch (desc->nr_channels) {
360b8e80941Smrg		case 1:
361b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_32;
362b8e80941Smrg		case 2:
363b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_32_32;
364b8e80941Smrg		case 3:
365b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_32_32_32;
366b8e80941Smrg		case 4:
367b8e80941Smrg			return V_008F14_IMG_DATA_FORMAT_32_32_32_32;
368b8e80941Smrg		}
369b8e80941Smrg	}
370b8e80941Smrg
371b8e80941Smrgout_unknown:
372b8e80941Smrg	/* R600_ERR("Unable to handle texformat %d %s\n", format, vk_format_name(format)); */
373b8e80941Smrg	return ~0;
374b8e80941Smrg}
375b8e80941Smrg
376b8e80941Smrguint32_t radv_translate_tex_numformat(VkFormat format,
377b8e80941Smrg				      const struct vk_format_description *desc,
378b8e80941Smrg				      int first_non_void)
379b8e80941Smrg{
380b8e80941Smrg	assert(vk_format_get_plane_count(format) == 1);
381b8e80941Smrg
382b8e80941Smrg	switch (format) {
383b8e80941Smrg	case VK_FORMAT_D24_UNORM_S8_UINT:
384b8e80941Smrg		return V_008F14_IMG_NUM_FORMAT_UNORM;
385b8e80941Smrg	default:
386b8e80941Smrg		if (first_non_void < 0) {
387b8e80941Smrg			if (vk_format_is_compressed(format)) {
388b8e80941Smrg				switch (format) {
389b8e80941Smrg				case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
390b8e80941Smrg				case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
391b8e80941Smrg				case VK_FORMAT_BC2_SRGB_BLOCK:
392b8e80941Smrg				case VK_FORMAT_BC3_SRGB_BLOCK:
393b8e80941Smrg				case VK_FORMAT_BC7_SRGB_BLOCK:
394b8e80941Smrg				case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
395b8e80941Smrg				case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
396b8e80941Smrg				case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
397b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_SRGB;
398b8e80941Smrg				case VK_FORMAT_BC4_SNORM_BLOCK:
399b8e80941Smrg				case VK_FORMAT_BC5_SNORM_BLOCK:
400b8e80941Smrg			        case VK_FORMAT_BC6H_SFLOAT_BLOCK:
401b8e80941Smrg				case VK_FORMAT_EAC_R11_SNORM_BLOCK:
402b8e80941Smrg				case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
403b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_SNORM;
404b8e80941Smrg				default:
405b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_UNORM;
406b8e80941Smrg				}
407b8e80941Smrg			} else if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
408b8e80941Smrg				return V_008F14_IMG_NUM_FORMAT_UNORM;
409b8e80941Smrg			} else {
410b8e80941Smrg				return V_008F14_IMG_NUM_FORMAT_FLOAT;
411b8e80941Smrg			}
412b8e80941Smrg		} else if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
413b8e80941Smrg			return V_008F14_IMG_NUM_FORMAT_SRGB;
414b8e80941Smrg		} else {
415b8e80941Smrg			switch (desc->channel[first_non_void].type) {
416b8e80941Smrg			case VK_FORMAT_TYPE_FLOAT:
417b8e80941Smrg				return V_008F14_IMG_NUM_FORMAT_FLOAT;
418b8e80941Smrg			case VK_FORMAT_TYPE_SIGNED:
419b8e80941Smrg				if (desc->channel[first_non_void].normalized)
420b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_SNORM;
421b8e80941Smrg				else if (desc->channel[first_non_void].pure_integer)
422b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_SINT;
423b8e80941Smrg				else
424b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_SSCALED;
425b8e80941Smrg			case VK_FORMAT_TYPE_UNSIGNED:
426b8e80941Smrg				if (desc->channel[first_non_void].normalized)
427b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_UNORM;
428b8e80941Smrg				else if (desc->channel[first_non_void].pure_integer)
429b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_UINT;
430b8e80941Smrg				else
431b8e80941Smrg					return V_008F14_IMG_NUM_FORMAT_USCALED;
432b8e80941Smrg			default:
433b8e80941Smrg				return V_008F14_IMG_NUM_FORMAT_UNORM;
434b8e80941Smrg			}
435b8e80941Smrg		}
436b8e80941Smrg	}
437b8e80941Smrg}
438b8e80941Smrg
439b8e80941Smrguint32_t radv_translate_color_numformat(VkFormat format,
440b8e80941Smrg					const struct vk_format_description *desc,
441b8e80941Smrg					int first_non_void)
442b8e80941Smrg{
443b8e80941Smrg	unsigned ntype;
444b8e80941Smrg
445b8e80941Smrg	assert(vk_format_get_plane_count(format) == 1);
446b8e80941Smrg
447b8e80941Smrg	if (first_non_void == -1 || desc->channel[first_non_void].type == VK_FORMAT_TYPE_FLOAT)
448b8e80941Smrg		ntype = V_028C70_NUMBER_FLOAT;
449b8e80941Smrg	else {
450b8e80941Smrg		ntype = V_028C70_NUMBER_UNORM;
451b8e80941Smrg		if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB)
452b8e80941Smrg			ntype = V_028C70_NUMBER_SRGB;
453b8e80941Smrg		else if (desc->channel[first_non_void].type == VK_FORMAT_TYPE_SIGNED) {
454b8e80941Smrg			if (desc->channel[first_non_void].pure_integer) {
455b8e80941Smrg				ntype = V_028C70_NUMBER_SINT;
456b8e80941Smrg			} else if (desc->channel[first_non_void].normalized) {
457b8e80941Smrg				ntype = V_028C70_NUMBER_SNORM;
458b8e80941Smrg			} else
459b8e80941Smrg				ntype = ~0u;
460b8e80941Smrg		} else if (desc->channel[first_non_void].type == VK_FORMAT_TYPE_UNSIGNED) {
461b8e80941Smrg			if (desc->channel[first_non_void].pure_integer) {
462b8e80941Smrg				ntype = V_028C70_NUMBER_UINT;
463b8e80941Smrg			} else if (desc->channel[first_non_void].normalized) {
464b8e80941Smrg				ntype = V_028C70_NUMBER_UNORM;
465b8e80941Smrg			} else
466b8e80941Smrg				ntype = ~0u;
467b8e80941Smrg		}
468b8e80941Smrg	}
469b8e80941Smrg	return ntype;
470b8e80941Smrg}
471b8e80941Smrg
472b8e80941Smrgstatic bool radv_is_sampler_format_supported(VkFormat format, bool *linear_sampling)
473b8e80941Smrg{
474b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
475b8e80941Smrg	uint32_t num_format;
476b8e80941Smrg	if (!desc || format == VK_FORMAT_UNDEFINED)
477b8e80941Smrg		return false;
478b8e80941Smrg	num_format = radv_translate_tex_numformat(format, desc,
479b8e80941Smrg						  vk_format_get_first_non_void_channel(format));
480b8e80941Smrg
481b8e80941Smrg	if (num_format == V_008F14_IMG_NUM_FORMAT_USCALED ||
482b8e80941Smrg	    num_format == V_008F14_IMG_NUM_FORMAT_SSCALED)
483b8e80941Smrg		return false;
484b8e80941Smrg
485b8e80941Smrg	if (num_format == V_008F14_IMG_NUM_FORMAT_UNORM ||
486b8e80941Smrg	    num_format == V_008F14_IMG_NUM_FORMAT_SNORM ||
487b8e80941Smrg	    num_format == V_008F14_IMG_NUM_FORMAT_FLOAT ||
488b8e80941Smrg	    num_format == V_008F14_IMG_NUM_FORMAT_SRGB)
489b8e80941Smrg		*linear_sampling = true;
490b8e80941Smrg	else
491b8e80941Smrg		*linear_sampling = false;
492b8e80941Smrg	return radv_translate_tex_dataformat(format, vk_format_description(format),
493b8e80941Smrg					     vk_format_get_first_non_void_channel(format)) != ~0U;
494b8e80941Smrg}
495b8e80941Smrg
496b8e80941Smrg
497b8e80941Smrgstatic bool radv_is_storage_image_format_supported(struct radv_physical_device *physical_device,
498b8e80941Smrg						   VkFormat format)
499b8e80941Smrg{
500b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
501b8e80941Smrg	unsigned data_format, num_format;
502b8e80941Smrg	if (!desc || format == VK_FORMAT_UNDEFINED)
503b8e80941Smrg		return false;
504b8e80941Smrg
505b8e80941Smrg	data_format = radv_translate_tex_dataformat(format, desc,
506b8e80941Smrg						    vk_format_get_first_non_void_channel(format));
507b8e80941Smrg	num_format = radv_translate_tex_numformat(format, desc,
508b8e80941Smrg						  vk_format_get_first_non_void_channel(format));
509b8e80941Smrg
510b8e80941Smrg	if(data_format == ~0 || num_format == ~0)
511b8e80941Smrg		return false;
512b8e80941Smrg
513b8e80941Smrg	/* Extracted from the GCN3 ISA document. */
514b8e80941Smrg	switch(num_format) {
515b8e80941Smrg	case V_008F14_IMG_NUM_FORMAT_UNORM:
516b8e80941Smrg	case V_008F14_IMG_NUM_FORMAT_SNORM:
517b8e80941Smrg	case V_008F14_IMG_NUM_FORMAT_UINT:
518b8e80941Smrg	case V_008F14_IMG_NUM_FORMAT_SINT:
519b8e80941Smrg	case V_008F14_IMG_NUM_FORMAT_FLOAT:
520b8e80941Smrg		break;
521b8e80941Smrg	default:
522b8e80941Smrg		return false;
523b8e80941Smrg	}
524b8e80941Smrg
525b8e80941Smrg	switch(data_format) {
526b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_8:
527b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_16:
528b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_8_8:
529b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_32:
530b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_16_16:
531b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_10_11_11:
532b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_11_11_10:
533b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_10_10_10_2:
534b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_2_10_10_10:
535b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_8_8_8_8:
536b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_32_32:
537b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_16_16_16_16:
538b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_32_32_32_32:
539b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_5_6_5:
540b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_1_5_5_5:
541b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_5_5_5_1:
542b8e80941Smrg	case V_008F14_IMG_DATA_FORMAT_4_4_4_4:
543b8e80941Smrg		/* TODO: FMASK formats. */
544b8e80941Smrg		return true;
545b8e80941Smrg	default:
546b8e80941Smrg		return false;
547b8e80941Smrg	}
548b8e80941Smrg}
549b8e80941Smrg
550b8e80941Smrgbool radv_is_buffer_format_supported(VkFormat format, bool *scaled)
551b8e80941Smrg{
552b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
553b8e80941Smrg	unsigned data_format, num_format;
554b8e80941Smrg	if (!desc || format == VK_FORMAT_UNDEFINED)
555b8e80941Smrg		return false;
556b8e80941Smrg
557b8e80941Smrg	data_format = radv_translate_buffer_dataformat(desc,
558b8e80941Smrg						       vk_format_get_first_non_void_channel(format));
559b8e80941Smrg	num_format = radv_translate_buffer_numformat(desc,
560b8e80941Smrg						     vk_format_get_first_non_void_channel(format));
561b8e80941Smrg
562b8e80941Smrg	if (scaled)
563b8e80941Smrg		*scaled = (num_format == V_008F0C_BUF_NUM_FORMAT_SSCALED) || (num_format == V_008F0C_BUF_NUM_FORMAT_USCALED);
564b8e80941Smrg	return data_format != V_008F0C_BUF_DATA_FORMAT_INVALID &&
565b8e80941Smrg		num_format != ~0;
566b8e80941Smrg}
567b8e80941Smrg
568b8e80941Smrgbool radv_is_colorbuffer_format_supported(VkFormat format, bool *blendable)
569b8e80941Smrg{
570b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
571b8e80941Smrg	uint32_t color_format = radv_translate_colorformat(format);
572b8e80941Smrg	uint32_t color_swap = radv_translate_colorswap(format, false);
573b8e80941Smrg	uint32_t color_num_format = radv_translate_color_numformat(format,
574b8e80941Smrg								   desc,
575b8e80941Smrg								   vk_format_get_first_non_void_channel(format));
576b8e80941Smrg
577b8e80941Smrg	if (color_num_format == V_028C70_NUMBER_UINT || color_num_format == V_028C70_NUMBER_SINT ||
578b8e80941Smrg	    color_format == V_028C70_COLOR_8_24 || color_format == V_028C70_COLOR_24_8 ||
579b8e80941Smrg	    color_format == V_028C70_COLOR_X24_8_32_FLOAT) {
580b8e80941Smrg		*blendable = false;
581b8e80941Smrg	} else
582b8e80941Smrg		*blendable = true;
583b8e80941Smrg	return color_format != V_028C70_COLOR_INVALID &&
584b8e80941Smrg		color_swap != ~0U &&
585b8e80941Smrg		color_num_format != ~0;
586b8e80941Smrg}
587b8e80941Smrg
588b8e80941Smrgstatic bool radv_is_zs_format_supported(VkFormat format)
589b8e80941Smrg{
590b8e80941Smrg	return radv_translate_dbformat(format) != V_028040_Z_INVALID || format == VK_FORMAT_S8_UINT;
591b8e80941Smrg}
592b8e80941Smrg
593b8e80941Smrgstatic bool radv_is_filter_minmax_format_supported(VkFormat format)
594b8e80941Smrg{
595b8e80941Smrg	/* From the Vulkan spec 1.1.71:
596b8e80941Smrg	 *
597b8e80941Smrg	 * "The following formats must support the
598b8e80941Smrg	 *  VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT feature with
599b8e80941Smrg	 *  VK_IMAGE_TILING_OPTIMAL, if they support
600b8e80941Smrg	 *  VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT."
601b8e80941Smrg	 */
602b8e80941Smrg	/* TODO: enable more formats. */
603b8e80941Smrg	switch (format) {
604b8e80941Smrg	case VK_FORMAT_R8_UNORM:
605b8e80941Smrg	case VK_FORMAT_R8_SNORM:
606b8e80941Smrg	case VK_FORMAT_R16_UNORM:
607b8e80941Smrg	case VK_FORMAT_R16_SNORM:
608b8e80941Smrg	case VK_FORMAT_R16_SFLOAT:
609b8e80941Smrg	case VK_FORMAT_R32_SFLOAT:
610b8e80941Smrg	case VK_FORMAT_D16_UNORM:
611b8e80941Smrg	case VK_FORMAT_X8_D24_UNORM_PACK32:
612b8e80941Smrg	case VK_FORMAT_D32_SFLOAT:
613b8e80941Smrg	case VK_FORMAT_D16_UNORM_S8_UINT:
614b8e80941Smrg	case VK_FORMAT_D24_UNORM_S8_UINT:
615b8e80941Smrg	case VK_FORMAT_D32_SFLOAT_S8_UINT:
616b8e80941Smrg		return true;
617b8e80941Smrg	default:
618b8e80941Smrg		return false;
619b8e80941Smrg	}
620b8e80941Smrg}
621b8e80941Smrg
622b8e80941Smrgbool
623b8e80941Smrgradv_device_supports_etc(struct radv_physical_device *physical_device)
624b8e80941Smrg{
625b8e80941Smrg	return physical_device->rad_info.family == CHIP_VEGA10 ||
626b8e80941Smrg	       physical_device->rad_info.family == CHIP_RAVEN ||
627b8e80941Smrg	       physical_device->rad_info.family == CHIP_STONEY;
628b8e80941Smrg}
629b8e80941Smrg
630b8e80941Smrgstatic void
631b8e80941Smrgradv_physical_device_get_format_properties(struct radv_physical_device *physical_device,
632b8e80941Smrg					   VkFormat format,
633b8e80941Smrg					   VkFormatProperties *out_properties)
634b8e80941Smrg{
635b8e80941Smrg	VkFormatFeatureFlags linear = 0, tiled = 0, buffer = 0;
636b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
637b8e80941Smrg	bool blendable;
638b8e80941Smrg	bool scaled = false;
639b8e80941Smrg	/* TODO: implement some software emulation of SUBSAMPLED formats. */
640b8e80941Smrg	if (!desc || desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
641b8e80941Smrg		out_properties->linearTilingFeatures = linear;
642b8e80941Smrg		out_properties->optimalTilingFeatures = tiled;
643b8e80941Smrg		out_properties->bufferFeatures = buffer;
644b8e80941Smrg		return;
645b8e80941Smrg	}
646b8e80941Smrg
647b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_ETC &&
648b8e80941Smrg	    !radv_device_supports_etc(physical_device)) {
649b8e80941Smrg		out_properties->linearTilingFeatures = linear;
650b8e80941Smrg		out_properties->optimalTilingFeatures = tiled;
651b8e80941Smrg		out_properties->bufferFeatures = buffer;
652b8e80941Smrg		return;
653b8e80941Smrg	}
654b8e80941Smrg
655b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_MULTIPLANE ||
656b8e80941Smrg	    desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
657b8e80941Smrg		uint32_t tiling = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
658b8e80941Smrg		                  VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
659b8e80941Smrg		                  VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
660b8e80941Smrg		                  VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
661b8e80941Smrg		                  VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
662b8e80941Smrg
663b8e80941Smrg		/* The subsampled formats have no support for linear filters. */
664b8e80941Smrg		if (desc->layout != VK_FORMAT_LAYOUT_SUBSAMPLED) {
665b8e80941Smrg			tiling |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
666b8e80941Smrg		}
667b8e80941Smrg
668b8e80941Smrg		/* Fails for unknown reasons with linear tiling & subsampled formats. */
669b8e80941Smrg		out_properties->linearTilingFeatures = desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED ? 0 : tiling;
670b8e80941Smrg		out_properties->optimalTilingFeatures = tiling;
671b8e80941Smrg		out_properties->bufferFeatures = 0;
672b8e80941Smrg		return;
673b8e80941Smrg	}
674b8e80941Smrg
675b8e80941Smrg	if (radv_is_storage_image_format_supported(physical_device, format)) {
676b8e80941Smrg		tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
677b8e80941Smrg		linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
678b8e80941Smrg	}
679b8e80941Smrg
680b8e80941Smrg	if (radv_is_buffer_format_supported(format, &scaled)) {
681b8e80941Smrg		buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
682b8e80941Smrg		if (!scaled)
683b8e80941Smrg			buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
684b8e80941Smrg				VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
685b8e80941Smrg	}
686b8e80941Smrg
687b8e80941Smrg	if (vk_format_is_depth_or_stencil(format)) {
688b8e80941Smrg		if (radv_is_zs_format_supported(format)) {
689b8e80941Smrg			tiled |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
690b8e80941Smrg			tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
691b8e80941Smrg			tiled |= VK_FORMAT_FEATURE_BLIT_SRC_BIT |
692b8e80941Smrg			         VK_FORMAT_FEATURE_BLIT_DST_BIT;
693b8e80941Smrg			tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
694b8e80941Smrg			         VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
695b8e80941Smrg
696b8e80941Smrg			if (radv_is_filter_minmax_format_supported(format))
697b8e80941Smrg				 tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT;
698b8e80941Smrg
699b8e80941Smrg			/* Don't support blitting surfaces with depth/stencil. */
700b8e80941Smrg			if (vk_format_is_depth(format) && vk_format_is_stencil(format))
701b8e80941Smrg				tiled &= ~VK_FORMAT_FEATURE_BLIT_DST_BIT;
702b8e80941Smrg
703b8e80941Smrg			/* Don't support linear depth surfaces */
704b8e80941Smrg			linear = 0;
705b8e80941Smrg		}
706b8e80941Smrg	} else {
707b8e80941Smrg		bool linear_sampling;
708b8e80941Smrg		if (radv_is_sampler_format_supported(format, &linear_sampling)) {
709b8e80941Smrg			linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
710b8e80941Smrg				VK_FORMAT_FEATURE_BLIT_SRC_BIT;
711b8e80941Smrg			tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
712b8e80941Smrg				VK_FORMAT_FEATURE_BLIT_SRC_BIT;
713b8e80941Smrg
714b8e80941Smrg			if (radv_is_filter_minmax_format_supported(format))
715b8e80941Smrg				 tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT;
716b8e80941Smrg
717b8e80941Smrg			if (linear_sampling) {
718b8e80941Smrg				linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
719b8e80941Smrg				tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
720b8e80941Smrg			}
721b8e80941Smrg
722b8e80941Smrg			/* Don't support blitting for R32G32B32 formats. */
723b8e80941Smrg			if (format == VK_FORMAT_R32G32B32_SFLOAT ||
724b8e80941Smrg			    format == VK_FORMAT_R32G32B32_UINT ||
725b8e80941Smrg			    format == VK_FORMAT_R32G32B32_SINT) {
726b8e80941Smrg				linear &= ~VK_FORMAT_FEATURE_BLIT_SRC_BIT;
727b8e80941Smrg			}
728b8e80941Smrg		}
729b8e80941Smrg		if (radv_is_colorbuffer_format_supported(format, &blendable)) {
730b8e80941Smrg			linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
731b8e80941Smrg			tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
732b8e80941Smrg			if (blendable) {
733b8e80941Smrg				linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
734b8e80941Smrg				tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
735b8e80941Smrg			}
736b8e80941Smrg		}
737b8e80941Smrg		if (tiled && !scaled) {
738b8e80941Smrg			tiled |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
739b8e80941Smrg			         VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
740b8e80941Smrg		}
741b8e80941Smrg
742b8e80941Smrg		/* Tiled formatting does not support NPOT pixel sizes */
743b8e80941Smrg		if (!util_is_power_of_two_or_zero(vk_format_get_blocksize(format)))
744b8e80941Smrg			tiled = 0;
745b8e80941Smrg	}
746b8e80941Smrg
747b8e80941Smrg	if (linear && !scaled) {
748b8e80941Smrg		linear |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
749b8e80941Smrg		          VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
750b8e80941Smrg	}
751b8e80941Smrg
752b8e80941Smrg	if (format == VK_FORMAT_R32_UINT || format == VK_FORMAT_R32_SINT) {
753b8e80941Smrg		buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
754b8e80941Smrg		linear |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
755b8e80941Smrg		tiled |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
756b8e80941Smrg	}
757b8e80941Smrg
758b8e80941Smrg	switch(format) {
759b8e80941Smrg	case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
760b8e80941Smrg	case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
761b8e80941Smrg	case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
762b8e80941Smrg	case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
763b8e80941Smrg	case VK_FORMAT_A2R10G10B10_SINT_PACK32:
764b8e80941Smrg	case VK_FORMAT_A2B10G10R10_SINT_PACK32:
765b8e80941Smrg		if (physical_device->rad_info.chip_class <= VI &&
766b8e80941Smrg		    physical_device->rad_info.family != CHIP_STONEY) {
767b8e80941Smrg			buffer &= ~(VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
768b8e80941Smrg			            VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT);
769b8e80941Smrg			linear = 0;
770b8e80941Smrg			tiled = 0;
771b8e80941Smrg		}
772b8e80941Smrg		break;
773b8e80941Smrg	default:
774b8e80941Smrg		break;
775b8e80941Smrg	}
776b8e80941Smrg
777b8e80941Smrg	out_properties->linearTilingFeatures = linear;
778b8e80941Smrg	out_properties->optimalTilingFeatures = tiled;
779b8e80941Smrg	out_properties->bufferFeatures = buffer;
780b8e80941Smrg}
781b8e80941Smrg
782b8e80941Smrguint32_t radv_translate_colorformat(VkFormat format)
783b8e80941Smrg{
784b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
785b8e80941Smrg
786b8e80941Smrg#define HAS_SIZE(x,y,z,w)						\
787b8e80941Smrg	(desc->channel[0].size == (x) && desc->channel[1].size == (y) && \
788b8e80941Smrg         desc->channel[2].size == (z) && desc->channel[3].size == (w))
789b8e80941Smrg
790b8e80941Smrg	if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) /* isn't plain */
791b8e80941Smrg		return V_028C70_COLOR_10_11_11;
792b8e80941Smrg
793b8e80941Smrg	if (desc->layout != VK_FORMAT_LAYOUT_PLAIN)
794b8e80941Smrg		return V_028C70_COLOR_INVALID;
795b8e80941Smrg
796b8e80941Smrg	/* hw cannot support mixed formats (except depth/stencil, since
797b8e80941Smrg	 * stencil is not written to). */
798b8e80941Smrg	if (desc->is_mixed && desc->colorspace != VK_FORMAT_COLORSPACE_ZS)
799b8e80941Smrg		return V_028C70_COLOR_INVALID;
800b8e80941Smrg
801b8e80941Smrg	switch (desc->nr_channels) {
802b8e80941Smrg	case 1:
803b8e80941Smrg		switch (desc->channel[0].size) {
804b8e80941Smrg		case 8:
805b8e80941Smrg			return V_028C70_COLOR_8;
806b8e80941Smrg		case 16:
807b8e80941Smrg			return V_028C70_COLOR_16;
808b8e80941Smrg		case 32:
809b8e80941Smrg			return V_028C70_COLOR_32;
810b8e80941Smrg		}
811b8e80941Smrg		break;
812b8e80941Smrg	case 2:
813b8e80941Smrg		if (desc->channel[0].size == desc->channel[1].size) {
814b8e80941Smrg			switch (desc->channel[0].size) {
815b8e80941Smrg			case 8:
816b8e80941Smrg				return V_028C70_COLOR_8_8;
817b8e80941Smrg			case 16:
818b8e80941Smrg				return V_028C70_COLOR_16_16;
819b8e80941Smrg			case 32:
820b8e80941Smrg				return V_028C70_COLOR_32_32;
821b8e80941Smrg			}
822b8e80941Smrg		} else if (HAS_SIZE(8,24,0,0)) {
823b8e80941Smrg			return V_028C70_COLOR_24_8;
824b8e80941Smrg		} else if (HAS_SIZE(24,8,0,0)) {
825b8e80941Smrg			return V_028C70_COLOR_8_24;
826b8e80941Smrg		}
827b8e80941Smrg		break;
828b8e80941Smrg	case 3:
829b8e80941Smrg		if (HAS_SIZE(5,6,5,0)) {
830b8e80941Smrg			return V_028C70_COLOR_5_6_5;
831b8e80941Smrg		} else if (HAS_SIZE(32,8,24,0)) {
832b8e80941Smrg			return V_028C70_COLOR_X24_8_32_FLOAT;
833b8e80941Smrg		}
834b8e80941Smrg		break;
835b8e80941Smrg	case 4:
836b8e80941Smrg		if (desc->channel[0].size == desc->channel[1].size &&
837b8e80941Smrg		    desc->channel[0].size == desc->channel[2].size &&
838b8e80941Smrg		    desc->channel[0].size == desc->channel[3].size) {
839b8e80941Smrg			switch (desc->channel[0].size) {
840b8e80941Smrg			case 4:
841b8e80941Smrg				return V_028C70_COLOR_4_4_4_4;
842b8e80941Smrg			case 8:
843b8e80941Smrg				return V_028C70_COLOR_8_8_8_8;
844b8e80941Smrg			case 16:
845b8e80941Smrg				return V_028C70_COLOR_16_16_16_16;
846b8e80941Smrg			case 32:
847b8e80941Smrg				return V_028C70_COLOR_32_32_32_32;
848b8e80941Smrg			}
849b8e80941Smrg		} else if (HAS_SIZE(5,5,5,1)) {
850b8e80941Smrg			return V_028C70_COLOR_1_5_5_5;
851b8e80941Smrg		} else if (HAS_SIZE(1,5,5,5)) {
852b8e80941Smrg			return V_028C70_COLOR_5_5_5_1;
853b8e80941Smrg		} else if (HAS_SIZE(10,10,10,2)) {
854b8e80941Smrg			return V_028C70_COLOR_2_10_10_10;
855b8e80941Smrg		}
856b8e80941Smrg		break;
857b8e80941Smrg	}
858b8e80941Smrg	return V_028C70_COLOR_INVALID;
859b8e80941Smrg}
860b8e80941Smrg
861b8e80941Smrguint32_t radv_colorformat_endian_swap(uint32_t colorformat)
862b8e80941Smrg{
863b8e80941Smrg	if (0/*SI_BIG_ENDIAN*/) {
864b8e80941Smrg		switch(colorformat) {
865b8e80941Smrg			/* 8-bit buffers. */
866b8e80941Smrg		case V_028C70_COLOR_8:
867b8e80941Smrg			return V_028C70_ENDIAN_NONE;
868b8e80941Smrg
869b8e80941Smrg			/* 16-bit buffers. */
870b8e80941Smrg		case V_028C70_COLOR_5_6_5:
871b8e80941Smrg		case V_028C70_COLOR_1_5_5_5:
872b8e80941Smrg		case V_028C70_COLOR_4_4_4_4:
873b8e80941Smrg		case V_028C70_COLOR_16:
874b8e80941Smrg		case V_028C70_COLOR_8_8:
875b8e80941Smrg			return V_028C70_ENDIAN_8IN16;
876b8e80941Smrg
877b8e80941Smrg			/* 32-bit buffers. */
878b8e80941Smrg		case V_028C70_COLOR_8_8_8_8:
879b8e80941Smrg		case V_028C70_COLOR_2_10_10_10:
880b8e80941Smrg		case V_028C70_COLOR_8_24:
881b8e80941Smrg		case V_028C70_COLOR_24_8:
882b8e80941Smrg		case V_028C70_COLOR_16_16:
883b8e80941Smrg			return V_028C70_ENDIAN_8IN32;
884b8e80941Smrg
885b8e80941Smrg			/* 64-bit buffers. */
886b8e80941Smrg		case V_028C70_COLOR_16_16_16_16:
887b8e80941Smrg			return V_028C70_ENDIAN_8IN16;
888b8e80941Smrg
889b8e80941Smrg		case V_028C70_COLOR_32_32:
890b8e80941Smrg			return V_028C70_ENDIAN_8IN32;
891b8e80941Smrg
892b8e80941Smrg			/* 128-bit buffers. */
893b8e80941Smrg		case V_028C70_COLOR_32_32_32_32:
894b8e80941Smrg			return V_028C70_ENDIAN_8IN32;
895b8e80941Smrg		default:
896b8e80941Smrg			return V_028C70_ENDIAN_NONE; /* Unsupported. */
897b8e80941Smrg		}
898b8e80941Smrg	} else {
899b8e80941Smrg		return V_028C70_ENDIAN_NONE;
900b8e80941Smrg	}
901b8e80941Smrg}
902b8e80941Smrg
903b8e80941Smrguint32_t radv_translate_dbformat(VkFormat format)
904b8e80941Smrg{
905b8e80941Smrg	switch (format) {
906b8e80941Smrg	case VK_FORMAT_D16_UNORM:
907b8e80941Smrg	case VK_FORMAT_D16_UNORM_S8_UINT:
908b8e80941Smrg		return V_028040_Z_16;
909b8e80941Smrg	case VK_FORMAT_D32_SFLOAT:
910b8e80941Smrg	case VK_FORMAT_D32_SFLOAT_S8_UINT:
911b8e80941Smrg		return V_028040_Z_32_FLOAT;
912b8e80941Smrg	default:
913b8e80941Smrg		return V_028040_Z_INVALID;
914b8e80941Smrg	}
915b8e80941Smrg}
916b8e80941Smrg
917b8e80941Smrgunsigned radv_translate_colorswap(VkFormat format, bool do_endian_swap)
918b8e80941Smrg{
919b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
920b8e80941Smrg
921b8e80941Smrg#define HAS_SWIZZLE(chan,swz) (desc->swizzle[chan] == VK_SWIZZLE_##swz)
922b8e80941Smrg
923b8e80941Smrg	if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32)
924b8e80941Smrg		return V_028C70_SWAP_STD;
925b8e80941Smrg
926b8e80941Smrg	if (desc->layout != VK_FORMAT_LAYOUT_PLAIN)
927b8e80941Smrg		return ~0U;
928b8e80941Smrg
929b8e80941Smrg	switch (desc->nr_channels) {
930b8e80941Smrg	case 1:
931b8e80941Smrg		if (HAS_SWIZZLE(0,X))
932b8e80941Smrg			return V_028C70_SWAP_STD; /* X___ */
933b8e80941Smrg		else if (HAS_SWIZZLE(3,X))
934b8e80941Smrg			return V_028C70_SWAP_ALT_REV; /* ___X */
935b8e80941Smrg		break;
936b8e80941Smrg	case 2:
937b8e80941Smrg		if ((HAS_SWIZZLE(0,X) && HAS_SWIZZLE(1,Y)) ||
938b8e80941Smrg		    (HAS_SWIZZLE(0,X) && HAS_SWIZZLE(1,NONE)) ||
939b8e80941Smrg		    (HAS_SWIZZLE(0,NONE) && HAS_SWIZZLE(1,Y)))
940b8e80941Smrg			return V_028C70_SWAP_STD; /* XY__ */
941b8e80941Smrg		else if ((HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(1,X)) ||
942b8e80941Smrg			 (HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(1,NONE)) ||
943b8e80941Smrg		         (HAS_SWIZZLE(0,NONE) && HAS_SWIZZLE(1,X)))
944b8e80941Smrg			/* YX__ */
945b8e80941Smrg			return (do_endian_swap ? V_028C70_SWAP_STD : V_028C70_SWAP_STD_REV);
946b8e80941Smrg		else if (HAS_SWIZZLE(0,X) && HAS_SWIZZLE(3,Y))
947b8e80941Smrg			return V_028C70_SWAP_ALT; /* X__Y */
948b8e80941Smrg		else if (HAS_SWIZZLE(0,Y) && HAS_SWIZZLE(3,X))
949b8e80941Smrg			return V_028C70_SWAP_ALT_REV; /* Y__X */
950b8e80941Smrg		break;
951b8e80941Smrg	case 3:
952b8e80941Smrg		if (HAS_SWIZZLE(0,X))
953b8e80941Smrg			return (do_endian_swap ? V_028C70_SWAP_STD_REV : V_028C70_SWAP_STD);
954b8e80941Smrg		else if (HAS_SWIZZLE(0,Z))
955b8e80941Smrg			return V_028C70_SWAP_STD_REV; /* ZYX */
956b8e80941Smrg		break;
957b8e80941Smrg	case 4:
958b8e80941Smrg		/* check the middle channels, the 1st and 4th channel can be NONE */
959b8e80941Smrg		if (HAS_SWIZZLE(1,Y) && HAS_SWIZZLE(2,Z)) {
960b8e80941Smrg			return V_028C70_SWAP_STD; /* XYZW */
961b8e80941Smrg		} else if (HAS_SWIZZLE(1,Z) && HAS_SWIZZLE(2,Y)) {
962b8e80941Smrg			return V_028C70_SWAP_STD_REV; /* WZYX */
963b8e80941Smrg		} else if (HAS_SWIZZLE(1,Y) && HAS_SWIZZLE(2,X)) {
964b8e80941Smrg			return V_028C70_SWAP_ALT; /* ZYXW */
965b8e80941Smrg		} else if (HAS_SWIZZLE(1,Z) && HAS_SWIZZLE(2,W)) {
966b8e80941Smrg			/* YZWX */
967b8e80941Smrg			if (desc->is_array)
968b8e80941Smrg				return V_028C70_SWAP_ALT_REV;
969b8e80941Smrg			else
970b8e80941Smrg				return (do_endian_swap ? V_028C70_SWAP_ALT : V_028C70_SWAP_ALT_REV);
971b8e80941Smrg		}
972b8e80941Smrg		break;
973b8e80941Smrg	}
974b8e80941Smrg	return ~0U;
975b8e80941Smrg}
976b8e80941Smrg
977b8e80941Smrgbool radv_format_pack_clear_color(VkFormat format,
978b8e80941Smrg				  uint32_t clear_vals[2],
979b8e80941Smrg				  VkClearColorValue *value)
980b8e80941Smrg{
981b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(format);
982b8e80941Smrg
983b8e80941Smrg	if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
984b8e80941Smrg		clear_vals[0] = float3_to_r11g11b10f(value->float32);
985b8e80941Smrg		clear_vals[1] = 0;
986b8e80941Smrg		return true;
987b8e80941Smrg	}
988b8e80941Smrg
989b8e80941Smrg	if (desc->layout != VK_FORMAT_LAYOUT_PLAIN) {
990b8e80941Smrg		fprintf(stderr, "failed to fast clear for non-plain format %d\n", format);
991b8e80941Smrg		return false;
992b8e80941Smrg	}
993b8e80941Smrg
994b8e80941Smrg	if (!util_is_power_of_two_or_zero(desc->block.bits)) {
995b8e80941Smrg		fprintf(stderr, "failed to fast clear for NPOT format %d\n", format);
996b8e80941Smrg		return false;
997b8e80941Smrg	}
998b8e80941Smrg
999b8e80941Smrg	if (desc->block.bits > 64) {
1000b8e80941Smrg		/*
1001b8e80941Smrg		 * We have a 128 bits format, check if the first 3 components are the same.
1002b8e80941Smrg		 * Every elements has to be 32 bits since we don't support 64-bit formats,
1003b8e80941Smrg		 * and we can skip swizzling checks as alpha always comes last for these and
1004b8e80941Smrg		 * we do not care about the rest as they have to be the same.
1005b8e80941Smrg		 */
1006b8e80941Smrg		if (desc->channel[0].type == VK_FORMAT_TYPE_FLOAT) {
1007b8e80941Smrg			if (value->float32[0] != value->float32[1] ||
1008b8e80941Smrg			    value->float32[0] != value->float32[2])
1009b8e80941Smrg				return false;
1010b8e80941Smrg		} else {
1011b8e80941Smrg			if (value->uint32[0] != value->uint32[1] ||
1012b8e80941Smrg			    value->uint32[0] != value->uint32[2])
1013b8e80941Smrg				return false;
1014b8e80941Smrg		}
1015b8e80941Smrg		clear_vals[0] = value->uint32[0];
1016b8e80941Smrg		clear_vals[1] = value->uint32[3];
1017b8e80941Smrg		return true;
1018b8e80941Smrg	}
1019b8e80941Smrg	uint64_t clear_val = 0;
1020b8e80941Smrg
1021b8e80941Smrg	for (unsigned c = 0; c < 4; ++c) {
1022b8e80941Smrg		if (desc->swizzle[c] >= 4)
1023b8e80941Smrg			continue;
1024b8e80941Smrg
1025b8e80941Smrg		const struct vk_format_channel_description *channel = &desc->channel[desc->swizzle[c]];
1026b8e80941Smrg		assert(channel->size);
1027b8e80941Smrg
1028b8e80941Smrg		uint64_t v = 0;
1029b8e80941Smrg		if (channel->pure_integer) {
1030b8e80941Smrg			v = value->uint32[c]  & ((1ULL << channel->size) - 1);
1031b8e80941Smrg		} else if (channel->normalized) {
1032b8e80941Smrg			if (channel->type == VK_FORMAT_TYPE_UNSIGNED &&
1033b8e80941Smrg			    desc->swizzle[c] < 3 &&
1034b8e80941Smrg			    desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
1035b8e80941Smrg				assert(channel->size == 8);
1036b8e80941Smrg
1037b8e80941Smrg				v = util_format_linear_float_to_srgb_8unorm(value->float32[c]);
1038b8e80941Smrg			} else {
1039b8e80941Smrg				float f = MIN2(value->float32[c], 1.0f);
1040b8e80941Smrg
1041b8e80941Smrg				if (channel->type == VK_FORMAT_TYPE_UNSIGNED) {
1042b8e80941Smrg					f = MAX2(f, 0.0f) * ((1ULL << channel->size) - 1);
1043b8e80941Smrg				} else {
1044b8e80941Smrg					f = MAX2(f, -1.0f) * ((1ULL << (channel->size - 1)) - 1);
1045b8e80941Smrg				}
1046b8e80941Smrg
1047b8e80941Smrg				/* The hardware rounds before conversion. */
1048b8e80941Smrg				if (f > 0)
1049b8e80941Smrg					f += 0.5f;
1050b8e80941Smrg				else
1051b8e80941Smrg					f -= 0.5f;
1052b8e80941Smrg
1053b8e80941Smrg				v = (uint64_t)f;
1054b8e80941Smrg			}
1055b8e80941Smrg		} else if (channel->type == VK_FORMAT_TYPE_FLOAT) {
1056b8e80941Smrg			if (channel->size == 32) {
1057b8e80941Smrg				memcpy(&v, &value->float32[c], 4);
1058b8e80941Smrg			} else if(channel->size == 16) {
1059b8e80941Smrg				v = util_float_to_half(value->float32[c]);
1060b8e80941Smrg			} else {
1061b8e80941Smrg				fprintf(stderr, "failed to fast clear for unhandled float size in format %d\n", format);
1062b8e80941Smrg				return false;
1063b8e80941Smrg			}
1064b8e80941Smrg		} else {
1065b8e80941Smrg			fprintf(stderr, "failed to fast clear for unhandled component type in format %d\n", format);
1066b8e80941Smrg			return false;
1067b8e80941Smrg		}
1068b8e80941Smrg		clear_val |= (v & ((1ULL << channel->size) - 1)) << channel->shift;
1069b8e80941Smrg	}
1070b8e80941Smrg
1071b8e80941Smrg	clear_vals[0] = clear_val;
1072b8e80941Smrg	clear_vals[1] = clear_val >> 32;
1073b8e80941Smrg
1074b8e80941Smrg	return true;
1075b8e80941Smrg}
1076b8e80941Smrg
1077b8e80941Smrgvoid radv_GetPhysicalDeviceFormatProperties(
1078b8e80941Smrg	VkPhysicalDevice                            physicalDevice,
1079b8e80941Smrg	VkFormat                                    format,
1080b8e80941Smrg	VkFormatProperties*                         pFormatProperties)
1081b8e80941Smrg{
1082b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
1083b8e80941Smrg
1084b8e80941Smrg	radv_physical_device_get_format_properties(physical_device,
1085b8e80941Smrg						   format,
1086b8e80941Smrg						   pFormatProperties);
1087b8e80941Smrg}
1088b8e80941Smrg
1089b8e80941Smrgvoid radv_GetPhysicalDeviceFormatProperties2(
1090b8e80941Smrg	VkPhysicalDevice                            physicalDevice,
1091b8e80941Smrg	VkFormat                                    format,
1092b8e80941Smrg	VkFormatProperties2*                        pFormatProperties)
1093b8e80941Smrg{
1094b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
1095b8e80941Smrg
1096b8e80941Smrg	radv_physical_device_get_format_properties(physical_device,
1097b8e80941Smrg						   format,
1098b8e80941Smrg						   &pFormatProperties->formatProperties);
1099b8e80941Smrg}
1100b8e80941Smrg
1101b8e80941Smrgstatic VkResult radv_get_image_format_properties(struct radv_physical_device *physical_device,
1102b8e80941Smrg						 const VkPhysicalDeviceImageFormatInfo2 *info,
1103b8e80941Smrg						 VkImageFormatProperties *pImageFormatProperties)
1104b8e80941Smrg
1105b8e80941Smrg{
1106b8e80941Smrg	VkFormatProperties format_props;
1107b8e80941Smrg	VkFormatFeatureFlags format_feature_flags;
1108b8e80941Smrg	VkExtent3D maxExtent;
1109b8e80941Smrg	uint32_t maxMipLevels;
1110b8e80941Smrg	uint32_t maxArraySize;
1111b8e80941Smrg	VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
1112b8e80941Smrg	const struct vk_format_description *desc = vk_format_description(info->format);
1113b8e80941Smrg
1114b8e80941Smrg	radv_physical_device_get_format_properties(physical_device, info->format,
1115b8e80941Smrg						   &format_props);
1116b8e80941Smrg	if (info->tiling == VK_IMAGE_TILING_LINEAR) {
1117b8e80941Smrg		format_feature_flags = format_props.linearTilingFeatures;
1118b8e80941Smrg	} else if (info->tiling == VK_IMAGE_TILING_OPTIMAL) {
1119b8e80941Smrg		format_feature_flags = format_props.optimalTilingFeatures;
1120b8e80941Smrg	} else {
1121b8e80941Smrg		unreachable("bad VkImageTiling");
1122b8e80941Smrg	}
1123b8e80941Smrg
1124b8e80941Smrg	if (format_feature_flags == 0)
1125b8e80941Smrg		goto unsupported;
1126b8e80941Smrg
1127b8e80941Smrg	if (info->type != VK_IMAGE_TYPE_2D && vk_format_is_depth_or_stencil(info->format))
1128b8e80941Smrg		goto unsupported;
1129b8e80941Smrg
1130b8e80941Smrg	switch (info->type) {
1131b8e80941Smrg	default:
1132b8e80941Smrg		unreachable("bad vkimage type\n");
1133b8e80941Smrg	case VK_IMAGE_TYPE_1D:
1134b8e80941Smrg		maxExtent.width = 16384;
1135b8e80941Smrg		maxExtent.height = 1;
1136b8e80941Smrg		maxExtent.depth = 1;
1137b8e80941Smrg		maxMipLevels = 15; /* log2(maxWidth) + 1 */
1138b8e80941Smrg		maxArraySize = 2048;
1139b8e80941Smrg		break;
1140b8e80941Smrg	case VK_IMAGE_TYPE_2D:
1141b8e80941Smrg		maxExtent.width = 16384;
1142b8e80941Smrg		maxExtent.height = 16384;
1143b8e80941Smrg		maxExtent.depth = 1;
1144b8e80941Smrg		maxMipLevels = 15; /* log2(maxWidth) + 1 */
1145b8e80941Smrg		maxArraySize = 2048;
1146b8e80941Smrg		break;
1147b8e80941Smrg	case VK_IMAGE_TYPE_3D:
1148b8e80941Smrg		maxExtent.width = 2048;
1149b8e80941Smrg		maxExtent.height = 2048;
1150b8e80941Smrg		maxExtent.depth = 2048;
1151b8e80941Smrg		maxMipLevels = 12; /* log2(maxWidth) + 1 */
1152b8e80941Smrg		maxArraySize = 1;
1153b8e80941Smrg		break;
1154b8e80941Smrg	}
1155b8e80941Smrg
1156b8e80941Smrg	if (desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED) {
1157b8e80941Smrg		/* Might be able to support but the entire format support is
1158b8e80941Smrg		 * messy, so taking the lazy way out. */
1159b8e80941Smrg		maxArraySize = 1;
1160b8e80941Smrg	}
1161b8e80941Smrg
1162b8e80941Smrg	if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
1163b8e80941Smrg	    info->type == VK_IMAGE_TYPE_2D &&
1164b8e80941Smrg	    (format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
1165b8e80941Smrg				     VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
1166b8e80941Smrg	    !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)) {
1167b8e80941Smrg		sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT;
1168b8e80941Smrg	}
1169b8e80941Smrg
1170b8e80941Smrg	if (info->tiling == VK_IMAGE_TILING_LINEAR &&
1171b8e80941Smrg	    (info->format == VK_FORMAT_R32G32B32_SFLOAT ||
1172b8e80941Smrg	     info->format == VK_FORMAT_R32G32B32_SINT ||
1173b8e80941Smrg	     info->format == VK_FORMAT_R32G32B32_UINT)) {
1174b8e80941Smrg		/* R32G32B32 is a weird format and the driver currently only
1175b8e80941Smrg		 * supports the barely minimum.
1176b8e80941Smrg		 * TODO: Implement more if we really need to.
1177b8e80941Smrg		 */
1178b8e80941Smrg		if (info->type == VK_IMAGE_TYPE_3D)
1179b8e80941Smrg			goto unsupported;
1180b8e80941Smrg		maxArraySize = 1;
1181b8e80941Smrg		maxMipLevels = 1;
1182b8e80941Smrg	}
1183b8e80941Smrg
1184b8e80941Smrg
1185b8e80941Smrg	/* We can't create 3d compressed 128bpp images that can be rendered to on GFX9 */
1186b8e80941Smrg	if (physical_device->rad_info.chip_class >= GFX9 &&
1187b8e80941Smrg	    info->type == VK_IMAGE_TYPE_3D &&
1188b8e80941Smrg	    vk_format_get_blocksizebits(info->format) == 128 &&
1189b8e80941Smrg	    vk_format_is_compressed(info->format) &&
1190b8e80941Smrg	    (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) &&
1191b8e80941Smrg	    ((info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) ||
1192b8e80941Smrg	     (info->usage & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))) {
1193b8e80941Smrg		goto unsupported;
1194b8e80941Smrg	}
1195b8e80941Smrg
1196b8e80941Smrg	if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
1197b8e80941Smrg		if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
1198b8e80941Smrg			goto unsupported;
1199b8e80941Smrg		}
1200b8e80941Smrg	}
1201b8e80941Smrg
1202b8e80941Smrg	if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
1203b8e80941Smrg		if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
1204b8e80941Smrg			goto unsupported;
1205b8e80941Smrg		}
1206b8e80941Smrg	}
1207b8e80941Smrg
1208b8e80941Smrg	if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
1209b8e80941Smrg		if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
1210b8e80941Smrg			goto unsupported;
1211b8e80941Smrg		}
1212b8e80941Smrg	}
1213b8e80941Smrg
1214b8e80941Smrg	if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1215b8e80941Smrg		if (!(format_feature_flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
1216b8e80941Smrg			goto unsupported;
1217b8e80941Smrg		}
1218b8e80941Smrg	}
1219b8e80941Smrg
1220b8e80941Smrg	if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
1221b8e80941Smrg		if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) {
1222b8e80941Smrg			goto unsupported;
1223b8e80941Smrg		}
1224b8e80941Smrg	}
1225b8e80941Smrg
1226b8e80941Smrg	if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
1227b8e80941Smrg		if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
1228b8e80941Smrg			goto unsupported;
1229b8e80941Smrg		}
1230b8e80941Smrg	}
1231b8e80941Smrg
1232b8e80941Smrg	if (info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
1233b8e80941Smrg		if (!(format_feature_flags & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
1234b8e80941Smrg		                              VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))) {
1235b8e80941Smrg			goto unsupported;
1236b8e80941Smrg		}
1237b8e80941Smrg	}
1238b8e80941Smrg
1239b8e80941Smrg	*pImageFormatProperties = (VkImageFormatProperties) {
1240b8e80941Smrg		.maxExtent = maxExtent,
1241b8e80941Smrg		.maxMipLevels = maxMipLevels,
1242b8e80941Smrg		.maxArrayLayers = maxArraySize,
1243b8e80941Smrg		.sampleCounts = sampleCounts,
1244b8e80941Smrg
1245b8e80941Smrg		/* FINISHME: Accurately calculate
1246b8e80941Smrg		 * VkImageFormatProperties::maxResourceSize.
1247b8e80941Smrg		 */
1248b8e80941Smrg		.maxResourceSize = UINT32_MAX,
1249b8e80941Smrg	};
1250b8e80941Smrg
1251b8e80941Smrg	return VK_SUCCESS;
1252b8e80941Smrgunsupported:
1253b8e80941Smrg	*pImageFormatProperties = (VkImageFormatProperties) {
1254b8e80941Smrg		.maxExtent = { 0, 0, 0 },
1255b8e80941Smrg		.maxMipLevels = 0,
1256b8e80941Smrg		.maxArrayLayers = 0,
1257b8e80941Smrg		.sampleCounts = 0,
1258b8e80941Smrg		.maxResourceSize = 0,
1259b8e80941Smrg	};
1260b8e80941Smrg
1261b8e80941Smrg	return VK_ERROR_FORMAT_NOT_SUPPORTED;
1262b8e80941Smrg}
1263b8e80941Smrg
1264b8e80941SmrgVkResult radv_GetPhysicalDeviceImageFormatProperties(
1265b8e80941Smrg	VkPhysicalDevice                            physicalDevice,
1266b8e80941Smrg	VkFormat                                    format,
1267b8e80941Smrg	VkImageType                                 type,
1268b8e80941Smrg	VkImageTiling                               tiling,
1269b8e80941Smrg	VkImageUsageFlags                           usage,
1270b8e80941Smrg	VkImageCreateFlags                          createFlags,
1271b8e80941Smrg	VkImageFormatProperties*                    pImageFormatProperties)
1272b8e80941Smrg{
1273b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
1274b8e80941Smrg
1275b8e80941Smrg	const VkPhysicalDeviceImageFormatInfo2 info = {
1276b8e80941Smrg		.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
1277b8e80941Smrg		.pNext = NULL,
1278b8e80941Smrg		.format = format,
1279b8e80941Smrg		.type = type,
1280b8e80941Smrg		.tiling = tiling,
1281b8e80941Smrg		.usage = usage,
1282b8e80941Smrg		.flags = createFlags,
1283b8e80941Smrg	};
1284b8e80941Smrg
1285b8e80941Smrg	return radv_get_image_format_properties(physical_device, &info,
1286b8e80941Smrg						pImageFormatProperties);
1287b8e80941Smrg}
1288b8e80941Smrg
1289b8e80941Smrgstatic void
1290b8e80941Smrgget_external_image_format_properties(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
1291b8e80941Smrg				     VkExternalMemoryHandleTypeFlagBits handleType,
1292b8e80941Smrg				     VkExternalMemoryProperties *external_properties)
1293b8e80941Smrg{
1294b8e80941Smrg	VkExternalMemoryFeatureFlagBits flags = 0;
1295b8e80941Smrg	VkExternalMemoryHandleTypeFlags export_flags = 0;
1296b8e80941Smrg	VkExternalMemoryHandleTypeFlags compat_flags = 0;
1297b8e80941Smrg	switch (handleType) {
1298b8e80941Smrg	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1299b8e80941Smrg	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1300b8e80941Smrg		switch (pImageFormatInfo->type) {
1301b8e80941Smrg		case VK_IMAGE_TYPE_2D:
1302b8e80941Smrg			flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT|VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1303b8e80941Smrg			compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
1304b8e80941Smrg						      VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1305b8e80941Smrg			break;
1306b8e80941Smrg		default:
1307b8e80941Smrg			break;
1308b8e80941Smrg		}
1309b8e80941Smrg		break;
1310b8e80941Smrg	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1311b8e80941Smrg		flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1312b8e80941Smrg		compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
1313b8e80941Smrg		break;
1314b8e80941Smrg	default:
1315b8e80941Smrg		break;
1316b8e80941Smrg	}
1317b8e80941Smrg
1318b8e80941Smrg	*external_properties = (VkExternalMemoryProperties) {
1319b8e80941Smrg		.externalMemoryFeatures = flags,
1320b8e80941Smrg		.exportFromImportedHandleTypes = export_flags,
1321b8e80941Smrg		.compatibleHandleTypes = compat_flags,
1322b8e80941Smrg	};
1323b8e80941Smrg}
1324b8e80941Smrg
1325b8e80941SmrgVkResult radv_GetPhysicalDeviceImageFormatProperties2(
1326b8e80941Smrg	VkPhysicalDevice                            physicalDevice,
1327b8e80941Smrg	const VkPhysicalDeviceImageFormatInfo2     *base_info,
1328b8e80941Smrg	VkImageFormatProperties2                   *base_props)
1329b8e80941Smrg{
1330b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
1331b8e80941Smrg	const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
1332b8e80941Smrg	VkExternalImageFormatProperties *external_props = NULL;
1333b8e80941Smrg	VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
1334b8e80941Smrg	VkResult result;
1335b8e80941Smrg
1336b8e80941Smrg	result = radv_get_image_format_properties(physical_device, base_info,
1337b8e80941Smrg						&base_props->imageFormatProperties);
1338b8e80941Smrg	if (result != VK_SUCCESS)
1339b8e80941Smrg		return result;
1340b8e80941Smrg
1341b8e80941Smrg	   /* Extract input structs */
1342b8e80941Smrg	vk_foreach_struct_const(s, base_info->pNext) {
1343b8e80941Smrg		switch (s->sType) {
1344b8e80941Smrg		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
1345b8e80941Smrg			external_info = (const void *) s;
1346b8e80941Smrg			break;
1347b8e80941Smrg		default:
1348b8e80941Smrg			break;
1349b8e80941Smrg		}
1350b8e80941Smrg	}
1351b8e80941Smrg
1352b8e80941Smrg	/* Extract output structs */
1353b8e80941Smrg	vk_foreach_struct(s, base_props->pNext) {
1354b8e80941Smrg		switch (s->sType) {
1355b8e80941Smrg		case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
1356b8e80941Smrg			external_props = (void *) s;
1357b8e80941Smrg			break;
1358b8e80941Smrg		case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
1359b8e80941Smrg			ycbcr_props = (void *) s;
1360b8e80941Smrg			break;
1361b8e80941Smrg		default:
1362b8e80941Smrg			break;
1363b8e80941Smrg		}
1364b8e80941Smrg	}
1365b8e80941Smrg
1366b8e80941Smrg	/* From the Vulkan 1.0.97 spec:
1367b8e80941Smrg	 *
1368b8e80941Smrg	 *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
1369b8e80941Smrg	 *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
1370b8e80941Smrg	 *    present and VkExternalImageFormatProperties will be ignored.
1371b8e80941Smrg	 */
1372b8e80941Smrg	if (external_info && external_info->handleType != 0) {
1373b8e80941Smrg		switch (external_info->handleType) {
1374b8e80941Smrg		case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1375b8e80941Smrg		case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1376b8e80941Smrg		case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1377b8e80941Smrg			get_external_image_format_properties(base_info, external_info->handleType,
1378b8e80941Smrg			                                     &external_props->externalMemoryProperties);
1379b8e80941Smrg			break;
1380b8e80941Smrg		default:
1381b8e80941Smrg			/* From the Vulkan 1.0.97 spec:
1382b8e80941Smrg			 *
1383b8e80941Smrg			 *    If handleType is not compatible with the [parameters] specified
1384b8e80941Smrg			 *    in VkPhysicalDeviceImageFormatInfo2, then
1385b8e80941Smrg			 *    vkGetPhysicalDeviceImageFormatProperties2 returns
1386b8e80941Smrg			 *    VK_ERROR_FORMAT_NOT_SUPPORTED.
1387b8e80941Smrg			 */
1388b8e80941Smrg			result = vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
1389b8e80941Smrg					   "unsupported VkExternalMemoryTypeFlagBitsKHR 0x%x",
1390b8e80941Smrg					   external_info->handleType);
1391b8e80941Smrg			goto fail;
1392b8e80941Smrg		}
1393b8e80941Smrg	}
1394b8e80941Smrg
1395b8e80941Smrg	if (ycbcr_props) {
1396b8e80941Smrg		ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(base_info->format);
1397b8e80941Smrg	}
1398b8e80941Smrg
1399b8e80941Smrg	return VK_SUCCESS;
1400b8e80941Smrg
1401b8e80941Smrgfail:
1402b8e80941Smrg	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
1403b8e80941Smrg		/* From the Vulkan 1.0.97 spec:
1404b8e80941Smrg		 *
1405b8e80941Smrg		 *    If the combination of parameters to
1406b8e80941Smrg		 *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by
1407b8e80941Smrg		 *    the implementation for use in vkCreateImage, then all members of
1408b8e80941Smrg		 *    imageFormatProperties will be filled with zero.
1409b8e80941Smrg		 */
1410b8e80941Smrg		base_props->imageFormatProperties = (VkImageFormatProperties) {0};
1411b8e80941Smrg	}
1412b8e80941Smrg
1413b8e80941Smrg	return result;
1414b8e80941Smrg}
1415b8e80941Smrg
1416b8e80941Smrgvoid radv_GetPhysicalDeviceSparseImageFormatProperties(
1417b8e80941Smrg	VkPhysicalDevice                            physicalDevice,
1418b8e80941Smrg	VkFormat                                    format,
1419b8e80941Smrg	VkImageType                                 type,
1420b8e80941Smrg	uint32_t                                    samples,
1421b8e80941Smrg	VkImageUsageFlags                           usage,
1422b8e80941Smrg	VkImageTiling                               tiling,
1423b8e80941Smrg	uint32_t*                                   pNumProperties,
1424b8e80941Smrg	VkSparseImageFormatProperties*              pProperties)
1425b8e80941Smrg{
1426b8e80941Smrg	/* Sparse images are not yet supported. */
1427b8e80941Smrg	*pNumProperties = 0;
1428b8e80941Smrg}
1429b8e80941Smrg
1430b8e80941Smrgvoid radv_GetPhysicalDeviceSparseImageFormatProperties2(
1431b8e80941Smrg	VkPhysicalDevice                            physicalDevice,
1432b8e80941Smrg	const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
1433b8e80941Smrg	uint32_t                                   *pPropertyCount,
1434b8e80941Smrg	VkSparseImageFormatProperties2             *pProperties)
1435b8e80941Smrg{
1436b8e80941Smrg	/* Sparse images are not yet supported. */
1437b8e80941Smrg	*pPropertyCount = 0;
1438b8e80941Smrg}
1439b8e80941Smrg
1440b8e80941Smrgvoid radv_GetPhysicalDeviceExternalBufferProperties(
1441b8e80941Smrg	VkPhysicalDevice                            physicalDevice,
1442b8e80941Smrg	const VkPhysicalDeviceExternalBufferInfo    *pExternalBufferInfo,
1443b8e80941Smrg	VkExternalBufferProperties                  *pExternalBufferProperties)
1444b8e80941Smrg{
1445b8e80941Smrg	VkExternalMemoryFeatureFlagBits flags = 0;
1446b8e80941Smrg	VkExternalMemoryHandleTypeFlags export_flags = 0;
1447b8e80941Smrg	VkExternalMemoryHandleTypeFlags compat_flags = 0;
1448b8e80941Smrg	switch(pExternalBufferInfo->handleType) {
1449b8e80941Smrg	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1450b8e80941Smrg	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1451b8e80941Smrg		flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
1452b8e80941Smrg		        VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1453b8e80941Smrg		compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
1454b8e80941Smrg					      VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1455b8e80941Smrg		break;
1456b8e80941Smrg	case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1457b8e80941Smrg		flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1458b8e80941Smrg		compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
1459b8e80941Smrg		break;
1460b8e80941Smrg	default:
1461b8e80941Smrg		break;
1462b8e80941Smrg	}
1463b8e80941Smrg	pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryProperties) {
1464b8e80941Smrg		.externalMemoryFeatures = flags,
1465b8e80941Smrg		.exportFromImportedHandleTypes = export_flags,
1466b8e80941Smrg		.compatibleHandleTypes = compat_flags,
1467b8e80941Smrg	};
1468b8e80941Smrg}
1469b8e80941Smrg
1470b8e80941Smrg/* DCC channel type categories within which formats can be reinterpreted
1471b8e80941Smrg * while keeping the same DCC encoding. The swizzle must also match. */
1472b8e80941Smrgenum dcc_channel_type {
1473b8e80941Smrg        dcc_channel_float32,
1474b8e80941Smrg        dcc_channel_uint32,
1475b8e80941Smrg        dcc_channel_sint32,
1476b8e80941Smrg        dcc_channel_float16,
1477b8e80941Smrg        dcc_channel_uint16,
1478b8e80941Smrg        dcc_channel_sint16,
1479b8e80941Smrg        dcc_channel_uint_10_10_10_2,
1480b8e80941Smrg        dcc_channel_uint8,
1481b8e80941Smrg        dcc_channel_sint8,
1482b8e80941Smrg        dcc_channel_incompatible,
1483b8e80941Smrg};
1484b8e80941Smrg
1485b8e80941Smrg/* Return the type of DCC encoding. */
1486b8e80941Smrgstatic enum dcc_channel_type
1487b8e80941Smrgradv_get_dcc_channel_type(const struct vk_format_description *desc)
1488b8e80941Smrg{
1489b8e80941Smrg        int i;
1490b8e80941Smrg
1491b8e80941Smrg        /* Find the first non-void channel. */
1492b8e80941Smrg        for (i = 0; i < desc->nr_channels; i++)
1493b8e80941Smrg                if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
1494b8e80941Smrg                        break;
1495b8e80941Smrg        if (i == desc->nr_channels)
1496b8e80941Smrg                return dcc_channel_incompatible;
1497b8e80941Smrg
1498b8e80941Smrg        switch (desc->channel[i].size) {
1499b8e80941Smrg        case 32:
1500b8e80941Smrg                if (desc->channel[i].type == VK_FORMAT_TYPE_FLOAT)
1501b8e80941Smrg                        return dcc_channel_float32;
1502b8e80941Smrg                if (desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED)
1503b8e80941Smrg                        return dcc_channel_uint32;
1504b8e80941Smrg                return dcc_channel_sint32;
1505b8e80941Smrg        case 16:
1506b8e80941Smrg                if (desc->channel[i].type == VK_FORMAT_TYPE_FLOAT)
1507b8e80941Smrg                        return dcc_channel_float16;
1508b8e80941Smrg                if (desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED)
1509b8e80941Smrg                        return dcc_channel_uint16;
1510b8e80941Smrg                return dcc_channel_sint16;
1511b8e80941Smrg        case 10:
1512b8e80941Smrg                return dcc_channel_uint_10_10_10_2;
1513b8e80941Smrg        case 8:
1514b8e80941Smrg                if (desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED)
1515b8e80941Smrg                        return dcc_channel_uint8;
1516b8e80941Smrg                return dcc_channel_sint8;
1517b8e80941Smrg        default:
1518b8e80941Smrg                return dcc_channel_incompatible;
1519b8e80941Smrg        }
1520b8e80941Smrg}
1521b8e80941Smrg
1522b8e80941Smrg/* Return if it's allowed to reinterpret one format as another with DCC enabled. */
1523b8e80941Smrgbool radv_dcc_formats_compatible(VkFormat format1,
1524b8e80941Smrg                                 VkFormat format2)
1525b8e80941Smrg{
1526b8e80941Smrg        const struct vk_format_description *desc1, *desc2;
1527b8e80941Smrg        enum dcc_channel_type type1, type2;
1528b8e80941Smrg        int i;
1529b8e80941Smrg
1530b8e80941Smrg        if (format1 == format2)
1531b8e80941Smrg                return true;
1532b8e80941Smrg
1533b8e80941Smrg        desc1 = vk_format_description(format1);
1534b8e80941Smrg        desc2 = vk_format_description(format2);
1535b8e80941Smrg
1536b8e80941Smrg        if (desc1->nr_channels != desc2->nr_channels)
1537b8e80941Smrg                return false;
1538b8e80941Smrg
1539b8e80941Smrg        /* Swizzles must be the same. */
1540b8e80941Smrg        for (i = 0; i < desc1->nr_channels; i++)
1541b8e80941Smrg                if (desc1->swizzle[i] <= VK_SWIZZLE_W &&
1542b8e80941Smrg                    desc2->swizzle[i] <= VK_SWIZZLE_W &&
1543b8e80941Smrg                    desc1->swizzle[i] != desc2->swizzle[i])
1544b8e80941Smrg                        return false;
1545b8e80941Smrg
1546b8e80941Smrg        type1 = radv_get_dcc_channel_type(desc1);
1547b8e80941Smrg        type2 = radv_get_dcc_channel_type(desc2);
1548b8e80941Smrg
1549b8e80941Smrg        return type1 != dcc_channel_incompatible &&
1550b8e80941Smrg               type2 != dcc_channel_incompatible &&
1551b8e80941Smrg               type1 == type2;
1552b8e80941Smrg}
1553b8e80941Smrg
1554