DXGI_SWAP_CHAIN_DESC 结构体详解

DXGI_SWAP_CHAIN_DESC 是 DirectX Graphics Infrastructure (DXGI) 中用于描述交换链(Swap Chain)配置的核心结构体。交换链是 D3D 渲染中用于管理前后缓冲区的机制,实现流畅的画面显示。


结构体定义

typedef struct DXGI_SWAP_CHAIN_DESC {
    DXGI_MODE_DESC      BufferDesc;     // 缓冲区显示模式
    DXGI_SAMPLE_DESC    SampleDesc;     // 多重采样设置
    DXGI_USAGE          BufferUsage;    // 缓冲区用途
    UINT                BufferCount;    // 缓冲区数量
    HWND                OutputWindow;   // 输出窗口句柄
    BOOL                Windowed;       // 是否窗口模式
    DXGI_SWAP_EFFECT    SwapEffect;     // 交换效果
    UINT                Flags;          // 标志位
} DXGI_SWAP_CHAIN_DESC;

各字段详解

1. BufferDesc (DXGI_MODE_DESC)

描述后备缓冲区的显示模式:

typedef struct DXGI_MODE_DESC {
    UINT                     Width;           // 缓冲区宽度(像素)
    UINT                     Height;          // 缓冲区高度(像素)
    DXGI_RATIONAL            RefreshRate;     // 刷新率(Numerator/Denominator)
    DXGI_FORMAT              Format;          // 像素格式
    DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;// 扫描线顺序
    DXGI_MODE_SCALING        Scaling;         // 缩放模式
} DXGI_MODE_DESC;
子字段 常用值 说明
Width/Height 1920×1080 缓冲区分辨率
RefreshRate 60/1 刷新率(60Hz)
Format DXGI_FORMAT_R8G8B8A8_UNORM RGBA 8位无归一化
ScanlineOrdering DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE 逐行扫描
Scaling DXGI_MODE_SCALING_UNSPECIFIED 未指定缩放

2. SampleDesc (DXGI_SAMPLE_DESC)

多重采样抗锯齿(MSAA)设置:

typedef struct DXGI_SAMPLE_DESC {
    UINT Count;     // 每像素采样数(1=无MSAA,2/4/8=多重采样)
    UINT Quality;   // 质量级别(0=默认,具体范围需查询设备)
} DXGI_SAMPLE_DESC;
说明
Count=1, Quality=0 无 MSAA(视频渲染推荐)
Count=4, Quality=0 4× MSAA(3D游戏常用)

视频渲染建议Count=1,MSAA 对视频质量提升有限,且增加开销。


3. BufferUsage (DXGI_USAGE)

缓冲区用途标志:

说明
DXGI_USAGE_RENDER_TARGET_OUTPUT 作为渲染目标输出(最常用)
DXGI_USAGE_SHADER_INPUT 可作为着色器输入纹理
DXGI_USAGE_UNORDERED_ACCESS 支持无序访问(计算着色器)

典型设置

sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

4. BufferCount (UINT)

后备缓冲区数量:

模式 说明
1 单缓冲 直接渲染到前台,有撕裂
2 双缓冲 标准配置,平衡性能和延迟
3 三重缓冲 减少等待,适合高帧率

推荐

  • 窗口模式:23
  • 翻转模式(Flip):最小 2

5. OutputWindow (HWND)

渲染输出的目标窗口句柄:

sd.OutputWindow = hWnd;  // 主窗口句柄

要求

  • 必须是有效的 Win32 窗口
  • 创建交换链时窗口必须存在

6. Windowed (BOOL)

窗口模式标志:

模式 特点
TRUE 窗口模式 与桌面共存,切换流畅
FALSE 全屏独占 性能最高,切换有延迟

现代推荐:使用 Windowed=TRUE + FLIP_DISCARD,性能接近全屏但切换流畅。


7. SwapEffect (DXGI_SWAP_EFFECT)

缓冲区交换方式:

说明 适用场景
DXGI_SWAP_EFFECT_DISCARD 丢弃旧内容 传统模式,兼容性最好
DXGI_SWAP_EFFECT_SEQUENTIAL 保留并顺序显示 需要读取前一帧
DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL 翻转顺序模式 Win10,低延迟
DXGI_SWAP_EFFECT_FLIP_DISCARD 翻转丢弃模式 Win10 推荐,最低延迟

Win10 推荐

sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd.BufferCount = 2;  // 翻转模式最小需要 2

8. Flags (UINT)

交换链标志位(可组合):

标志 说明
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH 0x01 允许全屏分辨率切换
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING 0x0200 允许撕裂(G-Sync/FreeSync)
DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT 0x0400 可等待帧延迟对象

常用组合

sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;  // 可变刷新率支持

典型配置示例

示例 1:传统窗口模式(兼容性好)

DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferDesc.Width = 1920;
sd.BufferDesc.Height = 1080;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 2;
sd.OutputWindow = hWnd;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;

示例 2:现代 Win10 低延迟模式(推荐)

DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferDesc.Width = 1920;
sd.BufferDesc.Height = 1080;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 2;  // 翻转模式最小 2
sd.OutputWindow = hWnd;
sd.Windowed = TRUE;  // 窗口模式 + 翻转 = 无边框全屏效果
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;

示例 3:全屏独占游戏模式

DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferDesc.Width = 1920;
sd.BufferDesc.Height = 1080;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 144;  // 高刷新率
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 3;  // 三重缓冲
sd.OutputWindow = hWnd;
sd.Windowed = FALSE;  // 全屏独占
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;  // 传统模式
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

与 Present 的关系

交换链配置决定了 Present() 的行为:

// 传统模式 (DISCARD)
m_pSwapChain->Present(1, 0);  // 等待 VSync,阻塞

// 翻转模式 + 允许撕裂
m_pSwapChain->Present(0, DXGI_PRESENT_ALLOW_TEARING);  // 非阻塞,可能撕裂
SwapEffect SyncInterval Flags 效果
DISCARD 1 0 标准 VSync,可能阻塞
DISCARD 0 0 立即呈现,可能撕裂
FLIP_DISCARD 0 ALLOW_TEARING 最低延迟,G-Sync/FreeSync 有效

总结

配置项 视频播放推荐 游戏推荐
BufferCount 2-3 2-3
Windowed TRUE FALSE(全屏)
SwapEffect FLIP_DISCARD FLIP_DISCARDDISCARD
Flags ALLOW_TEARING ALLOW_TEARING
SampleDesc.Count 1 1 或 4
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