mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2024-12-04 15:44:06 +08:00
docs/isl: Document ISL's units
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11366>
This commit is contained in:
parent
d07ec294bb
commit
3894e42590
@ -6,6 +6,11 @@ surface layout calculations for Intel graphics drivers. It was originally
|
||||
written by Chad Versace and is now maintained by Jason Ekstrand and Nanley
|
||||
Chery.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
units
|
||||
|
||||
The core representation of a surface in ISL is :cpp:struct:`isl_surf`.
|
||||
|
||||
.. doxygenstruct:: isl_surf
|
||||
|
81
docs/isl/units.rst
Normal file
81
docs/isl/units.rst
Normal file
@ -0,0 +1,81 @@
|
||||
Units
|
||||
=====
|
||||
|
||||
Almost every variable, function parameter, or struct field in ISL that carries
|
||||
a numeric value has explicit units associated with it. The units used in ISL
|
||||
are as follows:
|
||||
|
||||
* Pixels (px)
|
||||
* Samples (sa)
|
||||
* Elements (el)
|
||||
* Tiles (tl)
|
||||
* Bytes (B)
|
||||
* Rows of some other unit size (<unit>_rows)
|
||||
|
||||
These units are fundamental to ISL because they allow us to specify information
|
||||
about a surface in a canonical way that isn't dependent on hardware generation.
|
||||
Each field in an ISL data structure that stores any sort of dimension has a
|
||||
suffix that declares the units for that particular value: ":c:expr:`_el`" for
|
||||
elements, ":c:expr:`_sa`" for samples, etc. If the units of the particular
|
||||
field aren't quite what is wanted by the hardware, we do the conversion when we
|
||||
emit :c:expr:`RENDER_SURFACE_STATE`.
|
||||
|
||||
This is one of the primary differences between ISL and the old miptree code and
|
||||
one of the core design principles of ISL. In the old miptree code, we tried to
|
||||
keep everything in the same units as the hardware expects but this lead to
|
||||
unnecessary complications as the hardware evolved. One example of this
|
||||
difference is QPitch which specifies the distance between array slices. On
|
||||
Broadwell and earlier, QPitch field in :c:expr:`RENDER_SURFACE_STATE` was in
|
||||
rows of samples. For block-compressed images, this meant it had to be
|
||||
a multiple of the block height. On Skylake, it changed to always being in rows
|
||||
of elements so you have to divide the pitch in samples by the compresssion
|
||||
block height. Since the old surface state code tries to store things in
|
||||
hardware units, everyone who ever reads :cpp:expr:`brw_mipmap_tree::qpitch` has
|
||||
to change their interpretation based on hardware generation and whether or not
|
||||
the surface was block-compressed. In ISL, we have
|
||||
:cpp:member:`isl_surf::array_pitch_el_rows` which, as the name says, is in rows
|
||||
of elements. On Broadwell and earlier, we have to multiply by the block size
|
||||
of the texture when we finally fill out the hardware packet. However, the
|
||||
consistency of always being in rows of elements makes any other users of the
|
||||
field much simpler because they never have to look at hardware generation or
|
||||
whether or not the image is block-compressed.
|
||||
|
||||
**Pixels** are the most straightforward unit and are where everything starts. A
|
||||
pixel simply corresponds to a single pixel (or texel if you prefer) in the
|
||||
surface. For multisampled surfaces, a pixel may contain one or more samples.
|
||||
For compressed textures, a compression block may contain one or more pixels.
|
||||
When initially creating a surface, everything passed to isl_surf_init is
|
||||
implicitly in terms of pixels because this is what all of the APIs use.
|
||||
|
||||
The next unit in ISL's repertoire is **samples**. In a multisampled surface,
|
||||
each pixel corresponds to some number of samples given by
|
||||
:cpp:member:`isl_surf::samples`. The exact layout of the samples depends on
|
||||
the value of :cpp:member:`isl_surf::msaa_layout`. If the layout is
|
||||
:cpp:enumerator:`ISL_MSAA_LAYOUT_ARRAY` then each logical array in the surface
|
||||
corresponds to :cpp:member:`isl_surf::samples` actual slices
|
||||
in the resulting surface, one per array slice. If the layout is
|
||||
:cpp:enumerator:`ISL_MSAA_LAYOUT_INTERLEAVED` then each pixel corresponds to a
|
||||
2x1, 2x2, 4x2, or 4x4 grid of samples. In order to aid in calculations, one of
|
||||
the first things ISL does is to compute :cpp:member:`isl_surf::phys_level0_sa`
|
||||
which gives the dimensions of the base miplevel of the surface in samples. The
|
||||
type of :cpp:member:`isl_surf::phys_level0_sa` is :cpp:struct:`isl_extent4d`
|
||||
which allows us to express both the array and interleaved cases. Most of the
|
||||
calculations of how the different miplevels and array slices are laid out is
|
||||
done in terms of samples.
|
||||
|
||||
Next, we have surface **elements**. An element is the basic unit of actual
|
||||
surface memory. For multisampled textures, an element is equal to a single
|
||||
sample. For block compressed textures, an element corresponds to an entire
|
||||
compression block. The conversion from samples to elements is given by dividing
|
||||
by the block width and block height of the surface format. This is true
|
||||
regardless of whether or not the surface is multisampled; for multisampled
|
||||
compressed textures (these exist for certain auxiliary formats), the block
|
||||
width and block height are expressed in samples. Pixels cannot be converted
|
||||
directly to elements or vice versa; any conversion between pixels and elements
|
||||
*must* go through samples.
|
||||
|
||||
The final surface unit is **tiles**. A tile is a large rectangular block of
|
||||
surface data that all fits in a single contiguous block of memory (usually a 4K
|
||||
or 64K page, depending on tile format). Tiles are used to provide an
|
||||
arrangement of the data in memory that yields better cache performance. The
|
||||
size of a tile is always specified in surface elements.
|
Loading…
Reference in New Issue
Block a user