> ## 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.

# Mesh Shader 管線使用方式

> Mesh Shader 管線使用方式

在 Direct3D 12 中使用 Mesh Shader 管線，可歸結為下列熟悉的步驟。

1. 使用 DXC 撰寫並編譯 Mesh Shader 和 (選擇性的) Amplification Shader。
2. 使用編譯後的著色器位元組程式碼建立 Mesh Shader 管線狀態物件。
3. 使用命令清單記錄 Mesh Shader 管線狀態物件的分派。
4. 在命令佇列上執行命令清單。

## Mesh Shader 管線狀態物件

Direct3D 12 透過熟悉的圖形管線狀態物件 API 公開 Mesh Shader 管線。建立 Mesh Shader 管線狀態物件時，會使用管線狀態串流 API，如接下來的兩個程式碼範例所示。

ID3D12Device 和 ID3D12GraphicsCommandList API 可用於檢查硬體支援並分派 Mesh Shader 管線工作負載 (第二個程式碼範例)。請注意，在 XBOX Series X|S 上不需要檢查硬體支援。

下列程式碼範例顯示要提供給管線串流建立 API 的 Mesh Shader 管線串流描述。

```text theme={null}
struct MyPsoStreamDesc
{
    CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE        pRootSignature;
    CD3DX12_PIPELINE_STATE_STREAM_AS                    AS;
    CD3DX12_PIPELINE_STATE_STREAM_MS                    MS;
    CD3DX12_PIPELINE_STATE_STREAM_PS                    PS;
    CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC            BlendState;
    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1        DepthStencilState;
    CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER            RasterizerState;
    CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS RTFormats;
    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT  DepthFormat;
    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC           SampleDesc;
    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK           SampleMask;
};
```

下列程式碼範例顯示 Mesh Shader 管線狀態的建立和使用方式。

```text theme={null}
{
    // Check the hardware for Mesh Shader pipeline feature support, which is unnecessary on Xbox Series X&#124;S.
    D3D12_FEATURE_DATA_D3D12_OPTIONS7 options;
    device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &options, sizeof(options));
    
    if (options.MeshShaderTier == D3D12_MESH_SHADER_TIER_NOT_SUPPORTED)
        throw std::exception("Mesh Shaders not supported!"); 

    // Create the Mesh Shader pipeline by using the pipeline state stream APIs.
    MyPsoStreamDesc psoDesc;
    psoDesc.AS = {...};
    psoDesc.MS = {...};
    ...

    D3D12_PIPELINE_STATE_STREAM_DESC desc = { sizeof(psoDesc), &psoDesc };
    device->CreatePipelineState(&desc, IID_PPV_ARGS(&msPso));

    ...

    // Set the graphics root signature, Mesh Shader pipeline state object, and root parameters.
    cmdList->SetGraphicsRootSignature(&msRootSig);
    cmdList->SetPipelineState(&msPso); 
    ...

    // Dispatch the bound Mesh Shader pipeline directly ...
    cmdList->DispatchMesh(groupCount, 1, 1);
    
    // ... or indirectly.
    cmdList->ExecuteIndirect(&msCommandSig, ...);
}
```

## Mesh Shader

Mesh Shader 是使用 DXC 命令列工具或編譯器程式庫，以新的 Mesh Shader「*ms*」著色器設定檔進行編譯，例如 *ms\_6\_5*。第三個程式碼範例提供螢幕空間三角形 Mesh Shader 的範例實作，請以該程式碼範例作為參考來跟著操作。

下列是在命令列上編譯 Mesh Shader 的範例。

```text theme={null}
dxc.exe -T ms_6_5 -E main -Fo ExampleMS.cso ExampleMS.hlsl
```

著色器 **main** 函式以中繼資料屬性加以修飾。

* **NumThreads** 宣告執行緒群組維度
* **OutputTopology** 宣告基本型別類型

唯一的輸入是計算著色器中熟悉的執行緒識別碼。所有其他資料都必須透過常數緩衝區檢視 (CBV)、著色器資源檢視 (SRV) 或無序存取檢視 (UAV) 手動讀取。

幾何輸出是透過 *out* 參數宣告為\_共用輸出陣列\_。這些是唯寫陣列參數，其類型宣告了要從著色器匯出的使用者定義頂點和基本型別類型。*vertices*、*indices* 和 *primitives* 修飾詞會將每個參數指定為三種不同幾何輸出之一。這些陣列的長度必須是編譯時期常數，並定義可匯出的頂點和基本型別數量上限。

