enumdisplaysettings 用 enum_current_settings 获取显示器物理刷新率最可靠,dmdisplayfrequency 返回当前生效值(hz),多屏需先枚举设备名,为0时fallback至60。

Windows平台用 EnumDisplaySettings 读取刷新率最可靠
Windows没有全局“V-Sync开关”状态,所谓“V-Sync是否启用”实际取决于图形API(如OpenGL、DirectX)的呈现设置和驱动控制面板策略。但显示器物理刷新率是确定的,EnumDisplaySettings 能准确获取当前活动显示模式的 dmDisplayFrequency 值。
常见错误是调用时传入错误的设备名或模式索引——必须用 ENUM_CURRENT_SETTINGS(-1)查当前生效设置,而非遍历所有模式。示例关键片段:
DEVMODE dm = {};
dm.dmSize = sizeof(dm);
if (EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &dm)) {
int refresh = dm.dmDisplayFrequency; // 单位:Hz,通常是60、75、120、144等
}
- 传
nullptr表示主显示器;多屏需先用EnumDisplayDevices枚举设备名 -
dmDisplayFrequency为0表示未指定或不可读,此时应 fallback 到默认值60 - 该值反映显卡驱动报告的当前模式,不随应用开启/关闭V-Sync动态变化
Linux上通过 xrandr 或 drm 接口查原生刷新率
在X11环境下,xrandr --verbose 输出中每种模式带 + 标记的即为当前激活模式,其 h: ... v: ... 行末尾的数字就是刷新率(如 60.00* 中的60.00)。程序内解析需调用 xrandr 的libXrandr API,而非简单popen解析。
更底层且无X依赖的方式是读取 /sys/class/drm/card*/display/modes 或使用libdrm直接查询KMS——但注意:这些只暴露EDID解析出的物理支持模式,不保证当前生效。真正生效的刷新率要查 /sys/class/drm/card*/display/current_mode(若存在),格式如 1920x1080p-60。
-
xrandr命令行输出易受缩放、旋转影响,模式名可能含@2x等后缀,需按空格+连字符分割提取末字段 - Wayland下无统一接口,需依赖具体合成器(如wlroots提供
wlr_output_get_mode),且应用无法绕过合成器强制V-Sync - DRM节点路径因内核版本和GPU厂商差异大,
card0不一定存在,须遍历/sys/class/drm/
V-Sync“开启状态”无法跨平台直接获取,只能间接推断
操作系统本身不维护一个“V-Sync on/off”的全局布尔值。所谓“启用V-Sync”,本质是图形API在交换缓冲区(swap buffers)时是否等待下一个垂直消隐期。这个行为由三方面共同决定:应用调用的API设置(如GLX_SWAP_INTERVAL)、驱动控制面板全局策略、以及窗口系统合成器策略(尤其在Wayland或Windows 11 HDR混合渲染路径下)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
因此,没有标准C++函数能返回 is_vsync_enabled()。唯一可行的间接判断方式是测量连续两帧的 glFinish() 或 vkQueueWaitIdle() 后的时间差是否稳定接近 1000 / 刷新率(ms)——但这需要应用自身已启用同步绘制逻辑。
- Windows上,
DXGI_PRESENT_ALLOW_TEARING开启时即使驱动设了V-Sync,也可能撕裂,此时时间差会明显小于理论值 - Linux X11下,
__GL_SYNC_TO_VBLANK=1环境变量可强制驱动级同步,但无法反向查询该变量是否生效 - 不要尝试读取NVIDIA/AMD私有sysfs节点(如
/proc/driver/nvidia/params),它们不公开、不稳定、且需root权限
跨平台封装建议:分离“物理刷新率”与“同步策略”两个概念
写通用代码时,必须明确区分“显示器支持什么刷新率”和“当前渲染是否同步到该刷新率”。前者可用上述平台特定方法获取并缓存;后者应由图形子系统(如SDL2、GLFW)在创建上下文时通过 hint 控制,并在运行时通过计时采样验证。
例如用GLFW时,glfwSwapInterval(1) 请求开启V-Sync,但成功与否无返回值——只能后续用 glfwGetTime() 在循环中测帧间隔是否收敛。
- 避免在初始化阶段就假设 V-Sync 已生效;很多驱动默认关闭,尤其笔记本集显
- 高刷显示器(120Hz+)下,若应用未声明支持,Windows可能降频到60Hz模式,此时
EnumDisplaySettings返回的仍是60 - 游戏引擎常把“刷新率”硬编码为60,导致在144Hz屏上锁帧不准;应优先读取系统值,再按需做倍数适配(如 vsync=2 表示每两帧刷新一次)
真正的难点不在读取数值,而在于理解:V-Sync不是开关,是渲染管线中多个环节协商的结果。任何试图“一键获取开关状态”的设计,都会在驱动更新或窗口系统升级后失效。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










