为什么我的 Windows application/game 在 Intel GPU 上 运行 时上限为 30FPS?
Why is my Windows application/game capped at 30FPS when running on an Intel GPU?
我正在开发一个全屏 Windows 桌面应用程序,该应用程序的图形密集度适中,它使用 OpenGL 但仅呈现 2D 内容。没什么特别的,主要是将像素推送到屏幕(最高 4K,单显示器)和上传纹理。我们正在使用 VSync 来控制渲染帧率,即。在渲染结束时调用 SwapBuffers() 以阻塞直到下一个 VBlank。
我们的主要要求是应用程序在与触摸屏一起使用时以稳定的 60FPS 运行,并且交互需要尽可能流畅。
因为它非常基础,所以该应用程序在带有集成英特尔高清显卡 630 GPU 的第 8 代英特尔 i7 CPU 上运行得很好。 CPU 或 GPU 都没有接近峰值使用率,我们可以通过应用程序内的 FPS 仪表看到舒适的 60FPS。我在配备 Intel i7 和集成 Intel UHD Graphics 620 GPU 的 Surface Book 2 上也有类似的结果。运行
但是,我最近开始注意到该应用程序有时会开始下降到 30FPS,然后长时间或有时甚至永久停留在那里。通过我们的 FPS 仪表,我可以看出我们实际上并没有花任何时间进行渲染,只是我们的 SwapBuffers() 调用任意阻塞了 2 帧,将我们限制在 30FPS。回到 60FPS 的唯一方法是在另一个应用程序上按 alt-tab 键然后回到我们的应用程序,或者简单地调出 Windows 菜单然后返回应用程序。
因为应用程序之后会回到 60FPS,我很肯定这是英特尔驱动程序的预期行为,可能是为了游戏(游戏玩家更喜欢稳定的 30FPS 而不是 irregular/occasional 掉帧让游戏看起来起伏不定)。
然而,在我们的例子中,偶尔掉帧并不是什么大问题,但是上限为 30FPS 会使我们的 UI 和交互变得不那么赏心悦目,尤其是当它可以很容易地以改为平滑 60FPS。
是否有任何方法可以将驱动程序行为切换为更喜欢推动 60FPS 偶尔掉落而不是上限为 30FPS?
好的,所以我可以通过一些调整和逆向工程来解决这个问题:答案是,是的,这是英特尔驱动程序的预期但不幸的默认行为,它可以通过修复Intel HD Graphics Control Panel 应用程序(如果可用)或直接在注册表中(这是解决 Surface Book 和其他 Surface 设备上的问题的唯一方法,其中自定义 Intel 驱动程序不会公开 Intel HD Graphics Control Panel 应用程序不再)。
从简单的解决方案开始:在 Intel HD Graphics Control Panel 应用程序中,转到“3D”,然后 "Application Settings"。您首先需要创建一个应用程序配置文件,方法是 select 为创建 OpenGL window 的进程在磁盘上创建文件。完成后,您要调整的设置是 "Vertical Sync"。默认情况下,"Use Application Default Settings" 是 selected。这是导致上限为 30FPS 的设置。 Select "Use Driver Settings" 而不是禁用该行为并始终以 60FPS 为目标:
如果不是因为英特尔可怕的术语选择和难以理解的文档,这应该是非常明显的。在我看来,设置的选择似乎是颠倒的:我希望在 select "Use Driver Settings" 时发生上限,这意味着驱动程序可以自由调整缓冲区交换,因为它认为合适。同样,"Use Application Default Settings" 暗示应用程序决定何时推送帧,这与设置的作用恰恰相反。即使是应用程序中的小帮助气泡似乎也与这些设置的作用相矛盾...
ps:我将 post 基于注册表的解决方案放在一个单独的答案中以保持简短
这是 registry-based 的答案,如果您的驱动程序没有公开 Intel HD 控制面板(例如 Surface Book 和可能其他 Surface 笔记本电脑上使用的驱动程序),或者如果您想这样做通过 regedit.exe 或 Win32 API:
以编程方式修复
Intel HD 控制面板创建的应用程序配置文件保存在 HKCU\Software\Intel\Display\igfxcuiD
下的注册表中,使用带有进程文件名(例如 my_game.exe
)和 REG_BINARY 值的键有一个 536 字节的数据块,这样划分:
- 字节 0-3:各向异性过滤(0 = 使用应用程序默认值,2-10 = 乘数设置)
- 字节 4-7:垂直同步(0 = 使用应用程序默认设置,1 = 使用驱动程序设置)
- 字节 8-11:MSAA(0 = 使用应用默认设置,1 = 强制关闭)
- 字节 12-15:CMAA(0 = 使用应用默认值,1 = 覆盖,2 = 增强)
- 字节 16-535:应用程序显示名称(wide-chars,用于控制面板的应用程序列表)
注意:所有值都存储在little-endian
此外,您需要确保同一键下的全局值的第一个字节设置为1,这是一种全局切换。(当一个或多个条目时,控制面板将其设置为1被添加到应用程序列表,然后在从列表中删除最后一个条目时返回零)。
value 的格式也是一个 REG_BINARY 值,8 字节编码如下:
- 字节 0-3:应用程序条目的全局切换(0 = 无条目,1 = 条目)
- 字节 4-7:应用程序优化模式(0 = 启用,1 = 禁用)
例如:
我正在开发一个全屏 Windows 桌面应用程序,该应用程序的图形密集度适中,它使用 OpenGL 但仅呈现 2D 内容。没什么特别的,主要是将像素推送到屏幕(最高 4K,单显示器)和上传纹理。我们正在使用 VSync 来控制渲染帧率,即。在渲染结束时调用 SwapBuffers() 以阻塞直到下一个 VBlank。
我们的主要要求是应用程序在与触摸屏一起使用时以稳定的 60FPS 运行,并且交互需要尽可能流畅。
因为它非常基础,所以该应用程序在带有集成英特尔高清显卡 630 GPU 的第 8 代英特尔 i7 CPU 上运行得很好。 CPU 或 GPU 都没有接近峰值使用率,我们可以通过应用程序内的 FPS 仪表看到舒适的 60FPS。我在配备 Intel i7 和集成 Intel UHD Graphics 620 GPU 的 Surface Book 2 上也有类似的结果。运行
但是,我最近开始注意到该应用程序有时会开始下降到 30FPS,然后长时间或有时甚至永久停留在那里。通过我们的 FPS 仪表,我可以看出我们实际上并没有花任何时间进行渲染,只是我们的 SwapBuffers() 调用任意阻塞了 2 帧,将我们限制在 30FPS。回到 60FPS 的唯一方法是在另一个应用程序上按 alt-tab 键然后回到我们的应用程序,或者简单地调出 Windows 菜单然后返回应用程序。
因为应用程序之后会回到 60FPS,我很肯定这是英特尔驱动程序的预期行为,可能是为了游戏(游戏玩家更喜欢稳定的 30FPS 而不是 irregular/occasional 掉帧让游戏看起来起伏不定)。
然而,在我们的例子中,偶尔掉帧并不是什么大问题,但是上限为 30FPS 会使我们的 UI 和交互变得不那么赏心悦目,尤其是当它可以很容易地以改为平滑 60FPS。
是否有任何方法可以将驱动程序行为切换为更喜欢推动 60FPS 偶尔掉落而不是上限为 30FPS?
好的,所以我可以通过一些调整和逆向工程来解决这个问题:答案是,是的,这是英特尔驱动程序的预期但不幸的默认行为,它可以通过修复Intel HD Graphics Control Panel 应用程序(如果可用)或直接在注册表中(这是解决 Surface Book 和其他 Surface 设备上的问题的唯一方法,其中自定义 Intel 驱动程序不会公开 Intel HD Graphics Control Panel 应用程序不再)。
从简单的解决方案开始:在 Intel HD Graphics Control Panel 应用程序中,转到“3D”,然后 "Application Settings"。您首先需要创建一个应用程序配置文件,方法是 select 为创建 OpenGL window 的进程在磁盘上创建文件。完成后,您要调整的设置是 "Vertical Sync"。默认情况下,"Use Application Default Settings" 是 selected。这是导致上限为 30FPS 的设置。 Select "Use Driver Settings" 而不是禁用该行为并始终以 60FPS 为目标:
如果不是因为英特尔可怕的术语选择和难以理解的文档,这应该是非常明显的。在我看来,设置的选择似乎是颠倒的:我希望在 select "Use Driver Settings" 时发生上限,这意味着驱动程序可以自由调整缓冲区交换,因为它认为合适。同样,"Use Application Default Settings" 暗示应用程序决定何时推送帧,这与设置的作用恰恰相反。即使是应用程序中的小帮助气泡似乎也与这些设置的作用相矛盾...
ps:我将 post 基于注册表的解决方案放在一个单独的答案中以保持简短
这是 registry-based 的答案,如果您的驱动程序没有公开 Intel HD 控制面板(例如 Surface Book 和可能其他 Surface 笔记本电脑上使用的驱动程序),或者如果您想这样做通过 regedit.exe 或 Win32 API:
以编程方式修复Intel HD 控制面板创建的应用程序配置文件保存在 HKCU\Software\Intel\Display\igfxcuiD
下的注册表中,使用带有进程文件名(例如 my_game.exe
)和 REG_BINARY 值的键有一个 536 字节的数据块,这样划分:
- 字节 0-3:各向异性过滤(0 = 使用应用程序默认值,2-10 = 乘数设置)
- 字节 4-7:垂直同步(0 = 使用应用程序默认设置,1 = 使用驱动程序设置)
- 字节 8-11:MSAA(0 = 使用应用默认设置,1 = 强制关闭)
- 字节 12-15:CMAA(0 = 使用应用默认值,1 = 覆盖,2 = 增强)
- 字节 16-535:应用程序显示名称(wide-chars,用于控制面板的应用程序列表)
注意:所有值都存储在little-endian
此外,您需要确保同一键下的全局值的第一个字节设置为1,这是一种全局切换。(当一个或多个条目时,控制面板将其设置为1被添加到应用程序列表,然后在从列表中删除最后一个条目时返回零)。
value 的格式也是一个 REG_BINARY 值,8 字节编码如下:
- 字节 0-3:应用程序条目的全局切换(0 = 无条目,1 = 条目)
- 字节 4-7:应用程序优化模式(0 = 启用,1 = 禁用)
例如: