【D3D11】DXGI_SWAP_CHAIN_DESC 结构体
·
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 |
三重缓冲 | 减少等待,适合高帧率 |
推荐:
- 窗口模式:
2或3 - 翻转模式(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_DISCARD 或 DISCARD |
Flags |
ALLOW_TEARING |
ALLOW_TEARING |
SampleDesc.Count |
1 | 1 或 4 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)