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

# Direct3D 12 差異：Windows PC 與 GDK Game OS

> Windows PC 上的 Direct3D 12 與 Microsoft GDK Game OS 之間的差異

Microsoft GDK Game OS 上的 Direct3D 12 (Direct3D 12.x) 與 Windows PC 上的 Direct3D 12 (Direct3D 12/PC) 有一些值得注意的差異。

<a id="ID4E1" />

## 一般差異

* Microsoft GDK Game OS 支援管線狀態物件 (PSO) 序列化/還原序列化，以避免在驅動程式中產生執行階段 PSO 建構成本。此功能與 ERA 中的相同。Microsoft GDK Game OS 會接受預先編譯的著色器、未預先編譯的著色器、衍生的著色器和序列化的 PSO 作為有效輸入。我們建議使用序列化的 PSO，以獲得更快的速度、節省空間並提供更好的使用者控制。
* XBOX 提供 ESRAM，可讓緩衝區和紋理資源使用最快速的記憶體。充分利用 ESRAM 對於高效能至關重要。請參閱 [XBOX One 的原生資源管理](/zh-TW/build/core-features/graphics/directx/native-resource-management) 中的「為緩衝區或紋理指定快速 ESRAM 記憶體」小節，並參閱 [XG 記憶體概觀](/zh-TW/build/core-features/graphics/d3d12x/xg-memory-overview)。
* Microsoft GDK Game OS 上的命令佇列不是執行緒安全的。遊戲有責任明確同步處理對圖形、計算及複製/DMA 命令佇列的多執行緒存取。若未這樣做，可能會導致在佇列上發出的命令損毀，進而造成 GPU 停止回應或當機。
* 在 XBOX 上，每種類型只能建立一個命令佇列，除非使用 CreateCommandQueueX 擴充功能，為命令佇列明確選取管道/引擎及 (針對計算) 佇列索引。無論使用哪個 API，都只能建立單一圖形命令佇列。每個可用的 GPU 管道/引擎和佇列索引可以建立一個計算或複製/DMA 佇列。
* Microsoft GDK Game OS 資源屏障鼓勵廣泛使用 D3D12\_RESOURCE\_BARRIER\_FLAG\_BEGIN\_ONLY 和 D3D12\_RESOURCE\_BARRIER\_FLAG\_END\_ONLY 轉換，並建議在建立特定資源類型時指定額外的 D3D12XBOX\_RESOURCE\_FLAG\_PREFER\* 旗標 (請參閱 [D3D12\_RESOURCE\_FLAGS](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_resource_flags))。請參閱下方的「資源屏障」一節，以及 [D3D12\_RESOURCE\_BARRIER\_FLAGS](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_resource_barrier_flags)。
* Microsoft GDK Game OS 支援的呈現模型不同於 PC 上 Direct3D 12 的交換鏈 **Present** 系統。若要深入了解新的呈現模型，請參閱 [XBOX One 上的畫面排程與呈現](/zh-TW/build/core-features/graphics/directx/frame-scheduling-and-presentation)。
* Microsoft GDK Game OS 鼓勵以壓縮狀態存取多重取樣轉譯目標以提升效能，也鼓勵使用壓縮的深度/樣板資源。請參閱下方「資源屏障」一節中的「直接使用壓縮資源」。
* Microsoft GDK Game OS 支援多種 GPU 專屬的硬體擴充功能。
* Microsoft GDK Game OS Direct3D 12.x 擴充功能提供下列項目：
  * 其他描述元堆積類型
  * 直接操作描述元
  * 根簽章組合與廣播變體
  * 命令清單的非同步執行 (在關閉前執行)
* 遊戲有責任確保 GPU 在終結資源之前已完成對該資源的所有存取。遊戲必須在資源存取結束後插入柵欄，並等待通過這些柵欄後，才能將資源物件的參考計數釋放為 0。
* Microsoft GDK Game OS 不支援搭配標準 [ID3D12GraphicsCommandList](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12graphicscommandlist/id3d12graphicscommandlist) 介面使用 COPY 命令清單類型 ([D3D12\_COMMAND\_LIST\_TYPE\_COPY](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_command_list_type))。相反地，Microsoft GDK Game OS 為複製提供專用介面 ([ID3D12XboxDmaCommandList](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12xboxdmacommandlist/id3d12xboxdmacommandlist))。此介面包含 **ID3D12GraphicsCommandList** 的標準複製功能，以及 XBOX DMA 引擎硬體的擴充功能，例如 LZ 壓縮/解壓縮和 JPEG 解碼。如果您打算為 Direct3D 12 複製命令清單撰寫跨平台程式碼，建議您對複製命令清單介面使用 `typedef`，在 Microsoft GDK Game OS 上將其定義為 **ID3D12XboxDmaCommandList**，在 PC 上則定義為 **ID3D12GraphicsCommandList**。

