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

# 將著色器從 FXC 移植至 DXC

> 將著色器從 FXC 移植至 DXC

## 簡介

將現有的高階著色器語言 (HLSL) 著色器從 D3DCompiler (FXC) 移植至 DXCompiler (DXC) 時，應以本主題作為參考依據。具體來說，本主題提供下列項目的詳細資訊：

1. 啟用部分在 DXC 上預設停用的舊 FXC 編譯行為。DXC 透過下列編譯器旗標支援此功能：
   * `-Gec`：啟用 Direct3D 9 回溯相容性 (例如，啟用僅在 Direct3D 9 以前受支援之 `COLOR` 語意的支援)。
   * `-HV`：將語言版本設為 2016 (也就是 `-HV 2016`) 以啟用 FXC 回溯相容性。這會啟用 FXC 上可用的特定舊版語言語意。
   * `-flegacy-macro-expansion`：在執行語彙基元貼上作業之前展開運算元 (FXC 行為)。
   * `-flegacy-resource-reservation`：保留未使用的明確暫存器指派，以便與著色器模型 5.0 及更早版本相容。
   * `-D __XBOX_PRECOMPILE_ALL_STAGES`：對於 XBOX Series X|S，著色器預先編譯要保守得多。XBOX One 的預設值維持不變。如需詳細資訊，請參閱 [XBOX 定義](/zh-TW/tools/tools-console/shadercompiler/dxc-xbox-defines)。
2. 提供有關在 FXC 上受支援但在 DXC 上不再受支援之舊版已淘汰 HLSL 語法的資訊。

## 編譯器 .dll 介面變更

建議使用新的 `IDxcCompiler3::Compile` 函式來編譯 DXC 著色器。如需可讓現有程式碼更容易移植至新介面的協助程式常式以及範例程式碼的詳細資訊，請參閱[使用 DXC](/zh-TW/tools/tools-console/shadercompiler/dxc-usage)。

## 與 FXC 行為的回溯相容性

### 內建函式 [pow](https://learn.microsoft.com/windows/desktop/direct3dhlsl/dx-graphics-hlsl-pow) 的純乘法模式

根據預設，DXC 一律使用 *log-mul-exp 模式* (說明如下) 來實作 **pow** 函式。相反地，FXC 在某些情境中也會改用 *純乘法* 模式來實作 **pow** 函式。例如，對於較小的 *y* 常數值 (例如 *pow(x, 3)*)，FXC 會使用 *純乘法* 模式。這可能導致 **pow** 函式在某些情況下，使用 FXC 與 DXC 編譯時產生不同的結果。例如，對於執行階段值 *x=0*，*pow(x,3)* 在 DXC 與 FXC 上分別評估為 *NaN* 與 *0*。若要在 DXC 上達成與 FXC 相同的 **pow** 函式行為，請在編譯期間將語言版本設為 2016 (使用旗標 `-HV 2016`)。

#### 使用 log-mul-exp 模式實作 pow 的範例

```C++ theme={null}
pow(x,y) = e^(log(x) * y)
```

### 使用純乘法模式實作 pow 的範例

```C++ theme={null}
pow(x,3) = (x * x) * x
```

### 超出範圍的陣列存取

根據預設，DXC 在發現對陣列的常數索引參考超出範圍時會發生錯誤。例如，下列 HLSL 著色器會編譯失敗，並出現錯誤訊息：`error: array index 3 is out of bounds`。只有當超出範圍的存取發生在未使用或無效的程式碼中時，您才能將語言版本設為 2016 (也就是使用 `-HV 2016` 旗標)，將此錯誤轉換為警告。

```C++ theme={null}
void main()
{
  uint x[2];
  x[3]=1.f; // Out-of-bound access.
}
```

### 無法遵循 unroll 屬性時發出警告

當迴圈套用了 **unroll** 屬性，且無法在編譯時期確定迴圈次數或迴圈次數超過特定閾值時，根據預設，DXC 會無法編譯如下列的著色器。若要將此失敗轉換為警告，請將語言版本設為 2016。在 DXC 上使用 `-HV 2016` 旗標編譯下列著色器時，它會在不展開迴圈的情況下成功編譯，並產生警告訊息：`warning: Could not unroll the loop.`

```C++ theme={null}
uint main(uint x : IN) : OUT
{
   uint r = 0;
   [unroll]
   for(uint i=0; i<x; i++)
    r+=i;
   return r;
}
```

