mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-10-31 10:58:03 +03:00
init
This commit is contained in:
12511 files changed
+6156641
No files matched your search
@@ -0,0 +1,134 @@
|
||||
|
||||
External Hardware Documentation and Resources
|
||||
=============================================
|
||||
|
||||
Information about hardware behavior comes from a mix of official and
|
||||
reverse-engineered sources.
|
||||
|
||||
Command buffers
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
* `NVIDIA open-gpu-doc repository`_ is official documentation from NVIDIA that
|
||||
has been released to the public. The majority of this documentation comes in
|
||||
the form of class headers which describe the class state registers.
|
||||
|
||||
* `NVIDIA open-gpu-kernel-modules repository`_ is the open-source kernel mode
|
||||
driver that NVIDIA ships on Turing+ GPUs with GSP. The code here can provide
|
||||
examples of how to use some hardware features. If open-gpu-doc is missing a
|
||||
class header, sometimes there will be one here.
|
||||
|
||||
* Reverse-engineered command names from `envytools`_ are available in mesa
|
||||
under eg. ``src/gallium/drivers/nouveau/nvc0/nvc0_3d.xml.h``. These are no
|
||||
longer updated. nvk instead uses the open-gpu-doc headers
|
||||
|
||||
* `envyhooks`_ is the modern way to dump command sequences from the proprietary
|
||||
driver
|
||||
|
||||
* ``nv_push_dump`` is part of mesa and can disassemble command sequences (build
|
||||
with ``-D tools=nouveau``, run ``src/nouveau/headers/nv_push_dump`` from the
|
||||
build dir)
|
||||
|
||||
.. _NVIDIA open-gpu-doc repository: https://github.com/NVIDIA/open-gpu-doc
|
||||
.. _NVIDIA open-gpu-kernel-modules repository: https://github.com/NVIDIA/open-gpu-kernel-modules
|
||||
.. _envyhooks: https://gitlab.freedesktop.org/nouveau/envyhooks
|
||||
|
||||
Shader ISA
|
||||
^^^^^^^^^^
|
||||
|
||||
* `NVIDIA PTX documentation`_ is NVIDIA documentation for CUDA's
|
||||
intermediate representation. We don't use PTX directly, but this often has
|
||||
hints about how underlying hardware instructions work. For example, the PTX
|
||||
`redux` instruction is pretty much identical to the hardware instruction of
|
||||
the same name.
|
||||
|
||||
* `CUDA Binary Utilities`_ is documentation for CUDA's disassembler,
|
||||
`nvdisasm`. It includes a brief description of most hardware instructions.
|
||||
There's also an `older version`_ that has older architectures (Kepler through
|
||||
Volta).
|
||||
|
||||
* Kuter Dinel has reverse-engineered instruction encodings for the `Hopper
|
||||
ISA`_ and `Ada ISA`_ which are autogenerated from his `nv_isa_solver`_
|
||||
project.
|
||||
|
||||
* `nv-shader-tools`_ has some additional tools for disassembling and fuzzing
|
||||
the hardware ISA
|
||||
|
||||
* Mel has dumped a `list of avaiable instructions`_ and their opcodes on recent
|
||||
architectures by scraping nvdisasm error messages.
|
||||
|
||||
* The `Volta whitepaper`_ section "Independent Thread Scheduling" has an
|
||||
overview of the control flow model used on Volta+ GPUs.
|
||||
|
||||
* `Dissecting the NVidia Turing T4 GPU via Microbenchmarking`_ has
|
||||
reverse-engineered info about the Turing instruction encoding. See especially
|
||||
section "2.1 Control information" for an overview of compiler-inserted delays
|
||||
and waits on Maxwell and later.
|
||||
|
||||
* `Analyzing Modern NVIDIA GPU cores`_ has additional reverse-engineered info
|
||||
about the semantics of compiler-inserted delays and waits.
|
||||
|
||||
* `Control Flow Management in Modern GPUs`_ has more detail about control flow
|
||||
reconvergence on Volta+
|
||||
|
||||
* `maxas`_ has some reverse-engineered info on the Maxwell ISA
|
||||
|
||||
* `asfermi`_ has some reverse-engineered info on the older Fermi ISA
|
||||
|
||||
* Red Hat has some NDA'd documentation on instruction latencies from NVIDIA.
|
||||
Bother karolherbst or airlied on irc if you're missing a latency class for an
|
||||
instruction on recent architectures.
|
||||
|
||||
* Behavior of instructions are tested using the hardware tests in
|
||||
``src/nouveau/compiler/nak/hw_tests.rs`` and the corresponding ``Foldable``
|
||||
implementations in ``src/nouveau/compiler/nak/ir.rs`` (build with ``-D
|
||||
build-tests=true`` and run ``src/nouveau/compiler/nak hw_tests`` from the
|
||||
build dir)
|
||||
|
||||
* NAK's instruction encodings are tested against nvdisasm using
|
||||
``src/nouveau/compiler/nak/nvdisasm_tests.rs`` (build with ``-D
|
||||
build-tests=true`` and run ``src/nouveau/compiler/nak nvdisasm_tests`` from
|
||||
the build dir)
|
||||
|
||||
* The old GL driver's compiler, under ``src/gallium/drivers/nouveau/codegen``,
|
||||
has some information. This is especially useful for graphics-only
|
||||
instructions, which are often not covered by other sources.
|
||||
|
||||
* `Compiler explorer`_ is a convenient tool to see what assembly NVIDIA
|
||||
generates for a given CUDA program.
|
||||
|
||||
.. _NVIDIA PTX documentation: https://docs.nvidia.com/cuda/parallel-thread-execution/index.html
|
||||
.. _CUDA Binary Utilities: https://docs.nvidia.com/cuda/cuda-binary-utilities/index.html#instruction-set-reference
|
||||
.. _older version: https://docs.nvidia.com/cuda/archive/11.8.0/cuda-binary-utilities/index.html#instruction-set-ref
|
||||
.. _Hopper ISA: https://kuterdinel.com/nv_isa/
|
||||
.. _Ada ISA: https://kuterdinel.com/nv_isa_sm89/
|
||||
.. _nv_isa_solver: https://github.com/kuterd/nv_isa_solver
|
||||
.. _nv-shader-tools: https://gitlab.freedesktop.org/nouveau/nv-shader-tools
|
||||
.. _list of avaiable instructions: https://gitlab.freedesktop.org/mhenning/re/-/tree/main/opclass?ref_type=heads
|
||||
.. _Volta whitepaper: https://images.nvidia.com/content/volta-architecture/pdf/volta-architecture-whitepaper.pdf
|
||||
.. _Dissecting the NVidia Turing T4 GPU via Microbenchmarking: https://arxiv.org/pdf/1903.07486
|
||||
.. _Analyzing Modern NVIDIA GPU cores: https://arxiv.org/pdf/2503.20481
|
||||
.. _Control Flow Management in Modern GPUs: https://arxiv.org/pdf/2407.02944
|
||||
.. _maxas: https://github.com/NervanaSystems/maxas/wiki
|
||||
.. _asfermi: https://github.com/hyqneuron/asfermi/wiki
|
||||
.. _Compiler explorer: https://godbolt.org/z/1jrfhq5G7
|
||||
|
||||
Misc
|
||||
^^^^
|
||||
|
||||
* `envytools`_ has reverse-engineered documentation for maxwell and earlier
|
||||
hardware.
|
||||
* The nvidia architecture whitepapers give a basic overview of what has changed
|
||||
between hardware revisions. See eg. the `Blackwell whitepaper`_
|
||||
* The nvidia architecture tuning guides often mention how details of a hardware
|
||||
generation has changed, often with information about the memory subsystem or
|
||||
occupancy. See eg. the `Blackwell tuning guide`_
|
||||
* `The Nouveau wiki's CodeNames page`_ is useful for mapping NVIDIA marketing
|
||||
names to engineering names
|
||||
* `Matching CUDA arch and CUDA gencode for various NVIDIA architectures`_ has a
|
||||
useful table comparing SM versions to engineering names
|
||||
|
||||
.. _envytools: https://envytools.readthedocs.io/en/latest/hw/index.html
|
||||
.. _Blackwell whitepaper: https://images.nvidia.com/aem-dam/Solutions/geforce/blackwell/nvidia-rtx-blackwell-gpu-architecture.pdf
|
||||
.. _Blackwell tuning guide: https://docs.nvidia.com/cuda/blackwell-tuning-guide/index.html
|
||||
.. _The Nouveau wiki's CodeNames page: https://nouveau.freedesktop.org/CodeNames.html
|
||||
.. _Matching CUDA arch and CUDA gencode for various NVIDIA architectures: https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
Hardware docs
|
||||
=============
|
||||
|
||||
Command buffers
|
||||
---------------
|
||||
|
||||
Command format
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Each command sent to the GPU contains a method and some data. Method names are
|
||||
documented in corresponding header files copied from NVIDIA, eg. the fermi
|
||||
graphics methods are in src/nouveau/headers/nvidia/classes/cl9097.h
|
||||
|
||||
P_IMMD
|
||||
""""""
|
||||
|
||||
A lot of the time, you will want to issue a single method with its data, which
|
||||
can be done with P_IMMD::
|
||||
|
||||
P_IMMD(p, NV9097, WAIT_FOR_IDLE, 0);
|
||||
|
||||
P_IMMD will emit either a single `immediate-data method`_, which takes a single
|
||||
word, or a pair of words that's equivalent to P_MTHD + the provided data. Code
|
||||
must count P_IMMD as possibly 2 words as a result.
|
||||
|
||||
.. _immediate-data method: https://github.com/NVIDIA/open-gpu-doc/blob/87ba53e0c385285a3aa304b864dccb975a9a0dd4/manuals/turing/tu104/dev_ram.ref.txt#L1214
|
||||
|
||||
P_MTHD
|
||||
""""""
|
||||
|
||||
`P_MTHD`_ is a convenient way to execute multiple consecutive methods without
|
||||
repeating the method header. For example, the code::
|
||||
|
||||
P_MTHD(p, NV9097, SET_REPORT_SEMAPHORE_A);
|
||||
P_NV9097_SET_REPORT_SEMAPHORE_A(p, addr >> 32);
|
||||
P_NV9097_SET_REPORT_SEMAPHORE_B(p, addr);
|
||||
P_NV9097_SET_REPORT_SEMAPHORE_C(p, value);
|
||||
|
||||
generates four words - one word for the method header (defaulting to 1INC) and
|
||||
then the next three words for data. 1INC will automatically increment the method
|
||||
id by one word for each data value, which is why the example can advance from
|
||||
SET_REPORT_SEMAPHORE_A to B to C.
|
||||
|
||||
.. _P_MTHD: https://github.com/NVIDIA/open-gpu-doc/blob/87ba53e0c385285a3aa304b864dccb975a9a0dd4/manuals/turing/tu104/dev_ram.ref.txt#L1042
|
||||
|
||||
P_0INC
|
||||
""""""
|
||||
|
||||
`0INC`_ will issue the same method repeatedly for each following data word.
|
||||
|
||||
.. _0INC: https://github.com/NVIDIA/open-gpu-doc/blob/87ba53e0c385285a3aa304b864dccb975a9a0dd4/manuals/turing/tu104/dev_ram.ref.txt#L1096
|
||||
|
||||
P_1INC
|
||||
""""""
|
||||
|
||||
`1INC`_ will increment after one word and then issue the following method
|
||||
repeatedly. For example, the code::
|
||||
|
||||
P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_SET_PRIV_REG));
|
||||
P_INLINE_DATA(p, 0);
|
||||
P_INLINE_DATA(p, BITFIELD_BIT(3));
|
||||
|
||||
issues one NV9097_CALL_MME_MACRO command, then increments the method and issues
|
||||
two NV9097_CALL_MME_DATA commands.
|
||||
|
||||
.. _1INC: https://github.com/NVIDIA/open-gpu-doc/blob/87ba53e0c385285a3aa304b864dccb975a9a0dd4/manuals/turing/tu104/dev_ram.ref.txt#L1149
|
||||
|
||||
Execution barriers
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Commands within a command buffer can be synchronized in a few different ways.
|
||||
|
||||
* Explicit WFI - Idles all engines before executing the next command eg. via
|
||||
`NVA16F_WFI` or `NV9097_WAIT_FOR_IDLE`
|
||||
* Semaphores - Delay execution based on values in a memory location. See
|
||||
`open-gpu-doc on semaphores`_
|
||||
* A subchannel switch - Causes the hardware to execute an implied WFI
|
||||
|
||||
.. _open-gpu-doc on semaphores: https://github.com/NVIDIA/open-gpu-doc/blob/master/manuals/turing/tu104/dev_pbdma.ref.txt#L3231
|
||||
|
||||
Subchannel switches
|
||||
"""""""""""""""""""
|
||||
|
||||
A subchannel switch occurs when the hardware receives a command for a different
|
||||
subchannel than the one that it's currently executing. For example, if the
|
||||
hardware is currently executing commands on the 3D engine (`SUBC_NV9097 == 0`), a
|
||||
command executed on the compute engine (`SUBC_NV90C0 == 1`) will cause a
|
||||
subchannel switch. Host methods (class \*6F) are an exception to this - they can
|
||||
be issued to any subchannel and will not trigger a subchannel switch
|
||||
[#fhostsubcswitch]_ [#foverlapnvk]_.
|
||||
|
||||
Subchannel switches act the same way that an explicit WFI does - they fully idle
|
||||
the channel before issuing commands to the next engine [#fnsight]_
|
||||
[#foverlapnvk]_.
|
||||
|
||||
This works the same on Blackwell. Some NVIDIA documentation contradicts this:
|
||||
"On NVIDIA Blackwell Architecture GPUs and newer, subchannel switches do not
|
||||
occur between 3D and compute workloads"[#fnsight]_. This documentation appears
|
||||
to be wrong or inapplicable for some reason - tests do not reproduce this
|
||||
behavior [#foverlapnvk]_ [#foverlapprop]_, and the blob does not change its
|
||||
event implementation for blackwell [#feventprop]_.
|
||||
|
||||
|
||||
.. [#fnsight] https://docs.nvidia.com/nsight-graphics/UserGuide/gpu-trace-ui.html#subchannel-switch-overlay
|
||||
.. [#foverlapnvk] Based on reverse engineering by running
|
||||
https://gitlab.freedesktop.org/mhenning/re/-/tree/main/vk_test_overlap_exec
|
||||
under nvk, possibly with alterations to the way nvk generates commands for
|
||||
pipeline barriers.
|
||||
.. [#foverlapprop] By running
|
||||
https://gitlab.freedesktop.org/mhenning/re/-/tree/main/vk_test_overlap_exec
|
||||
under the proprietary driver and examining the main output (eg. execution
|
||||
overlaps without pipeline barriers)
|
||||
.. [#feventprop] For example, the event commands generated here only wait on a
|
||||
single engine
|
||||
https://gitlab.freedesktop.org/mhenning/re/-/blob/6ce8c860da65fbf2ab26d124d25f907dea2cf33a/vk_event/blackwell.out#L20612-20793
|
||||
.. [#fhostsubcswitch] https://github.com/NVIDIA/open-gpu-doc/blob/87ba53e0c385285a3aa304b864dccb975a9a0dd4/manuals/turing/tu104/dev_ram.ref.txt#L1009
|
||||
|
||||
Copy engine
|
||||
^^^^^^^^^^^
|
||||
|
||||
The copy engine's `PIPELINED` mode allows a new transfer to start before the
|
||||
previous transfer finishes, while `NON_PIPELINED` acts as an execution barrier
|
||||
between the current copy and the previous one [#fpipelined]_.
|
||||
|
||||
.. [#fpipelined] https://github.com/NVIDIA/open-gpu-kernel-modules/blob/2b436058a616676ec888ef3814d1db6b2220f2eb/src/common/sdk/nvidia/inc/ctrl/ctrl0050.h#L75-L83
|
||||
@@ -0,0 +1,66 @@
|
||||
ISBE Layout
|
||||
=============================================
|
||||
|
||||
The ISBE is a piece of staging memory shared between the :abbr:`PE (Primitive Engine)`
|
||||
and :abbr:`SM (Streaming Multiprocessor)` containing the attributes for
|
||||
:abbr:`VTG (Vertex, Tesselation, Geometry)` stages.
|
||||
|
||||
In normal cases, no shader needs to access it and instead use ``ALD`` or ``AST``
|
||||
but in some some cases (like ``ALD`` vtx handling or mesh shaders) direct access to
|
||||
it is necessary.
|
||||
|
||||
This document the observations made about the layout of it.
|
||||
|
||||
The ISBE "space" is separated in multiple regions (map, patch, primitive and attribute)
|
||||
and can be accessed with ``ISBERD`` and ``ISBEWR`` instructions.
|
||||
|
||||
There is always two ISBE "space" present: one for inputs and one for outputs.
|
||||
Input and output ISBE memory can be shared by setting bit 25 of the
|
||||
:abbr:`SPH (Shader Program Header)`.
|
||||
|
||||
**NOTE**: Before Turing, only ``ISBERD`` was supported with the ``.MAP`` flag.
|
||||
|
||||
Map region
|
||||
""""""""""
|
||||
|
||||
The Map region contains all the vertex indices for all primitives.
|
||||
|
||||
When used as output, it starts with the primitives count.
|
||||
|
||||
==================================================== ==================== ===================================================
|
||||
Byte Range Name Note
|
||||
==================================================== ==================== ===================================================
|
||||
0x0 primitive_count 32-bit, Only present as output ISBE
|
||||
0x0?..(0x0? + primitive_count * $vtx_per_prim_count) primitive_indices[i] 8-bit, Offset is 0x04 as output ISBE otherwise 0x00
|
||||
==================================================== ==================== ===================================================
|
||||
|
||||
Attribute region
|
||||
""""""""""""""""
|
||||
|
||||
The Attribute region contains all attributes and is allocated based on the
|
||||
:abbr:`SPH (Shader Program Header)` input/output mask and :doc:`mesh shader methods <mesh_shading_notes>`.
|
||||
|
||||
With the ``SKEW`` flag applied on ``ISBERD`` and ``ISBEWR``, each type of attribute is packed with
|
||||
32 values of the same type forming "memory lines" of 128 bytes each.
|
||||
|
||||
Additionally, the order of the attribute packs is determined by the unique attribute id.
|
||||
(see `nak_attr` or :abbr:`SPH (Shader Program Header)` headers definitions for the values)
|
||||
|
||||
Finally, if more than 32 values are needed, the layout repeat itself.
|
||||
|
||||
Here is an example for 256 vertices being defined with ``ATTR_POINT_SIZE`` (0x6C) and
|
||||
``ATTR_POSITION_X`` (0x70) active:
|
||||
|
||||
==================================================== ========================
|
||||
Byte Range Name
|
||||
==================================================== ========================
|
||||
0x000..0x080 ATTR_POINT_SIZE[0..31]
|
||||
0x000..0x100 ATTR_POSITION_X[0..31]
|
||||
0x180..0x200 ATTR_POINT_SIZE[32..63]
|
||||
0x200..0x280 ATTR_POSITION_X[32..63]
|
||||
0x280..0x300 ATTR_POINT_SIZE[63..95]
|
||||
0x300..0x380 ATTR_POSITION_X[63..95]
|
||||
... ...
|
||||
0x700..0x780 ATTR_POINT_SIZE[224..255]
|
||||
0x780..0x800 ATTR_POSITION_X[224..255]
|
||||
==================================================== ========================
|
||||
@@ -0,0 +1,159 @@
|
||||
Mesh Shading Notes
|
||||
=============================================
|
||||
|
||||
Mesh shaders support is present on Turing and later.
|
||||
It reuses the 3D engine and regular graphics stages.
|
||||
|
||||
Draw
|
||||
""""
|
||||
|
||||
When performing a draw with a mesh shader bound, ``SET_DRAW_CONTROL_A`` needs to
|
||||
be used while ignoring the base indices.
|
||||
|
||||
This can be done with the following commands:
|
||||
.. code-block::
|
||||
|
||||
NVC597_SET_VERTEX_ID_BASE
|
||||
.V = (0x0)
|
||||
NVC597_SET_DRAW_CONTROL_A
|
||||
.TOPOLOGY = POINTS
|
||||
.PRIMITIVE_ID = FIRST
|
||||
.INSTANCE_ID = FIRST
|
||||
.SPLIT_MODE = NORMAL_BEGIN_NORMAL_END
|
||||
.INSTANCE_ITERATE_ENABLE = FALSE
|
||||
.IGNORE_GLOBAL_BASE_VERTEX_INDEX = TRUE
|
||||
.IGNORE_GLOBAL_BASE_INSTANCE_INDEX = TRUE
|
||||
NVC597_DRAW_VERTEX_ARRAY_BEGIN_END_A
|
||||
.START = (0x0)
|
||||
NVC597_DRAW_VERTEX_ARRAY_BEGIN_END_B
|
||||
.COUNT = ($groupCount)
|
||||
|
||||
|
||||
Where:
|
||||
|
||||
- ``$groupCount`` is the number of local workgroups to dispatch.
|
||||
|
||||
**NOTE**: The topology of ``SET_DRAW_CONTROL_A`` will be ignored and
|
||||
``SET_MESH_SHADER_A`` topology will be used.
|
||||
|
||||
Stages
|
||||
""""""
|
||||
|
||||
Before binding a task or mesh shader, ``SET_MESH_CONTROL`` needs to be set.
|
||||
|
||||
Shared Memory
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Shared memory is allocated in the output :doc:`ISBE Attribute region <isbe_layout>` after all attributes.
|
||||
|
||||
Part of the shared memory can be made accessible to the next stage
|
||||
as part of the input :doc:`ISBE Attribute region <isbe_layout>` using ``.OUTPUT_TO_M_S_LINES``.
|
||||
|
||||
As such, the task payload is the first part of the shared memory on the task stage.
|
||||
|
||||
|
||||
Task
|
||||
^^^^
|
||||
|
||||
The task shader is always bound as a vertex shader.
|
||||
|
||||
Additionally, ``SET_MESH_INIT_SHADER`` is used to set the number of local invocations
|
||||
to use and the size used for shared memory.
|
||||
|
||||
This can be done with the following command:
|
||||
::
|
||||
|
||||
NVC597_SET_MESH_INIT_SHADER
|
||||
.THREAD_COUNT = ($thread_count)
|
||||
.LOCAL_BUFFER_LINES = ($local_buffer_lines)
|
||||
.OUTPUT_TO_M_S_LINES = ($output_to_m_s_lines)
|
||||
|
||||
Where:
|
||||
|
||||
- ``$thread_count`` is the number of local invocations (up to 32).
|
||||
- ``$local_buffer_lines`` is the total amount of shared memory lines (including task payload)
|
||||
to allocate in the output :doc:`ISBE Attribute region <isbe_layout>` after all attributes.
|
||||
- ``$output_to_m_s_lines`` is the total amount of shared memory lines that will be available
|
||||
to the next stage.
|
||||
|
||||
**NOTE**: The size of a memory line is 128 bytes.
|
||||
|
||||
The workgroup_index is implemented using the ``VERTEX_ID`` read from the input :doc:`ISBE Attribute region <isbe_layout>` (with SKEW applied).
|
||||
|
||||
``EmitMeshTasksEXT`` is lowered to the equivalent pseudo code:
|
||||
::
|
||||
|
||||
void EmitMeshTasksEXT(uint x, uint y, uint z) {
|
||||
uint taskCount = x * y * z;
|
||||
|
||||
ISBEWR.O.ATTR.32 [0x04], taskCount;
|
||||
ISBEWR.O.ATTR.32 [0x08], x;
|
||||
ISBEWR.O.ATTR.32 [0x0C], y;
|
||||
ISBEWR.O.ATTR.32 [0x10], z;
|
||||
}
|
||||
|
||||
Mesh
|
||||
^^^^
|
||||
|
||||
The mesh shader is bound to the vertex stage if no task shader is present
|
||||
or the tess control stage otherwise.
|
||||
|
||||
Attributes are stored in the output :doc:`ISBE Attribute region <isbe_layout>` **with SKEW applied**.
|
||||
|
||||
If any per primitive attributes are in use, they are stored after all per vertex
|
||||
attributes and the geometry stage will be enabled in passthrough mode with only
|
||||
its program header present.
|
||||
|
||||
For more details about the ISBE Attribute or Map layout, see the dedicated :doc:`ISBE <isbe_layout>` page.
|
||||
|
||||
Additionally, ``SET_MESH_SHADER_A`` and ``SET_MESH_SHADER_B`` are used
|
||||
to set the number of local invocations to use, the size used for shared memory
|
||||
and topology details.
|
||||
|
||||
This can be done with the following command:
|
||||
::
|
||||
|
||||
NVC597_SET_MESH_SHADER_A
|
||||
.OUTPUT_TOPOLOGY = $topology
|
||||
.MAX_VERTEX = ($max_vertex)
|
||||
.MAX_PRIMITIVE = ($max_primitive)
|
||||
NVC597_SET_MESH_SHADER_B
|
||||
.SHARED_MEM_LINES = ($shared_mem_lines)
|
||||
.THREAD_COUNT = ($thread_count)
|
||||
|
||||
Where:
|
||||
|
||||
- ``$topology`` is the topology to use.
|
||||
- ``$max_vertex`` is the max count of vertices used by the mesh shader.
|
||||
- ``$max_primitive`` is the max count primitives used by the mesh shader.
|
||||
- ``$shared_mem_lines`` is the total amount of shared memory line to allocate
|
||||
in the output :doc:`ISBE Attribute region <isbe_layout>` after all attributes.
|
||||
- ``$thread_count`` is the number of local invocations (up to 32).
|
||||
|
||||
**NOTE**: The size of a memory line is 128 bytes.
|
||||
|
||||
The workgroup_index is implemented in the following way:
|
||||
|
||||
- If a task shader is present, the value is read from the input :doc:`ISBE Attribute region <isbe_layout>` **without SKEW applied**.
|
||||
- Otherwise, it is implemented using the ``VERTEX_ID`` read from the input :doc:`ISBE Attribute region <isbe_layout>` **with SKEW applied**.
|
||||
|
||||
``SetMeshOutputsEXT`` is lowered to the equivalent pseudo code:
|
||||
::
|
||||
|
||||
void SetMeshOutputsEXT(uint vertexCount, uint primitiveCount) {
|
||||
// vertexCount is unused
|
||||
ISBEWR.O.MAP.32 [0x3], primitiveCount;
|
||||
}
|
||||
|
||||
**NOTE**: This is effectively a write to offset 0x0 but the output :doc:`ISBE Map region <isbe_layout>` process writes in reverse.
|
||||
|
||||
All primitive indices are stored as 8-bit indices starting at offset 0x4 in the ouptut :doc:`ISBE Map region <isbe_layout>`.
|
||||
|
||||
|
||||
Hardware limitations
|
||||
""""""""""""""""""""
|
||||
|
||||
* Only up to 32 local invocations are supported.
|
||||
* The shared memory being part of the :doc:`ISBE Attribute region <isbe_layout>` makes it that
|
||||
we do not have any atomics for it.
|
||||
* Task / mesh invocations need to be counted inside the shader.
|
||||
Reference in new issue
Block a user