1Units 2===== 3 4Almost every variable, function parameter, or struct field in ISL that carries 5a numeric value has explicit units associated with it. The units used in ISL 6are as follows: 7 8 * Pixels (px) 9 * Samples (sa) 10 * Elements (el) 11 * Tiles (tl) 12 * Bytes (B) 13 * Rows of some other unit size (<unit>_rows) 14 15These units are fundamental to ISL because they allow us to specify information 16about a surface in a canonical way that isn't dependent on hardware generation. 17Each field in an ISL data structure that stores any sort of dimension has a 18suffix that declares the units for that particular value: ":c:expr:`_el`" for 19elements, ":c:expr:`_sa`" for samples, etc. If the units of the particular 20field aren't quite what is wanted by the hardware, we do the conversion when we 21emit :c:expr:`RENDER_SURFACE_STATE`. 22 23This is one of the primary differences between ISL and the old miptree code and 24one of the core design principles of ISL. In the old miptree code, we tried to 25keep everything in the same units as the hardware expects but this lead to 26unnecessary complications as the hardware evolved. One example of this 27difference is QPitch which specifies the distance between array slices. On 28Broadwell and earlier, QPitch field in :c:expr:`RENDER_SURFACE_STATE` was in 29rows of samples. For block-compressed images, this meant it had to be 30a multiple of the block height. On Skylake, it changed to always being in rows 31of elements so you have to divide the pitch in samples by the compresssion 32block height. Since the old surface state code tries to store things in 33hardware units, everyone who ever reads :cpp:expr:`brw_mipmap_tree::qpitch` has 34to change their interpretation based on hardware generation and whether or not 35the surface was block-compressed. In ISL, we have 36:cpp:member:`isl_surf::array_pitch_el_rows` which, as the name says, is in rows 37of elements. On Broadwell and earlier, we have to multiply by the block size 38of the texture when we finally fill out the hardware packet. However, the 39consistency of always being in rows of elements makes any other users of the 40field much simpler because they never have to look at hardware generation or 41whether or not the image is block-compressed. 42 43**Pixels** are the most straightforward unit and are where everything starts. A 44pixel simply corresponds to a single pixel (or texel if you prefer) in the 45surface. For multisampled surfaces, a pixel may contain one or more samples. 46For compressed textures, a compression block may contain one or more pixels. 47When initially creating a surface, everything passed to isl_surf_init is 48implicitly in terms of pixels because this is what all of the APIs use. 49 50The next unit in ISL's repertoire is **samples**. In a multisampled surface, 51each pixel corresponds to some number of samples given by 52:cpp:member:`isl_surf::samples`. The exact layout of the samples depends on 53the value of :cpp:member:`isl_surf::msaa_layout`. If the layout is 54:cpp:enumerator:`ISL_MSAA_LAYOUT_ARRAY` then each logical array in the surface 55corresponds to :cpp:member:`isl_surf::samples` actual slices 56in the resulting surface, one per array slice. If the layout is 57:cpp:enumerator:`ISL_MSAA_LAYOUT_INTERLEAVED` then each pixel corresponds to a 582x1, 2x2, 4x2, or 4x4 grid of samples. In order to aid in calculations, one of 59the first things ISL does is to compute :cpp:member:`isl_surf::phys_level0_sa` 60which gives the dimensions of the base miplevel of the surface in samples. The 61type of :cpp:member:`isl_surf::phys_level0_sa` is :cpp:struct:`isl_extent4d` 62which allows us to express both the array and interleaved cases. Most of the 63calculations of how the different miplevels and array slices are laid out is 64done in terms of samples. 65 66Next, we have surface **elements**. An element is the basic unit of actual 67surface memory. For multisampled textures, an element is equal to a single 68sample. For block compressed textures, an element corresponds to an entire 69compression block. The conversion from samples to elements is given by dividing 70by the block width and block height of the surface format. This is true 71regardless of whether or not the surface is multisampled; for multisampled 72compressed textures (these exist for certain auxiliary formats), the block 73width and block height are expressed in samples. Pixels cannot be converted 74directly to elements or vice versa; any conversion between pixels and elements 75*must* go through samples. 76 77The final surface unit is **tiles**. A tile is a large rectangular block of 78surface data that all fits in a single contiguous block of memory (usually a 4K 79or 64K page, depending on tile format). Tiles are used to provide an 80arrangement of the data in memory that yields better cache performance. The 81size of a tile is always specified in surface elements. 82