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

# Cmask 解碼

> Cmask 解碼

Cmask 是一種表面，會為相關聯色彩緩衝區中每個 8x8 像素大小的區塊 (Cmask 圖格) 儲存中繼資料。此中繼資料是 Fast Clear 機制的必要部分，但不限於此。Fast Clear 是一種方法，可在色彩緩衝區中即將被轉譯覆寫的區域略過 Clear 作業。此方法包含三個步驟。第一個步驟需要初始化 Cmask 表面，讓每一份中繼資料都將色彩緩衝區中相關聯的 8x8 圖格追蹤為已清除。第二個步驟會發出任意順序的繪製作業，以更新設定為使用此 Cmask 的色彩緩衝區。Color Block (CB) 同時會以色彩緩衝區中被觸及區域的相關資訊更新 Cmask 表面。轉譯完成時，所有保持未觸及的區域都會被清除 (也稱為 Fast Clear Eliminate 作業)。這通常發生在色彩緩衝區從可寫入狀態轉換為可讀取狀態時。

在許多情況下，知道色彩緩衝區的哪些 8x8 圖格 (甚至哪些子圖格) 被轉譯觸及會很有幫助。為此，必須了解如何解碼 Cmask 表面。

<a name="cmask-nibble" />

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/cmask-decoding-cmask-nibble.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=657d9d49ba94e83799eb5d87f4443224" alt="Cmask 元素是一個 4 位元值 (也稱為「半位元組」)，會為每個 Cmask 圖格編碼資訊。" width="1105" height="290" data-path="images/gdk/features/graphics/cmask-decoding-cmask-nibble.png" />

**圖 1：** *Cmask 元素是一個 4 位元值 (也稱為「半位元組」)，會為每個 Cmask 圖格編碼資訊。*

