diff --git a/docs/drivers/panfrost/varyings.rst b/docs/drivers/panfrost/varyings.rst new file mode 100644 index 00000000000..52a2a145f00 --- /dev/null +++ b/docs/drivers/panfrost/varyings.rst @@ -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