turnip: rework format helpers
[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 static 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 struct tu_native_format
318 tu6_format_color(VkFormat format, enum a6xx_tile_mode tile_mode)
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 fmt.fmt = FMT6_10_10_10_2_UNORM_DEST;
325
326 if (tile_mode)
327 fmt.swap = WZYX;
328
329 return fmt;
330 }
331
332 struct tu_native_format
333 tu6_format_texture(VkFormat format, enum a6xx_tile_mode tile_mode)
334 {
335 struct tu_native_format fmt = tu6_get_native_format(format);
336 assert(fmt.supported & FMT_TEXTURE);
337
338 if (!tile_mode) {
339 /* different from format table when used as linear src */
340 if (format == VK_FORMAT_R5G5B5A1_UNORM_PACK16)
341 fmt.fmt = FMT6_1_5_5_5_UNORM, fmt.swap = WXYZ;
342 if (format == VK_FORMAT_B5G5R5A1_UNORM_PACK16)
343 fmt.fmt = FMT6_1_5_5_5_UNORM, fmt.swap = WZYX;
344 } else {
345 fmt.swap = WZYX;
346 }
347
348 return fmt;
349 }
350
351 enum a6xx_2d_ifmt
352 tu6_fmt_to_ifmt(enum a6xx_format fmt)
353 {
354 switch (fmt) {
355 case FMT6_A8_UNORM:
356 case FMT6_8_UNORM:
357 case FMT6_8_SNORM:
358 case FMT6_8_8_UNORM:
359 case FMT6_8_8_SNORM:
360 case FMT6_8_8_8_8_UNORM:
361 case FMT6_8_8_8_X8_UNORM:
362 case FMT6_8_8_8_8_SNORM:
363 case FMT6_4_4_4_4_UNORM:
364 case FMT6_5_5_5_1_UNORM:
365 case FMT6_5_6_5_UNORM:
366 case FMT6_Z24_UNORM_S8_UINT:
367 case FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8:
368 return R2D_UNORM8;
369
370 case FMT6_32_UINT:
371 case FMT6_32_SINT:
372 case FMT6_32_32_UINT:
373 case FMT6_32_32_SINT:
374 case FMT6_32_32_32_32_UINT:
375 case FMT6_32_32_32_32_SINT:
376 return R2D_INT32;
377
378 case FMT6_16_UINT:
379 case FMT6_16_SINT:
380 case FMT6_16_16_UINT:
381 case FMT6_16_16_SINT:
382 case FMT6_16_16_16_16_UINT:
383 case FMT6_16_16_16_16_SINT:
384 case FMT6_10_10_10_2_UINT:
385 return R2D_INT16;
386
387 case FMT6_8_UINT:
388 case FMT6_8_SINT:
389 case FMT6_8_8_UINT:
390 case FMT6_8_8_SINT:
391 case FMT6_8_8_8_8_UINT:
392 case FMT6_8_8_8_8_SINT:
393 return R2D_INT8;
394
395 case FMT6_16_UNORM:
396 case FMT6_16_SNORM:
397 case FMT6_16_16_UNORM:
398 case FMT6_16_16_SNORM:
399 case FMT6_16_16_16_16_UNORM:
400 case FMT6_16_16_16_16_SNORM:
401 case FMT6_32_FLOAT:
402 case FMT6_32_32_FLOAT:
403 case FMT6_32_32_32_32_FLOAT:
404 return R2D_FLOAT32;
405
406 case FMT6_16_FLOAT:
407 case FMT6_16_16_FLOAT:
408 case FMT6_16_16_16_16_FLOAT:
409 case FMT6_11_11_10_FLOAT:
410 case FMT6_10_10_10_2_UNORM:
411 case FMT6_10_10_10_2_UNORM_DEST:
412 return R2D_FLOAT16;
413
414 default:
415 unreachable("bad format");
416 return 0;
417 }
418 }
419
420 enum a6xx_depth_format
421 tu6_pipe2depth(VkFormat format)
422 {
423 switch (format) {
424 case VK_FORMAT_D16_UNORM:
425 return DEPTH6_16;
426 case VK_FORMAT_X8_D24_UNORM_PACK32:
427 case VK_FORMAT_D24_UNORM_S8_UINT:
428 return DEPTH6_24_8;
429 case VK_FORMAT_D32_SFLOAT:
430 return DEPTH6_32;
431 default:
432 return ~0;
433 }
434 }
435
436 static uint32_t
437 tu_pack_mask(int bits)
438 {
439 assert(bits <= 32);
440 return (1ull << bits) - 1;
441 }
442
443 static uint32_t
444 tu_pack_float32_for_unorm(float val, int bits)
445 {
446 const uint32_t max = tu_pack_mask(bits);
447 if (val < 0.0f)
448 return 0;
449 else if (val > 1.0f)
450 return max;
451 else
452 return _mesa_lroundevenf(val * (float) max);
453 }
454
455 static uint32_t
456 tu_pack_float32_for_snorm(float val, int bits)
457 {
458 const int32_t max = tu_pack_mask(bits - 1);
459 int32_t tmp;
460 if (val < -1.0f)
461 tmp = -max;
462 else if (val > 1.0f)
463 tmp = max;
464 else
465 tmp = _mesa_lroundevenf(val * (float) max);
466
467 return tmp & tu_pack_mask(bits);
468 }
469
470 static uint32_t
471 tu_pack_float32_for_uscaled(float val, int bits)
472 {
473 const uint32_t max = tu_pack_mask(bits);
474 if (val < 0.0f)
475 return 0;
476 else if (val > (float) max)
477 return max;
478 else
479 return (uint32_t) val;
480 }
481
482 static uint32_t
483 tu_pack_float32_for_sscaled(float val, int bits)
484 {
485 const int32_t max = tu_pack_mask(bits - 1);
486 const int32_t min = -max - 1;
487 int32_t tmp;
488 if (val < (float) min)
489 tmp = min;
490 else if (val > (float) max)
491 tmp = max;
492 else
493 tmp = (int32_t) val;
494
495 return tmp & tu_pack_mask(bits);
496 }
497
498 static uint32_t
499 tu_pack_uint32_for_uint(uint32_t val, int bits)
500 {
501 return val & tu_pack_mask(bits);
502 }
503
504 static uint32_t
505 tu_pack_int32_for_sint(int32_t val, int bits)
506 {
507 return val & tu_pack_mask(bits);
508 }
509
510 static uint32_t
511 tu_pack_float32_for_sfloat(float val, int bits)
512 {
513 assert(bits == 16 || bits == 32);
514 return bits == 16 ? util_float_to_half(val) : fui(val);
515 }
516
517 union tu_clear_component_value {
518 float float32;
519 int32_t int32;
520 uint32_t uint32;
521 };
522
523 static uint32_t
524 tu_pack_clear_component_value(union tu_clear_component_value val,
525 const struct util_format_channel_description *ch)
526 {
527 uint32_t packed;
528
529 switch (ch->type) {
530 case UTIL_FORMAT_TYPE_UNSIGNED:
531 /* normalized, scaled, or pure integer */
532 if (ch->normalized)
533 packed = tu_pack_float32_for_unorm(val.float32, ch->size);
534 else if (ch->pure_integer)
535 packed = tu_pack_uint32_for_uint(val.uint32, ch->size);
536 else
537 packed = tu_pack_float32_for_uscaled(val.float32, ch->size);
538 break;
539 case UTIL_FORMAT_TYPE_SIGNED:
540 /* normalized, scaled, or pure integer */
541 if (ch->normalized)
542 packed = tu_pack_float32_for_snorm(val.float32, ch->size);
543 else if (ch->pure_integer)
544 packed = tu_pack_int32_for_sint(val.int32, ch->size);
545 else
546 packed = tu_pack_float32_for_sscaled(val.float32, ch->size);
547 break;
548 case UTIL_FORMAT_TYPE_FLOAT:
549 packed = tu_pack_float32_for_sfloat(val.float32, ch->size);
550 break;
551 default:
552 unreachable("unexpected channel type");
553 packed = 0;
554 break;
555 }
556
557 assert((packed & tu_pack_mask(ch->size)) == packed);
558 return packed;
559 }
560
561 static const struct util_format_channel_description *
562 tu_get_format_channel_description(const struct util_format_description *desc,
563 int comp)
564 {
565 switch (desc->swizzle[comp]) {
566 case PIPE_SWIZZLE_X:
567 return &desc->channel[0];
568 case PIPE_SWIZZLE_Y:
569 return &desc->channel[1];
570 case PIPE_SWIZZLE_Z:
571 return &desc->channel[2];
572 case PIPE_SWIZZLE_W:
573 return &desc->channel[3];
574 default:
575 return NULL;
576 }
577 }
578
579 static union tu_clear_component_value
580 tu_get_clear_component_value(const VkClearValue *val, int comp,
581 enum util_format_colorspace colorspace)
582 {
583 assert(comp < 4);
584
585 union tu_clear_component_value tmp;
586 switch (colorspace) {
587 case UTIL_FORMAT_COLORSPACE_ZS:
588 assert(comp < 2);
589 if (comp == 0)
590 tmp.float32 = val->depthStencil.depth;
591 else
592 tmp.uint32 = val->depthStencil.stencil;
593 break;
594 case UTIL_FORMAT_COLORSPACE_SRGB:
595 if (comp < 3) {
596 tmp.float32 = util_format_linear_to_srgb_float(val->color.float32[comp]);
597 break;
598 }
599 default:
600 assert(comp < 4);
601 tmp.uint32 = val->color.uint32[comp];
602 break;
603 }
604
605 return tmp;
606 }
607
608 /**
609 * Pack a VkClearValue into a 128-bit buffer. \a format is respected except
610 * for the component order. The components are always packed in WZYX order
611 * (i.e., msb is white and lsb is red).
612 *
613 * Return the number of uint32_t's used.
614 */
615 void
616 tu_pack_clear_value(const VkClearValue *val, VkFormat format, uint32_t buf[4])
617 {
618 const struct util_format_description *desc = vk_format_description(format);
619
620 switch (format) {
621 case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
622 buf[0] = float3_to_r11g11b10f(val->color.float32);
623 return;
624 case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
625 buf[0] = float3_to_rgb9e5(val->color.float32);
626 return;
627 default:
628 break;
629 }
630
631 assert(desc && desc->layout == UTIL_FORMAT_LAYOUT_PLAIN);
632
633 /* S8_UINT is special and has no depth */
634 const int max_components =
635 format == VK_FORMAT_S8_UINT ? 2 : desc->nr_channels;
636
637 int buf_offset = 0;
638 int bit_shift = 0;
639 for (int comp = 0; comp < max_components; comp++) {
640 const struct util_format_channel_description *ch =
641 tu_get_format_channel_description(desc, comp);
642 if (!ch) {
643 assert((format == VK_FORMAT_S8_UINT && comp == 0) ||
644 (format == VK_FORMAT_X8_D24_UNORM_PACK32 && comp == 1));
645 continue;
646 }
647
648 union tu_clear_component_value v = tu_get_clear_component_value(
649 val, comp, desc->colorspace);
650
651 /* move to the next uint32_t when there is not enough space */
652 assert(ch->size <= 32);
653 if (bit_shift + ch->size > 32) {
654 buf_offset++;
655 bit_shift = 0;
656 }
657
658 if (bit_shift == 0)
659 buf[buf_offset] = 0;
660
661 buf[buf_offset] |= tu_pack_clear_component_value(v, ch) << bit_shift;
662 bit_shift += ch->size;
663 }
664 }
665
666 void
667 tu_2d_clear_color(const VkClearColorValue *val, VkFormat format, uint32_t buf[4])
668 {
669 const struct util_format_description *desc = vk_format_description(format);
670
671 /* not supported by 2D engine, cleared as U32 */
672 if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
673 buf[0] = float3_to_rgb9e5(val->float32);
674 return;
675 }
676
677 enum a6xx_2d_ifmt ifmt = tu6_fmt_to_ifmt(tu6_get_native_format(format).fmt);
678
679 assert(desc && (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
680 format == VK_FORMAT_B10G11R11_UFLOAT_PACK32));
681
682 for (unsigned i = 0; i < desc->nr_channels; i++) {
683 const struct util_format_channel_description *ch = &desc->channel[i];
684
685 switch (ifmt) {
686 case R2D_INT32:
687 case R2D_INT16:
688 case R2D_INT8:
689 case R2D_FLOAT32:
690 buf[i] = val->uint32[i];
691 break;
692 case R2D_FLOAT16:
693 buf[i] = util_float_to_half(val->float32[i]);
694 break;
695 case R2D_UNORM8: {
696 float linear = val->float32[i];
697 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB && i < 3)
698 linear = util_format_linear_to_srgb_float(val->float32[i]);
699
700 if (ch->type == UTIL_FORMAT_TYPE_SIGNED)
701 buf[i] = tu_pack_float32_for_snorm(linear, 8);
702 else
703 buf[i] = tu_pack_float32_for_unorm(linear, 8);
704 } break;
705 default:
706 unreachable("unexpected ifmt");
707 break;
708 }
709 }
710 }
711
712 void
713 tu_2d_clear_zs(const VkClearDepthStencilValue *val, VkFormat format, uint32_t buf[4])
714 {
715 switch (format) {
716 case VK_FORMAT_X8_D24_UNORM_PACK32:
717 case VK_FORMAT_D24_UNORM_S8_UINT:
718 buf[0] = tu_pack_float32_for_unorm(val->depth, 24);
719 buf[1] = buf[0] >> 8;
720 buf[2] = buf[0] >> 16;
721 buf[3] = val->stencil;
722 return;
723 case VK_FORMAT_D16_UNORM:
724 case VK_FORMAT_D32_SFLOAT:
725 buf[0] = fui(val->depth);
726 return;
727 case VK_FORMAT_S8_UINT:
728 buf[0] = val->stencil;
729 return;
730 default:
731 unreachable("unexpected zs format");
732 break;
733 }
734 }
735
736 static void
737 tu_physical_device_get_format_properties(
738 struct tu_physical_device *physical_device,
739 VkFormat format,
740 VkFormatProperties *out_properties)
741 {
742 VkFormatFeatureFlags linear = 0, optimal = 0, buffer = 0;
743 const struct util_format_description *desc = vk_format_description(format);
744 const struct tu_native_format native_fmt = tu6_get_native_format(format);
745 if (!desc || !native_fmt.supported) {
746 goto end;
747 }
748
749 buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
750 if (native_fmt.supported & FMT_VERTEX)
751 buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
752
753 if (native_fmt.supported & FMT_TEXTURE) {
754 optimal |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
755 VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
756 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
757 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
758 buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
759 }
760
761 if (native_fmt.supported & FMT_COLOR) {
762 assert(native_fmt.supported & FMT_TEXTURE);
763 optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
764 VK_FORMAT_FEATURE_BLIT_SRC_BIT |
765 VK_FORMAT_FEATURE_BLIT_DST_BIT;
766 }
767
768 /* For the most part, we can do anything with a linear image that we could
769 * do with a tiled image. However, we can't support sysmem rendering with a
770 * linear depth texture, because we don't know if there's a bit to control
771 * the tiling of the depth buffer in BYPASS mode, and the blob also
772 * disables linear depth rendering, so there's no way to discover it. We
773 * also can't force GMEM mode, because there are other situations where we
774 * have to use sysmem rendering. So follow the blob here, and only enable
775 * DEPTH_STENCIL_ATTACHMENT_BIT for the optimal features.
776 */
777 linear = optimal;
778 if (tu6_pipe2depth(format) != (enum a6xx_depth_format)~0)
779 optimal |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
780
781 end:
782 out_properties->linearTilingFeatures = linear;
783 out_properties->optimalTilingFeatures = optimal;
784 out_properties->bufferFeatures = buffer;
785 }
786
787 void
788 tu_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
789 VkFormat format,
790 VkFormatProperties *pFormatProperties)
791 {
792 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
793
794 tu_physical_device_get_format_properties(physical_device, format,
795 pFormatProperties);
796 }
797
798 void
799 tu_GetPhysicalDeviceFormatProperties2(
800 VkPhysicalDevice physicalDevice,
801 VkFormat format,
802 VkFormatProperties2 *pFormatProperties)
803 {
804 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
805
806 tu_physical_device_get_format_properties(
807 physical_device, format, &pFormatProperties->formatProperties);
808
809 VkDrmFormatModifierPropertiesListEXT *list =
810 vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
811 if (list) {
812 VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,
813 &list->drmFormatModifierCount);
814
815 vk_outarray_append(&out, mod_props) {
816 mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
817 mod_props->drmFormatModifierPlaneCount = 1;
818 }
819
820 /* TODO: any cases where this should be disabled? */
821 vk_outarray_append(&out, mod_props) {
822 mod_props->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
823 mod_props->drmFormatModifierPlaneCount = 1;
824 }
825 }
826 }
827
828 static VkResult
829 tu_get_image_format_properties(
830 struct tu_physical_device *physical_device,
831 const VkPhysicalDeviceImageFormatInfo2 *info,
832 VkImageFormatProperties *pImageFormatProperties)
833
834 {
835 VkFormatProperties format_props;
836 VkFormatFeatureFlags format_feature_flags;
837 VkExtent3D maxExtent;
838 uint32_t maxMipLevels;
839 uint32_t maxArraySize;
840 VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
841
842 tu_physical_device_get_format_properties(physical_device, info->format,
843 &format_props);
844
845 switch (info->tiling) {
846 case VK_IMAGE_TILING_LINEAR:
847 format_feature_flags = format_props.linearTilingFeatures;
848 break;
849
850 case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
851 /* The only difference between optimal and linear is currently whether
852 * depth/stencil attachments are allowed on depth/stencil formats.
853 * There's no reason to allow importing depth/stencil textures, so just
854 * disallow it and then this annoying edge case goes away.
855 *
856 * TODO: If anyone cares, we could enable this by looking at the
857 * modifier and checking if it's LINEAR or not.
858 */
859 if (vk_format_is_depth_or_stencil(info->format))
860 goto unsupported;
861
862 assert(format_props.optimalTilingFeatures == format_props.linearTilingFeatures);
863 /* fallthrough */
864 case VK_IMAGE_TILING_OPTIMAL:
865 format_feature_flags = format_props.optimalTilingFeatures;
866 break;
867 default:
868 unreachable("bad VkPhysicalDeviceImageFormatInfo2");
869 }
870
871 if (format_feature_flags == 0)
872 goto unsupported;
873
874 if (info->type != VK_IMAGE_TYPE_2D &&
875 vk_format_is_depth_or_stencil(info->format))
876 goto unsupported;
877
878 switch (info->type) {
879 default:
880 unreachable("bad vkimage type\n");
881 case VK_IMAGE_TYPE_1D:
882 maxExtent.width = 16384;
883 maxExtent.height = 1;
884 maxExtent.depth = 1;
885 maxMipLevels = 15; /* log2(maxWidth) + 1 */
886 maxArraySize = 2048;
887 break;
888 case VK_IMAGE_TYPE_2D:
889 maxExtent.width = 16384;
890 maxExtent.height = 16384;
891 maxExtent.depth = 1;
892 maxMipLevels = 15; /* log2(maxWidth) + 1 */
893 maxArraySize = 2048;
894 break;
895 case VK_IMAGE_TYPE_3D:
896 maxExtent.width = 2048;
897 maxExtent.height = 2048;
898 maxExtent.depth = 2048;
899 maxMipLevels = 12; /* log2(maxWidth) + 1 */
900 maxArraySize = 1;
901 break;
902 }
903
904 if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
905 info->type == VK_IMAGE_TYPE_2D &&
906 (format_feature_flags &
907 (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
908 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
909 !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
910 !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
911 sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
912 /* note: most operations support 8 samples (GMEM render/resolve do at least)
913 * but some do not (which ones?), just disable 8 samples completely,
914 * (no 8x msaa matches the blob driver behavior)
915 */
916 }
917
918 if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
919 if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
920 goto unsupported;
921 }
922 }
923
924 if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
925 if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
926 goto unsupported;
927 }
928 }
929
930 if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
931 if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
932 goto unsupported;
933 }
934 }
935
936 if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
937 if (!(format_feature_flags &
938 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
939 goto unsupported;
940 }
941 }
942
943 *pImageFormatProperties = (VkImageFormatProperties) {
944 .maxExtent = maxExtent,
945 .maxMipLevels = maxMipLevels,
946 .maxArrayLayers = maxArraySize,
947 .sampleCounts = sampleCounts,
948
949 /* FINISHME: Accurately calculate
950 * VkImageFormatProperties::maxResourceSize.
951 */
952 .maxResourceSize = UINT32_MAX,
953 };
954
955 return VK_SUCCESS;
956 unsupported:
957 *pImageFormatProperties = (VkImageFormatProperties) {
958 .maxExtent = { 0, 0, 0 },
959 .maxMipLevels = 0,
960 .maxArrayLayers = 0,
961 .sampleCounts = 0,
962 .maxResourceSize = 0,
963 };
964
965 return VK_ERROR_FORMAT_NOT_SUPPORTED;
966 }
967
968 VkResult
969 tu_GetPhysicalDeviceImageFormatProperties(
970 VkPhysicalDevice physicalDevice,
971 VkFormat format,
972 VkImageType type,
973 VkImageTiling tiling,
974 VkImageUsageFlags usage,
975 VkImageCreateFlags createFlags,
976 VkImageFormatProperties *pImageFormatProperties)
977 {
978 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
979
980 const VkPhysicalDeviceImageFormatInfo2 info = {
981 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
982 .pNext = NULL,
983 .format = format,
984 .type = type,
985 .tiling = tiling,
986 .usage = usage,
987 .flags = createFlags,
988 };
989
990 return tu_get_image_format_properties(physical_device, &info,
991 pImageFormatProperties);
992 }
993
994 static VkResult
995 tu_get_external_image_format_properties(
996 const struct tu_physical_device *physical_device,
997 const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
998 VkExternalMemoryHandleTypeFlagBits handleType,
999 VkExternalMemoryProperties *external_properties)
1000 {
1001 VkExternalMemoryFeatureFlagBits flags = 0;
1002 VkExternalMemoryHandleTypeFlags export_flags = 0;
1003 VkExternalMemoryHandleTypeFlags compat_flags = 0;
1004
1005 /* From the Vulkan 1.1.98 spec:
1006 *
1007 * If handleType is not compatible with the format, type, tiling,
1008 * usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
1009 * then vkGetPhysicalDeviceImageFormatProperties2 returns
1010 * VK_ERROR_FORMAT_NOT_SUPPORTED.
1011 */
1012
1013 switch (handleType) {
1014 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1015 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1016 switch (pImageFormatInfo->type) {
1017 case VK_IMAGE_TYPE_2D:
1018 flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
1019 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
1020 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1021 compat_flags = export_flags =
1022 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
1023 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1024 break;
1025 default:
1026 return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
1027 "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
1028 handleType, pImageFormatInfo->type);
1029 }
1030 break;
1031 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1032 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1033 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
1034 break;
1035 default:
1036 return vk_errorf(physical_device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
1037 "VkExternalMemoryTypeFlagBits(0x%x) unsupported",
1038 handleType);
1039 }
1040
1041 *external_properties = (VkExternalMemoryProperties) {
1042 .externalMemoryFeatures = flags,
1043 .exportFromImportedHandleTypes = export_flags,
1044 .compatibleHandleTypes = compat_flags,
1045 };
1046
1047 return VK_SUCCESS;
1048 }
1049
1050 VkResult
1051 tu_GetPhysicalDeviceImageFormatProperties2(
1052 VkPhysicalDevice physicalDevice,
1053 const VkPhysicalDeviceImageFormatInfo2 *base_info,
1054 VkImageFormatProperties2 *base_props)
1055 {
1056 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
1057 const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
1058 VkExternalImageFormatProperties *external_props = NULL;
1059 VkResult result;
1060
1061 result = tu_get_image_format_properties(
1062 physical_device, base_info, &base_props->imageFormatProperties);
1063 if (result != VK_SUCCESS)
1064 return result;
1065
1066 /* Extract input structs */
1067 vk_foreach_struct_const(s, base_info->pNext)
1068 {
1069 switch (s->sType) {
1070 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
1071 external_info = (const void *) s;
1072 break;
1073 default:
1074 break;
1075 }
1076 }
1077
1078 /* Extract output structs */
1079 vk_foreach_struct(s, base_props->pNext)
1080 {
1081 switch (s->sType) {
1082 case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
1083 external_props = (void *) s;
1084 break;
1085 default:
1086 break;
1087 }
1088 }
1089
1090 /* From the Vulkan 1.0.42 spec:
1091 *
1092 * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
1093 * behave as if VkPhysicalDeviceExternalImageFormatInfo was not
1094 * present and VkExternalImageFormatProperties will be ignored.
1095 */
1096 if (external_info && external_info->handleType != 0) {
1097 result = tu_get_external_image_format_properties(
1098 physical_device, base_info, external_info->handleType,
1099 &external_props->externalMemoryProperties);
1100 if (result != VK_SUCCESS)
1101 goto fail;
1102 }
1103
1104 return VK_SUCCESS;
1105
1106 fail:
1107 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
1108 /* From the Vulkan 1.0.42 spec:
1109 *
1110 * If the combination of parameters to
1111 * vkGetPhysicalDeviceImageFormatProperties2 is not supported by
1112 * the implementation for use in vkCreateImage, then all members of
1113 * imageFormatProperties will be filled with zero.
1114 */
1115 base_props->imageFormatProperties = (VkImageFormatProperties) { 0 };
1116 }
1117
1118 return result;
1119 }
1120
1121 void
1122 tu_GetPhysicalDeviceSparseImageFormatProperties(
1123 VkPhysicalDevice physicalDevice,
1124 VkFormat format,
1125 VkImageType type,
1126 uint32_t samples,
1127 VkImageUsageFlags usage,
1128 VkImageTiling tiling,
1129 uint32_t *pNumProperties,
1130 VkSparseImageFormatProperties *pProperties)
1131 {
1132 /* Sparse images are not yet supported. */
1133 *pNumProperties = 0;
1134 }
1135
1136 void
1137 tu_GetPhysicalDeviceSparseImageFormatProperties2(
1138 VkPhysicalDevice physicalDevice,
1139 const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
1140 uint32_t *pPropertyCount,
1141 VkSparseImageFormatProperties2 *pProperties)
1142 {
1143 /* Sparse images are not yet supported. */
1144 *pPropertyCount = 0;
1145 }
1146
1147 void
1148 tu_GetPhysicalDeviceExternalBufferProperties(
1149 VkPhysicalDevice physicalDevice,
1150 const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
1151 VkExternalBufferProperties *pExternalBufferProperties)
1152 {
1153 VkExternalMemoryFeatureFlagBits flags = 0;
1154 VkExternalMemoryHandleTypeFlags export_flags = 0;
1155 VkExternalMemoryHandleTypeFlags compat_flags = 0;
1156 switch (pExternalBufferInfo->handleType) {
1157 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
1158 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
1159 flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
1160 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1161 compat_flags = export_flags =
1162 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
1163 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
1164 break;
1165 case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
1166 flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
1167 compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
1168 break;
1169 default:
1170 break;
1171 }
1172 pExternalBufferProperties->externalMemoryProperties =
1173 (VkExternalMemoryProperties) {
1174 .externalMemoryFeatures = flags,
1175 .exportFromImportedHandleTypes = export_flags,
1176 .compatibleHandleTypes = compat_flags,
1177 };
1178 }