<a id="drivers" />

## 零售版、檢測版和偵錯版驅動程式

透過 Gaming eXtensions Development Kit (GXDK)，可以使用三種驅動程式來協助測試和偵錯遊戲。

**零售版驅動程式：** 針對效能最佳化，而非針對檢測或偵錯。不會檢查參數的正確性。傳遞給零售版驅動程式的不正確參數很可能會造成損毀、當機或 GPU 停止回應。遊戲只能以零售版驅動程式發行。其他驅動程式 (檢測版和偵錯版) 只存在於開發套件上。

**檢測版驅動程式：** 啟用 PIX 檢測。相當輕量。可用來協助偵錯同步處理和其他計時問題。不會檢查參數的正確性。

**偵錯版驅動程式：** 對傳遞給 API 呼叫的參數執行驗證測試，有助於偵錯正確性和效能問題。不過，使用偵錯版驅動程式時可能無法重現計時錯誤，因為驗證處理會影響執行階段效能。若要調整驗證層級，請呼叫 [ID3D12Device::SetDebugFlagsX](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_setdebugflagsx)。

若要選取要使用的驅動程式，請呼叫下列其中一個方法。

* [D3D12XboxSetProcessDebugFlags](/zh-TW/reference/graphics/d3d12_x/functions/d3d12xboxsetprocessdebugflags)
* [ID3D12Debug::SetProcessDebugFlags](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12debug/methods/id3d12debug_setprocessdebugflags)
* [ID3D12Debug::EnableDebugLayer](https://msdn.microsoft.com/library/windows/desktop/dn986877\(v=vs.85\).aspx)

<a id="offline_psos" />

## 離線和衍生的管線狀態物件 (PSO)

離線管線狀態物件 (PSO) 將管線狀態 (包括著色器) 封裝成可快速載入和設定的單一物件，因此相較於在執行階段建立管線狀態，可大幅提升效能。離線 PSO 會儲存預先編譯的著色器、轉譯目標和深度樣板的狀態。

離線 PSO 物件儲存在磁碟上，之後在需要時由應用程式載入。在 PC 上，有一個類似但不完全相同的系統，稱為 *PSO 快取*。

若要建立離線 PSO 物件，可以使用 PSO 工具 (以 Microsoft Game Development Kit (GDK) 範例形式提供，位於 GXDK `\bin` 資料夾中)，或撰寫您自己的工具來使用下列管線狀態序列化 API。

<a id="ID4EWF" />

### 離線 PSO 的 API

下列 API 可操作離線 PSO。

* [ID3D12Device::SerializeGraphicsPipelineStateX](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_serializegraphicspipelinestatex)：此方法會序列化 PSO，以便在執行階段有效率地載入。它的用途是在 PC 上執行的離線內容建立流程中呼叫 (由驅動程式 `umd12_pc.dll` 或 `xgs12_pc_xs.dll` 支援)，而不是在遊戲執行階段呼叫。
* [ID3D12Device::DeserializeGraphicsPipelineStateX](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_deserializegraphicspipelinestatex)：此方法會還原序列化 (載入) 先前序列化的圖形 PSO。此方法永遠不會叫用執行階段著色器編譯，但在極少數情況下，此方法會叫用一個錯誤，指出較舊的 PSO 需要重新編譯。
* [D3D12XBOX\_SERIALIZE\_SHADER](/zh-TW/reference/graphics/d3d12_x/structs/d3d12xbox_serialize_shader)：此結構包含指向序列化著色器 GPU 指令的指標，可能還包含序列化的中繼資料。
* [D3D12XBOX\_DESERIALIZE\_SHADER](/zh-TW/reference/graphics/d3d12_x/structs/d3d12xbox_deserialize_shader)：此結構包含指向原始還原序列化著色器 GPU 指令和還原序列化中繼資料的指標。
* [D3D12XBOX\_SERIALIZE\_FLAGS](/zh-TW/reference/graphics/d3d12_x/enums/d3d12xbox_serialize_flags)：此列舉定義序列化旗標。
* [D3D12XBOX\_SERIALIZE\_GRAPHICS\_PIPELINE\_STATE](/zh-TW/reference/graphics/d3d12_x/structs/d3d12xbox_serialize_graphics_pipeline_state)：此結構包含序列化的管線狀態。
* [D3D12XBOX\_DESERIALIZE\_GRAPHICS\_PIPELINE\_STATE](/zh-TW/reference/graphics/d3d12_x/structs/d3d12xbox_deserialize_graphics_pipeline_state)：此結構包含還原序列化的管線狀態。

<a id="ID4EOH" />

### 衍生的 PSO


由於管線狀態的變更數量可能比應用程式所需的還多，為每個變化建立離線 PSO 並不合理。相反地，請為常用的基本狀態建立離線 PSO，然後使用衍生的 PSO 對離線 PSO 進行有限的修改。對離線 PSO 所做的修改不能涉及著色器或轉譯目標的變更。

對於典型的遊戲，大多數 PSO 物件應以離線方式建立，並在執行階段使用下列 API 進行排列組合。

* [ID3D12Device::CreateDerivedGraphicsPipelineStateX](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_createderivedgraphicspipelinestatex)：此方法提供有效率的方式，從來源圖形 PSO 衍生建立圖形 PSO 的變化。此方法保證在建立過程中不會進行著色器重新編譯或修補。
* [D3D12XBOX\_DERIVED\_GRAPHICS\_STATE\_TYPE](/zh-TW/reference/graphics/d3d12_x/enums/d3d12xbox_derived_graphics_state_type)：此列舉識別可以變更的狀態 (深度/樣板、點陣化、混合和取樣遮罩)。
* [D3D12XBOX\_DERIVED\_GRAPHICS\_STATE\_DESC](/zh-TW/reference/graphics/d3d12_x/structs/d3d12xbox_derived_graphics_state_desc)：此結構保存新的所需狀態的描述。

如果來源 PSO 是透過呼叫 [ID3D12Device::DeserializeGraphicsPipelineStateX](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_deserializegraphicspipelinestatex) 建立的，應用程式有責任確保 GPU 指令在原始物件和衍生物件的存留期間都持續存在。如果來源 PSO 是使用標準 Direct3D 12 方法 [ID3D12Device::CreateGraphicsPipelineState](https://msdn.microsoft.com/library/windows/desktop/dn788663%28v=vs.85%29.aspx) 建立的，Direct3D 12.x 會自動為來源物件增加參考計數，以確保其 GPU 指令在衍生物件的存留期間持續存在。

<a id="ID4EZAAC" />

### 示範離線 PSO 和衍生 PSO 的範例

Deferred Context Direct3D 12.x 範例使用離線 PSO 和衍生的 PSO。

下列 Direct3D 12.x 範例使用離線 PSO。

* Bokeh Effect
* Compute Particles
* Deferred Particles
* Draw Bundles
* Dynamic Cube Map
* ESRAM
* Mesh Rendering
* Simple Bezier
* Simple Instancing
* Simple Lighting
* Simple Triangle

如需詳細資訊，請參閱 [Microsoft Game Development Kit 範例清單](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/development-downloads/gdk-samples-list) 主題。

<a id="ID4EGEAC" />

## 描述元堆積

在 Windows PC 上，使用 [D3D12\_DESCRIPTOR\_HEAP\_FLAG\_SHADER\_VISIBLE](https://msdn.microsoft.com/library/windows/desktop/Dn859378\(v=VS.85\).aspx) 建立的描述元堆積無法作為描述元複製的來源。

在 Microsoft Game Development Kit (GDK) 上，使用 [ID3D12Device::CopyDescriptors](https://msdn.microsoft.com/library/windows/desktop/dn899176\(v=vs.85\).aspx) 和 [ID3D12Device::CopyDescriptorsSimple](https://msdn.microsoft.com/library/windows/desktop/dn899177\(v=vs.85\).aspx) 建立的描述元複製支援將所有描述元堆積作為來源堆積，而且複製作業會透過來源堆積的高效快取唯讀檢視來執行。

<a id="ID4E4EAC" />

## 資源建立

間接引數資源必須在建立資源時指定 D3D12XBOX\_RESOURCE\_FLAG\_ALLOW\_INDIRECT\_BUFFER。具有此旗標的資源必須轉換為 D3D12\_RESOURCE\_STATE\_INDIRECT\_ARGUMENT 資源狀態。在 Microsoft GDK Game OS 上，D3D12\_RESOURCE\_STATE\_INDIRECT\_ARGUMENT 不包含在 D3D12\_RESOURCE\_STATE\_GENERIC\_READ 組合資源狀態中。

在 Microsoft GDK Game OS 上，D3D12\_RESOURCE\_STATE\_GENERIC\_READ 的宣告如下：

```cpp theme={null}
D3D12_RESOURCE_STATE_GENERIC_READ =
    D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER |
    D3D12_RESOURCE_STATE_INDEX_BUFFER |
    D3D12_RESOURCE_STATE_COPY_SOURCE |
    D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
    D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE  
```

相較之下，在 Direct3D 12/PC 上，D3D12\_RESOURCE\_STATE\_GENERIC\_READ 的宣告除了前述的值之外，還包含 D3D12\_RESOURCE\_STATE\_INDIRECT\_ARGUMENT。

如需詳細資訊，請參閱 [D3D12\_RESOURCE\_FLAGS](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_resource_flags) 和 [D3D12\_RESOURCE\_STATES](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_resource_states)。

<a id="resource_barriers" />

## 資源屏障

資源屏障會通知驅動程式，可能需要同步處理對單一資源的多個存取，例如同步處理對同一個紋理的讀取和寫入。

Microsoft GDK Game OS GXDK 版本的 [ID3D12GraphicsCommandList::ResourceBarrier](https://msdn.microsoft.com/library/windows/desktop/dn903898\(v=vs.85\).aspx) 支援 D3D12\_RESOURCE\_STATE\_COPY\_SOURCE 和 D3D12\_RESOURCE\_STATE\_COPY\_DEST 旗標的組合，因此支援資源內複製。資源內複製是指來源和目的地位於同一個資源的同一個子資源中。

* [資源屏障的 API](#ID4EFGAC)
* [用途轉換時的資源屏障](#ID4EHHAC)
* [直接使用壓縮資源](#ID4EFIAC)
* [在包含與不包含寫入存取的用途狀態之間轉換的屏障](#ID4EQJAC)

<a id="ID4EFGAC" />

### 資源屏障的 API

在 Microsoft GDK Game OS 上，資源屏障是透過呼叫下列方法來實作。

* **ID3D12GraphicsCommandList::ResourceBarrier**。此方法會通知驅動程式需要同步處理對資源的多個存取。此方法 (針對 PC 上的用法) 在 Microsoft Docs 上有詳細的說明：[ID3D12GraphicsCommandList::ResourceBarrier](https://msdn.microsoft.com/library/windows/desktop/dn903898\(v=vs.85\).aspx)。[ID3D12GraphicsCommandList](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12graphicscommandlist/id3d12graphicscommandlist) 的 XBOX 專屬方法記載於 GDK 中。
* [ID3D12XboxDmaCommandList::ResourceBarrier](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12xboxdmacommandlist/methods/id3d12xboxdmacommandlist_resourcebarrier)

<a id="ID4EHHAC" />

### 用途轉換時的資源屏障

在 Windows PC 上，資源屏障可以執行保守的 GPU 閒置以及快取的排清/失效。相較之下，在 Microsoft GDK Game OS 上，資源屏障會在用途轉換時執行保守的同步處理、失效和解壓縮。

作為此差異的一部分，有一些建議 (但非必要) 的 XBOX 專屬資源建立旗標。

* D3D12XBOX\_RESOURCE\_FLAG\_PREFER\_INDEX\_BUFFER
* D3D12XBOX\_RESOURCE\_FLAG\_PREFER\_INDIRECT\_BUFFER
* D3D12XBOX\_RESOURCE\_FLAG\_PREFER\_PREDICATION\_BUFFER
* D3D12XBOX\_RESOURCE\_FLAG\_PREFER\_STREAM\_OUTPUT
* D3D12XBOX\_RESOURCE\_FLAG\_DENY\_COMPRESSION\_DATA

這些旗標是 Microsoft GDK Game OS Direct3D 12.x 擴充功能，屬於 [D3D12\_RESOURCE\_FLAGS](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_resource_flags) 列舉常數。

<a id="ID4EFIAC" />

### 直接使用壓縮資源

下列資源用途類型會在資源屏障轉換時抑制解壓縮，並允許以壓縮狀態使用資源。

* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_COMPRESSED\_COLOR
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_COMPRESSED\_DEPTH
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_COMPRESSED\_STENCIL
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_COMPRESSED\_DEPTH\_STENCIL
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_INDIRECT\_COLOR\_CLEAR
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_SCATTERED\_COLOR\_FMASK

有一組對應的 PRESERVE\_EXPANDED 旗標，作為 PRESERVE\_COMPRESSED 旗標的對應項，可在通常會重新啟用壓縮的轉換之後，讓資源保持在解壓縮狀態。

* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_EXPANDED\_COLOR
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_EXPANDED\_DEPTH
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_EXPANDED\_STENCIL
* D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_EXPANDED\_DEPTH\_STENCIL

例如，從多重取樣資源的讀取狀態切換到 D3D12\_RESOURCE\_STATE\_RENDER\_TARGET 狀態時，可以使用 D3D12XBOX\_RESOURCE\_STATE\_PRESERVE\_EXPANDED\_COLOR，以防止對目標的新寫入以壓縮方式儲存。

這兩組旗標都是 Microsoft GDK Game OS Direct3D 12.x 擴充功能，屬於 Microsoft GDK Game OS 專屬的 [D3D12\_RESOURCE\_STATES](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_resource_states) 列舉常數。

<a id="ID4EQJAC" />

### 在包含與不包含寫入存取的用途狀態之間轉換的屏障

在 Microsoft GDK Game OS 上，除了 Direct3D 12/PC 的方法之外，執行屏障轉換的建議方法是識別從包含寫入存取的用途狀態轉換到不包含寫入存取的用途狀態的屏障。當這些屏障在 D3D12\_RESOURCE\_BARRIER\_ALL\_SUBRESOURCES 上執行，且有獨立的 GPU 工作可供執行時，應將其分割為分割屏障，使用 BEGIN\_ONLY 和 END\_ONLY 呼叫，如下所示。

1. 使用 D3D12\_RESOURCE\_BARRIER\_FLAG\_BEGIN\_ONLY 開始新狀態的屏障轉換 (但不完成)，使資源處於暫時無法存取的狀況。
2. 將獨立的工作新增至命令清單。
3. 在後續的 **ResourceBarrier** 呼叫中使用 D3D12\_RESOURCE\_BARRIER\_FLAG\_END\_ONLY 完成轉換，從暫時無法存取的狀況和舊狀態切換為新狀態中的使用中存取。

BEGIN/END 旗標可以搭配 [D3D12\_RESOURCE\_BARRIER\_TYPE\_UAV](https://msdn.microsoft.com/library/windows/desktop/Dn770393\(v=VS.85\).aspx) 類型使用。

前面提到的 D3D12\_RESOURCE\_BARRIER\_ALL\_SUBRESOURCES 是 Direct3D 12.x 和 Direct3D 12/PC 的 `#define` 值。

請參閱 [D3D12\_RESOURCE\_BARRIER\_FLAGS](/zh-TW/reference/graphics/d3d12_x/enums/d3d12_resource_barrier_flags)。

<a id="ID4EWKAC" />

## 對齊方式的差異

Microsoft GDK Game OS 上的資料列間距對齊為 1024 位元組，而不是 PC 上的 512 位元組 (這是透過將 D3D12XBOX\_TEXTURE\_DATA\_PITCH\_ALIGNMENT 設定為 1024 來定義)。此外，PC 要求緩衝區以 64 KB/4 MB 對齊的需求並不適用於 XBOX，即使不遵守這些對齊方式時，驗證程式碼仍可能顯示錯誤。

常數緩衝區的預設對齊為 16 位元組，而不是 PC 上的 256 位元組。此對齊是由 D3D12\_CONSTANT\_BUFFER\_DATA\_PLACEMENT\_ALIGNMENT 常數指定。

<a id="ID4E4KAC" />

## 另請參閱

[d3d12x](/zh-TW/reference/graphics/d3d12_x/d3d12_x_members)


## Related topics

- [NDA 主題目錄 - Microsoft Learn 線上連結](/zh-TW/nda/nda-topic-directory.md)
- [Guia de programação do Direct3D 12](/pt-BR/build/gdk-and-engines/guides/directx-12-programming-guide.md)
- [Direct3D 12 programming guide](/build/gdk-and-engines/guides/directx-12-programming-guide.md)
- [Project templates in Visual Studio for PC game development](/tools/tools-pc/visualstudio/gr-vs-templates.md)
- [Guide de programmation Direct3D 12](/fr/build/gdk-and-engines/guides/directx-12-programming-guide.md)
