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