> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ejemplo de selección de meshlets

> Ejemplo de selección de meshlets

Se recomienda que primero lea el tema [Meshlets](/build/core-features/graphics/newfeatures/ms/ms-meshlet-render).

El tema Ejemplo de selección de meshlets presenta el pseudocódigo de una implementación de sombreador de amplificación de una técnica denominada *selección de meshlets* (meshlet culling). Dado que, idealmente, las primitivas de un meshlet presentan coherencia espacial y de orientación, podemos almacenar datos de selección eficaces por meshlet. Esto se puede usar para seleccionar rápidamente una lista de meshlets con respecto a una vista en un sombreador de amplificación y distribuir instancias de sombreador de malla solo para los meshlets supervivientes.

La técnica comienza con un sombreador de amplificación en el que cada subproceso procesa un único meshlet. Esto significa que debemos distribuir ceil(MeshletCount / GROUP\_SIZE) grupos de subprocesos en la lista de comandos.

Cada grupo de subprocesos del sombreador de amplificación es entonces responsable de procesar GROUP\_SIZE meshlets. Cada subproceso selecciona su meshlet con respecto al tronco de vista, determina su ranura de exportación y, a continuación, escribe su índice en los datos de carga. Después usa [DispatchMesh](https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html#dispatchmesh-intrinsic) para distribuir un grupo de subprocesos de sombreador de malla por cada meshlet superviviente que se va a representar. Cada grupo de subprocesos de sombreador de malla carga entonces su meshlet a partir de los datos de carga y exporta su geometría.

El ejemplo completo se puede encontrar en la [página de descargas para desarrolladores de XBOX](https://aka.ms/xgddl).

## Sombreador de amplificación

La estructura del sombreador de amplificación es idéntica a la de los sombreadores de proceso, pero concluye con como máximo una llamada a 'DispatchMesh(…)'. Primero, cada subproceso carga su meshlet y lo selecciona con respecto a la vista. A continuación, se realiza una rutina de compactación para determinar la ubicación de escritura final de cada subproceso. Esto también proporciona el recuento final de meshlets no descartados para el grupo de subprocesos. Por último, el índice del meshlet se escribe en los datos de carga groupshared y se llama a DispatchMesh con el recuento de meshlets supervivientes y los datos de carga.

En el ejemplo siguiente se muestra un sombreador de amplificación que implementa la selección de meshlets en pseudocódigo.

```
#define GROUP_SIZE 128

struct Meshlet
{
    // Meshlet data.
    uint VertexOffset;
    uint VertexCount;
    uint PrimitiveOffset;
    uint PrimitiveCount;

    // Local Culling data.
    float4 BoundingSphere;
    float4 NormalCone;
};

StructuredBuffer<Meshlet> Meshlets : register(t0);

cbuffer ViewProps : register(b0)
{
    float4x4 ViewMat;
    float4x4 ViewProjMat;
    float3   ViewPosition;
};

struct MyPayload 
{ 
    uint MeshletIndices[GROUP_SIZE]; 
};

groupshared MyPayload payload;

bool CullTests(Meshlet m) { ... }
void CalcPayloadIndexAndCount(bool isCulled, out index, out count) { ... }

[NumThreads(GROUP_SIZE, 1, 1)] 
void main(
    uint dispatchThreadId : SV_DispatchThreadID,
    uint groupThreadId : SV_GroupThreadID
)
{
    Meshlet meshlet = Meshlets[dispatchThreadId];
    bool isCulled = CullTests(meshlet);
    
    uint index, count;
    CalcPayloadIndexAndCount(groupThreadId, isCulled, index, count);
    
    if (!isCulled)
    {
        payload.MeshletIndices[index] = dispatchThreadId;
    }

    DispatchMesh(count, 1, 1, payload);
}
```

## Sombreador de malla

El sombreador de malla de la canalización es muy similar a la representación de meshlets mediante una canalización de solo sombreador de malla, con la excepción de que leemos el índice del meshlet del grupo de subprocesos desde los datos de carga. Los datos de carga son los mismos datos que se generan y exportan desde el sombreador de amplificación anterior. Los GroupID y DispatchThreadID están localizados en el clúster de sombreador de malla que se distribuye desde el grupo de subprocesos del sombreador de amplificación que lo invoca, y todos comparten los mismos datos de carga.

En este ejemplo de código se muestra el sombreador de malla que sigue al sombreador de amplificación anterior.

```
#define MAX_MESHLET_SIZE 128

StructureBuffer<MyVertex>   Vertices;
StructureBuffer<Meshlet>    Meshlets;
StructuredBuffer<uint>      UniqueVertexIndices;
StructureBuffer<uint3>      PrimitiveIndices;

VertexOut TransformVertex(MyVertex v) { ... }

[NumThreads(MAX_MESHLET_SIZE, 1, 1)]
[OutputTopology("triangle")]
void main(
    uint groupThreadId : SV_GroupIndex,
    uint groupId : SV_GroupID,
    in payload MyPayload payload,
    out vertices VertexOut verts[MAX_MESHLET_SIZE],
    out indices uint3 tris[MAX_MESHLET_SIZE])
{
    uint meshletIndex = payload.MeshletIndices[groupId];
    Meshlet m = Meshlets[meshletIndex];

    SetMeshOutputCounts(m.VertCount, m.PrimCount);

    if (groupThreadId < m.PrimCount) 
    {
        tris[groupThreadId] = PrimitiveIndices[m.PrimOffset + groupThreadId];
    }

    if (groupThreadId < m.VertCount) 
    {
        uint index = UniqueVertexIndices[m.VertOffset + groupThreadId];
        MyVertex vin = Vertices[index];

        verts[groupThreadId] = TransformVertex(vin);
    }
}

```

## Consulte también

[Información general de la canalización de sombreadores de malla](/build/core-features/graphics/newfeatures/ms/ms-overview)

[¿Por qué sombreadores de malla?](/build/core-features/graphics/newfeatures/ms/ms-why)

[Información general de la API de sombreadores de malla](/build/core-features/graphics/newfeatures/ms/ms-api-design)

[Meshlets](/build/core-features/graphics/newfeatures/ms/ms-meshlet-render)
