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