[SetMeshOutputCounts](https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html#setmeshoutputcounts) 內建函式會宣告執行緒群組實際的頂點和基本型別匯出數量。此呼叫為選擇性，numVerts 和 numPrims 的預設值皆為零。這些值必須小於或等於輸出陣列的長度。此呼叫可以在寫入共用輸出陣列\_之前\_的任何時間發生。所提供的值預期在執行緒群組內為常數，且會從第一個通道讀取。

接著，頂點和基本型別會由執行緒群組轉換，並寫入共用輸出陣列。對 **SetMeshOutputCounts()** 的呼叫必須在任何寫入發生之前執行，且寫入必須在該呼叫所宣告的範圍內。

下列程式碼範例顯示轉譯單一螢幕空間三角形的 Mesh Shader。

```text theme={null}
static const float4 Vertices[3] = 
{
    float4(-0.5f, -0.5f, 0.0f, 1.0f),
    float4( 0.0f,  0.5f, 0.0f, 1.0f),
    float4( 0.5f, -0.5f, 0.0f, 1.0f)
};
static const uint3 Primitives[1] = { uint3(0, 1, 2) };

[NumThreads(32, 1, 1)]
[OutputTopology("triangle")]
void main(
    uint groupThreadId : SV_GroupIndex,
    out vertices VertexOut verts[3],
    out indices uint3 tris[1],
    out primitives PrimitiveOut prims[1])
{
    SetMeshOutputCounts(3, 1);

    if (groupThreadId < 3)
    {
        VertexOut vout;
        vout.Position = Vertices[groupThreadId];
        vout.Color = float3(1.0, 1.0, 1.0);
        
        verts[groupThreadId] = vout;
    }

    if (groupThreadId < 1)
    {
        tris[groupThreadId] = Primitives[groupThreadId];

        prims[groupThreadId].PrimitiveId = groupThreadId;
    }
}
```

## Amplification Shader

Amplification Shader 是使用 DXC 命令列工具或程式庫，以新的 Amplification Shader「*as*」著色器設定檔進行編譯，例如 *as\_6\_5*。

下列是在命令列上編譯 Amplification Shader 的範例。

```text theme={null}
dxc.exe -T as_6_5 -E main -Fo ExampleAS.cso ExampleAS.hlsl
```

其結構與計算著色器相同，差別只在於選擇性的 [DispatchMesh](https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html#dispatchmesh-intrinsic) 內建函式呼叫，此呼叫會分派一組 Mesh Shader 子系。下列程式碼範例概述了一個非常通用的 Amplification Shader，只是為了顯示整體結構。

如需 Amplification Shader 的完整應用，請參閱 [Meshlet 剔除範例](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-meshlet-culling)。

下列程式碼範例顯示 Amplification Shader 的通用概要。

```text theme={null}
struct MyPayload 
{ 
    uint   SomeData;
    float4 MoreData;
    float3 DataData[32];
};

groupshared MyPayload payload;

[NumThreads(32, 1, 1)] 
void main(
    uint3 dispatchThreadId : SV_DispatchThreadID,
    uint3 groupThreadId : SV_GroupThreadID,
    uint groupId : SV_GroupID
)
{
    ReadMyResourceData(dispatchThreadId);

    uint count = GetMyThreadgroupCount(groupId, groupThreadId);
    BuildMyPayload(groupId, groupThreadId, payload);

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

## 另請參閱

[Mesh Shader 管線概觀](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-overview)

[為什麼要使用 Mesh Shader？](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-why)

[Mesh Shader API 概觀](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-api-design)

[Meshlet](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-meshlet-render)

[Meshlet 剔除範例](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-meshlet-culling)


## Related topics

- [Mesh Shader 管線 API 概觀](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-api-design.md)
- [為什麼要使用 Mesh Shader？](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-why.md)
- [XBOX Series X|S 上的 Mesh Shader 與 Meshlet](/zh-TW/build/core-features/graphics/newfeatures/ms/index.md)
- [Meshlet](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-meshlet-render.md)
- [Mesh Shader 管線概觀](/zh-TW/build/core-features/graphics/newfeatures/ms/ms-overview.md)
