我一直在修改自己的WebGL项目,并发现了尴尬的性能问题。起初我将自己的渲染减少到只留下一行:
gl.clear(gl.COLOR_BUFFER_BIT);
仅仅调用一行就会导致性能从60fps下降到~40fps。调用该行不会直接影响性能,js-profiler显示大部分时间都在“空闲”中,但是对requestAnimationFrame的调用只发生了大约40次。
然后我注意到问题似乎取决于我有浏览器的屏幕。当我将标签拉到主屏幕时,fps保持在~60。我还有2个屏幕,它们都是1080p,但在二级屏幕上做任何WebGL的性能下降到~40fps。 CPU负载和GPU负载似乎没有区别,只有fps可以。
我不仅可以使用我的代码重现这一点,还可以使用以下代码重现: http://media.tojicode.com/q3bsp/
在我的主屏幕上播放全屏会让我体验60 fps。在我的辅助屏幕上它是~40fps。
有没有解释为什么性能在二级屏幕上不可靠?我正在运行Radeon HD 7850作为显卡。主屏幕通过HDMI连接,两个辅助屏幕都使用DVI到mini-Displayport适配器。 问题显示在Chrome和Firefox中,但不在IE11中。我在Windows 7 x64上。
答案 0 :(得分:3)
TL; DR:AFAIK除了最后一段中提到的
之外没有解决方案据我所知,这只是Windows的工作方式,而且很难修复。浏览器必须修复它,这将是太多工作的方式。
问题是,至少据我记忆,Windows将每个显示器视为一个单独的设备。这些设备彼此有效隔离。就Windows而言,它们可能在不同的图形卡上运行,即使它们恰好在同一张卡上运行,它也会像在单独的卡上运行一样对待它们
因此,当您编写本机Windows图形程序(例如浏览器)时,默认情况下您选择1个设备。您创建一个窗口,分配设备,并将所有图形资源分配给该设备(着色器,纹理,缓冲区,渲染缓冲区)
如果您的窗口移动到另一个屏幕,那么其他设备上不存在这些资源(着色器,纹理,缓冲区,渲染缓冲区)。事实上,鉴于该设备可能在不同的图形卡上运行,资源甚至可能与该卡不兼容。 (例如:纹理太大,第二张卡上没有着色器功能,......)
因此,Windows所做的是在设备上选择程序窗口,然后将结果复制到另一台设备,以便在第二台设备的屏幕上显示。 此复制和重新显示是减速的来源。
在窗户跨越2显示的情况下,没有其他解决方案。在窗口完全移动到另一个显示器的情况下,智能程序可以识别窗口在不同的显示器上,创建该设备上所有资源的副本,并开始在该设备上呈现。我上面提到的问题是设备可能没有与第一个设备相同的功能/内存/功能,因此它可能无法运行。更糟糕的是,某些事情,比如复制渲染缓冲区,真的很痛苦。
某些directX示例会在您移动窗口时切换设备,但DirectX具有此模型,您的应用程序可以随时重新加载所有资源。
Chrome,Safari,Firefox并没有真正拥有这种奢侈品。如果你在一台设备上启动你的页面,他们就无法真正切换到新设备(就像我上面提到的那样,因为它很难,因为该设备可能无法运行你的页面。也许设备1支持浮点纹理而设备2不支持) / p>
OSX没有此问题AFAIK,因为OSX不允许多个图形卡。这意味着当您使用第二个显示器时,他们总是知道所有内容都在同一个GPU上。当然这也意味着你无法运行更多的显示器?我不是一个mac guru。也许它确实支持更多的GPU可以或习惯并遇到类似的问题。
在某些较新版本的Windows中,它们可能以某种方式虚拟化设备或更改模型,以便同一GPU上的设备神奇地无需复制。我不认为他们已经这样做了。
某些GPU供应商(AMD,NVidia)在其控制面板中有一个特殊模式,用于2个完全相同分辨率的显示器。在这种情况下,他们有效地告诉操作系统有1个显示器,但在卡中他们将显示器分成2个以上的显示器。因为操作系统认为只有1个显示器,所以只有1个设备,这些问题就会消失。如果您有2台具有相同分辨率的显示器,请尝试启用此模式。