1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * Based on u_format.h which is:
6 * Copyright 2009-2010 Vmware, Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 */
26
27 #pragma once
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 #include <assert.h>
34 #include <vulkan/vulkan.h>
35 #include <util/macros.h>
36 enum vk_format_layout {
37 /**
38 * Formats with vk_format_block::width == vk_format_block::height == 1
39 * that can be described as an ordinary data structure.
40 */
41 VK_FORMAT_LAYOUT_PLAIN = 0,
42
43 /**
44 * Formats with sub-sampled channels.
45 *
46 * This is for formats like YVYU where there is less than one sample per
47 * pixel.
48 */
49 VK_FORMAT_LAYOUT_SUBSAMPLED = 3,
50
51 /**
52 * S3 Texture Compression formats.
53 */
54 VK_FORMAT_LAYOUT_S3TC = 4,
55
56 /**
57 * Red-Green Texture Compression formats.
58 */
59 VK_FORMAT_LAYOUT_RGTC = 5,
60
61 /**
62 * Ericsson Texture Compression
63 */
64 VK_FORMAT_LAYOUT_ETC = 6,
65
66 /**
67 * BC6/7 Texture Compression
68 */
69 VK_FORMAT_LAYOUT_BPTC = 7,
70
71 /**
72 * ASTC
73 */
74 VK_FORMAT_LAYOUT_ASTC = 8,
75
76 /**
77 * Everything else that doesn't fit in any of the above layouts.
78 */
79 VK_FORMAT_LAYOUT_OTHER = 9
80 };
81
82 struct vk_format_block
83 {
84 /** Block width in pixels */
85 unsigned width;
86
87 /** Block height in pixels */
88 unsigned height;
89
90 /** Block size in bits */
91 unsigned bits;
92 };
93
94 enum vk_format_type {
95 VK_FORMAT_TYPE_VOID = 0,
96 VK_FORMAT_TYPE_UNSIGNED = 1,
97 VK_FORMAT_TYPE_SIGNED = 2,
98 VK_FORMAT_TYPE_FIXED = 3,
99 VK_FORMAT_TYPE_FLOAT = 4
100 };
101
102
103 enum vk_format_colorspace {
104 VK_FORMAT_COLORSPACE_RGB = 0,
105 VK_FORMAT_COLORSPACE_SRGB = 1,
106 VK_FORMAT_COLORSPACE_YUV = 2,
107 VK_FORMAT_COLORSPACE_ZS = 3
108 };
109
110 struct vk_format_channel_description {
111 unsigned type:5;
112 unsigned normalized:1;
113 unsigned pure_integer:1;
114 unsigned scaled:1;
115 unsigned size:8;
116 unsigned shift:16;
117 };
118
119 struct vk_format_description
120 {
121 VkFormat format;
122 const char *name;
123 const char *short_name;
124
125 struct vk_format_block block;
126 enum vk_format_layout layout;
127
128 unsigned nr_channels:3;
129 unsigned is_array:1;
130 unsigned is_bitmask:1;
131 unsigned is_mixed:1;
132
133 struct vk_format_channel_description channel[4];
134
135 unsigned char swizzle[4];
136
137 enum vk_format_colorspace colorspace;
138 };
139
140 extern const struct vk_format_description vk_format_description_table[];
141
142 const struct vk_format_description *vk_format_description(VkFormat format);
143
144 /**
145 * Return total bits needed for the pixel format per block.
146 */
147 static inline unsigned
vk_format_get_blocksizebits(VkFormat format)148 vk_format_get_blocksizebits(VkFormat format)
149 {
150 const struct vk_format_description *desc = vk_format_description(format);
151
152 assert(desc);
153 if (!desc) {
154 return 0;
155 }
156
157 return desc->block.bits;
158 }
159
160 /**
161 * Return bytes per block (not pixel) for the given format.
162 */
163 static inline unsigned
vk_format_get_blocksize(VkFormat format)164 vk_format_get_blocksize(VkFormat format)
165 {
166 unsigned bits = vk_format_get_blocksizebits(format);
167 unsigned bytes = bits / 8;
168
169 assert(bits % 8 == 0);
170 assert(bytes > 0);
171 if (bytes == 0) {
172 bytes = 1;
173 }
174
175 return bytes;
176 }
177
178 static inline unsigned
vk_format_get_blockwidth(VkFormat format)179 vk_format_get_blockwidth(VkFormat format)
180 {
181 const struct vk_format_description *desc = vk_format_description(format);
182
183 assert(desc);
184 if (!desc) {
185 return 1;
186 }
187
188 return desc->block.width;
189 }
190
191 static inline unsigned
vk_format_get_blockheight(VkFormat format)192 vk_format_get_blockheight(VkFormat format)
193 {
194 const struct vk_format_description *desc = vk_format_description(format);
195
196 assert(desc);
197 if (!desc) {
198 return 1;
199 }
200
201 return desc->block.height;
202 }
203
204 /**
205 * Return the index of the first non-void channel
206 * -1 if no non-void channels
207 */
208 static inline int
vk_format_get_first_non_void_channel(VkFormat format)209 vk_format_get_first_non_void_channel(VkFormat format)
210 {
211 const struct vk_format_description *desc = vk_format_description(format);
212 int i;
213
214 for (i = 0; i < 4; i++)
215 if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
216 break;
217
218 if (i == 4)
219 return -1;
220
221 return i;
222 }
223
224 enum vk_swizzle {
225 VK_SWIZZLE_X,
226 VK_SWIZZLE_Y,
227 VK_SWIZZLE_Z,
228 VK_SWIZZLE_W,
229 VK_SWIZZLE_0,
230 VK_SWIZZLE_1,
231 VK_SWIZZLE_NONE,
232 VK_SWIZZLE_MAX, /**< Number of enums counter (must be last) */
233 };
234
235 static inline VkImageAspectFlags
vk_format_aspects(VkFormat format)236 vk_format_aspects(VkFormat format)
237 {
238 switch (format) {
239 case VK_FORMAT_UNDEFINED:
240 return 0;
241
242 case VK_FORMAT_S8_UINT:
243 return VK_IMAGE_ASPECT_STENCIL_BIT;
244
245 case VK_FORMAT_D16_UNORM_S8_UINT:
246 case VK_FORMAT_D24_UNORM_S8_UINT:
247 case VK_FORMAT_D32_SFLOAT_S8_UINT:
248 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
249
250 case VK_FORMAT_D16_UNORM:
251 case VK_FORMAT_X8_D24_UNORM_PACK32:
252 case VK_FORMAT_D32_SFLOAT:
253 return VK_IMAGE_ASPECT_DEPTH_BIT;
254
255 default:
256 return VK_IMAGE_ASPECT_COLOR_BIT;
257 }
258 }
259
260 static inline enum vk_swizzle
radv_swizzle_conv(VkComponentSwizzle component,const unsigned char chan[4],VkComponentSwizzle vk_swiz)261 radv_swizzle_conv(VkComponentSwizzle component, const unsigned char chan[4], VkComponentSwizzle vk_swiz)
262 {
263 int x;
264
265 if (vk_swiz == VK_COMPONENT_SWIZZLE_IDENTITY)
266 vk_swiz = component;
267 switch (vk_swiz) {
268 case VK_COMPONENT_SWIZZLE_ZERO:
269 return VK_SWIZZLE_0;
270 case VK_COMPONENT_SWIZZLE_ONE:
271 return VK_SWIZZLE_1;
272 case VK_COMPONENT_SWIZZLE_R:
273 for (x = 0; x < 4; x++)
274 if (chan[x] == 0)
275 return x;
276 return VK_SWIZZLE_0;
277 case VK_COMPONENT_SWIZZLE_G:
278 for (x = 0; x < 4; x++)
279 if (chan[x] == 1)
280 return x;
281 return VK_SWIZZLE_0;
282 case VK_COMPONENT_SWIZZLE_B:
283 for (x = 0; x < 4; x++)
284 if (chan[x] == 2)
285 return x;
286 return VK_SWIZZLE_0;
287 case VK_COMPONENT_SWIZZLE_A:
288 for (x = 0; x < 4; x++)
289 if (chan[x] == 3)
290 return x;
291 return VK_SWIZZLE_1;
292 default:
293 unreachable("Illegal swizzle");
294 }
295 }
296
vk_format_compose_swizzles(const VkComponentMapping * mapping,const unsigned char swz[4],enum vk_swizzle dst[4])297 static inline void vk_format_compose_swizzles(const VkComponentMapping *mapping,
298 const unsigned char swz[4],
299 enum vk_swizzle dst[4])
300 {
301 dst[0] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_R, swz, mapping->r);
302 dst[1] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_G, swz, mapping->g);
303 dst[2] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_B, swz, mapping->b);
304 dst[3] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_A, swz, mapping->a);
305 }
306
307 static inline bool
vk_format_is_compressed(VkFormat format)308 vk_format_is_compressed(VkFormat format)
309 {
310 const struct vk_format_description *desc = vk_format_description(format);
311
312 assert(desc);
313 if (!desc) {
314 return false;
315 }
316
317 switch (desc->layout) {
318 case VK_FORMAT_LAYOUT_S3TC:
319 case VK_FORMAT_LAYOUT_RGTC:
320 case VK_FORMAT_LAYOUT_ETC:
321 case VK_FORMAT_LAYOUT_BPTC:
322 case VK_FORMAT_LAYOUT_ASTC:
323 /* XXX add other formats in the future */
324 return true;
325 default:
326 return false;
327 }
328 }
329
330 static inline bool
vk_format_has_depth(const struct vk_format_description * desc)331 vk_format_has_depth(const struct vk_format_description *desc)
332 {
333 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
334 desc->swizzle[0] != VK_SWIZZLE_NONE;
335 }
336
337 static inline bool
vk_format_has_stencil(const struct vk_format_description * desc)338 vk_format_has_stencil(const struct vk_format_description *desc)
339 {
340 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
341 desc->swizzle[1] != VK_SWIZZLE_NONE;
342 }
343
344 static inline bool
vk_format_is_depth_or_stencil(VkFormat format)345 vk_format_is_depth_or_stencil(VkFormat format)
346 {
347 const struct vk_format_description *desc = vk_format_description(format);
348
349 assert(desc);
350 if (!desc) {
351 return false;
352 }
353
354 return vk_format_has_depth(desc) ||
355 vk_format_has_stencil(desc);
356 }
357
358 static inline bool
vk_format_is_depth(VkFormat format)359 vk_format_is_depth(VkFormat format)
360 {
361 const struct vk_format_description *desc = vk_format_description(format);
362
363 assert(desc);
364 if (!desc) {
365 return false;
366 }
367
368 return vk_format_has_depth(desc);
369 }
370
371 static inline bool
vk_format_is_color(VkFormat format)372 vk_format_is_color(VkFormat format)
373 {
374 return !vk_format_is_depth_or_stencil(format);
375 }
376
377 static inline VkFormat
vk_format_depth_only(VkFormat format)378 vk_format_depth_only(VkFormat format)
379 {
380 switch (format) {
381 case VK_FORMAT_D16_UNORM_S8_UINT:
382 return VK_FORMAT_D16_UNORM;
383 case VK_FORMAT_D24_UNORM_S8_UINT:
384 return VK_FORMAT_X8_D24_UNORM_PACK32;
385 case VK_FORMAT_D32_SFLOAT_S8_UINT:
386 return VK_FORMAT_D32_SFLOAT;
387 default:
388 return format;
389 }
390 }
391
392 static inline bool
vk_format_is_int(VkFormat format)393 vk_format_is_int(VkFormat format)
394 {
395 const struct vk_format_description *desc = vk_format_description(format);
396 int channel = vk_format_get_first_non_void_channel(format);
397
398 return channel >= 0 && desc->channel[channel].pure_integer;
399 }
400
401 static inline VkFormat
vk_format_stencil_only(VkFormat format)402 vk_format_stencil_only(VkFormat format)
403 {
404 return VK_FORMAT_S8_UINT;
405 }
406
407 static inline unsigned
vk_format_get_component_bits(VkFormat format,enum vk_format_colorspace colorspace,unsigned component)408 vk_format_get_component_bits(VkFormat format,
409 enum vk_format_colorspace colorspace,
410 unsigned component)
411 {
412 const struct vk_format_description *desc = vk_format_description(format);
413 enum vk_format_colorspace desc_colorspace;
414
415 assert(format);
416 if (!format) {
417 return 0;
418 }
419
420 assert(component < 4);
421
422 /* Treat RGB and SRGB as equivalent. */
423 if (colorspace == VK_FORMAT_COLORSPACE_SRGB) {
424 colorspace = VK_FORMAT_COLORSPACE_RGB;
425 }
426 if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
427 desc_colorspace = VK_FORMAT_COLORSPACE_RGB;
428 } else {
429 desc_colorspace = desc->colorspace;
430 }
431
432 if (desc_colorspace != colorspace) {
433 return 0;
434 }
435
436 switch (desc->swizzle[component]) {
437 case VK_SWIZZLE_X:
438 return desc->channel[0].size;
439 case VK_SWIZZLE_Y:
440 return desc->channel[1].size;
441 case VK_SWIZZLE_Z:
442 return desc->channel[2].size;
443 case VK_SWIZZLE_W:
444 return desc->channel[3].size;
445 default:
446 return 0;
447 }
448 }
449 #ifdef __cplusplus
450 } // extern "C" {
451 #endif
452