• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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