turnip: Enable geometryShader device feature
[mesa.git] / src / freedreno / vulkan / tu_formats.c
1
2 /*
3 * Copyright © 2016 Red Hat.
4 * Copyright © 2016 Bas Nieuwenhuizen
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "tu_private.h"
27
28 #include "registers/adreno_common.xml.h"
29 #include "registers/a6xx.xml.h"
30
31 #include "util/format_r11g11b10f.h"
32 #include "util/format_rgb9e5.h"
33 #include "util/format_srgb.h"
34 #include "util/u_half.h"
35 #include "vk_format.h"
36 #include "vk_util.h"
37 #include "drm-uapi/drm_fourcc.h"
38
39 #define FMT6_x -1
40
41 #define TU6_FMT(vkfmt, hwfmt, swapfmt, valid) \
42 [VK_FORMAT_##vkfmt] = { \
43 .fmt = FMT6_##hwfmt, \
44 .swap = swapfmt, \
45 .supported = valid, \
46 }
47
48 #define TU6_VTC(vk, fmt, swap) TU6_FMT(vk, fmt, swap, FMT_VERTEX | FMT_TEXTURE | FMT_COLOR)
49 #define TU6_xTC(vk, fmt, swap) TU6_FMT(vk, fmt, swap, FMT_TEXTURE | FMT_COLOR)
50 #define TU6_Vxx(vk, fmt, swap) TU6_FMT(vk, fmt, swap, FMT_VERTEX)
51 #define TU6_xTx(vk, fmt, swap) TU6_FMT(vk, fmt, swap, FMT_TEXTURE)
52 #define TU6_xxx(vk, fmt, swap) TU6_FMT(vk, x, WZYX, false)
53
54 static const struct tu_native_format tu6_format_table[] = {
55 TU6_xxx(UNDEFINED, x, x), /* 0 */
56
57 /* 8-bit packed */
58 TU6_xxx(R4G4_UNORM_PACK8, 4_4_UNORM, WZXY), /* 1 */
59
60 /* 16-bit packed */
61 TU6_xTC(R4G4B4A4_UNORM_PACK16, 4_4_4_4_UNORM, XYZW), /* 2 */
62 TU6_xTC(B4G4R4A4_UNORM_PACK16, 4_4_4_4_UNORM, ZYXW), /* 3 */
63 TU6_xTC(R5G6B5_UNORM_PACK16, 5_6_5_UNORM, WXYZ), /* 4 */
64 TU6_xTC(B5G6R5_UNORM_PACK16, 5_6_5_UNORM, WZYX), /* 5 */
65 TU6_xTC(R5G5B5A1_UNORM_PACK16, 5_5_5_1_UNORM, XYZW), /* 6 */
66 TU6_xTC(B5G5R5A1_UNORM_PACK16, 5_5_5_1_UNORM, ZYXW), /* 7 */
67 TU6_xTC(A1R5G5B5_UNORM_PACK16, 5_5_5_1_UNORM, WXYZ), /* 8 */
68
69 /* 8-bit R */
70 TU6_VTC(R8_UNORM, 8_UNORM, WZYX), /* 9 */
71 TU6_VTC(R8_SNORM, 8_SNORM, WZYX), /* 10 */
72 TU6_Vxx(R8_USCALED, 8_UINT, WZYX), /* 11 */
73 TU6_Vxx(R8_SSCALED, 8_SINT, WZYX), /* 12 */
74 TU6_VTC(R8_UINT, 8_UINT, WZYX), /* 13 */
75 TU6_VTC(R8_SINT, 8_SINT, WZYX), /* 14 */
76 TU6_xTC(R8_SRGB, 8_UNORM, WZYX), /* 15 */
77
78 /* 16-bit RG */
79 TU6_VTC(R8G8_UNORM, 8_8_UNORM, WZYX), /* 16 */
80 TU6_VTC(R8G8_SNORM, 8_8_SNORM, WZYX), /* 17 */
81 TU6_Vxx(R8G8_USCALED, 8_8_UINT, WZYX), /* 18 */
82 TU6_Vxx(R8G8_SSCALED, 8_8_SINT, WZYX), /* 19 */
83 TU6_VTC(R8G8_UINT, 8_8_UINT, WZYX), /* 20 */
84 TU6_VTC(R8G8_SINT, 8_8_SINT, WZYX), /* 21 */
85 TU6_xTC(R8G8_SRGB, 8_8_UNORM, WZYX), /* 22 */
86
87 /* 24-bit RGB */
88 TU6_Vxx(R8G8B8_UNORM, 8_8_8_UNORM, WZYX), /* 23 */
89 TU6_Vxx(R8G8B8_SNORM, 8_8_8_SNORM, WZYX), /* 24 */
90 TU6_Vxx(R8G8B8_USCALED, 8_8_8_UINT, WZYX), /* 25 */
91 TU6_Vxx(R8G8B8_SSCALED, 8_8_8_SINT, WZYX), /* 26 */
92 TU6_Vxx(R8G8B8_UINT, 8_8_8_UINT, WZYX), /* 27 */
93 TU6_Vxx(R8G8B8_SINT, 8_8_8_SINT, WZYX), /* 28 */
94 TU6_xxx(R8G8B8_SRGB, 8_8_8_UNORM, WZYX), /* 29 */
95
96 /* 24-bit BGR */
97 TU6_xxx(B8G8R8_UNORM, 8_8_8_UNORM, WXYZ), /* 30 */
98 TU6_xxx(B8G8R8_SNORM, 8_8_8_SNORM, WXYZ), /* 31 */
99 TU6_xxx(B8G8R8_USCALED, 8_8_8_UINT, WXYZ), /* 32 */
100 TU6_xxx(B8G8R8_SSCALED, 8_8_8_SINT, WXYZ), /* 33 */
101 TU6_xxx(B8G8R8_UINT, 8_8_8_UINT, WXYZ), /* 34 */
102 TU6_xxx(B8G8R8_SINT, 8_8_8_SINT, WXYZ), /* 35 */
103 TU6_xxx(B8G8R8_SRGB, 8_8_8_UNORM, WXYZ), /* 36 */
104
105 /* 32-bit RGBA */
106 TU6_VTC(R8G8B8A8_UNORM, 8_8_8_8_UNORM, WZYX), /* 37 */
107 TU6_VTC(R8G8B8A8_SNORM, 8_8_8_8_SNORM, WZYX), /* 38 */
108 TU6_Vxx(R8G8B8A8_USCALED, 8_8_8_8_UINT, WZYX), /* 39 */
109 TU6_Vxx(R8G8B8A8_SSCALED, 8_8_8_8_SINT, WZYX), /* 40 */
110 TU6_VTC(R8G8B8A8_UINT, 8_8_8_8_UINT, WZYX), /* 41 */
111 TU6_VTC(R8G8B8A8_SINT, 8_8_8_8_SINT, WZYX), /* 42 */
112 TU6_xTC(R8G8B8A8_SRGB, 8_8_8_8_UNORM, WZYX), /* 43 */
113
114 /* 32-bit BGRA */
115 TU6_VTC(B8G8R8A8_UNORM, 8_8_8_8_UNORM, WXYZ), /* 44 */
116 TU6_VTC(B8G8R8A8_SNORM, 8_8_8_8_SNORM, WXYZ), /* 45 */
117 TU6_Vxx(B8G8R8A8_USCALED, 8_8_8_8_UINT, WXYZ), /* 46 */
118 TU6_Vxx(B8G8R8A8_SSCALED, 8_8_8_8_SINT, WXYZ), /* 47 */
119 TU6_VTC(B8G8R8A8_UINT, 8_8_8_8_UINT, WXYZ), /* 48 */
120 TU6_VTC(B8G8R8A8_SINT, 8_8_8_8_SINT, WXYZ), /* 49 */
121 TU6_xTC(B8G8R8A8_SRGB, 8_8_8_8_UNORM, WXYZ), /* 50 */
122
123 /* 32-bit packed */
124 TU6_VTC(A8B8G8R8_UNORM_PACK32, 8_8_8_8_UNORM, WZYX), /* 51 */
125 TU6_VTC(A8B8G8R8_SNORM_PACK32, 8_8_8_8_SNORM, WZYX), /* 52 */
126 TU6_Vxx(A8B8G8R8_USCALED_PACK32, 8_8_8_8_UINT, WZYX), /* 53 */
127 TU6_Vxx(A8B8G8R8_SSCALED_PACK32, 8_8_8_8_SINT, WZYX), /* 54 */
128 TU6_VTC(A8B8G8R8_UINT_PACK32, 8_8_8_8_UINT, WZYX), /* 55 */
129 TU6_VTC(A8B8G8R8_SINT_PACK32, 8_8_8_8_SINT, WZYX), /* 56 */
130 TU6_xTC(A8B8G8R8_SRGB_PACK32, 8_8_8_8_UNORM, WZYX), /* 57 */
131 TU6_VTC(A2R10G10B10_UNORM_PACK32, 10_10_10_2_UNORM, WXYZ), /* 58 */
132 TU6_Vxx(A2R10G10B10_SNORM_PACK32, 10_10_10_2_SNORM, WXYZ), /* 59 */
133 TU6_Vxx(A2R10G10B10_USCALED_PACK32, 10_10_10_2_UINT, WXYZ), /* 60 */
134 TU6_Vxx(A2R10G10B10_SSCALED_PACK32, 10_10_10_2_SINT, WXYZ), /* 61 */
135 TU6_VTC(A2R10G10B10_UINT_PACK32, 10_10_10_2_UINT, WXYZ), /* 62 */
136 TU6_Vxx(A2R10G10B10_SINT_PACK32, 10_10_10_2_SINT, WXYZ), /* 63 */
137 TU6_VTC(A2B10G10R10_UNORM_PACK32, 10_10_10_2_UNORM, WZYX), /* 64 */
138 TU6_Vxx(A2B10G10R10_SNORM_PACK32, 10_10_10_2_SNORM, WZYX), /* 65 */
139 TU6_Vxx(A2B10G10R10_USCALED_PACK32, 10_10_10_2_UINT, WZYX), /* 66 */
140 TU6_Vxx(A2B10G10R10_SSCALED_PACK32, 10_10_10_2_SINT, WZYX), /* 67 */
141 TU6_VTC(A2B10G10R10_UINT_PACK32, 10_10_10_2_UINT, WZYX), /* 68 */
142 TU6_Vxx(A2B10G10R10_SINT_PACK32, 10_10_10_2_SINT, WZYX), /* 69 */
143
144 /* 16-bit R */
145 TU6_VTC(R16_UNORM, 16_UNORM, WZYX), /* 70 */
146 TU6_VTC(R16_SNORM, 16_SNORM, WZYX), /* 71 */
147 TU6_Vxx(R16_USCALED, 16_UINT, WZYX), /* 72 */
148 TU6_Vxx(R16_SSCALED, 16_SINT, WZYX), /* 73 */
149 TU6_VTC(R16_UINT, 16_UINT, WZYX), /* 74 */
150 TU6_VTC(R16_SINT, 16_SINT, WZYX), /* 75 */
151 TU6_VTC(R16_SFLOAT, 16_FLOAT, WZYX), /* 76 */
152
153 /* 32-bit RG */
154 TU6_VTC(R16G16_UNORM, 16_16_UNORM, WZYX), /* 77 */
155 TU6_VTC(R16G16_SNORM, 16_16_SNORM, WZYX), /* 78 */
156 TU6_Vxx(R16G16_USCALED, 16_16_UINT, WZYX), /* 79 */
157 TU6_Vxx(R16G16_SSCALED, 16_16_SINT, WZYX), /* 80 */
158 TU6_VTC(R16G16_UINT, 16_16_UINT, WZYX), /* 81 */
159 TU6_VTC(R16G16_SINT, 16_16_SINT, WZYX), /* 82 */
160 TU6_VTC(R16G16_SFLOAT, 16_16_FLOAT, WZYX), /* 83 */
161
162 /* 48-bit RGB */
163 TU6_Vxx(R16G16B16_UNORM, 16_16_16_UNORM, WZYX), /* 84 */
164 TU6_Vxx(R16G16B16_SNORM, 16_16_16_SNORM, WZYX), /* 85 */
165 TU6_Vxx(R16G16B16_USCALED, 16_16_16_UINT, WZYX), /* 86 */
166 TU6_Vxx(R16G16B16_SSCALED, 16_16_16_SINT, WZYX), /* 87 */
167 TU6_Vxx(R16G16B16_UINT, 16_16_16_UINT, WZYX), /* 88 */
168 TU6_Vxx(R16G16B16_SINT, 16_16_16_SINT, WZYX), /* 89 */
169 TU6_Vxx(R16G16B16_SFLOAT, 16_16_16_FLOAT, WZYX), /* 90 */
170
171 /* 64-bit RGBA */
172 TU6_VTC(R16G16B16A16_UNORM, 16_16_16_16_UNORM, WZYX), /* 91 */
173 TU6_VTC(R16G16B16A16_SNORM, 16_16_16_16_SNORM, WZYX), /* 92 */
174 TU6_Vxx(R16G16B16A16_USCALED, 16_16_16_16_UINT, WZYX), /* 93 */
175 TU6_Vxx(R16G16B16A16_SSCALED, 16_16_16_16_SINT, WZYX), /* 94 */
176 TU6_VTC(R16G16B16A16_UINT, 16_16_16_16_UINT, WZYX), /* 95 */
177 TU6_VTC(R16G16B16A16_SINT, 16_16_16_16_SINT, WZYX), /* 96 */
178 TU6_VTC(R16G16B16A16_SFLOAT, 16_16_16_16_FLOAT, WZYX), /* 97 */
179
180 /* 32-bit R */
181 TU6_VTC(R32_UINT, 32_UINT, WZYX), /* 98 */
182 TU6_VTC(R32_SINT, 32_SINT, WZYX), /* 99 */
183 TU6_VTC(R32_SFLOAT, 32_FLOAT, WZYX), /* 100 */
184
185 /* 64-bit RG */
186 TU6_VTC(R32G32_UINT, 32_32_UINT, WZYX), /* 101 */
187 TU6_VTC(R32G32_SINT, 32_32_SINT, WZYX), /* 102 */
188 TU6_VTC(R32G32_SFLOAT, 32_32_FLOAT, WZYX), /* 103 */
189
190 /* 96-bit RGB */
191 TU6_Vxx(R32G32B32_UINT, 32_32_32_UINT, WZYX), /* 104 */
192 TU6_Vxx(R32G32B32_SINT, 32_32_32_SINT, WZYX), /* 105 */
193 TU6_Vxx(R32G32B32_SFLOAT, 32_32_32_FLOAT, WZYX), /* 106 */
194
195 /* 128-bit RGBA */
196 TU6_VTC(R32G32B32A32_UINT, 32_32_32_32_UINT, WZYX), /* 107 */
197 TU6_VTC(R32G32B32A32_SINT, 32_32_32_32_SINT, WZYX), /* 108 */
198 TU6_VTC(R32G32B32A32_SFLOAT, 32_32_32_32_FLOAT, WZYX), /* 109 */
199
200 /* 64-bit R */
201 TU6_xxx(R64_UINT, 64_UINT, WZYX), /* 110 */
202 TU6_xxx(R64_SINT, 64_SINT, WZYX), /* 111 */
203 TU6_xxx(R64_SFLOAT, 64_FLOAT, WZYX), /* 112 */
204
205 /* 128-bit RG */
206 TU6_xxx(R64G64_UINT, 64_64_UINT, WZYX), /* 113 */
207 TU6_xxx(R64G64_SINT, 64_64_SINT, WZYX), /* 114 */
208 TU6_xxx(R64G64_SFLOAT, 64_64_FLOAT, WZYX), /* 115 */
209
210 /* 192-bit RGB */
211 TU6_xxx(R64G64B64_UINT, 64_64_64_UINT, WZYX), /* 116 */
212 TU6_xxx(R64G64B64_SINT, 64_64_64_SINT, WZYX), /* 117 */
213 TU6_xxx(R64G64B64_SFLOAT, 64_64_64_FLOAT, WZYX), /* 118 */
214
215 /* 256-bit RGBA */
216 TU6_xxx(R64G64B64A64_UINT, 64_64_64_64_UINT, WZYX), /* 119 */
217 TU6_xxx(R64G64B64A64_SINT, 64_64_64_64_SINT, WZYX), /* 120 */
218 TU6_xxx(R64G64B64A64_SFLOAT, 64_64_64_64_FLOAT, WZYX), /* 121 */
219
220 /* 32-bit packed float */
221 TU6_VTC(B10G11R11_UFLOAT_PACK32, 11_11_10_FLOAT, WZYX), /* 122 */
222 TU6_xTx(E5B9G9R9_UFLOAT_PACK32, 9_9_9_E5_FLOAT, WZYX), /* 123 */
223
224 /* depth/stencil */
225 TU6_xTC(D16_UNORM, 16_UNORM, WZYX), /* 124 */
226 TU6_xTC(X8_D24_UNORM_PACK32, Z24_UNORM_S8_UINT, WZYX), /* 125 */
227 TU6_xTC(D32_SFLOAT, 32_FLOAT, WZYX), /* 126 */
228 TU6_xTC(S8_UINT, 8_UINT, WZYX), /* 127 */
229 TU6_xxx(D16_UNORM_S8_UINT, X8Z16_UNORM, WZYX), /* 128 */
230 TU6_xTC(D24_UNORM_S8_UINT, Z24_UNORM_S8_UINT, WZYX), /* 129 */
231 TU6_xxx(D32_SFLOAT_S8_UINT, x, WZYX), /* 130 */
232
233 /* compressed */
234 TU6_xTx(BC1_RGB_UNORM_BLOCK, DXT1, WZYX), /* 131 */
235 TU6_xTx(BC1_RGB_SRGB_BLOCK, DXT1, WZYX), /* 132 */
236 TU6_xTx(BC1_RGBA_UNORM_BLOCK, DXT1, WZYX), /* 133 */
237 TU6_xTx(BC1_RGBA_SRGB_BLOCK, DXT1, WZYX), /* 134 */
238 TU6_xTx(BC2_UNORM_BLOCK, DXT3, WZYX), /* 135 */
239 TU6_xTx(BC2_SRGB_BLOCK, DXT3, WZYX), /* 136 */
240 TU6_xTx(BC3_UNORM_BLOCK, DXT5, WZYX), /* 137 */
241 TU6_xTx(BC3_SRGB_BLOCK, DXT5, WZYX), /* 138 */
242 TU6_xTx(BC4_UNORM_BLOCK, RGTC1_UNORM, WZYX), /* 139 */
243 TU6_xTx(BC4_SNORM_BLOCK, RGTC1_SNORM, WZYX), /* 140 */
244 TU6_xTx(BC5_UNORM_BLOCK, RGTC2_UNORM, WZYX), /* 141 */
245 TU6_xTx(BC5_SNORM_BLOCK, RGTC2_SNORM, WZYX), /* 142 */
246 TU6_xTx(BC6H_UFLOAT_BLOCK, BPTC_UFLOAT, WZYX), /* 143 */
247 TU6_xTx(BC6H_SFLOAT_BLOCK, BPTC_FLOAT, WZYX), /* 144 */
248 TU6_xTx(BC7_UNORM_BLOCK, BPTC, WZYX), /* 145 */
249 TU6_xTx(BC7_SRGB_BLOCK, BPTC, WZYX), /* 146 */
250 TU6_xTx(ETC2_R8G8B8_UNORM_BLOCK, ETC2_RGB8, WZYX), /* 147 */
251 TU6_xTx(ETC2_R8G8B8_SRGB_BLOCK, ETC2_RGB8, WZYX), /* 148 */
252 TU6_xTx(ETC2_R8G8B8A1_UNORM_BLOCK, ETC2_RGB8A1, WZYX), /* 149 */
253 TU6_xTx(ETC2_R8G8B8A1_SRGB_BLOCK, ETC2_RGB8A1, WZYX), /* 150 */
254 TU6_xTx(ETC2_R8G8B8A8_UNORM_BLOCK, ETC2_RGBA8, WZYX), /* 151 */
255 TU6_xTx(ETC2_R8G8B8A8_SRGB_BLOCK, ETC2_RGBA8, WZYX), /* 152 */
256 TU6_xTx(EAC_R11_UNORM_BLOCK, ETC2_R11_UNORM, WZYX), /* 153 */
257 TU6_xTx(EAC_R11_SNORM_BLOCK, ETC2_R11_SNORM, WZYX), /* 154 */
258 TU6_xTx(EAC_R11G11_UNORM_BLOCK, ETC2_RG11_UNORM, WZYX), /* 155 */
259 TU6_xTx(EAC_R11G11_SNORM_BLOCK, ETC2_RG11_SNORM, WZYX), /* 156 */
260 TU6_xTx(ASTC_4x4_UNORM_BLOCK, ASTC_4x4, WZYX), /* 157 */
261 TU6_xTx(ASTC_4x4_SRGB_BLOCK, ASTC_4x4, WZYX), /* 158 */
262 TU6_xTx(ASTC_5x4_UNORM_BLOCK, ASTC_5x4, WZYX), /* 159 */
263 TU6_xTx(ASTC_5x4_SRGB_BLOCK, ASTC_5x4, WZYX), /* 160 */
264 TU6_xTx(ASTC_5x5_UNORM_BLOCK, ASTC_5x5, WZYX), /* 161 */
265 TU6_xTx(ASTC_5x5_SRGB_BLOCK, ASTC_5x5, WZYX), /* 162 */
266 TU6_xTx(ASTC_6x5_UNORM_BLOCK, ASTC_6x5, WZYX), /* 163 */
267 TU6_xTx(ASTC_6x5_SRGB_BLOCK, ASTC_6x5, WZYX), /* 164 */
268 TU6_xTx(ASTC_6x6_UNORM_BLOCK, ASTC_6x6, WZYX), /* 165 */
269 TU6_xTx(ASTC_6x6_SRGB_BLOCK, ASTC_6x6, WZYX), /* 166 */
270 TU6_xTx(ASTC_8x5_UNORM_BLOCK, ASTC_8x5, WZYX), /* 167 */
271 TU6_xTx(ASTC_8x5_SRGB_BLOCK, ASTC_8x5, WZYX), /* 168 */
272 TU6_xTx(ASTC_8x6_UNORM_BLOCK, ASTC_8x6, WZYX), /* 169 */
273 TU6_xTx(ASTC_8x6_SRGB_BLOCK, ASTC_8x6, WZYX), /* 170 */
274 TU6_xTx(ASTC_8x8_UNORM_BLOCK, ASTC_8x8, WZYX), /* 171 */
275 TU6_xTx(ASTC_8x8_SRGB_BLOCK, ASTC_8x8, WZYX), /* 172 */
276 TU6_xTx(ASTC_10x5_UNORM_BLOCK, ASTC_10x5, WZYX), /* 173 */
277 TU6_xTx(ASTC_10x5_SRGB_BLOCK, ASTC_10x5, WZYX), /* 174 */
278 TU6_xTx(ASTC_10x6_UNORM_BLOCK, ASTC_10x6, WZYX), /* 175 */
279 TU6_xTx(ASTC_10x6_SRGB_BLOCK, ASTC_10x6, WZYX), /* 176 */
280 TU6_xTx(ASTC_10x8_UNORM_BLOCK, ASTC_10x8, WZYX), /* 177 */
281 TU6_xTx(ASTC_10x8_SRGB_BLOCK, ASTC_10x8, WZYX), /* 178 */
282 TU6_xTx(ASTC_10x10_UNORM_BLOCK, ASTC_10x10, WZYX), /* 179 */
283 TU6_xTx(ASTC_10x10_SRGB_BLOCK, ASTC_10x10, WZYX), /* 180 */
284 TU6_xTx(ASTC_12x10_UNORM_BLOCK, ASTC_12x10, WZYX), /* 181 */
285 TU6_xTx(ASTC_12x10_SRGB_BLOCK, ASTC_12x10, WZYX), /* 182 */
286 TU6_xTx(ASTC_12x12_UNORM_BLOCK, ASTC_12x12, WZYX), /* 183 */
287 TU6_xTx(ASTC_12x12_SRGB_BLOCK, ASTC_12x12, WZYX), /* 184 */
288 };
289
290 struct tu_native_format
291 tu6_get_native_format(VkFormat format)
292 {
293 struct tu_native_format fmt = {};
294
295 if (format >= ARRAY_SIZE(tu6_format_table))
296 return fmt;
297
298 if (!tu6_format_table[format].supported)
299 return fmt;
300
301 if (vk_format_to_pipe_format(format) == PIPE_FORMAT_NONE) {
302 tu_finishme("vk_format %d missing matching pipe format.\n", format);
303 return fmt;
304 }
305
306 return tu6_format_table[format];
307 }
308
309 struct tu_native_format
310 tu6_format_vtx(VkFormat format)
311 {
312 struct tu_native_format fmt = tu6_get_native_format(format);
313 assert(fmt.supported & FMT_VERTEX);
314 return fmt;
315 }
316
317 enum a6xx_format
318 tu6_format_gmem(VkFormat format)
319 {
320 struct tu_native_format fmt = tu6_get_native_format(format);
321 assert(fmt.supported & FMT_COLOR);
322
323 if (fmt.fmt == FMT6_10_10_10_2_UNORM)
324 return FMT6_10_10_10_2_UNORM_DEST;
325
326 return fmt.fmt;
327 }
328
329 struct tu_native_format
330 tu6_format_color(VkFormat format, bool tiled)
331 {
332 struct tu_native_format fmt = tu6_get_native_format(format);
333 assert(fmt.supported & FMT_COLOR);
334
335 if (fmt.fmt == FMT6_10_10_10_2_UNORM)
336 fmt.fmt = FMT6_10_10_10_2_UNORM_DEST;
337
338 if (tiled)
339 fmt.swap = WZYX;
340
341 return fmt;
342 }
343
344 struct tu_native_format
345 tu6_format_texture(VkFormat format, bool tiled)
346 {
347 struct tu_native_format fmt = tu6_get_native_format(format);
348 assert(fmt.supported & FMT_TEXTURE);
349
350 if (!tiled) {
351 /* different from format table when used as linear src */
352 if (format == VK_FORMAT_R5G5B5A1_UNORM_PACK16)
353 fmt.fmt = FMT6_1_5_5_5_UNORM, fmt.swap = WXYZ;
354 if (format == VK_FORMAT_B5G5R5A1_UNORM_PACK16)
355 fmt.fmt = FMT6_1_5_5_5_UNORM, fmt.swap = WZYX;
356 } else {
357 fmt.swap = WZYX;
358 }
359
360 return fmt;
361 }
362
363 enum a6xx_2d_ifmt
364 tu6_fmt_to_ifmt(enum a6xx_format fmt)
365 {
366 switch (fmt) {
367 case FMT6_A8_UNORM:
368 case FMT6_8_UNORM:
369 case FMT6_8_SNORM:
370 case FMT6_8_8_UNORM:
371 case FMT6_8_8_SNORM:
372 case FMT6_8_8_8_8_UNORM:
373 case FMT6_8_8_8_X8_UNORM:
374 case FMT6_8_8_8_8_SNORM:
375 case FMT6_4_4_4_4_UNORM:
376 case FMT6_5_5_5_1_UNORM:
377 case FMT6_5_6_5_UNORM:
378 case FMT6_Z24_UNORM_S8_UINT:
379 case FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8:
380 return R2D_UNORM8;
381
382 case FMT6_32_UINT:
383 case FMT6_32_SINT:
384 case FMT6_32_32_UINT:
385 case FMT6_32_32_SINT:
386 case FMT6_32_32_32_32_UINT:
387 case FMT6_32_32_32_32_SINT:
388 return R2D_INT32;
389
390 case FMT6_16_UINT:
391 case FMT6_16_SINT:
392 case FMT6_16_16_UINT:
393 case FMT6_16_16_SINT:
394 case FMT6_16_16_16_16_UINT:
395 case FMT6_16_16_16_16_SINT:
396 case FMT6_10_10_10_2_UINT:
397 return R2D_INT16;
398
399 case FMT6_8_UINT:
400 case FMT6_8_SINT:
401 case FMT6_8_8_UINT:
402 case FMT6_8_8_SINT:
403 case FMT6_8_8_8_8_UINT:
404 case FMT6_8_8_8_8_SINT:
405 return R2D_INT8;
406
407 case FMT6_16_UNORM:
408 case FMT6_16_SNORM:
409 case FMT6_16_16_UNORM:
410 case FMT6_16_16_SNORM:
411 case FMT6_16_16_16_16_UNORM:
412 case FMT6_16_16_16_16_SNORM:
413 case FMT6_32_FLOAT:
414 case FMT6_32_32_FLOAT:
415 case FMT6_32_32_32_32_FLOAT:
416 return R2D_FLOAT32;
417
418 case FMT6_16_FLOAT:
419 case FMT6_16_16_FLOAT:
420 case FMT6_16_16_16_16_FLOAT:
421 case FMT6_11_11_10_FLOAT:
422 case FMT6_10_10_10_2_UNORM:
423 case FMT6_10_10_10_2_UNORM_DEST:
424 return R2D_FLOAT16;
425
426 default:
427 unreachable("bad format");
428 return 0;
429 }
430 }
431
432 enum a6xx_depth_format
433 tu6_pipe2depth(VkFormat format)
434 {
435 switch (format) {
436 case VK_FORMAT_D16_UNORM:
437 return DEPTH6_16;
438 case VK_FORMAT_X8_D24_UNORM_PACK32:
439 case VK_FORMAT_D24_UNORM_S8_UINT:
440 return DEPTH6_24_8;
441 case VK_FORMAT_D32_SFLOAT:
442 return DEPTH6_32;
443 default:
444 return ~0;
445 }
446 }
447
448 static uint32_t
449 tu_pack_mask(int bits)
450 {
451 assert(bits <= 32);
452 return (1ull << bits) - 1;
453 }
454
455 static uint32_t
456 tu_pack_float32_for_unorm(float val, int bits)
457 {
458 const uint32_t max = tu_pack_mask(bits);
459 if (val < 0.0f)
460 return 0;
461 else if (val > 1.0f)
462 return max;
463 else
464 return _mesa_lroundevenf(val * (float) max);
465 }
466
467 static uint32_t
468 tu_pack_float32_for_snorm(float val, int bits)
469 {
470 const int32_t max = tu_pack_mask(bits - 1);
471 int32_t tmp;
472 if (val < -1.0f)
473 tmp = -max;
474 else if (val > 1.0f)
475 tmp = max;
476 else
477 tmp = _mesa_lroundevenf(val * (float) max);
478
479 return tmp & tu_pack_mask(bits);
480 }
481
482 static uint32_t
483 tu_pack_float32_for_uscaled(float val, int bits)
484 {
485 const uint32_t max = tu_pack_mask(bits);
486 if (val < 0.0f)
487 return 0;
488 else if (val > (float) max)
489 return max;
490 else
491 return (uint32_t) val;
492 }
493
494 static uint32_t
495 tu_pack_float32_for_sscaled(float val, int bits)
496 {
497 const int32_t max = tu_pack_mask(bits - 1);
498 const int32_t min = -max - 1;
499 int32_t tmp;
500 if (val < (float) min)
501 tmp = min;
502 else if (val > (float) max)
503 tmp = max;
504 else
505 tmp = (int32_t) val;
506
507 return tmp & tu_pack_mask(bits);
508 }
509
510 static uint32_t
511 tu_pack_uint32_for_uint(uint32_t val, int bits)
512 {
513 return val & tu_pack_mask(bits);
514 }
515
516 static uint32_t
517 tu_pack_int32_for_sint(int32_t val, int bits)
518 {
519 return val & tu_pack_mask(bits);
520 }
521
522 static uint32_t
523 tu_pack_float32_for_sfloat(float val, int bits)
524 {
525 assert(bits == 16 || bits == 32);
526 return bits == 16 ? util_float_to_half(val) : fui(val);
527 }
528
529 union tu_clear_component_value {
530 float float32;
531 int32_t int32;
532 uint32_t uint32;
533 };
534
535 static uint32_t
536 tu_pack_clear_component_value(union tu_clear_component_value val,
537 const struct util_format_channel_description *ch)
538 {
539 uint32_t packed;
540
541 switch (ch->type) {
542 case UTIL_FORMAT_TYPE_UNSIGNED:
543 /* normalized, scaled, or pure integer */
544 if (ch->normalized)
545 packed = tu_pack_float32_for_unorm(val.float32, ch->size);
546 else if (ch->pure_integer)
547 packed = tu_pack_uint32_for_uint(val.uint32, ch->size);
548 else
549 packed = tu_pack_float32_for_uscaled(val.float32, ch->size);
550 break;
551 case UTIL_FORMAT_TYPE_SIGNED:
552 /* normalized, scaled, or pure integer */
553 if (ch->normalized)
554 packed = tu_pack_float32_for_snorm(val.float32, ch->size);
555 else if (ch->pure_integer)
556 packed = tu_pack_int32_for_sint(val.int32, ch->size);
557 else
558 packed = tu_pack_float32_for_sscaled(val.float32, ch->size);
559 break;
560 case UTIL_FORMAT_TYPE_FLOAT:
561 packed = tu_pack_float32_for_sfloat(val.float32, ch->size);
562 break;
563 default:
564 unreachable("unexpected channel type");
565 packed = 0;
566 break;
567 }
568
569 assert((packed & tu_pack_mask(ch->size)) == packed);
570 return packed;
571 }
572
573 static const struct util_format_channel_description *
574 tu_get_format_channel_description(const struct util_format_description *desc,
575 int comp)
576 {
577 switch (desc->swizzle[comp]) {
578 case PIPE_SWIZZLE_X:
579 return &desc->channel[0];
580 case PIPE_SWIZZLE_Y:
581 return &desc->channel[1];
582 case PIPE_SWIZZLE_Z:
583 return &desc->channel[2];
584 case PIPE_SWIZZLE_W:
585 return &desc->channel[3];
586 default:
587 return NULL;
588 }
589 }
590
591 static union tu_clear_component_value
592 tu_get_clear_component_value(const VkClearValue *val, int comp,
593 enum util_format_colorspace colorspace)
594 {
595 assert(comp < 4);
596
597 union tu_clear_component_value tmp;
598 switch (colorspace) {
599 case UTIL_FORMAT_COLORSPACE_ZS:
600 assert(comp < 2);
601 if (comp == 0)
602 tmp.float32 = val->depthStencil.depth;
603 else
604 tmp.uint32 = val->depthStencil.stencil;
605 break;
606 case UTIL_FORMAT_COLORSPACE_SRGB:
607 if (comp < 3) {
608 tmp.float32 = util_format_linear_to_srgb_float(val->color.float32[comp]);
609 break;
610 }
611 default:
612 assert(comp < 4);
613 tmp.uint32 = val->color.uint32[comp];
614 break;
615 }
616
617 return tmp;
618 }
619
620 /**
621 * Pack a VkClearValue into a 128-bit buffer. \a format is respected except
622 * for the component order. The components are always packed in WZYX order
623 * (i.e., msb is white and lsb is red).
624 *
625 * Return the number of uint32_t's used.
626 */
627 void
628 tu_pack_clear_value(const VkClearValue *val, VkFormat format, uint32_t buf[4])
629 {
630 const struct util_format_description *desc = vk_format_description(format);
631
632 switch (format) {
633 case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
634 buf[0] = float3_to_r11g11b10f(val->color.float32);
635 return;
636 case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
637 buf[0] = float3_to_rgb9e5(val->color.float32);
638 return;
639 default:
640 break;
641 }
642
643 assert(desc && desc->layout == UTIL_FORMAT_LAYOUT_PLAIN);
644
645 /* S8_UINT is special and has no depth */
646 const int max_components =
647 format == VK_FORMAT_S8_UINT ? 2 : desc->nr_channels;
648
649 int buf_offset = 0;
650 int bit_shift = 0;
651 for (int comp = 0; comp < max_components; comp++) {
652 const struct util_format_channel_description *ch =
653 tu_get_format_channel_description(desc, comp);
654 if (!ch) {
655 assert((format == VK_FORMAT_S8_UINT && comp == 0) ||
656 (format == VK_FORMAT_X8_D24_UNORM_PACK32 && comp == 1));
657 continue;
658 }
659
660 union tu_clear_component_value v = tu_get_clear_component_value(
661 val, comp, desc->colorspace);
662
663 /* move to the next uint32_t when there is not enough space */
664 assert(ch->size <= 32);
665 if (bit_shift + ch->size > 32) {
666 buf_offset++;
667 bit_shift = 0;
668 }
669
670 if (bit_shift == 0)
671 buf[buf_offset] = 0;
672
673 buf[buf_offset] |= tu_pack_clear_component_value(v, ch) << bit_shift;
674 bit_shift += ch->size;
675 }
676 }
677
678 void
679 tu_2d_clear_color(const VkClearColorValue *val, VkFormat format, uint32_t buf[4])
680 {
681 const struct util_format_description *desc = vk_format_description(format);
682
683 /* not supported by 2D engine, cleared as U32 */
684 if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
685 buf[0] = float3_to_rgb9e5(val->float32);
686 return;
687 }
688
689 enum a6xx_2d_ifmt ifmt = tu6_fmt_to_ifmt(tu6_get_native_format(format).fmt);
690
691 assert(desc && (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
692 format == VK_FORMAT_B10G11R11_UFLOAT_PACK32));
693
694 for (unsigned i = 0; i < desc->nr_channels; i++) {
695 const struct util_format_channel_description *ch = &desc->channel[i];
696
697 switch (ifmt) {
698 case R2D_INT32:
699 case R2D_INT16:
700 case R2D_INT8:
701 case R2D_FLOAT32:
702 buf[i] = val->uint32[i];
703 break;
704 case R2D_FLOAT16:
705 buf[i] = util_float_to_half(val->float32[i]);
706 break;
707 case R2D_UNORM8: {
708 float linear = val->float32[i];
709 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB && i < 3)
710 linear = util_format_linear_to_srgb_float(val->float32[i]);
711
712 if (ch->type == UTIL_FORMAT_TYPE_SIGNED)
713 buf[i] = tu_pack_float32_for_snorm(linear, 8);
714 else
715 buf[i] = tu_pack_float32_for_unorm(linear, 8);
716 } break;
717 default:
718 unreachable("unexpected ifmt");
719 break;
720 }
721 }
722 }
723
724 void
725 tu_2d_clear_zs(const VkClearDepthStencilValue *val, VkFormat format, uint32_t buf[4])
726 {
727 switch (format) {
728 case VK_FORMAT_X8_D24_UNORM_PACK32:
729 case VK_FORMAT_D24_UNORM_S8_UINT:
730 buf[0] = tu_pack_float32_for_unorm(val->depth, 24);
731 buf[1] = buf[0] >> 8;
732 buf[2] = buf[0] >> 16;
733 buf[3] = val->stencil;
734 return;
735 case VK_FORMAT_D16_UNORM:
736 case VK_FORMAT_D32_SFLOAT:
737 buf[0] = fui(val->depth);
738 return;
739 case VK_FORMAT_S8_UINT:
740 buf[0] = val->stencil;
741 return;
742 default:
743 unreachable("unexpected zs format");
744 break;
745 }
746 }
747
748 static void
749 tu_physical_device_get_format_properties(
750 struct tu_physical_device *physical_device,
751 VkFormat format,
752 VkFormatProperties *out_properties)
753 {
754 VkFormatFeatureFlags linear = 0, optimal = 0, buffer = 0;
755 const struct util_format_description *desc = vk_format_description(format);
756 const struct tu_native_format native_fmt = tu6_get_native_format(format);
757 if (!desc || !native_fmt.supported) {
758 goto end;
759 }
760
761 buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
762 if (native_fmt.supported & FMT_VERTEX)
763 buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
764
765 if (native_fmt.supported & FMT_TEXTURE) {
766 optimal |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
767 VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
768 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
769 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
770 buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
771 }
772
773 if (native_fmt.supported & FMT_COLOR) {
774 assert(native_fmt.supported & FMT_TEXTURE);
775 optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
776 VK_FORMAT_FEATURE_BLIT_SRC_BIT |
777 VK_FORMAT_FEATURE_BLIT_DST_BIT;
778 }
779
780 /* For the most part, we can do anything with a linear image that we could
781 * do with a tiled image. However, we can't support sysmem rendering with a
782 * linear depth texture, because we don't know if there's a bit to control
783 * the tiling of the depth buffer in BYPASS mode, and the blob also
784 * disables linear depth rendering, so there's no way to discover it. We
785 * also can't force GMEM mode, because there are other situations where we
786 * have to use sysmem rendering. So follow the blob here, and only enable
787 * DEPTH_STENCIL_ATTACHMENT_BIT for the optimal features.
788 */
789 linear = optimal;
790 if (tu6_pipe2depth(format) != (enum a6xx_depth_format)~0)
791 optimal |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
792
793 end:
794 out_properties->linearTilingFeatures = linear;
795 out_properties->optimalTilingFeatures = optimal;
796 out_properties->bufferFeatures = buffer;
797 }
798
799 void
800 tu_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
801 VkFormat format,
802 VkFormatProperties *pFormatProperties)
803 {
804 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
805
806 tu_physical_device_get_format_properties(physical_device, format,
807 pFormatProperties);
808 }
809
810 void
811 tu_GetPhysicalDeviceFormatProperties2(
812 VkPhysicalDevice physicalDevice,
813 VkFormat format,
814 VkFormatProperties2 *pFormatProperties)
815 {
816 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
817
818 tu_physical_device_get_format_properties(
819 physical_device, format, &pFormatProperties->formatProperties);
820
821 VkDrmFormatModifierPropertiesListEXT *list =
822 vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
823 if (list) {
824 VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,
825 &list->drmFormatModifierCount);
826
827 vk_outarray_append(&out, mod_props) {
828 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
829 mod_props->drmFormatModifierPlaneCount = 1;
830 }
831
832 /* TODO: any cases where this should be disabled? */
833 vk_outarray_append(&out, mod_props) {
834 mod_props->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
835 mod_props->drmFormatModifierPlaneCount = 1;
836 }
837 }
838 }
839
840 static VkResult
841 tu_get_image_format_properties(
842 struct tu_physical_device *physical_device,
843 const VkPhysicalDeviceImageFormatInfo2 *info,
844 VkImageFormatProperties *pImageFormatProperties)
845
846 {
847 VkFormatProperties format_props;
848 VkFormatFeatureFlags format_feature_flags;
849 VkExtent3D maxExtent;
850 uint32_t maxMipLevels;
851 uint32_t maxArraySize;
852 VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
853
854 tu_physical_device_get_format_properties(physical_device, info->format,
855 &format_props);
856
857 switch (info->tiling) {
858 case VK_IMAGE_TILING_LINEAR:
859 format_feature_flags = format_props.linearTilingFeatures;
860 break;
861
862 case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
863 /* The only difference between optimal and linear is currently whether
864 * depth/stencil attachments are allowed on depth/stencil formats.
865 * There's no reason to allow importing depth/stencil textures, so just
866 * disallow it and then this annoying edge case goes away.
867 *
868 * TODO: If anyone cares, we could enable this by looking at the
869 * modifier and checking if it's LINEAR or not.
870 */
871 if (vk_format_is_depth_or_stencil(info->format))
872 goto unsupported;
873
874 assert(format_props.optimalTilingFeatures == format_props.linearTilingFeatures);
875 /* fallthrough */
876 case VK_IMAGE_TILING_OPTIMAL:
877 format_feature_flags = format_props.optimalTilingFeatures;
878 break;
879 default:
880 unreachable("bad VkPhysicalDeviceImageFormatInfo2");
881 }
882
883 if (format_feature_flags == 0)
884 goto unsupported;
885
886 if (info->type != VK_IMAGE_TYPE_2D &&
887 vk_format_is_depth_or_stencil(info->format))
888 goto unsupported;
889
890 switch (info->type) {
891 default:
892 unreachable("bad vkimage type\n");
893 case VK_IMAGE_TYPE_1D:
894 maxExtent.width = 16384;
895 maxExtent.height = 1;
896 maxExtent.depth = 1;
897 maxMipLevels = 15; /* log2(maxWidth) + 1 */
898 maxArraySize = 2048;
899 break;
900 case VK_IMAGE_TYPE_2D:
901 maxExtent.width = 16384;
902 maxExtent.height = 16384;
903 maxExtent.depth = 1;
904 maxMipLevels = 15; /* log2(maxWidth) + 1 */
905 maxArraySize = 2048;
906 break;
907 case VK_IMAGE_TYPE_3D:
908 maxExtent.width = 2048;
909 maxExtent.height = 2048;
910 maxExtent.depth = 2048;
911 maxMipLevels = 12; /* log2(maxWidth) + 1 */
912 maxArraySize = 1;
913 break;
914 }
915
916 if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
917 info->type == VK_IMAGE_TYPE_2D &&
918 (format_feature_flags &
919 (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
920 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
921 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
922 !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
923 sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
924 /* 8x MSAA on 128bpp formats doesn't seem to work */
925 if (vk_format_get_blocksize(info->format) <= 8)
926 sampleCounts |= VK_SAMPLE_COUNT_8_BIT;
927 }
928
929 if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
930 if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
931 goto unsupported;
932 }
933 }
934
935 if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
936 if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
937 goto unsupported;
938 }
939 }
940
941 if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
942 if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
943 goto unsupported;
944 }
945 }
946
947 if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
948 if (!(format_feature_flags &
949 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
950 goto unsupported;
951 }
952 }
953
954 *pImageFormatProperties = (VkImageFormatProperties) {
955 .maxExtent = maxExtent,
956 .maxMipLevels = maxMipLevels,
957 .maxArrayLayers = maxArraySize,
958 .sampleCounts = sampleCounts,
959
960 /* FINISHME: Accurately calculate
961 * VkImageFormatProperties::maxResourceSize.
962 */
963 .maxResourceSize = UINT32_MAX,
964 };
965
966 return VK_SUCCESS;
967 unsupported:
968 *pImageFormatProperties = (VkImageFormatProperties) {
969 .maxExtent = { 0, 0, 0 },
970 .maxMipLevels = 0,
971 .maxArrayLayers = 0,
972 .sampleCounts = 0,
973 .maxResourceSize = 0,
974 };
975
976 return VK_ERROR_FORMAT_NOT_SUPPORTED;
977 }
978
979 VkResult
980 tu_GetPhysicalDeviceImageFormatProperties(
981 VkPhysicalDevice physicalDevice,
982 VkFormat format,
983 VkImageType type,
984 VkImageTiling tiling,
985 VkImageUsageFlags usage,
986 VkImageCreateFlags createFlags,
987 VkImageFormatProperties *pImageFormatProperties)
988 {
989 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
990
991 const VkPhysicalDeviceImageFormatInfo2 info = {
992 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
993 .pNext = NULL,
994 .format = format,
995 .type = type,
996 .tiling = tiling,
997 .usage = usage,
998 .flags = createFlags,
999 };
1000
1001 return tu_get_image_format_properties(physical_device, &info,
1002 pImageFormatProperties);
1003 }
1004
1005 static VkResult
1006 tu_get_external_image_format_properties(
1007 const struct tu_physical_device *physical_device,
1008 const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
1009 VkExternalMemoryHandleTypeFlagBits handleType,
1010 VkExternalMemoryProperties *external_properties)
1011 {
1012 VkExternalMemoryFeatureFlagBits flags = 0;
1013 VkExternalMemoryHandleTypeFlags export_flags = 0;
1014 VkExternalMemoryHandleTypeFlags compat_flags = 0;
1015
1016 /* From the Vulkan 1.1.98 spec:
1017 *
1018 * If handleType is not compatible with the format, type, tiling,
1019 * usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
1020 * then vkGetPhysicalDeviceImageFormatProperties2 returns
1021 * VK_ERROR_FORMAT_NOT_SUPPORTED.
1022 */
1023
1024 switch (handleType) {
1025 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1026 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1027 switch (pImageFormatInfo->type) {
1028 case VK_IMAGE_TYPE_2D:
1029 flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
1030 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
1031 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1032 compat_flags = export_flags =
1033 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
1034 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1035 break;
1036 default:
1037 return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
1038 "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
1039 handleType, pImageFormatInfo->type);
1040 }
1041 break;
1042 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1043 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1044 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
1045 break;
1046 default:
1047 return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
1048 "VkExternalMemoryTypeFlagBits(0x%x) unsupported",
1049 handleType);
1050 }
1051
1052 *external_properties = (VkExternalMemoryProperties) {
1053 .externalMemoryFeatures = flags,
1054 .exportFromImportedHandleTypes = export_flags,
1055 .compatibleHandleTypes = compat_flags,
1056 };
1057
1058 return VK_SUCCESS;
1059 }
1060
1061 VkResult
1062 tu_GetPhysicalDeviceImageFormatProperties2(
1063 VkPhysicalDevice physicalDevice,
1064 const VkPhysicalDeviceImageFormatInfo2 *base_info,
1065 VkImageFormatProperties2 *base_props)
1066 {
1067 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
1068 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
1069 VkExternalImageFormatProperties *external_props = NULL;
1070 VkResult result;
1071
1072 result = tu_get_image_format_properties(
1073 physical_device, base_info, &base_props->imageFormatProperties);
1074 if (result != VK_SUCCESS)
1075 return result;
1076
1077 /* Extract input structs */
1078 vk_foreach_struct_const(s, base_info->pNext)
1079 {
1080 switch (s->sType) {
1081 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
1082 external_info = (const void *) s;
1083 break;
1084 default:
1085 break;
1086 }
1087 }
1088
1089 /* Extract output structs */
1090 vk_foreach_struct(s, base_props->pNext)
1091 {
1092 switch (s->sType) {
1093 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
1094 external_props = (void *) s;
1095 break;
1096 default:
1097 break;
1098 }
1099 }
1100
1101 /* From the Vulkan 1.0.42 spec:
1102 *
1103 * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
1104 * behave as if VkPhysicalDeviceExternalImageFormatInfo was not
1105 * present and VkExternalImageFormatProperties will be ignored.
1106 */
1107 if (external_info && external_info->handleType != 0) {
1108 result = tu_get_external_image_format_properties(
1109 physical_device, base_info, external_info->handleType,
1110 &external_props->externalMemoryProperties);
1111 if (result != VK_SUCCESS)
1112 goto fail;
1113 }
1114
1115 return VK_SUCCESS;
1116
1117 fail:
1118 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
1119 /* From the Vulkan 1.0.42 spec:
1120 *
1121 * If the combination of parameters to
1122 * vkGetPhysicalDeviceImageFormatProperties2 is not supported by
1123 * the implementation for use in vkCreateImage, then all members of
1124 * imageFormatProperties will be filled with zero.
1125 */
1126 base_props->imageFormatProperties = (VkImageFormatProperties) { 0 };
1127 }
1128
1129 return result;
1130 }
1131
1132 void
1133 tu_GetPhysicalDeviceSparseImageFormatProperties(
1134 VkPhysicalDevice physicalDevice,
1135 VkFormat format,
1136 VkImageType type,
1137 uint32_t samples,
1138 VkImageUsageFlags usage,
1139 VkImageTiling tiling,
1140 uint32_t *pNumProperties,
1141 VkSparseImageFormatProperties *pProperties)
1142 {
1143 /* Sparse images are not yet supported. */
1144 *pNumProperties = 0;
1145 }
1146
1147 void
1148 tu_GetPhysicalDeviceSparseImageFormatProperties2(
1149 VkPhysicalDevice physicalDevice,
1150 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
1151 uint32_t *pPropertyCount,
1152 VkSparseImageFormatProperties2 *pProperties)
1153 {
1154 /* Sparse images are not yet supported. */
1155 *pPropertyCount = 0;
1156 }
1157
1158 void
1159 tu_GetPhysicalDeviceExternalBufferProperties(
1160 VkPhysicalDevice physicalDevice,
1161 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
1162 VkExternalBufferProperties *pExternalBufferProperties)
1163 {
1164 VkExternalMemoryFeatureFlagBits flags = 0;
1165 VkExternalMemoryHandleTypeFlags export_flags = 0;
1166 VkExternalMemoryHandleTypeFlags compat_flags = 0;
1167 switch (pExternalBufferInfo->handleType) {
1168 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1169 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1170 flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
1171 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1172 compat_flags = export_flags =
1173 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
1174 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1175 break;
1176 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1177 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1178 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
1179 break;
1180 default:
1181 break;
1182 }
1183 pExternalBufferProperties->externalMemoryProperties =
1184 (VkExternalMemoryProperties) {
1185 .externalMemoryFeatures = flags,
1186 .exportFromImportedHandleTypes = export_flags,
1187 .compatibleHandleTypes = compat_flags,
1188 };
1189 }