在 Windows 10 / DirectX 上仅在全屏模式下使用 VSYNC 撕裂(窗口模式工作正常)
Tearing with VSYNC in full screen mode only (windowed mode works fine) on Windows 10 / DirectX
我认为我的 DirectX 11 应用程序在以前的系统上运行良好(我有大约 70% 的把握)。但是现在,在 Windows 10(笔记本电脑)我只在全屏模式下出现撕裂问题(窗口模式下没有任何撕裂)。
场景相当"heavy"(它应该是针对我的应用程序进行性能测试的)。当 DirectX 渲染 "heavier" 部分时,它在短时间内下降到大约 50fps(我的测量可能有点不准确)然后又回到 60-61fps。奇怪的是,我没有看到 "heavier" 部分(约 50fps)撕裂。
我听说它可能与 DWM 有某种关系,DWM 为窗口应用程序提供自己的同步(这就是我的程序在窗口模式下运行良好的原因?)。
我该怎么办?
交换链:
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = numerator;
sd.BufferDesc.RefreshRate.Denominator = denominator;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = *hwnd;
sd.SampleDesc.Count = sampleCount; //1 (and 0 for quality) to turn off multisampling
sd.SampleDesc.Quality = maxQualityLevel;
sd.Windowed = fullScreen ? FALSE : TRUE;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; //allow full-screen switchin
// Set the scan line ordering and scaling to unspecified.
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// Discard the back buffer contents after presenting.
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
其中numerator
和denominator
是根据this tutorial计算的:
...
numerator = displayModeList[i].RefreshRate.Numerator;
denominator = displayModeList[i].RefreshRate.Denominator;
returns 两个非常高的值,当彼此相除时给出大约 60
(我将它们设置为 60
和 [=18= 会得到相同的效果吗? ]?):
我还渲染了:
if(VSYNC){
swapChain->Present(1, 0); //lock to screen refresh rate
}else{
swapChain->Present(0, 0); //present as fast as possible
}
我是不是漏掉了什么?还是我做错了什么?
我的评论作为回答:
Did you try to zero out the numerator and denominator? The DXGI will then calculate proper values automatically. (doc) The link also covers, why 60/1 shouldn't be hardcoded (can lead to problems on some systems).
我认为我的 DirectX 11 应用程序在以前的系统上运行良好(我有大约 70% 的把握)。但是现在,在 Windows 10(笔记本电脑)我只在全屏模式下出现撕裂问题(窗口模式下没有任何撕裂)。
场景相当"heavy"(它应该是针对我的应用程序进行性能测试的)。当 DirectX 渲染 "heavier" 部分时,它在短时间内下降到大约 50fps(我的测量可能有点不准确)然后又回到 60-61fps。奇怪的是,我没有看到 "heavier" 部分(约 50fps)撕裂。
我听说它可能与 DWM 有某种关系,DWM 为窗口应用程序提供自己的同步(这就是我的程序在窗口模式下运行良好的原因?)。
我该怎么办?
交换链:
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = numerator;
sd.BufferDesc.RefreshRate.Denominator = denominator;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = *hwnd;
sd.SampleDesc.Count = sampleCount; //1 (and 0 for quality) to turn off multisampling
sd.SampleDesc.Quality = maxQualityLevel;
sd.Windowed = fullScreen ? FALSE : TRUE;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; //allow full-screen switchin
// Set the scan line ordering and scaling to unspecified.
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// Discard the back buffer contents after presenting.
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
其中numerator
和denominator
是根据this tutorial计算的:
...
numerator = displayModeList[i].RefreshRate.Numerator;
denominator = displayModeList[i].RefreshRate.Denominator;
returns 两个非常高的值,当彼此相除时给出大约 60
(我将它们设置为 60
和 [=18= 会得到相同的效果吗? ]?):
我还渲染了:
if(VSYNC){
swapChain->Present(1, 0); //lock to screen refresh rate
}else{
swapChain->Present(0, 0); //present as fast as possible
}
我是不是漏掉了什么?还是我做错了什么?
我的评论作为回答:
Did you try to zero out the numerator and denominator? The DXGI will then calculate proper values automatically. (doc) The link also covers, why 60/1 shouldn't be hardcoded (can lead to problems on some systems).