17ec681f3SmrgSurface Formats 27ec681f3Smrg=============== 37ec681f3Smrg 47ec681f3SmrgA surface format describes the encoding of color information into the actual 57ec681f3Smrgdata stored in memory. Surface formats in isl are specified via the 67ec681f3Smrg:cpp:enum:`isl_format` enum. A complete list of surface formats is included at 77ec681f3Smrgthe end of this chapter. 87ec681f3Smrg 97ec681f3SmrgIn general, a surface format definition consists of two parts: encoding and 107ec681f3Smrglayout. 117ec681f3Smrg 127ec681f3SmrgData Encoding 137ec681f3Smrg------------- 147ec681f3Smrg 157ec681f3SmrgThere are several different ways that one can encode a number (or vector) into 167ec681f3Smrga binary form, and each makes different trade-offs. By default, most color 177ec681f3Smrgvalues lie in the range [0, 1], so one of the most common encodings for color 187ec681f3Smrgdata is unsigned normalized where the range of an unsigned integer of a 197ec681f3Smrgparticular size is mapped linearly onto the interval [0, 1]. While normalized 207ec681f3Smrgis certainly the most common representation for color data, not all data is 217ec681f3Smrgcolor data, and not all values are nicely bounded. The possible data encodings 227ec681f3Smrgare specified by :cpp:enum:`isl_base_type`: 237ec681f3Smrg 247ec681f3Smrg.. doxygenenum:: isl_base_type 257ec681f3Smrg 267ec681f3SmrgData Layout 277ec681f3Smrg----------- 287ec681f3Smrg 297ec681f3SmrgThe different data layouts fall into two categories: array and packed. When an 307ec681f3Smrgarray layout is used, the components are stored sequentially in an array of the 317ec681f3Smrggiven encoding. For instance, if the data is encoded in an 8-bit RGBA array 327ec681f3Smrgformat the data is stored in an array of type :c:type:`uint8_t` where the blue 337ec681f3Smrgcomponent of the :c:expr:`i`'th color value is accessed as: 347ec681f3Smrg 357ec681f3Smrg.. code-block:: C 367ec681f3Smrg 377ec681f3Smrg uint8_t r = ((uint8_t *)data)[i * 4 + 0]; 387ec681f3Smrg uint8_t g = ((uint8_t *)data)[i * 4 + 1]; 397ec681f3Smrg uint8_t b = ((uint8_t *)data)[i * 4 + 2]; 407ec681f3Smrg uint8_t a = ((uint8_t *)data)[i * 4 + 3]; 417ec681f3Smrg 427ec681f3SmrgArray formats are popular because of their simplicity. However, they are 437ec681f3Smrglimited to formats where all components have the same size and fit in 447ec681f3Smrga standard C data type. 457ec681f3Smrg 467ec681f3SmrgPacked formats, on the other hand, are encoded with the entire color value 477ec681f3Smrgpacked into a single 8, 16, or 32-bit value. The components are specified by 487ec681f3Smrgwhich bits they occupy within that value. For instance, with the popular 497ec681f3Smrg:c:expr:`RGB565` format, each :c:type:`vec3` takes up 16 bits and the 507ec681f3Smrg:c:expr:`i`'th color value is accessed as: 517ec681f3Smrg 527ec681f3Smrg.. code-block:: C 537ec681f3Smrg 547ec681f3Smrg uint8_t r = (*(uint16_t *)data >> 0) & 0x1f; 557ec681f3Smrg uint8_t g = (*(uint16_t *)data >> 5) & 0x3f; 567ec681f3Smrg uint8_t b = (*(uint16_t *)data >> 11) & 0x1f; 577ec681f3Smrg 587ec681f3SmrgPacked formats are useful because they allow you to specify formats with uneven 597ec681f3Smrgcomponent sizes such as :c:expr:`RGBA1010102` or where the components are 607ec681f3Smrgsmaller than 8 bits such as :c:expr:`RGB565` discussed above. It does, 617ec681f3Smrghowever, come with the restriction that the entire vector must fit within 8, 627ec681f3Smrg16, or 32 bits. 637ec681f3Smrg 647ec681f3SmrgOne has to be careful when reasoning about packed formats because it is easy to 657ec681f3Smrgget the color order wrong. With array formats, the channel ordering is usually 667ec681f3Smrgimplied directly from the format name with :c:expr:`RGBA8888` storing the 677ec681f3Smrgformats as in the first example and :c:expr:`BGRA8888` storing them in the BGRA 687ec681f3Smrgordering. Packed formats, however, are not as simple because some 697ec681f3Smrgspecifications choose to use a MSB to LSB ordering and others LSB to MSB. One 707ec681f3Smrgmust be careful to pay attention to the enum in question in order to avoid 717ec681f3Smrggetting them backwards. 727ec681f3Smrg 737ec681f3SmrgFrom an API perspective, both types of formats are available. In Vulkan, the 747ec681f3Smrgformats that are of the form :c:enumerator:`VK_FORMAT_xxx_PACKEDn` are packed 757ec681f3Smrgformats where the entire color fits in :c:expr:`n` bits and formats without the 767ec681f3Smrg:c:expr:`_PACKEDn` suffix are array formats. In GL, if you specify one of the 777ec681f3Smrgbase types such as :c:enumerator:`GL_FLOAT` you get an array format but if you 787ec681f3Smrgspecify a packed type such as :c:enumerator:`GL_UNSIGNED_INT_8_8_8_8_REV` you 797ec681f3Smrgget a packed format. 807ec681f3Smrg 817ec681f3SmrgThe following table provides a summary of the bit orderings of different packed 827ec681f3Smrgformat specifications. The bit ordering is relative to the reading of the enum 837ec681f3Smrgname from left to right. 847ec681f3Smrg 857ec681f3Smrg===================== ============== 867ec681f3SmrgComponent Left → Right 877ec681f3Smrg===================== ============== 887ec681f3SmrgGL MSB → LSB 897ec681f3SmrgVulkan MSB → LSB 907ec681f3Smrgmesa_format LSB → MSB 917ec681f3SmrgIntel surface format LSB → MSB 927ec681f3Smrg===================== ============== 937ec681f3Smrg 947ec681f3SmrgUnderstanding sRGB 957ec681f3Smrg------------------ 967ec681f3Smrg 977ec681f3SmrgThe sRGB colorspace is one of the least tractable concepts in the entire world 987ec681f3Smrgof surfaces and formats. Most texture formats are stored in a linear 997ec681f3Smrgcolorspace where the floating-point value corresponds linearly to intensity 1007ec681f3Smrgvalues. The sRGB color space, on the other hand, is non-linear and provides 1017ec681f3Smrggreater precision in the lower-intensity (darker) end of the spectrum. The 1027ec681f3Smrgrelationship between linear and sRGB is governed by the following continuous 1037ec681f3Smrgbijection: 1047ec681f3Smrg 1057ec681f3Smrg.. math:: 1067ec681f3Smrg 1077ec681f3Smrg c_l = 1087ec681f3Smrg \begin{cases} 1097ec681f3Smrg \frac{c_s}{12.92} &\text{if } c_s \le 0.04045 \\\\ 1107ec681f3Smrg \left(\frac{c_s + 0.055}{1.055}\right)^{2.4} &\text{if } c_s > 0.04045 1117ec681f3Smrg \end{cases} 1127ec681f3Smrg 1137ec681f3Smrgwhere :math:`c_l` is the linear color and :math:`c_s` is the color in sRGB. 1147ec681f3SmrgIt is important to note that, when an alpha channel is present, the alpha 1157ec681f3Smrgchannel is always stored in the linear colorspace. 1167ec681f3Smrg 1177ec681f3SmrgThe key to understanding sRGB is to think about it starting from the physical 1187ec681f3Smrgdisplay. All displays work natively in sRGB. On older displays, there isn't 1197ec681f3Smrgso much a conversion operation as a fact of how the hardware works. All 1207ec681f3Smrgdisplay hardware has a natural gamma curve required to get from linear to the 1217ec681f3Smrgsignal level required to generate the correct color. On older CRT displays, 1227ec681f3Smrgthe gamma curve of your average CRT is approximately the sRGB curve. More 1237ec681f3Smrgmodern display hardware has support for additional gamma curves to try and get 1247ec681f3Smrgaccurate colors but, for the sake of compatibility, everything still operates 1257ec681f3Smrgin sRGB. When an image is sent to the X server, X passes the pixels on to the 1267ec681f3Smrgdisplay verbatim without doing any conversions. (Fun fact: When dealing with 1277ec681f3Smrgtranslucent windows, X blends in the wrong colorspace.) This means that the 1287ec681f3Smrgimage into which you are rendering will always be interpreted as if it were in 1297ec681f3Smrgthe sRGB colorspace. 1307ec681f3Smrg 1317ec681f3SmrgWhen sampling from a texture, the value returned to the shader is in the linear 1327ec681f3Smrgcolorspace. The conversion from sRGB happens as part of sampling. In OpenGL, 1337ec681f3Smrgthanks mostly to history, there are various knobs for determining when you 1347ec681f3Smrgshould or should not encode or decode sRGB. In 2007, GL_EXT_texture_sRGB added 1357ec681f3Smrgsupport for sRGB texture formats and was included in OpenGL 2.1. In 2010, 1367ec681f3SmrgGL_EXT_texture_sRGB_decode added a flag to allow you to disable texture 1377ec681f3Smrgdecoding so that the shader received the data still in the sRGB colorspace. 1387ec681f3SmrgThen, in 2012, GL_ARB_texture_view came along and made 1397ec681f3SmrgGL_EXT_texture_sRGB_decode` simultaneously obsolete and very confusing. Now, 1407ec681f3Smrgthanks to the combination of extensions, you can upload a texture as linear, 1417ec681f3Smrgcreate an sRGB view of it and ask that sRGB not be decoded. What format is it 1427ec681f3Smrgin again? 1437ec681f3Smrg 1447ec681f3SmrgThe situation with render targets is a bit different. Historically, you got 1457ec681f3Smrgyour render target from the window system (which is always sRGB) and the spec 1467ec681f3Smrgsaid nothing whatsoever about encoding. All render targets were sRGB because 1477ec681f3Smrgthat's how monitors worked and application writers were expected to understand 1487ec681f3Smrgthat their final rendering needed to be in sRGB. However, with the advent of 1497ec681f3SmrgEXT_framebuffer_object this was no longer true. Also, sRGB was causing 1507ec681f3Smrgproblems with blending because GL was blind to the fact that the output was 1517ec681f3SmrgsRGB and blending was occurring in the wrong colorspace. In 2006, a set of 1527ec681f3SmrgEXT_framebuffer_sRGB extensions added support (on both the GL and window-system 1537ec681f3Smrgsides) for detecting whether a particular framebuffer was in sRGB and 1547ec681f3Smrginstructing GL to do the conversion into the sRGB colorspace as the final step 1557ec681f3Smrgprior to writing out to the render target. Enabling sRGB also implied that 1567ec681f3Smrgblending would occur in the linear colorspace prior to sRGB conversion and 1577ec681f3Smrgwould therefore be more accurate. When sRGB was added to the OpenGL ES spec in 1587ec681f3Smrg3.1, they added the query for sRGB but did not add the flag to allow you to 1597ec681f3Smrgturn it on and off. 1607ec681f3Smrg 1617ec681f3SmrgIn Vulkan, this is all much more straightforward. Your format is sRGB or it 1627ec681f3Smrgisn't. If you have an sRGB image and you don't want sRGB decoding to happen 1637ec681f3Smrgwhen you sample from it, you simply create a c:struct:`VkImageView` that has 1647ec681f3Smrgthe appropriate linear format and the data will be treated as linear and not 1657ec681f3Smrgconverted. Similarly for render targets, blending always happens in the same 1667ec681f3Smrgcolorspace as the shader output and you determine whether or not you want sRGB 1677ec681f3Smrgconversion by the format of the c:struct:`VkImageView` used as the render 1687ec681f3Smrgtarget. 1697ec681f3Smrg 1707ec681f3SmrgSurface Format Introspection API 1717ec681f3Smrg-------------------------------- 1727ec681f3Smrg 1737ec681f3SmrgISL provides an API for introspecting the :cpp:enum:`isl_format` enum and 1747ec681f3Smrggetting various bits of information about a format. ISL provides helpers for 1757ec681f3Smrgintrospecting both the data layout of an cpp:enum:`isl_format` and the 1767ec681f3Smrgcapabilities of that format for a particular piece of Intel hardware. 1777ec681f3Smrg 1787ec681f3SmrgFormat Layout Introspection 1797ec681f3Smrg^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1807ec681f3Smrg 1817ec681f3SmrgTo get the layout of a given :cpp:enum:`isl_format`, call 1827ec681f3Smrg:cpp:func:`isl_format_get_layout`: 1837ec681f3Smrg 1847ec681f3Smrg.. doxygenfunction:: isl_format_get_layout 1857ec681f3Smrg 1867ec681f3Smrg.. doxygenstruct:: isl_format_layout 1877ec681f3Smrg :members: 1887ec681f3Smrg 1897ec681f3Smrg.. doxygenstruct:: isl_channel_layout 1907ec681f3Smrg :members: 1917ec681f3Smrg 1927ec681f3SmrgThere are also quite a few helpers for many of the common cases that allow you 1937ec681f3Smrgto avoid using :cpp:struct:`isl_format_layout` manually. There are a lot of 1947ec681f3Smrgthem so we won't include a full list here. Look at isl.h for more details. 1957ec681f3Smrg 1967ec681f3SmrgHardware Format Support Introspection 1977ec681f3Smrg^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1987ec681f3Smrg 1997ec681f3SmrgThis is provided by means of a table located in isl_format.c. Looking at the 2007ec681f3Smrgtable directly is often useful for understanding HW support for various 2017ec681f3Smrgformats. However, for the purposes of code cleanliness, the table is not 2027ec681f3Smrgexposed directly and, instead, hardware support information is exposed via 2037ec681f3Smrga set of helper functions: 2047ec681f3Smrg 2057ec681f3Smrg.. doxygenfunction:: isl_format_supports_rendering 2067ec681f3Smrg.. doxygenfunction:: isl_format_supports_alpha_blending 2077ec681f3Smrg.. doxygenfunction:: isl_format_supports_sampling 2087ec681f3Smrg.. doxygenfunction:: isl_format_supports_filtering 2097ec681f3Smrg.. doxygenfunction:: isl_format_supports_vertex_fetch 2107ec681f3Smrg.. doxygenfunction:: isl_format_supports_typed_writes 2117ec681f3Smrg.. doxygenfunction:: isl_format_supports_typed_reads 2127ec681f3Smrg.. doxygenfunction:: isl_format_supports_ccs_d 2137ec681f3Smrg.. doxygenfunction:: isl_format_supports_ccs_e 2147ec681f3Smrg.. doxygenfunction:: isl_format_supports_multisampling 2157ec681f3Smrg.. doxygenfunction:: isl_formats_are_ccs_e_compatible 2167ec681f3Smrg 2177ec681f3SmrgSurface Format Enums 2187ec681f3Smrg-------------------- 2197ec681f3Smrg 2207ec681f3SmrgEverything in ISL is done in terms of the :cpp:enum:`isl_format` enum. However, 2217ec681f3Smrgfor the sake of interacting with other parts of Mesa, we provide a helper for 2227ec681f3Smrgconverting a :cpp:enum:`pipe_format` to an :cpp:enum:`isl_format`: 2237ec681f3Smrg 2247ec681f3Smrg.. doxygenfunction:: isl_format_for_pipe_format 2257ec681f3Smrg 2267ec681f3SmrgThe :cpp:enum:`isl_format` enum is as follows: 2277ec681f3Smrg 2287ec681f3Smrg.. doxygenenum:: isl_format 229