解碼通常需要兩個步驟。第一個步驟是擷取對應到所提供 Cmask 圖格座標的 Cmask 半位元組 ([圖 1](#cmask-nibble))。這可以透過 *MiniEngines* 的 **ColorDecompressUtility.hlsli** 中的 `GetCMask` 協助程式函式來完成。

<a name="cmask-nibble-modes" />

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/cmask-decoding-cmask-nibble-modes.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=efa40fb91ec6677f9dabf1d0225a2386" alt="解譯 Cmask 半位元組的可能變體" width="1030" height="715" data-path="images/gdk/features/graphics/cmask-decoding-cmask-nibble-modes.png" />

**圖 2：** *解譯 Cmask 半位元組 ([圖 1](#cmask-nibble)) 的可能變體。(1) - 每個 Cmask 位元會編碼對應到此位元的子圖格 (位於 8x8 Cmask 圖格內) 是否已被轉譯觸及 (位元已設定)，或仍保持快速清除狀態 (位元未設定)。此變體用於已啟用 Fast Clear 且已停用 VRS 提示匯出 (僅適用於 XBOX Series X|S) 的非 MSAA 色彩緩衝區。(2) - 用於已啟用 Fast Clear 且已停用 VRS 提示匯出之已啟用 MSAA 色彩緩衝區的變體。上面兩個位元以類似 (1) 的方式編碼 Fast Clear 資訊。由於只有兩個位元可用於 Fast Clear，Cmask 圖格內只能有兩個子圖格。下面兩個位元編碼為指定的 8x8 圖格編碼 FMask 指標所需的 Fmask 位元平面數目。位元平面數目受限於所選 MSAA 模式中取樣數的 log2。(3) - 類似於 (2)，但上面兩個位元設定為 **1**，因為此模式適用於已停用 Fast Clear 的 MSAA 色彩緩衝區。(4) - 適用於 Fast Clear 位元被改用來儲存匯出之 VRS 速率提示 (僅限 XBOX Series X|S) 的 MSAA 色彩緩衝區，但下面的位元與 (2) 和 (3) 類似，會為整個 Cmask 圖格編碼 Fmask 位元平面數目。(5) - 類似於 (4)，但用於非 MSAA 色彩緩衝區，因此不使用下面兩個位元。*

擷取 Cmask 半位元組之後，第二個步驟需要解譯所有四個位元的意義。這取決於數個因素，例如對應的色彩緩衝區是否已啟用 MSAA、色彩格式的位元深度為何、色彩緩衝區的微並排模式 (在 XBOX One 和 XBOX Series X|S 上) 或拌和模式 (XBOX Series X|S)，以及是否匯出 VRS 提示 (XBOX Series X|S)。[圖 2](#cmask-nibble-modes) 根據轉譯期間 Color Block (CB) 的設定方式，顯示五種編碼配置變體。如果設定為使用 Fast Clear，則每個 Cmask 半位元組都會編碼對應 Cmask 圖格內的哪些子圖格已被觸及。對於有和沒有 MSAA 的表面，編碼方式略有不同 (變體 (**1**) 和 (**2**))，因為只有兩個位元可用來追蹤 8x8 圖格中子圖格的狀態。

[圖 3](#non-msaa-cmask) 示範 Cmask 圖格內子圖格的可能設定，以及 Cmask 半位元組的位元與對應此半位元組之 Cmask 圖格內子圖格之間的對應。這些設定可用於非 MSAA 色彩緩衝區。

<a name="non-msaa-cmask" />

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/cmask-decoding-cmask-subtiles-non-msaa.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=f5705aaf4aaf1bfcd5f3837133cf82c5" alt="非 MSAA 色彩緩衝區 (且在 XBOX Series X|S 上已停用 VRS 提示匯出) 在 Cmask 圖格 (8x8 像素) 內放置子圖格的可能變體。" width="1178" height="340" data-path="images/gdk/features/graphics/cmask-decoding-cmask-subtiles-non-msaa.png" />

**圖 3：** *非 MSAA 色彩緩衝區 (且在 XBOX Series X|S 上已停用 VRS 提示匯出) 在 Cmask 圖格 (8x8 像素) 內放置子圖格的可能變體。請注意，不同的子圖格對應到 Cmask 半位元組 ([圖 1](#cmask-nibble)) 的不同位元。由左至右：**CM0** -- 四個各為 8x2 像素大小的子圖格，排列成 1x4 網格，**CM1** -- 四個各為 2x8 像素大小的子圖格，排列成 4x1 網格，**CM2** -- 四個各為 4x4 像素大小的子圖格，排列成 2x2 網格，**C3** -- 四個各為 4x4 像素大小的子圖格，排列成 2x2 網格 (請注意與 **CM2** 相比順序不同，左下角圖格對應到位置 **1** 的位元)*

Cmask 圖格中子圖格的排列方式，可以從色彩格式的位元深度以及色彩緩衝區的並排/拌和模式判斷。這些相依性摘要於 [表 1](#scarlett-cmask-modes) (適用於 XBOX Series X|S) 和 [表 2](#scorpio-durpio-cmask-modes) (適用於 XBOX One 和 XBOX Series X|S)。

<a name="scarlett-cmask-modes" />

| 色彩格式 Bpp / 拌和模式 | `SW_*_D` | `SW_*_R` | `SW_*_S` | `SW_*_Z` |
| :-: | :-: | :-: | :-: | :-: |
| 8 位元 | CM0 | CM0 | CM0 | CM2 |
| 16 位元 | CM0 | CM0 | CM0 | CM2 |
| 32 位元 | CM2 | CM2 | CM3 | CM2 |
| 64 位元 | CM0 | CM0 | CM2 | CM2 |
| 128 位元 | CM3 | CM2 | CM3 | CM2 |

**表 1：** *XBOX Series X|S 上非 MSAA 色彩緩衝區的色彩格式位元深度、拌和模式與 Cmask 子圖格放置模式 (請參閱 [圖 3](#non-msaa-cmask)) 之間的相依性。拌和模式由 XG 程式庫中的 `XG_SWIZZLE_MODE` 定義。*

<a name="scorpio-durpio-cmask-modes" />

| 色彩格式 Bpp / 微並排模式 | `THIN` | `DISPLAY` | `ROTATED` |
| :-: | :-: | :-: | :-: |
| 8 位元 | CM2 | CM0 | CM1 |
| 16 位元 | CM2 | CM0 | CM1 |
| 32 位元 | CM2 | CM0 | CM1 |
| 64 位元 | CM2 | CM0 | CM2 |

**表 2：** *XBOX One 和 XBOX Series X|S 上非 MSAA 色彩緩衝區的色彩格式位元深度、微並排模式與 Cmask 子圖格放置模式 (請參閱 [圖 3](#non-msaa-cmask)) 之間的相依性。微並排模式對應到 XG 程式庫中 `XG_TILE_MODE` 的後置詞。例如，`XG_TILE_MODE_*_THIN` 圖格模式使用 `THIN` 微並排。`ROTATED` 微並排並未使用，但為求完整而列於此表中。*

已啟用 MSAA 之色彩緩衝區在 Cmask 圖格內放置子圖格的變體如 [圖 4](#msaa-cmask) 所示。在 XBOX Series X|S 上，無論基礎色彩格式的位元寬度和拌和模式為何，*CMM1* 都是唯一可能的選項 (啟用 MSAA 時一律為 `SW_*_R`)。在 XBOX One 和 XBOX Series X|S 上，兩種變體都有可能，但 *CMM0* 僅用於 `ROTATED` 微並排以及每像素位元寬度小於 64 位元的色彩格式。由於驅動程式不使用 `ROTATED` 微並排，因此不太可能遇到此配置。

<a name="msaa-cmask" />

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/cmask-decoding-cmask-subtiles-msaa.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=9ffae2d8fd7ccc78482faa3663593591" alt="已啟用 MSAA 之色彩緩衝區在 Cmask 圖格 (8x8 像素) 內放置子圖格的可能變體。" width="580" height="328" data-path="images/gdk/features/graphics/cmask-decoding-cmask-subtiles-msaa.png" />

**圖 4：** *已啟用 MSAA 之色彩緩衝區在 Cmask 圖格 (8x8 像素) 內放置子圖格的可能變體。**CMM0** -- 兩個 4x8 像素的子圖格，**CMM1** -- 兩個 8x4 像素的子圖格。*

接下來兩頁包含 [**CMaskDecode**](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/development-downloads/gdk-samples-list#graphics) 範例中 `PSOverlay` 著色器的主體，此著色器會解譯 Cmask 半位元組。

```c theme={null}
[RootSignature(FullScreenQuadRS)]
float4 PSOverlay(Interpolators In) : SV_TARGET0
{
    const float4 vRed = float4( 1.0f, 0.0f, 0.0f, 0.5f );
    const float4 vGreen = float4( 0.0f, 1.0f, 0.0f, 0.5f );

    uint2 ScreenPosition = uint2(In.Position.xy);

    // Cmask tile size is always 8x8;
    uint2 CmaskTileCoord = ScreenPosition >> 3;

    // Fetch Cmask value that is has 4 bits
    uint CmaskNibble = g_texThumb[CmaskTileCoord];

#if g_bSubTile

    // Compute coordinates of 2x2 quad within Cmask 8x8 tile
    uint2 QuadLocalCoord = uint2(
        __XB_UBFE(2u, 1u, ScreenPosition.x),
        __XB_UBFE(2u, 1u, ScreenPosition.y)
    );

    /** Based on the layout mode of Cmask sub-tiles and coordinates of the current quad
     *  within Cmask 8x8 tile, determine the position of the bit within a Cmask nibble
     *  that indicates whether the sub-tile covering current quad was touched by
     *  rendering or not
     */
     uint SubTileBitPos = 0;

    if (SubTileLayoutMode == 0)
    {
        /** 2x2 mode.
         *  4x4 pixel tiles correspond to the following bits:
         *      +---+---+
         *      | 0 | 1 |
         *      +---+---+
         *      | 2 | 3 |
         *      +---+---+
         */
        SubTileBitPos = (QuadLocalCoord.x >> 1u) | (QuadLocalCoord.y & 0x2);
    }
    else if (SubTileLayoutMode == 1)
    {
        /** 2x2 rotated mode (Xbox Series X|S only).
         *  4x4 tiles correspond to the following bits:
         *      +---+---+
         *      | 0 | 2 |
         *      +---+---+
         *      | 1 | 3 |
         *      +---+---+
         */
        SubTileBitPos = (QuadLocalCoord.y >> 1u) | (QuadLocalCoord.x & 0x2);
    }
    else if (SubTileLayoutMode == 2)
    {
        /** 4x1 mode (Xbox One only).
         *  2x8 tiles correspond to the following bits:
         *      +-+-+-+-+
         *      | | | | |
         *      |0|1|2|3|
         *      | | | | |
         *      +-+-+-+-+
         */
        SubTileBitPos = QuadLocalCoord.x;
    }
    else if (SubTileLayoutMode == 3)
    {
        /** 1x4 mode.
         *  8x2 tiles correspond to the following bits:
         *      +---0---+
         *      +---1---+
         *      +---2---+
         *      +---3---+
         */
        SubTileBitPos = QuadLocalCoord.y;
    }
    else if (SubTileLayoutMode == 4)
    {
        /** 2x1 mode (Xbox One only, MSAA only).
         *  4x8 tiles correspond to the following bits:
         *      +---+---+
         *      |   |   |
         *      | 0 | 1 |
         *      |   |   |
         *      +---+---+
         */
        SubTileBitPos = 2u + (QuadLocalCoord.x >> 1u);
    }
    else if (SubTileLayoutMode == 5)
    {
        /** 1x2 mode (MSAA only).
         *  8x4 tiles correspond to the following bits:
         *      +-------+
         *      +   0   +
         *      +-------+
         *      +   1   +
         *      +-------+
         */
        SubTileBitPos = 2u + (QuadLocalCoord.y >> 1u);
    }
    return __XB_UBFE(1u, SubTileBitPos, CmaskNibble) != 0 ? vRed : vGreen;
#else
    /** Layout modes 4 and 5 are only set when Msaa is enabled.
     *  That means only upper 2 bits out of 4 are valid
     */
    if (SubTileLayoutMode >= 4)
        return (CmaskNibble & 0xc) != 0 ? vRed : vGreen;
    else
        return (CmaskNibble & 0xf) != 0 ? vRed : vGreen;
#endif
}
```

## 另請參閱

[圖形概觀](/zh-TW/build/core-features/graphics/overviews/graphics)


## Related topics

- [NDA 主題目錄 - Microsoft Learn 線上連結](/zh-TW/nda/nda-topic-directory.md)
- [NDA topics index for XBOX GDK console development](/nda/nda-overview.md)
- [XBOX GDK 主机开发 NDA 主题索引](/zh-CN/nda/nda-overview.md)
- [XBOX GDK 콘솔 개발용 NDA 주제 색인](/ko/nda/nda-overview.md)
- [Índice de temas de NDA para el desarrollo de consolas con el GDK de XBOX](/es/nda/nda-overview.md)
