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

# 使用 DirectStorage 和 XBTC 最佳化壓縮內容

> 使用 DirectStorage 和 XBTC 最佳化壓縮內容

使用本主題來了解 Microsoft Game Development Kit 中新 DirectStorage API 的特定解壓縮案例，以及用於為這些案例匯入內容的 [XBOX 紋理壓縮工具 (XBTC)](/zh-TW/build/core-features/graphics/newfeatures/xbtc/xbtc)。

目標是提供指導方針，協助您根據每個遊戲的需求取得最佳結果。

## 內容

* [免責聲明](#Disclaimer)
* [簡介](#Introduction)
* [架構](#Architecture)
* [記憶體解壓縮單元](#MDU)
  * [階段：zlib](#MDU_zlib)
  * [階段：BCPack](#MDU_bcpack)
  * [階段：Swizzle 區塊](#MDU_swizzle)
* [為 MDU 封裝資料](#PackagingData)
* [紋理磚化與 Sampler Feedback Streaming (SFS)](#Tiling)
* [DirectStorage 作業的記憶體集區限制](#MemoryLimits)
* [XBOX 紋理壓縮工具 (XBTC.exe)](#XBTC)
  * [匯入內容](#XBTC_importing)
  * [壓縮](#XBTC_compression)
  * [SFS 區域選取](#XBTC_SFS)
  * [非 SFS 區域選取](#XBTC_mips)
  * [套用](#XBTC_application)
  * [位元率失真最佳化 (RDO)](#RDO)
  * [BC7 編碼器模式限制](#BC7_modes)
* [最佳效能的考量事項](#Considerations)

<a id="Disclaimer" />

## 免責聲明

本主題中的效能測量是使用 2020 年 6 月 GDK 和復原，並使用自 2020 年 7 月起隨硬體更新一併出貨的開發套件所取得。

所有測量皆來自以零售磁碟機模式安裝在主機上的已封裝 XVC。使用鬆散檔案部署所做的測量預期會略低，因為開發磁碟機可能有資料片段化，而且無法使用唯讀 XVC 所具備的部分效能最佳化。

未設定為零售磁碟機模式的主機，其測量結果會有不同的效能特性。

本主題中所提供的所有數字都使用業界標準標記法來區分 10 進位與 2 進位數字。2 進位數字使用 kibibyte (KiB) 或 mebibyte (MiB) 標記法。10 進位數字使用 SI 前置詞 kilobyte (KB) 或 megabyte (MB)，如下列範例所示。

* 1 MB == 1,000,000 位元組
* 1 MiB == 1,048,576 位元組

<a id="Introduction" />

## 簡介

本主題說明如何透過 DirectStorage API 使用 [XBOX 紋理壓縮工具 (XBTC)](/zh-TW/build/core-features/graphics/newfeatures/xbtc/xbtc) 和[記憶體解壓縮單元 (MDU)](#MDU)，包括達到最高效能的最佳做法。

在閱讀本主題之前，您應先閱讀 [DirectStorage 使用方式與內部詳細資料](/zh-TW/build/console-features/storage/directstorage/directstorage-white-paper)主題，其中說明 NVMe SSD 的基礎 IO 輸送量特性。

XBOX Series 主機中的 MDU 為多階段，並支援對相同資料執行多項作業。它可以單獨用於執行記憶體內解壓縮，或者更常見的是在 DirectStorage IO 管線中使用，在從儲存體載入內容時以透明方式進行解壓縮。

MDU 的設計使其輸送量超過來自儲存體 2 GB/s 壓縮位元組的完整 NVMe IO 速率。

<a id="Architecture" />

## 架構

DirectStorage 的架構旨在以最低的 CPU 額外負荷達到最高頻寬。它以管線模型處理批次要求，如本主題[記憶體解壓縮單元](#MDU)一節的圖 1 所示。

如需整個系統基礎架構的詳細資訊，請參閱 [DirectStorage 使用方式與內部詳細資料](/zh-TW/build/console-features/storage/directstorage/directstorage-white-paper)。

DirectStorage 直接與[記憶體解壓縮單元 (MDU)](#MDU) 繫結，因此您也可以輕鬆地將所有解壓縮工作從 CPU 卸載。

MDU 的運作方式是使用所有 DirectStorage 案例共用的中繼記憶體集區，並將結果直接寫入遊戲所提供的目的地緩衝區。每個 DirectStorage 要求在加入佇列時都會附帶中繼資料，說明資料串流通過 MDU 時應如何處理。

若要使用此功能，資源必須經過封裝，讓個別資料串流以及描述它們的中繼資料可以在個別的 DirectStorage 要求中載入。載入資產的串流中繼資料之後，個別資料串流會根據與每個要求相關聯的選項，在對 NVMe SSD 的 IO 要求中以透明方式解壓縮。

若資料串流是透過其他方法 (例如網路要求) 載入，則可以使用另一種 DirectStorage 佇列類型和要求類型，在遊戲指定的緩衝區之間進行解壓縮。

對於紋理這個主要案例 (紋理佔大多數遊戲資產的絕大部分)，XBTC 工具可協助壓縮和封裝資產，以便在執行階段解壓縮。

<a id="MDU" />

## 記憶體解壓縮單元

記憶體解壓縮單元 (MDU) 由兩個獨立的硬體模組組成，每個模組都有三個作業階段，如圖 1 所示。每個硬體模組的最大讀取速度為 1.6 GB/s，輸出速率為 4 GB/s，因此合併輸送量 (輸入 3.2 GB/s，輸出 8 GB/s) 超過 NVMe 可維持的 2 GB/s 速率。

這表示在一般情況下，即使 MDU 已讓 NVMe SSD 的 IO 達到飽和，它仍可處理執行記憶體內解壓縮的要求。遊戲實際可達到的輸送量取決於內容的壓縮比、封裝方式、存取模式，以及 DirectStorage API 的具體使用方式。

前述輸送量數字 (輸入 3.2 GB/s，輸出 8 GB/s) 代表在有其他 IO 存在時，實際內容的實用限制。使用 MDU 解壓縮可完美壓縮的頁面作為一種 memset 時，輸出至記憶體的絕對上限為 12 GB/s。[SimpleMDU](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/development-downloads/gdk-samples-list) 範例示範了輸送量行為。

**圖 1. 顯示 MDU 作業的三個階段，包括 zlib 解壓縮、BCPack 和 Swizzle 區塊；這些階段由所有 DirectStorage 佇列共用**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_MDU_breakdown.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=1bbf908d57db9c54348837aaa17cc427" alt="三個 MDU 階段明細的螢幕擷取畫面" width="934" height="595" data-path="images/gdk/features/console/DSMDU_MDU_breakdown.png" />

這三項作業都可以依序執行而不會降低速度，結果會直接儲存在加入佇列之要求物件內所指定的遊戲記憶體中。

視 `DSTORAGE_REQUEST_OPTIONS` 而定，可以略過任何階段。非紋理資源通常只會使用第一個 zlib 階段，並直接寫入遊戲記憶體。紋理資源可能會使用這三個階段的任何組合，並將結果寫入遊戲記憶體。

未壓縮的讀取會略過所有階段，但仍會由 MDU 移至遊戲記憶體。

<a id="MDU_zlib" />

### MDU zlib 階段

您可以使用 MDU 的第一個階段 (也稱為 zlib 或 Deflate 壓縮)，解壓縮符合 [IETF RFC 1950](https://ietf.org/rfc/rfc1950.txt) 的資料串流。XBOX Series 主機支援規格中完整的 32 KiB 視窗大小，而且沒有 XBOX One 系列主機上存在的 4 KiB 限制。

與規格之間確實存在兩項差異。首先，壓縮大小必須小於解壓縮大小。如果您的資料串流因為套用壓縮而擴展為相同或更大的大小，則應改為封裝成未壓縮的資料。遊戲的工具和載入路徑必須能夠識別壓縮與未壓縮的資料區段。其次，解壓縮的資料串流大小有上限，此上限以代表遊戲所做的記憶體保留大小 (32 MiB) 為基礎。

若要為指定的資料串流啟用 MDU 的這個階段，必須在 `DSTORAGE_REQUEST::Options` 上設定下列旗標。

`UINT64 DSTORAGE_REQUEST_OPTIONS::ZlibDecompress:1`

此外，如果對資料串流在 BCPack 之上套用 zlib，則必須將 `DSTORAGE_REQUEST::IntermediateSize` 設定為資料串流在 zlib 解壓縮之後、BCPack 解壓縮之前的預期大小。否則，`IntermediateSize` 應保留為零。

剖析和載入 XBTC 封存時，當串流的 `XBTC_STREAM_INFO` 具有與其 `CompressedSize` 不同的 `InflatedSize` 時，即表示該串流存在 zlib 壓縮。`SimpleSFS` 範例中 *TiledTexture.cpp* 檔案的下列程式碼示範了這一點。

```C++ theme={null}
for (UINT x = 0; x < TilingInfo[mip].WidthInTiles; x++)
{
    auto tileInfo = xbtcFile.GetStreamInfo(tileIndex);
    Tiles[tileIndex].LoadSize = tileInfo->CompressedSize;
    Tiles[tileIndex].OffsetInFile = baseOffset + tileInfo->RelativeOffset;
    Tiles[tileIndex].Coord = { x, y, 0, mip };
    Tiles[tileIndex].ZlibCompressed = (tileInfo->CompressedSize != tileInfo->InflatedSize);   //  <<---
    Tiles[tileIndex].BCPacked = (tileInfo->UncompressedSize != tileInfo->InflatedSize);

    auto parentTileX = x >> 1;
    auto parentTileY = y >> 1;
    Tiles[tileIndex].pParentTile = GetTile(parentTileX, parentTileY, mip + 1);

    tileIndex++;

    // Tiles are required to be 64 KB.
    assert(tileInfo->UncompressedSize == D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES);
}
```

<a id="MDU_bcpack" />

### MDU BCPack 階段

BCPack 是 Microsoft 推出的新紋理壓縮演算法，專門針對區塊壓縮 GPU 紋理格式 (BC1-7)，並能理解 XBOX Series 主機的原生紋理 swizzle 模式。

每種區塊壓縮格式都有一組專屬的編碼和解碼路徑。對於每個壓縮串流，必須在發出解壓縮要求時得知並指定編碼器的類型 (或不使用編碼器)。

透過設定下列選項，即可為指定的 `DSTORAGE_REQUEST` 啟用 BCPack 並選取特定解碼器。

<Note>
  與 zlib 壓縮合併使用時，必須設定 `IntermediateSize`。否則，它會保留為零。
</Note>

```C++ theme={null}
DSTORAGE_BCPACK_MODE DSTORAGE_REQUEST_OPTIONS::BcpackMode: 4  
enum DSTORAGE_BCPACK_MODE : UINT64 {  
    DSTORAGE_BCPACK_MODE_NONE = 0,
    DSTORAGE_BCPACK_MODE_BC1  = 1,  
    DSTORAGE_BCPACK_MODE_BC2  = 2,  
    DSTORAGE_BCPACK_MODE_BC3  = 3,  
    DSTORAGE_BCPACK_MODE_BC4  = 4,  
    DSTORAGE_BCPACK_MODE_BC5  = 5,  
    DSTORAGE_BCPACK_MODE_BC6H = 6,  
    DSTORAGE_BCPACK_MODE_BC7  = 7,  
};
```

剖析和載入 XBTC 封存時，當串流的 `XBTC_STREAM_INFO` 具有與其 `UncompressedSize` 不同的 `InflatedSize` 時，即表示該串流存在 zlib 壓縮。前述 `SimpleSFS` 程式碼範例也示範了這一點。

<a id="MDU_swizzle" />

### MDU Swizzle 區塊階段

Swizzle 區塊階段可以在未壓縮資料寫出至遊戲記憶體時，對其提供額外的轉換。從 2024 年 3 月 GDK 開始，提供數種模式，這些模式設計為與 Deflate 或 BCPack 搭配使用時，可進一步縮減 BC1、BC3、BC4 和 BC5 的壓縮大小。如需這些格式的相關資訊，請參閱 [DirectStorage 重排格式](/zh-TW/build/console-features/storage/directstorage/directstorage-shuffles)。

Swizzle 由下列程式碼控制。如果未使用特殊的重排格式，應將其設定為 `DSTORAGE_SWIZZLE_MODE_NONE` (0)。

`DSTORAGE_SWIZZLE_MODE DSTORAGE_REQUEST_OPTIONS::SwizzleMode: 16`

如果您認為您的案例能受益於目前選項未涵蓋的其他解壓縮後材質像素 swizzle 轉換，請連絡您的 Microsoft 客戶經理。

<a id="PackagingData" />

## 為 MDU 封裝資料

建置要由 MDU 硬體解壓縮的資料串流時，有兩種主要路徑：主要用於非紋理資源的純 Deflate 壓縮，以及用於紋理資源的 Deflate 加 BCPack 壓縮。

在第一種案例中，您可以自由選擇最符合需求的資料串流大小，而第二種案例則會預先定義壓縮串流大小。不論哪種案例，基本需求都相同。與來自 NVMe SSD 的其他要求一樣，資料串流必須以 16 位元組對齊。

MDU 也支援一組有限的 swizzle 或重排選項，可與 Deflate 和 BCPack 搭配使用。如需這些格式的相關資訊，請參閱 [DirectStorage 重排格式](/zh-TW/build/console-features/storage/directstorage/directstorage-shuffles)。

<a id="Tiling" />

## 紋理磚化與 Sampler Feedback Streaming (SFS)

紋理磚化是將大型紋理分割成可個別載入之小型子區段的方法。有時也稱為部分常駐紋理 (PRT)、虛擬紋理或磚狀資源。

使用紋理磚化時，只會載入所需的紋理部分，因此遊戲可以隨時使用更多的紋理資源，更有效率地使用可用記憶體。

XBOX Series 主機的 GPU 中有硬體擴充功能，讓此系統在執行階段更容易實作且更有效率。這個合併的系統稱為 [Sampler Feedback Streaming (SFS)](/zh-TW/build/core-features/graphics/newfeatures/sfs/sf-overview)。

XBOX Series 主機的圖形資源使用 64 KiB 的頁面大小，這是將內容最佳化為 GPU 原生配置時，最常見原生紋理 swizzle 模式的大小。

SFS 的主要目標是確保您的遊戲能取得最大量的作用中圖形資源，做法是不將這些資源中未使用的部分保留在常駐記憶體中。因此，選擇 64 KiB 作為 SFS 的基本大小，因為紋理中每個 64 KiB 頁面都是獨立的，可以單獨載入和捨棄。

這是最精細且最有效率的記憶體使用方式。

如需紋理配置的詳細資訊，請參閱 [Sampler Feedback Streaming](/zh-TW/build/core-features/graphics/newfeatures/sfs/sf-overview) 和 [XBOX Series X|S 紋理配置 (新)](/zh-TW/build/core-features/graphics/scarlett-tex-layouts)。

為了說明紋理磚與 SFS 之間的關係，請考慮一個 2048 × 2048 的正方形 BC7 紋理。它由下列 86 個磚 (每個 64 KiB) 組成。BC7 每個 4 × 4 材質像素區塊需要 16 位元組，因此 mip0 需要 (2048 × 2048) = 4,194,304 位元組 = 4,096 KiB = 64 個 64 KiB 頁面。mip0 之後的每個 mip 都是四分之一大小，或屬於 mip 尾端的一部分，如圖 2 所示。

**圖 2. 顯示 2048 × 2048 BC7 紋理，由 86 個 64 KiB 頁面組成；針對 SFS 封裝時，每個頁面都是個別的可串流磚**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_TextureLayout.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=f35b0adb59508c9f6fbece522aa3cbf4" alt="2K BC7 紋理配置的螢幕擷取畫面" width="290" height="539" data-path="images/gdk/features/console/DSMDU_TextureLayout.png" />

任何部分常駐紋理的實作，都能以基本 64 KiB 磚大小的任何整數倍作為最小的載入和捨棄動作。SFS 使用基本的 64 KiB 大小，因此前述紋理會處理成 86 個壓縮串流，以便在執行階段個別擷取。

決定如何封裝遊戲資產時，壓縮性會因這些資源的編碼、串流大小和每個資源的內容而異。

圖 3 和圖 4 顯示兩個內容集區範例。這些圖表代表最初隨 XBOX One X HDR 和 4K 示範「Insects」一併出貨的 4096 × 4096 紋理集區。

每個圖表都顯示以特定編碼 (BC1 或 BC7) 處理的內容集區，然後透過下列案例進行封裝。

* 將資料分割為預先定義大小並個別壓縮的純 Deflate 壓縮 (zlib 或 zopfli)
* 使用 XBTC 的 Deflate 加 BCPack 壓縮
  * 以 zlib 或 zopfli 加 BCPack 壓縮的 SFS 64 KB 磚化
* 用於非 SFS 細節層級 (LOD) 串流的整個 mip 壓縮，使用 zlib 或 zopfli 加 BCPack

**圖 3. 顯示使用各封裝選項時 Insects HDR 4K BC7 內容集區的壓縮大小**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC7_Compresibility.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=5371fbbbb80f44034fad00e2381600d4" alt="使用各封裝選項時 Insects HDR 4K BC7 內容集區壓縮大小的螢幕擷取畫面 " width="634" height="381" data-path="images/gdk/features/console/DSMDU_BC7_Compresibility.png" />

**圖 4. 顯示使用各封裝選項時 Insects HDR 4K BC1 內容集區的壓縮大小**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC1_Compresibility.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=51b5ee2a54b5bd9a6fb311209d8d47cd" alt="使用各封裝選項時 Insects HDR 4K BC1 內容集區壓縮大小的螢幕擷取畫面 " width="635" height="382" data-path="images/gdk/features/console/DSMDU_BC1_Compresibility.png" />

隨著個別壓縮之磚和區塊的大小增加，兩種 Deflate 實作 (zlib 和 zopfli) 都能達到更好的壓縮比，但效益遞減 (較大的磚較佳)。

兩種 Deflate 選項的壓縮比都在約 1,024 KiB 的串流時達到最大值，更大的大小在這方面沒有任何優勢。Zopfli 的壓縮比比 zlib 更好 (1 到 2 個百分點)，但壓縮時間的計算成本高出許多 (約 10 倍)。

透過 XBTC 提供的 BCPack 加 Deflate 選項，其壓縮比明顯高於任何純 Deflate 選項。我們強烈建議紋理資源使用 BCPack 加 Deflate 選項。

<Note>
  `xbtc-mip` 封裝是每個 mip 一個資料串流，因此資料串流大小不固定。將其置於 4 MiB 磚大小以進行比較，是為了說明雖然它放棄了較小磚大小和更精細記憶體使用的優勢，但相較於主要 SFS 案例，它並未帶來壓縮上的改善。
</Note>

<a id="MemoryLimits" />

## DirectStorage 作業的記憶體集區需求

當遊戲第一次呼叫 [DStorageGetFactory](/zh-TW/reference/system/dstorage/functions/dstoragegetfactory) 初始化 DirectStorage 時，會為暫存緩衝區保留 32 MiB 的記憶體，其中包含目前進行中的作業。DirectStorage 初始化之後，可以使用 [SetStagingBuffer](/zh-TW/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setstagingbuffersize) 方法變更此預設大小，從而為您的遊戲節省記憶體。

此記憶體會與 DirectStorage 堆疊的其他階段共用。要求使用的最後一個階段會將最終輸出直接寫入遊戲記憶體。

以下是系統的限制。

* 對於解壓縮要求，壓縮大小必須小於解壓縮大小。
* <em>任何</em>單一 DirectStorage 要求的大小上限為 1 GiB。對於解壓縮要求，此值為來源與目的地大小的總和。

這些限制會在要求加入佇列時強制執行，而且可以使用 [SetDebugFlags](/zh-TW/reference/system/dstorage/interfaces/IDStorageFactoryX/methods/idstoragefactoryx_setdebugflags) 方法，針對這些錯誤狀況啟用其他偵錯行為。

<a id="XBTC" />

## XBOX 紋理壓縮工具 (XBTC.exe)

對於 XBOX Series 主機，您可以使用 GDK 中的 [XBTC](/zh-TW/build/core-features/graphics/newfeatures/xbtc/xbtc) 工具來匯入、匯出和編碼紋理。

這可透過 *XBTC.exe* 中的命令列介面、程式庫 *XBTC.dll*，或在符合額外 NDA 需求之後以原始程式碼形式完成。在預設的 GDK 安裝中，可在 \*C:\Program Files (x86)\Microsoft GDK\[version]\GXDK\bin\Scarlett\* 找到此工具組。

如果您需要存取工具組的原始程式碼，請連絡您的 Microsoft 客戶經理。

<a id="XBTC_importing" />

<h3 id="XBTC_importing">
  匯入內容
</h3>

XBTC 支援直接從多種格式匯入，包括 .png、.tiff 和 .jpg，也可以匯出為這些檔案類型。XBTC 包含 [BC1-BC7 GPU 格式](https://learn.microsoft.com/windows/win32/direct3d11/texture-block-compression-in-direct3d-11)的編碼器，並可將內容 swizzle 為 XBOX Series X|S 的原生 GPU 紋理配置，或從該配置進行 swizzle。

每當 XBTC 執行失真作業 (例如將原始資產轉換為區塊壓縮格式) 時，都會產生該轉換的影像品質指標。

匯出至 .dds 檔案時，只會使用 XBTC 的匯入器和 BC 編碼器部分。不會套用壓縮。

<a id="XBTC_compression" />

### 壓縮

XBTC 會處理選取的紋理區域，並將該區域壓縮為較大封存檔案中的子串流。根據預設，它會以三種不同方式壓縮每個區域 (純 Deflate、純 BCPack、先 BCPack 再 Deflate)。三者中的最佳結果會連同該區域的中繼資料一起儲存，另外兩個則會捨棄。

紋理如何分割成區域，取決於該紋理的預定用途，以及傳遞給 XBTC 的 `--tilemode` 和 `--mipstreams` 選項。

<a id="XBTC_SFS" />

#### SFS 區域選取

在 2K 正方形 BC7 紋理的範例中，基礎紋理配置有 86 個 64 KiB 頁面。

區域選取有兩種方法，如圖 5 所示。左側是 SFS 磚化模式，其中每個頁面都會個別處理，並預設所有 mip 都應可個別串流。結果為 86 個個別區域。

右側是相同的紋理，但向 XBTC 指定只有單一 mip 應可串流。在此情況下，會有 65 個串流：64 個用於 mip0，另外再加一個串流。額外的串流會將所有其他 mip 合併在一起，因為非可串流的 mip 一律常駐於記憶體中。

**圖 5. 顯示 (左) 具有 64 KiB SFS 磚化且所有 mip 皆可串流的 2K BC7 紋理 (86 個磚串流)，以及 (右) 只有一個可串流 mip 的相同 SFS 紋理 (65 個資料串流)**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_TextureLayout_SFS.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=216a502a1dfc92c97cc672c25b2080d2" alt="所有 mip 皆可串流及只有一個可串流 mip 之 SFS 紋理的螢幕擷取畫面" width="514" height="461" data-path="images/gdk/features/console/DSMDU_TextureLayout_SFS.png" />

<a id="XBTC_mips" />

#### 非 SFS 區域選取

對於任何不打算在 SFS 虛擬紋理設定中使用的內容，或只以整個 mip 為單位載入 LOD 的內容，適用相同的原則，只是區域較少。

對於相同的 2K BC7 紋理，使用預設的 64 KB 非 SFS 磚模式，會將圖 6 所示的五個區域個別壓縮。

如果您想指定只有兩個 mip 可串流，則會個別處理三個區域，其中 mip2-11 會合併在一律常駐的串流中。

**圖 6. 顯示 (左) 具有 64 KiB 非 SFS 磚化且所有 mip 皆可串流的 2K BC7 紋理 (五個資料串流)，以及 (右) 具有兩個可串流 mip 和一個包含 mip2-11 之一律常駐資料串流的相同紋理**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_TextureLayout_miptiles.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=cbd222101190311ca2493e8f2d83ed17" alt="所有 mip 皆可串流及只有一個可串流 mip 之非 SFS 紋理的螢幕擷取畫面" width="608" height="465" data-path="images/gdk/features/console/DSMDU_TextureLayout_miptiles.png" />

<Note>
  對於大於或等於 8K 的超大型紋理，mip 可能會超過 MDU 硬體允許的大小上限 (32 MiB)。為了解決此問題，即將推出的版本將提供選項，可將非 SFS 紋理 mip 分割成最適合循序載入大小的磚。
</Note>

<a id="XBTC_application" />

#### 套用

決定紋理中哪些區域要個別壓縮，並選取其中一種 Deflate 實作 (透過是否使用 `--usezopfli` 參數) 之後，每個區域會壓縮三次。分別以 Deflate 實作壓縮一次、以 BCPack 壓縮一次，以及同時套用兩者壓縮一次。

MDU 能以完整 IO 速度處理這些組合中的任何一種 (或未壓縮的內容)，因此您可以為指定的資料區域選取最佳編碼。產生的資料結構會封裝成 XBTC 封存檔案，其中包含一組壓縮串流以及描述它們的標頭。

您可以直接使用封存檔案，並以 GDK 範例中的程式碼作為載入的基礎，也可以擷取壓縮串流和中繼資料，重新封裝成最適合的任何容器。

在執行階段，標頭資料會直接提供給該資產的 DirectStorage 要求。

<a id="RDO" />

### 位元率失真最佳化 (RDO)

您可以使用 RDO 以壓縮品質換取更高的壓縮比。就區塊壓縮格式 (BC1-7) 而言，這可能只是以不同方式重新編碼區塊這麼簡單。

透過重新編碼，您可以減少存在的離散色彩點數量，或強制色彩點與相鄰的色彩點相符，讓套用至紋理的額外壓縮達到更高的比率。

2006 QFE1 GDK 版本為 XBTC 新增了 BC1-5 的 RDO 選項，其他模式將在未來的版本中推出。XBTC 中的 RDO 實作只存在於 BC 編碼器階段，並可在匯出回 .dds 檔案時使用。不過，它是針對 BCPack 壓縮器而設計的。

套用 RDO 比單純選取壓縮或品質設定更為複雜。不同類型和編碼的資產可能有不同的理想品質設定。正確的設定通常需要反覆調整規則系統，並在必要時進行抽查和調整。

為了協助完成此作業，XBTC 提供了額外的 `compare`、`view` 和 `export` 子命令。

您可以使用 `compare` 子命令執行影像品質分析。此子命令會將 RDO 資產與原始資產或 RDO 之前的 BC 資產進行比較。您可以使用這些子命令來建立各種規則。

例如，某個遊戲的規則可能是：對於 BC1 法線貼圖，可容許 2 分貝 (dB) 的峰值訊噪比 (PSNR) 損失。新增或變更資產時，需要完成一次性處理，以判斷哪個品質等級符合該可容許的品質損失。

您可以使用 `view` 子命令載入資產以進行檢查。這可讓您輕鬆抽查已處理的資產，並判斷是否需要變更規則或設定例外。您也可以保留該資訊供未來的組建使用。

您也可以將影像 `export` 回另一種格式，以便使用其他工具處理。

<Note>
  RDO 會改變壓縮比，而且可能對最佳載入有其他影響。
</Note>

BC1 內容通常比 BC7 更容易壓縮 (2:1 對比 1.6:1)，因此 BC1 64 KiB 磚的壓縮大小平均約為 32 KiB。使用 RDO 將壓縮大小再縮減 25%，並不直接等於輸出至記憶體的輸送量再增加 25%，因為大量小型 IO 要求會產生額外負荷。

如果您將磚化為較大的大小，MDU 的輸送量會直接隨著壓縮率而調整。不過，對於開始接近 MDU 8 GiB/s 輸出限制的高壓縮性內容，此效果會逐漸減弱。

圖 7 是這些效果組合的範例，使用來自 Insects HDR 和 4K 示範的 4K 解析度紋理。在此案例中，選取的 RDO (品質和壓縮) 設定讓產生的 XBTC 封存比預設的非 RDO 版本小約 14%。若與原始未壓縮大小相比，則再小 7%。

請注意，XBTC 中的 RDO 編碼器會優先組織資料，以便在 XBTC 壓縮鏈中以 BCPack 達到最佳壓縮。因此，SFS 案例的相對增益會高於以 Deflate 作為非 SFS 案例時，如圖 7 所示。

**圖 7.   顯示 Insects HDR 4K 內容集區的 BC1 大小與 RDO 選項的比較**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC1_Compresibility_RDO.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=c8bbccca29e6539272489ac50dc0e607" alt="Insects HDR 4K 內容集區的 BC1 大小與 RDO 選項比較的螢幕擷取畫面" width="693" height="382" data-path="images/gdk/features/console/DSMDU_BC1_Compresibility_RDO.png" />

在執行階段，這些效果的組合會產生下列輸送量特性。使用 XBTC 作為 RDO 編碼器，然後使用可變串流大小以非 SFS 形式封裝時，較大的大小 (大於或等於 128 KiB) 可觀察到輸送量增加約 13%。

此差異幾乎反映了壓縮優勢。較小的資料串流大小 (小於或等於 64 KiB) 則會導致改善效果遞減，如圖 8 所示。

**圖 8.   顯示 Insects HDR 4K 內容集區 (BC1) 的 MDU 輸送量與 RDO 選項的比較**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC1_Throughput_RDO.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=2c15d1d48931ab9898f0684ec27bfaa0" alt="Insects HDR 4K 內容集區 (BC1) 的 MDU 輸送量與 RDO 選項比較的螢幕擷取畫面" width="701" height="373" data-path="images/gdk/features/console/DSMDU_BC1_Throughput_RDO.png" />

<a id="BC7_modes" />

### BC7 編碼器模式限制

BC7 允許每個 4 × 4 材質像素群組[以 8 種模式中的任何一種進行編碼](https://learn.microsoft.com/windows/win32/direct3d11/bc7-format-mode-reference)，視哪種模式能為該群組保留最高的逼真度而定。

透過這種方式，編碼器能產生品質非常高的原生 GPU 紋理，但這也表示產生之紋理的編碼位元具有較高的熵，因為編碼模式經常在不同模式之間變更。BC7 紋理本質上比許多其他區塊壓縮格式更難壓縮。

XBTC 中的 BC7 編碼器包含限制可用模式的選項，直接犧牲格式的部分高逼真度以統一編碼模式，從而使其更容易壓縮。

使用這些選項可以大幅改變產生之紋理的壓縮性，不過建議您抽查並反覆調整這些設定，以確認產生的紋理只有很少或沒有可察覺的品質損失。

圖 9 顯示來自 XBOX One 示範 Insects HDR 的 4K 紋理資料集集區。啟用所有模式的一般 BC7 編碼所產生的紋理集區，Zopfli 可將其壓縮為原始大小的 64%，若使用 XBTC 與 BCPack 合併，則為 61.5%。

不過，如果只允許模式 7 (`--bc7modes 0x80`)，產生的紋理會更容易壓縮，壓縮比超過 2:1，而保留的紋理與以較低逼真度 BC1 編碼的相同紋理相比，具有 3-5dB 的 PSNR 優勢。

**圖 9.   顯示 Insects HDR 4K 內容集區的壓縮性，BC7 所有模式對比僅模式 7**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC7_Compresibility_mode7.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=eca29249d9584adc265edded70616977" alt="Insects HDR 4K 內容集區壓縮性 (BC7 所有模式對比僅模式 7) 的螢幕擷取畫面" width="695" height="381" data-path="images/gdk/features/console/DSMDU_BC7_Compresibility_mode7.png" />

此額外的壓縮比會直接轉換為載入時輸出至記憶體的更高輸送量。此 BC7 內容以預設值 (模式 0-7) 以及僅啟用模式 7 進行編碼時的輸送量特性，如圖 10 所示。

<Note>
  從 NVMe 的讀取速度幾乎相同，而僅模式 7 的內容在 MDU 輸出端測量時，具有約 20% 到 40% 的輸送量優勢。
</Note>

**圖 10.   顯示 Insects HDR 4K 內容集區 (BC7) 使用所有模式對比僅模式 7 時的 MDU 輸送量**

<img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC7_Throughput_mode7.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=583cd0458f7171eebef793517c0ee172" alt="Insects HDR 4K 內容集區 (BC7) 使用所有模式對比僅模式 7 時 MDU 輸送量的螢幕擷取畫面" width="785" height="410" data-path="images/gdk/features/console/DSMDU_BC7_Throughput_mode7.png" />

<a id="Considerations" />

## 最佳效能的考量事項

使用 MDU 進行解壓縮時，適用 [DirectStorage 使用方式與內部詳細資料](/zh-TW/build/console-features/storage/directstorage/directstorage-white-paper)主題中的指導方針。

<Note>
  保持足夠的進行中要求，讓管線保持滿載。例如，如果您每 16.7 毫秒加入佇列一次，則在該間隔期間可以載入 33.4 MB 的壓縮資料。
</Note>

若要在加入間隔期間保持管線滿載，請保持 33.4 MB 加 32 MiB 的進行中要求。總計約為 64 MiB。不過，由於 NVMe SSD 的實際輸送量可能隨時間變化，而且 2000 MB/s 的保證是針對任何 250 毫秒期間，因此遊戲應保持超過此 64 MiB 最低值的進行中要求，以協助將輸送量最大化。

以下是 MDU 硬體實作特有的其他因素。

* 對於提交給 MDU 硬體的每項工作，都有少量的初始化和設定成本。請避免大量的小型工作。實際上，如果您嘗試接近 NVMe SSD 的輸送量，要求的大小下限為壓縮後 32 KiB (解壓縮後 64 KiB)。
  * 不過，只有在串流大小為此大小的二到四倍時，才能達到最大輸送量。使用各封裝選項時，Insects HDR 示範的 4K 內容讀取輸送量在未壓縮大小低於 64 KiB 時會急遽下降，如圖 11 和圖 12 所示。**圖 11.   顯示使用各封裝選項時 Insects HDR 4K 內容集區 (BC1) 的載入輸送量** <img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC1_Throughput.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=6a05fb7b011b4f6b5905ce9343a3e1c0" alt="使用各封裝選項時 Insects HDR 4K 內容集區 (BC1) 載入輸送量的螢幕擷取畫面" width="701" height="402" data-path="images/gdk/features/console/DSMDU_BC1_Throughput.png" /> **圖 12.   顯示使用各封裝選項時 Insects HDR 4K 內容 (BC7) 的載入輸送量** <img src="https://mintcdn.com/microsoft-4404708b/CwRBzaXvHw9zaPoe/images/gdk/features/console/DSMDU_BC7_Throughput.png?fit=max&auto=format&n=CwRBzaXvHw9zaPoe&q=85&s=570b5425d470ed84ae2ade3b6b24570c" alt="使用各封裝選項時 Insects HDR 4K 內容 (BC7) 載入輸送量的螢幕擷取畫面" width="702" height="409" data-path="images/gdk/features/console/DSMDU_BC7_Throughput.png" />
* 壓縮資料大於 512 KiB 的大型要求會分割成多個 IO 要求，然後在從 NVMe SSD 擷取資料之後，以多個要求的形式提交給 MDU。這對大型要求的輸送量有輕微但可測量的影響，對壓縮後剛好超過此臨界值大小的資料串流影響最大。
* 壓縮比會直接影響解壓縮位元組輸出至遊戲記憶體的最終輸送量。RDO 或 BC7 模式限制會產生雙重效果：較小的壓縮大小和更快的載入時間。如需詳細資訊和範例，請參閱本主題的 [BC7 編碼器模式限制](#BC7_modes)一節和 [RDO](#RDO) 一節。
* 對於使用 XBTC SFS 64 KiB 磚化的紋理資料，搭配以每個磚為單位的 BCPack 和 Deflate，可產生最佳的硬體支援壓縮，並具有比其他選項更高 (或相當) 的輸送量。

## 另請參閱

[DirectStorage](/zh-TW/build/console-features/storage/directstorage-toc)

[DirectStorage 使用方式與內部詳細資料](/zh-TW/build/console-features/storage/directstorage/directstorage-white-paper)

[分析 DirectStorage 效能](/zh-TW/tools/tools-console/pix/pix-directstorage)

[GDK 範例清單](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/development-downloads/gdk-samples-list)


## Related topics

- [DirectStorage 概述](/zh-CN/build/console-features/storage/directstorage/directstorage-overview.md)
- [NDA 主題目錄 - Microsoft Learn 線上連結](/zh-TW/nda/nda-topic-directory.md)
- [DirectStorage](/zh-CN/build/console-features/storage/directstorage-toc.md)
- [DirectStorage の概要](/ja-jp/build/console-features/storage/directstorage/directstorage-overview.md)
- [DirectStorage Overview](/build/console-features/storage/directstorage/directstorage-overview.md)