### COLOR 語意

DXC 預設不支援 COLOR 語意。撰寫以 DXC 為目標的新 HLSL 著色器時，您應改用 [SV\_Target](https://learn.microsoft.com/windows/desktop/direct3dhlsl/dx-graphics-hlsl-semantics#migration-from-direct3d-9-to-direct3d-10-and-later)。不過，DXC 也提供選項，可透過傳遞 `-Gec` 旗標來編譯參考 COLOR 語意的著色器。例如，使用 `-Gec` 旗標時，下列 HLSL 程式碼應可在 DXC 上成功編譯。

```C++ theme={null}
float main() : COLOR
{
    return 1.f;
}
```

### 常數陣列上的 Length 屬性

在 `-Gec` 旗標下，DXC 支援常數陣列上的 `Length` 屬性，如下列範例所示。

```C++ theme={null}
uint main() : OUT
{
    int x[5];
    return x.Length;
}
```

### 寫入全域變數

在 HLSL 中，全域變數被視為常數，但與 FXC 相同，DXC 也可透過 `-Gec` 旗標支援寫入全域變數，如下列範例所示。

```C++ theme={null}
float gvar; // Write enabled with "-Gec"

float4 main(uint a : A) : SV_Target
{
  gvar = a * 2.0f;  
  return (float4) gvar;
}
```

### 使用 `-flegacy-resource-reservation` 旗標的舊版資源保留

對於著色器模型 5.0 或更早版本，FXC 在為已使用的資源進行暫存器配置時，會將未使用資源的暫存器配置納入考量。例如，在 FXC 上以 SM5.0 與 5.1 編譯下列著色器時，`Tex1[1]` 分別繫結至 `t4` 與 `t0`。使用 DXC 時，若要以 SM5.0 或更早版本達成 FXC 的資源配置行為，請使用 `-flegacy-resource-reservation` 旗標。

```C++ theme={null}
Texture2D Tex0[2] : register(t1);
Texture2D Tex1[2];

float4 main() : SV_Target
{
    return Tex1[1].Load((uint3)0);
}
```

#### FXC 搭配 SM5.0 的資源繫結

```C++ theme={null}
// Resource bindings:
//
// Name                                 Type  Format         Dim      HLSL Bind  Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// Tex1[1]                           texture  float4          2d             t4      1
```

#### FXC 搭配 SM5.1 的資源繫結

```C++ theme={null}
// Resource bindings:
//
// Name                                 Type  Format         Dim      ID      HLSL Bind  Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// Tex1                              texture  float4          2d      T0             t0      2
```

#### DXC 搭配 SM6.0 且不使用 `-flegacy-resource-reservation` 旗標的資源繫結

```C++ theme={null}
// Resource bindings:
//
// Name                                 Type  Format         Dim      ID      HLSL Bind  Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// Tex1                              texture     f32          2d      T0             t0     2
```

#### DXC 搭配 SM6.0 且使用 `-flegacy-resource-reservation` 旗標的資源繫結

```C++ theme={null}
// Resource bindings:
//
// Name                                 Type  Format         Dim      ID      HLSL Bind  Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// Tex1                              texture     f32          2d      T0             t3     2
```

### 使用 `-flegacy-macro-expansion` 旗標的舊版巨集展開

下列 HLSL 著色器在 FXC 上可成功編譯，但在 DXC 上會發生錯誤，因為 `b##slot` 會被替換為 `bSLOT_VAL` 而非 `b3`，因而導致編譯失敗。若要在 DXC 上達成 FXC 的語彙基元替換行為，請使用額外的旗標 "`-flegacy-macro-expansion`" 進行編譯。

```C++ theme={null}
#define SLOT_VAL 3
#define CBUFFER_ALIGNED( name, slot ) cbuffer name : register( b##slot )

CBUFFER_ALIGNED( MyCBuffer, SLOT_VAL )
{
       float4        val;
};
```

在此情況下，您可以遵循標準前置處理器規則來避免使用 -flegacy-macro-expansion 旗標。

```C++ theme={null}
#define SLOT_VAL 3
#define PASTE1(a, b) a##b
#define PASTE(a, b) PASTE1(a, b)
#define CBUFFER_ALIGNED( name, slot ) cbuffer name : register( PASTE(b, slot) )
CBUFFER_ALIGNED( MyCBuffer, SLOT_VAL )
{
       float4        val;
};
```

對於語彙基元不是巨集引數的情況，-flegacy-macro-expansion 並沒有幫助，但 fxc 仍會展開這些語彙基元。即使使用了 -flegacy-macro-expansion，下列程式碼仍會導致錯誤。

```C++ theme={null}
#define C 4
#define A4 float4
#define TYPE A##C

#define FUNC(ty) ty main() : OUT { return 0; }
FUNC(TYPE)
```

下列變更會讓 HLSL 與標準前置處理器規則相容，不再需要 -flegacy-macro-expansion 選項。

```C++ theme={null}
#define C 4
#define A4 float4
#define PASTE1(a, b) a##b
#define PASTE(a, b) PASTE1(a, b)
#define TYPE PASTE(A, C)

#define FUNC(ty) ty main() : OUT { return 0; }
FUNC(TYPE)
```

## 不受支援的 FXC 行為

### Effect Framework

與效果架構相關的功能已不再受支援。

### 進入函式上的 Uniform 參數

進入函式上的 Uniform 參數已不再受支援。

### 介面

介面已不再受支援。

### 不再支援維度特定的紋理取樣函式

[tex1D](https://learn.microsoft.com/windows/desktop/direct3dhlsl/dx-graphics-hlsl-tex1d)、[tex2D](https://learn.microsoft.com/windows/desktop/direct3dhlsl/dx-graphics-hlsl-tex2d) 與類似取樣函式的支援現已淘汰。若要了解如何移植至受支援的取樣函式，請參閱下列範例。

#### 使用已不再受支援之舊取樣語法的範例

```C++ theme={null}
sampler FontTextureSampler : register(s0);
struct VS_OUT
{
   float2 TexCoord0 : TEXCOORD0;
};

float4 PSMain_Unsupported( VS_OUT In ) : SV_Target
{
    return tex2D( FontTextureSampler, In.TexCoord0 ).zyxw; // tex2D is unsupported.
}
```

#### 顯示受支援取樣語法的範例

```C++ theme={null}
SamplerState FontTextureSampler : register(s0);
Texture2D FontTexture2D : register( t0 ); // Step 1. Declare texture.

struct VS_OUT
{
   float2 TexCoord0 : TEXCOORD0;
};

float4 PSMain( VS_OUT In ) : SV_Target
{
    // Step 2. Use "Sample" method of the texture declared in the previous step.
    return FontTexture2D.Sample( FontTextureSampler, In.TexCoord0 ).zyxw;
}
```

### 不支援語意重疊

DXC 不允許使用重複的語意。例如，下列著色器將在 DXC 上編譯失敗。

```C++ theme={null}
uint main(uint a : SV_VertexID, uint b : SV_VertexID) : OUT
{
    return a + b;
}
```

### 不支援以 "ConstantBuffer" 作為常數緩衝區名稱

從 SM5.1 開始，HLSL 使用 *ConstantBuffer* 範本建構支援[可索引的常數緩衝區](https://learn.microsoft.com/windows/desktop/direct3d12/resource-binding-in-hlsl#constant-buffers)。因此，*ConstantBuffer* 是保留關鍵字，DXC 不允許將其用作緩衝區名稱。

```C++ theme={null}
cbuffer ConstantBuffer : register(b0) // ConstantBuffer as buffer name not allowed.
{
 float2 field1;
 float field2;
}
```

## 聯絡我們

如果您有疑問、需要協助或想要回報問題，可以透過 [AskHLSL@microsoft.com](mailto:AskHLSL@microsoft.com) 與我們聯絡。

## 另請參閱

[著色器編譯器](/zh-TW/tools/tools-console/shadercompiler/shader-compiler)


## Related topics

- [適用於 XBOX GDK 的 HLSL 著色器編譯器 (DXC)](/zh-TW/tools/tools-console/shadercompiler/index.md)
- [NDA 主題目錄 - Microsoft Learn 線上連結](/zh-TW/nda/nda-topic-directory.md)
- [移植到 XBOX GDK 的指南](/zh-TW/home/build-first-title/porting-guides.md)
- [XBOX GDK 主機開發的 NDA 主題索引](/zh-TW/nda/nda-overview.md)
- [D3D12_SHADER_BYTECODE](/zh-TW/reference/graphics/d3d12/structs/d3d12_shader_bytecode_public.md)
