vk_format.h revision b8e80941
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
34enum 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	 * Formats that contain multiple planes.
81	 */
82	VK_FORMAT_LAYOUT_MULTIPLANE = 10,
83};
84
85struct vk_format_block
86{
87	/** Block width in pixels */
88	unsigned width;
89
90	/** Block height in pixels */
91	unsigned height;
92
93	/** Block size in bits */
94	unsigned bits;
95};
96
97enum vk_format_type {
98	VK_FORMAT_TYPE_VOID = 0,
99	VK_FORMAT_TYPE_UNSIGNED = 1,
100	VK_FORMAT_TYPE_SIGNED = 2,
101	VK_FORMAT_TYPE_FIXED = 3,
102	VK_FORMAT_TYPE_FLOAT = 4
103};
104
105
106enum vk_format_colorspace {
107	VK_FORMAT_COLORSPACE_RGB = 0,
108	VK_FORMAT_COLORSPACE_SRGB = 1,
109	VK_FORMAT_COLORSPACE_YUV = 2,
110	VK_FORMAT_COLORSPACE_ZS = 3
111};
112
113struct vk_format_channel_description {
114	unsigned type:5;
115	unsigned normalized:1;
116	unsigned pure_integer:1;
117	unsigned scaled:1;
118	unsigned size:8;
119	unsigned shift:16;
120};
121
122struct vk_format_description
123{
124	VkFormat format;
125	const char *name;
126	const char *short_name;
127
128	struct vk_format_block block;
129	enum vk_format_layout layout;
130
131	unsigned nr_channels:3;
132	unsigned is_array:1;
133	unsigned is_bitmask:1;
134	unsigned is_mixed:1;
135
136	struct vk_format_channel_description channel[4];
137
138	unsigned char swizzle[4];
139
140	enum vk_format_colorspace colorspace;
141
142	unsigned plane_count:2;
143	unsigned width_divisor:2;
144	unsigned height_divisor:2;
145	VkFormat plane_formats[3];
146};
147
148extern const struct vk_format_description vk_format_description_table[];
149
150const struct vk_format_description *vk_format_description(VkFormat format);
151
152/**
153 * Return total bits needed for the pixel format per block.
154 */
155static inline unsigned
156vk_format_get_blocksizebits(VkFormat format)
157{
158	const struct vk_format_description *desc = vk_format_description(format);
159
160	assert(desc);
161	if (!desc) {
162		return 0;
163	}
164
165	return desc->block.bits;
166}
167
168/**
169 * Return bytes per block (not pixel) for the given format.
170 */
171static inline unsigned
172vk_format_get_blocksize(VkFormat format)
173{
174	unsigned bits = vk_format_get_blocksizebits(format);
175	unsigned bytes = bits / 8;
176
177	assert(bits % 8 == 0);
178	assert(bytes > 0);
179	if (bytes == 0) {
180		bytes = 1;
181	}
182
183	return bytes;
184}
185
186static inline unsigned
187vk_format_get_blockwidth(VkFormat format)
188{
189	const struct vk_format_description *desc = vk_format_description(format);
190
191	assert(desc);
192	if (!desc) {
193		return 1;
194	}
195
196	return desc->block.width;
197}
198
199static inline unsigned
200vk_format_get_blockheight(VkFormat format)
201{
202	const struct vk_format_description *desc = vk_format_description(format);
203
204	assert(desc);
205	if (!desc) {
206		return 1;
207	}
208
209	return desc->block.height;
210}
211
212/**
213 * Return the index of the first non-void channel
214 * -1 if no non-void channels
215 */
216static inline int
217vk_format_get_first_non_void_channel(VkFormat format)
218{
219	const struct vk_format_description *desc = vk_format_description(format);
220	int i;
221
222	for (i = 0; i < 4; i++)
223		if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
224			break;
225
226	if (i == 4)
227		return -1;
228
229	return i;
230}
231
232enum vk_swizzle {
233	VK_SWIZZLE_X,
234	VK_SWIZZLE_Y,
235	VK_SWIZZLE_Z,
236	VK_SWIZZLE_W,
237	VK_SWIZZLE_0,
238	VK_SWIZZLE_1,
239	VK_SWIZZLE_NONE,
240	VK_SWIZZLE_MAX, /**< Number of enums counter (must be last) */
241};
242
243static inline VkImageAspectFlags
244vk_format_aspects(VkFormat format)
245{
246	switch (format) {
247	case VK_FORMAT_UNDEFINED:
248		return 0;
249
250	case VK_FORMAT_S8_UINT:
251		return VK_IMAGE_ASPECT_STENCIL_BIT;
252
253	case VK_FORMAT_D16_UNORM_S8_UINT:
254	case VK_FORMAT_D24_UNORM_S8_UINT:
255	case VK_FORMAT_D32_SFLOAT_S8_UINT:
256		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
257
258	case VK_FORMAT_D16_UNORM:
259	case VK_FORMAT_X8_D24_UNORM_PACK32:
260	case VK_FORMAT_D32_SFLOAT:
261		return VK_IMAGE_ASPECT_DEPTH_BIT;
262
263	default:
264		return VK_IMAGE_ASPECT_COLOR_BIT;
265	}
266}
267
268static inline enum vk_swizzle
269radv_swizzle_conv(VkComponentSwizzle component, const unsigned char chan[4], VkComponentSwizzle vk_swiz)
270{
271	int x;
272
273	if (vk_swiz == VK_COMPONENT_SWIZZLE_IDENTITY)
274		vk_swiz = component;
275	switch (vk_swiz) {
276	case VK_COMPONENT_SWIZZLE_ZERO:
277		return VK_SWIZZLE_0;
278	case VK_COMPONENT_SWIZZLE_ONE:
279		return VK_SWIZZLE_1;
280	case VK_COMPONENT_SWIZZLE_R:
281		for (x = 0; x < 4; x++)
282			if (chan[x] == 0)
283				return x;
284		return VK_SWIZZLE_0;
285	case VK_COMPONENT_SWIZZLE_G:
286		for (x = 0; x < 4; x++)
287			if (chan[x] == 1)
288				return x;
289		return VK_SWIZZLE_0;
290	case VK_COMPONENT_SWIZZLE_B:
291		for (x = 0; x < 4; x++)
292			if (chan[x] == 2)
293				return x;
294		return VK_SWIZZLE_0;
295	case VK_COMPONENT_SWIZZLE_A:
296		for (x = 0; x < 4; x++)
297			if (chan[x] == 3)
298				return x;
299		return VK_SWIZZLE_1;
300	default:
301		unreachable("Illegal swizzle");
302	}
303}
304
305static inline void vk_format_compose_swizzles(const VkComponentMapping *mapping,
306					      const unsigned char swz[4],
307					      enum vk_swizzle dst[4])
308{
309	dst[0] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_R, swz, mapping->r);
310	dst[1] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_G, swz, mapping->g);
311	dst[2] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_B, swz, mapping->b);
312	dst[3] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_A, swz, mapping->a);
313}
314
315static inline bool
316vk_format_is_compressed(VkFormat format)
317{
318	const struct vk_format_description *desc = vk_format_description(format);
319
320	assert(desc);
321	if (!desc) {
322		return false;
323	}
324
325	switch (desc->layout) {
326	case VK_FORMAT_LAYOUT_S3TC:
327	case VK_FORMAT_LAYOUT_RGTC:
328	case VK_FORMAT_LAYOUT_ETC:
329	case VK_FORMAT_LAYOUT_BPTC:
330	case VK_FORMAT_LAYOUT_ASTC:
331		/* XXX add other formats in the future */
332		return true;
333	default:
334		return false;
335	}
336}
337
338static inline bool
339vk_format_is_subsampled(VkFormat format)
340{
341	const struct vk_format_description *desc = vk_format_description(format);
342
343	assert(desc);
344	if (!desc) {
345		return false;
346	}
347
348	return desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED;
349}
350
351static inline bool
352vk_format_has_depth(const struct vk_format_description *desc)
353{
354	return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
355		desc->swizzle[0] != VK_SWIZZLE_NONE;
356}
357
358static inline bool
359vk_format_has_stencil(const struct vk_format_description *desc)
360{
361	return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
362		desc->swizzle[1] != VK_SWIZZLE_NONE;
363}
364
365static inline bool
366vk_format_is_depth_or_stencil(VkFormat format)
367{
368	const struct vk_format_description *desc = vk_format_description(format);
369
370	assert(desc);
371	if (!desc) {
372		return false;
373	}
374
375	return vk_format_has_depth(desc) ||
376		vk_format_has_stencil(desc);
377}
378
379static inline bool
380vk_format_is_depth(VkFormat format)
381{
382	const struct vk_format_description *desc = vk_format_description(format);
383
384	assert(desc);
385	if (!desc) {
386		return false;
387	}
388
389	return vk_format_has_depth(desc);
390}
391
392static inline bool
393vk_format_is_stencil(VkFormat format)
394{
395	const struct vk_format_description *desc = vk_format_description(format);
396
397	assert(desc);
398	if (!desc) {
399		return false;
400	}
401
402	return vk_format_has_stencil(desc);
403}
404
405static inline bool
406vk_format_is_color(VkFormat format)
407{
408	return !vk_format_is_depth_or_stencil(format);
409}
410
411static inline VkFormat
412vk_format_depth_only(VkFormat format)
413{
414	switch (format) {
415	case VK_FORMAT_D16_UNORM_S8_UINT:
416		return VK_FORMAT_D16_UNORM;
417	case VK_FORMAT_D24_UNORM_S8_UINT:
418		return VK_FORMAT_X8_D24_UNORM_PACK32;
419	case VK_FORMAT_D32_SFLOAT_S8_UINT:
420		return VK_FORMAT_D32_SFLOAT;
421	default:
422		return format;
423	}
424}
425
426static inline bool
427vk_format_is_int(VkFormat format)
428{
429	const struct vk_format_description *desc = vk_format_description(format);
430	int channel =  vk_format_get_first_non_void_channel(format);
431
432	return channel >= 0 && desc->channel[channel].pure_integer;
433}
434
435static inline bool
436vk_format_is_srgb(VkFormat format)
437{
438	const struct vk_format_description *desc = vk_format_description(format);
439	return desc->colorspace == VK_FORMAT_COLORSPACE_SRGB;
440}
441
442static inline VkFormat
443vk_format_no_srgb(VkFormat format)
444{
445	switch(format) {
446	case VK_FORMAT_R8_SRGB:
447		return VK_FORMAT_R8_UNORM;
448	case VK_FORMAT_R8G8_SRGB:
449		return VK_FORMAT_R8G8_UNORM;
450	case VK_FORMAT_R8G8B8_SRGB:
451		return VK_FORMAT_R8G8B8_UNORM;
452	case VK_FORMAT_B8G8R8_SRGB:
453		return VK_FORMAT_B8G8R8_UNORM;
454	case VK_FORMAT_R8G8B8A8_SRGB:
455		return VK_FORMAT_R8G8B8A8_UNORM;
456	case VK_FORMAT_B8G8R8A8_SRGB:
457		return VK_FORMAT_B8G8R8A8_UNORM;
458	case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
459		return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
460	case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
461		return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
462	case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
463		return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
464	case VK_FORMAT_BC2_SRGB_BLOCK:
465		return VK_FORMAT_BC2_UNORM_BLOCK;
466	case VK_FORMAT_BC3_SRGB_BLOCK:
467		return VK_FORMAT_BC3_UNORM_BLOCK;
468	case VK_FORMAT_BC7_SRGB_BLOCK:
469		return VK_FORMAT_BC7_UNORM_BLOCK;
470	case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
471		return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
472	case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
473		return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
474	case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
475		return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
476	default:
477		assert(!vk_format_is_srgb(format));
478		return format;
479	}
480}
481
482static inline VkFormat
483vk_format_stencil_only(VkFormat format)
484{
485	return VK_FORMAT_S8_UINT;
486}
487
488static inline unsigned
489vk_format_get_component_bits(VkFormat format,
490			     enum vk_format_colorspace colorspace,
491			     unsigned component)
492{
493	const struct vk_format_description *desc = vk_format_description(format);
494	enum vk_format_colorspace desc_colorspace;
495
496	assert(format);
497	if (!format) {
498		return 0;
499	}
500
501	assert(component < 4);
502
503	/* Treat RGB and SRGB as equivalent. */
504	if (colorspace == VK_FORMAT_COLORSPACE_SRGB) {
505		colorspace = VK_FORMAT_COLORSPACE_RGB;
506	}
507	if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
508		desc_colorspace = VK_FORMAT_COLORSPACE_RGB;
509	} else {
510		desc_colorspace = desc->colorspace;
511	}
512
513	if (desc_colorspace != colorspace) {
514		return 0;
515	}
516
517	switch (desc->swizzle[component]) {
518	case VK_SWIZZLE_X:
519		return desc->channel[0].size;
520	case VK_SWIZZLE_Y:
521		return desc->channel[1].size;
522	case VK_SWIZZLE_Z:
523		return desc->channel[2].size;
524	case VK_SWIZZLE_W:
525		return desc->channel[3].size;
526	default:
527		return 0;
528	}
529}
530
531static inline VkFormat
532vk_to_non_srgb_format(VkFormat format)
533{
534	switch(format) {
535	case VK_FORMAT_R8_SRGB :
536		return VK_FORMAT_R8_UNORM;
537	case VK_FORMAT_R8G8_SRGB:
538		return VK_FORMAT_R8G8_UNORM;
539	case VK_FORMAT_R8G8B8_SRGB:
540		return VK_FORMAT_R8G8B8_UNORM;
541	case VK_FORMAT_B8G8R8_SRGB:
542		return VK_FORMAT_B8G8R8_UNORM;
543	case VK_FORMAT_R8G8B8A8_SRGB :
544		return VK_FORMAT_R8G8B8A8_UNORM;
545	case VK_FORMAT_B8G8R8A8_SRGB:
546		return VK_FORMAT_B8G8R8A8_UNORM;
547	case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
548		return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
549	default:
550		return format;
551	}
552}
553
554static inline unsigned
555vk_format_get_nr_components(VkFormat format)
556{
557	const struct vk_format_description *desc = vk_format_description(format);
558	return desc->nr_channels;
559}
560
561static inline unsigned
562vk_format_get_plane_count(VkFormat format)
563{
564	const struct vk_format_description *desc = vk_format_description(format);
565
566	return desc->plane_count;
567}
568
569static inline VkFormat
570vk_format_get_plane_format(VkFormat format, unsigned plane_id)
571{
572	const struct vk_format_description *desc = vk_format_description(format);
573
574	if (desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE) {
575		assert(plane_id == 0);
576		return format;
577	}
578
579	assert(plane_id < desc->plane_count);
580
581	return desc->plane_formats[plane_id];
582}
583
584
585#endif /* VK_FORMAT_H */
586