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 #ifndef VK_FORMAT_H
28 #define VK_FORMAT_H
29
30 #include <assert.h>
31 #include <vulkan/vulkan.h>
32 #include <util/macros.h>
33
34 enum vk_format_layout {
35 /**
36 * Formats with vk_format_block::width == vk_format_block::height == 1
37 * that can be described as an ordinary data structure.
38 */
39 VK_FORMAT_LAYOUT_PLAIN = 0,
40
41 /**
42 * Formats with sub-sampled channels.
43 *
44 * This is for formats like YVYU where there is less than one sample per
45 * pixel.
46 */
47 VK_FORMAT_LAYOUT_SUBSAMPLED = 3,
48
49 /**
50 * S3 Texture Compression formats.
51 */
52 VK_FORMAT_LAYOUT_S3TC = 4,
53
54 /**
55 * Red-Green Texture Compression formats.
56 */
57 VK_FORMAT_LAYOUT_RGTC = 5,
58
59 /**
60 * Ericsson Texture Compression
61 */
62 VK_FORMAT_LAYOUT_ETC = 6,
63
64 /**
65 * BC6/7 Texture Compression
66 */
67 VK_FORMAT_LAYOUT_BPTC = 7,
68
69 /**
70 * ASTC
71 */
72 VK_FORMAT_LAYOUT_ASTC = 8,
73
74 /**
75 * Everything else that doesn't fit in any of the above layouts.
76 */
77 VK_FORMAT_LAYOUT_OTHER = 9
78 };
79
80 struct vk_format_block
81 {
82 /** Block width in pixels */
83 unsigned width;
84
85 /** Block height in pixels */
86 unsigned height;
87
88 /** Block size in bits */
89 unsigned bits;
90 };
91
92 enum vk_format_type {
93 VK_FORMAT_TYPE_VOID = 0,
94 VK_FORMAT_TYPE_UNSIGNED = 1,
95 VK_FORMAT_TYPE_SIGNED = 2,
96 VK_FORMAT_TYPE_FIXED = 3,
97 VK_FORMAT_TYPE_FLOAT = 4
98 };
99
100
101 enum vk_format_colorspace {
102 VK_FORMAT_COLORSPACE_RGB = 0,
103 VK_FORMAT_COLORSPACE_SRGB = 1,
104 VK_FORMAT_COLORSPACE_YUV = 2,
105 VK_FORMAT_COLORSPACE_ZS = 3
106 };
107
108 struct vk_format_channel_description {
109 unsigned type:5;
110 unsigned normalized:1;
111 unsigned pure_integer:1;
112 unsigned scaled:1;
113 unsigned size:8;
114 unsigned shift:16;
115 };
116
117 struct vk_format_description
118 {
119 VkFormat format;
120 const char *name;
121 const char *short_name;
122
123 struct vk_format_block block;
124 enum vk_format_layout layout;
125
126 unsigned nr_channels:3;
127 unsigned is_array:1;
128 unsigned is_bitmask:1;
129 unsigned is_mixed:1;
130
131 struct vk_format_channel_description channel[4];
132
133 unsigned char swizzle[4];
134
135 enum vk_format_colorspace colorspace;
136 };
137
138 extern const struct vk_format_description vk_format_description_table[];
139
140 const struct vk_format_description *vk_format_description(VkFormat format);
141
142 /**
143 * Return total bits needed for the pixel format per block.
144 */
145 static inline unsigned
vk_format_get_blocksizebits(VkFormat format)146 vk_format_get_blocksizebits(VkFormat format)
147 {
148 const struct vk_format_description *desc = vk_format_description(format);
149
150 assert(desc);
151 if (!desc) {
152 return 0;
153 }
154
155 return desc->block.bits;
156 }
157
158 /**
159 * Return bytes per block (not pixel) for the given format.
160 */
161 static inline unsigned
vk_format_get_blocksize(VkFormat format)162 vk_format_get_blocksize(VkFormat format)
163 {
164 unsigned bits = vk_format_get_blocksizebits(format);
165 unsigned bytes = bits / 8;
166
167 assert(bits % 8 == 0);
168 assert(bytes > 0);
169 if (bytes == 0) {
170 bytes = 1;
171 }
172
173 return bytes;
174 }
175
176 static inline unsigned
vk_format_get_blockwidth(VkFormat format)177 vk_format_get_blockwidth(VkFormat format)
178 {
179 const struct vk_format_description *desc = vk_format_description(format);
180
181 assert(desc);
182 if (!desc) {
183 return 1;
184 }
185
186 return desc->block.width;
187 }
188
189 static inline unsigned
vk_format_get_blockheight(VkFormat format)190 vk_format_get_blockheight(VkFormat format)
191 {
192 const struct vk_format_description *desc = vk_format_description(format);
193
194 assert(desc);
195 if (!desc) {
196 return 1;
197 }
198
199 return desc->block.height;
200 }
201
202 /**
203 * Return the index of the first non-void channel
204 * -1 if no non-void channels
205 */
206 static inline int
vk_format_get_first_non_void_channel(VkFormat format)207 vk_format_get_first_non_void_channel(VkFormat format)
208 {
209 const struct vk_format_description *desc = vk_format_description(format);
210 int i;
211
212 for (i = 0; i < 4; i++)
213 if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
214 break;
215
216 if (i == 4)
217 return -1;
218
219 return i;
220 }
221
222 enum vk_swizzle {
223 VK_SWIZZLE_X,
224 VK_SWIZZLE_Y,
225 VK_SWIZZLE_Z,
226 VK_SWIZZLE_W,
227 VK_SWIZZLE_0,
228 VK_SWIZZLE_1,
229 VK_SWIZZLE_NONE,
230 VK_SWIZZLE_MAX, /**< Number of enums counter (must be last) */
231 };
232
233 static inline VkImageAspectFlags
vk_format_aspects(VkFormat format)234 vk_format_aspects(VkFormat format)
235 {
236 switch (format) {
237 case VK_FORMAT_UNDEFINED:
238 return 0;
239
240 case VK_FORMAT_S8_UINT:
241 return VK_IMAGE_ASPECT_STENCIL_BIT;
242
243 case VK_FORMAT_D16_UNORM_S8_UINT:
244 case VK_FORMAT_D24_UNORM_S8_UINT:
245 case VK_FORMAT_D32_SFLOAT_S8_UINT:
246 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
247
248 case VK_FORMAT_D16_UNORM:
249 case VK_FORMAT_X8_D24_UNORM_PACK32:
250 case VK_FORMAT_D32_SFLOAT:
251 return VK_IMAGE_ASPECT_DEPTH_BIT;
252
253 default:
254 return VK_IMAGE_ASPECT_COLOR_BIT;
255 }
256 }
257
258 static inline enum vk_swizzle
radv_swizzle_conv(VkComponentSwizzle component,const unsigned char chan[4],VkComponentSwizzle vk_swiz)259 radv_swizzle_conv(VkComponentSwizzle component, const unsigned char chan[4], VkComponentSwizzle vk_swiz)
260 {
261 int x;
262
263 if (vk_swiz == VK_COMPONENT_SWIZZLE_IDENTITY)
264 vk_swiz = component;
265 switch (vk_swiz) {
266 case VK_COMPONENT_SWIZZLE_ZERO:
267 return VK_SWIZZLE_0;
268 case VK_COMPONENT_SWIZZLE_ONE:
269 return VK_SWIZZLE_1;
270 case VK_COMPONENT_SWIZZLE_R:
271 for (x = 0; x < 4; x++)
272 if (chan[x] == 0)
273 return x;
274 return VK_SWIZZLE_0;
275 case VK_COMPONENT_SWIZZLE_G:
276 for (x = 0; x < 4; x++)
277 if (chan[x] == 1)
278 return x;
279 return VK_SWIZZLE_0;
280 case VK_COMPONENT_SWIZZLE_B:
281 for (x = 0; x < 4; x++)
282 if (chan[x] == 2)
283 return x;
284 return VK_SWIZZLE_0;
285 case VK_COMPONENT_SWIZZLE_A:
286 for (x = 0; x < 4; x++)
287 if (chan[x] == 3)
288 return x;
289 return VK_SWIZZLE_1;
290 default:
291 unreachable("Illegal swizzle");
292 }
293 }
294
vk_format_compose_swizzles(const VkComponentMapping * mapping,const unsigned char swz[4],enum vk_swizzle dst[4])295 static inline void vk_format_compose_swizzles(const VkComponentMapping *mapping,
296 const unsigned char swz[4],
297 enum vk_swizzle dst[4])
298 {
299 dst[0] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_R, swz, mapping->r);
300 dst[1] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_G, swz, mapping->g);
301 dst[2] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_B, swz, mapping->b);
302 dst[3] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_A, swz, mapping->a);
303 }
304
305 static inline bool
vk_format_is_compressed(VkFormat format)306 vk_format_is_compressed(VkFormat format)
307 {
308 const struct vk_format_description *desc = vk_format_description(format);
309
310 assert(desc);
311 if (!desc) {
312 return false;
313 }
314
315 switch (desc->layout) {
316 case VK_FORMAT_LAYOUT_S3TC:
317 case VK_FORMAT_LAYOUT_RGTC:
318 case VK_FORMAT_LAYOUT_ETC:
319 case VK_FORMAT_LAYOUT_BPTC:
320 case VK_FORMAT_LAYOUT_ASTC:
321 /* XXX add other formats in the future */
322 return true;
323 default:
324 return false;
325 }
326 }
327
328 static inline bool
vk_format_has_depth(const struct vk_format_description * desc)329 vk_format_has_depth(const struct vk_format_description *desc)
330 {
331 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
332 desc->swizzle[0] != VK_SWIZZLE_NONE;
333 }
334
335 static inline bool
vk_format_has_stencil(const struct vk_format_description * desc)336 vk_format_has_stencil(const struct vk_format_description *desc)
337 {
338 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
339 desc->swizzle[1] != VK_SWIZZLE_NONE;
340 }
341
342 static inline bool
vk_format_is_depth_or_stencil(VkFormat format)343 vk_format_is_depth_or_stencil(VkFormat format)
344 {
345 const struct vk_format_description *desc = vk_format_description(format);
346
347 assert(desc);
348 if (!desc) {
349 return false;
350 }
351
352 return vk_format_has_depth(desc) ||
353 vk_format_has_stencil(desc);
354 }
355
356 static inline bool
vk_format_is_depth(VkFormat format)357 vk_format_is_depth(VkFormat format)
358 {
359 const struct vk_format_description *desc = vk_format_description(format);
360
361 assert(desc);
362 if (!desc) {
363 return false;
364 }
365
366 return vk_format_has_depth(desc);
367 }
368
369 static inline bool
vk_format_is_stencil(VkFormat format)370 vk_format_is_stencil(VkFormat format)
371 {
372 const struct vk_format_description *desc = vk_format_description(format);
373
374 assert(desc);
375 if (!desc) {
376 return false;
377 }
378
379 return vk_format_has_stencil(desc);
380 }
381
382 static inline bool
vk_format_is_color(VkFormat format)383 vk_format_is_color(VkFormat format)
384 {
385 return !vk_format_is_depth_or_stencil(format);
386 }
387
388 static inline VkFormat
vk_format_depth_only(VkFormat format)389 vk_format_depth_only(VkFormat format)
390 {
391 switch (format) {
392 case VK_FORMAT_D16_UNORM_S8_UINT:
393 return VK_FORMAT_D16_UNORM;
394 case VK_FORMAT_D24_UNORM_S8_UINT:
395 return VK_FORMAT_X8_D24_UNORM_PACK32;
396 case VK_FORMAT_D32_SFLOAT_S8_UINT:
397 return VK_FORMAT_D32_SFLOAT;
398 default:
399 return format;
400 }
401 }
402
403 static inline bool
vk_format_is_int(VkFormat format)404 vk_format_is_int(VkFormat format)
405 {
406 const struct vk_format_description *desc = vk_format_description(format);
407 int channel = vk_format_get_first_non_void_channel(format);
408
409 return channel >= 0 && desc->channel[channel].pure_integer;
410 }
411
412 static inline bool
vk_format_is_srgb(VkFormat format)413 vk_format_is_srgb(VkFormat format)
414 {
415 const struct vk_format_description *desc = vk_format_description(format);
416 return desc->colorspace == VK_FORMAT_COLORSPACE_SRGB;
417 }
418
419 static inline VkFormat
vk_format_stencil_only(VkFormat format)420 vk_format_stencil_only(VkFormat format)
421 {
422 return VK_FORMAT_S8_UINT;
423 }
424
425 static inline unsigned
vk_format_get_component_bits(VkFormat format,enum vk_format_colorspace colorspace,unsigned component)426 vk_format_get_component_bits(VkFormat format,
427 enum vk_format_colorspace colorspace,
428 unsigned component)
429 {
430 const struct vk_format_description *desc = vk_format_description(format);
431 enum vk_format_colorspace desc_colorspace;
432
433 assert(format);
434 if (!format) {
435 return 0;
436 }
437
438 assert(component < 4);
439
440 /* Treat RGB and SRGB as equivalent. */
441 if (colorspace == VK_FORMAT_COLORSPACE_SRGB) {
442 colorspace = VK_FORMAT_COLORSPACE_RGB;
443 }
444 if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
445 desc_colorspace = VK_FORMAT_COLORSPACE_RGB;
446 } else {
447 desc_colorspace = desc->colorspace;
448 }
449
450 if (desc_colorspace != colorspace) {
451 return 0;
452 }
453
454 switch (desc->swizzle[component]) {
455 case VK_SWIZZLE_X:
456 return desc->channel[0].size;
457 case VK_SWIZZLE_Y:
458 return desc->channel[1].size;
459 case VK_SWIZZLE_Z:
460 return desc->channel[2].size;
461 case VK_SWIZZLE_W:
462 return desc->channel[3].size;
463 default:
464 return 0;
465 }
466 }
467
468 static inline VkFormat
vk_to_non_srgb_format(VkFormat format)469 vk_to_non_srgb_format(VkFormat format)
470 {
471 switch(format) {
472 case VK_FORMAT_R8_SRGB :
473 return VK_FORMAT_R8_UNORM;
474 case VK_FORMAT_R8G8_SRGB:
475 return VK_FORMAT_R8G8_UNORM;
476 case VK_FORMAT_R8G8B8_SRGB:
477 return VK_FORMAT_R8G8B8_UNORM;
478 case VK_FORMAT_B8G8R8_SRGB:
479 return VK_FORMAT_B8G8R8_UNORM;
480 case VK_FORMAT_R8G8B8A8_SRGB :
481 return VK_FORMAT_R8G8B8A8_UNORM;
482 case VK_FORMAT_B8G8R8A8_SRGB:
483 return VK_FORMAT_B8G8R8A8_UNORM;
484 case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
485 return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
486 default:
487 return format;
488 }
489 }
490
491 #endif /* VK_FORMAT_H */
492