panfrost/docs: Document varyings

Signed-off-by: Lorenzo Rossi <lorenzo.rossi@collabora.com>
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Acked-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38681>
This commit is contained in:
Lorenzo Rossi 2026-03-05 15:40:48 +01:00 committed by Marge Bot
parent 51f8bf028b
commit f9819925ca

View file

@ -0,0 +1,110 @@
Varyings
========
This is the naming convention followed by the hardware (slightly different
from Vulkan naming):
- "Attribute": per-vertex data
- "Varying": per-fragment data
Thus vertex shaders always interact with attributes and fragment/pixel shaders
only interact with varyings (commonly shortened to "VAR").
Hardware descriptors
====================
Before Valhall there were two types of hardware descriptors:
- ``AttributeDescriptor``: Descriptor for a single attribute in a larger buffer,
contains offset, stride and the in-memory format.
- ``BufferDescriptor``: Buffer, when used for attributes and varyings it
contains: pointer, size and stride
Midgard (v5)
============
Attributes are loaded/stored using ``LD_ATTR``/``ST_ATTR``, those query the
attribute descriptors and buffer descriptors to find the real global memory
offset before loading/storing.
All varyings are loaded using ``LD_VAR``, including flat attributes (using a
modifier), and special attributes (position, psiz, ecc...). Special attributes
require a special descriptor, that is not backed by any buffer, it generates
data on-the-fly.
There is a concept of in-memory format and register format, the first is written
inside of the ``AttributeDescriptor`` while the register format is a modifier of
the instructions, when those two disagree the hardware will try to convert them,
this is only supported between int-int or float-float operations.
Bifrost (v6)
============
Changes:
- ``ST_ATTR`` is replaced by ``LEA_ATTR`` and ``ST_CVT`` pairs.
- ``LEA_ATTR`` queries memory address and format from the appropriate
descriptor.
- ``ST_CVT`` performs the actual conversion and memory store.
- A new ``LD_VAR_SPECIAL`` is introduced, now special attributes do not need
special descriptors.
- ``LD_VAR`` only handles interpolated varyings, flat varyings are now handled
by ``LD_VAR_FLAT``.
Valhall (v9)
============
Valhall introduced layout-specific instructions, ``LEA_BUF`` and ``LD_VAR_BUF``,
those do not use ``AttributeDescriptor`` but read ``BufferDescriptor`` directly.
These new instructions bake the offset and in-memory format of the attribute
inside of the shader code itself, saving a lookup. If all shaders in a program
use those instructions, we can remove all ``AttributeDescriptor``. If the
shaders aren't compiled together, one of the shaders cannot know the data layout,
and it needs to fall back to the old ``AttributeDescriptor``-based path. We
also have to fall back to ``AttributeDescriptor`` completely if the attribute
offset overflows the immediate field.
``LD_VAR_BUF`` only supports ``.f16`` and ``.f32`` as register modifiers, we can
also load (flat) ints with those. We need to specify no conversion
(``.f16.src_flat16`` or ``.f32.src_flat32``), but with those we can load both
16-bit and 32-bit integers.
In this architecture the descriptors got a major update too and now there is
just one set of descriptors for both the VS and FS.
Challenges
==========
Theoretically, the output types from the VS and input types from the FS should
always agree. In practice we cannot always trust the varyings types given to us,
here are some challenging examples:
* Shaders are allowed to use the same types with different precision modifiers.
* ``nir_opt_varying`` erases highp flat types with "float32" and packs them
together.
* Some games like to play with ``intBitsToFloat`` / ``floatBitsToInt``, so it's
possible to have VS write int and FS read float (in that case, we treat the
underlying bits as float, allowing for NaN normalization)
In practice you have to follow these rules:
* Only FS knows a varying smoothness, VS sees everything as flat.
* When linked together, you cannot trust highp flat types, but you can trust
precision
* While loading/storing data, mistaking a float for an int is ok, mistaking an
int for a float seems to be lossy even without bit-size conversions. Be
conservative on what you say is a float.
* You cannot lower flat varyings after they passed through ``nir_opt_varying``
Current implementation rules:
* VS decides the memory layout
* On v9+, FS decides the descriptor formats, VS uses auto32 for 32-bit types
* On v7-, descriptor formats can mismatch (VS int - FS float)
* Descriptor formats always match what the instructions are using (unless V9
auto32)
To regain the type information:
* in VS, every highp varying is written as U32
* in FS, highp flat varyings are read as U32, highp smooth are read as F32
* for mediump, we trust the original type