我的应用程序每帧更改一些非常简单的视图(旋转,平移)的属性.根据Android性能文章的建议,我使用了systrace来检查我是否丢帧.
出乎意料的事情出现了.当设备静止不动时(即使我触摸屏幕)CPU使用率更高,systrace上的警报出现,GPU渲染分析器的红色部分更长.当我快速旋转或震动设备时,一切都很好.
以下是结果的链接.Shake
是我快速旋转设备的no_shake
时候,就是把它放在我的桌子上.
我制作了一个非常简单的测试应用程序,它使用单个翻译动画:源代码.
看一下帧速率平滑的shake systrace,为什么HW_VSYNC_0和HW_VSYNC_ON_0行没有数据?如何读取CPU频率(我在捕获跟踪时启用了该选项).
关于这个问题,我的理论是该设备可能会降低CPU频率.我怎么能在systrace中读到这个?我使用第三方应用来测试这个假设,如下所示.那么,我该怎么做才能避免这个问题呢?
为什么设备会这样做?起初,我认为设备使用加速度计数据来了解它是否未被使用,然后降低了CPU频率.但是,为了增加CPU频率,我必须非常努力地摇动设备.像普通人一样握住它不会增加CPU频率.
我知道这是很多问题,但是在阅读了有关Android图形管道的所有相关文章之后,我的想法就出错了.
在运行Android 5.1的Sony Xperia Z3上出现此问题.运行Android 6的Nexus 5无法重现此问题.
更新
似乎性能问题是由CPU/GPU限制引起的.同样的设备,Xperia Z3,在运行Android 4.4时,即使它降低了时钟速度,它根据Systrace表现更好.此外,摇动时不会提高速度.
关于提高CPU速度所需的摇动手势,我注意到当我尝试将设备从纵向旋转到横向或反之亦然时,CPU时钟会在触发时增加(即使应用程序没有改变方向).因此,我认为监控此手势的原因是为了加快可能的方向变化.
我需要创建一个 C++ 函数,它将返回到下一个 Vsync 间隔的秒数作为浮点值。
为什么?
我正在创建显示跟随鼠标光标的矩形的程序。表面上,OpenGL 在 glXSwapBuffers 函数中提供了一个 vsync 机制,但我发现这是不可靠的。使用某些卡驱动程序,您可以获得 vsync;与其他人你不。在某些情况下,您会获得 vsync,但也会获得额外的 2 帧延迟。
但这不是 OpenGL 中的错误。规范故意含糊其辞:“后台缓冲区的内容然后变得未定义。更新通常发生在监视器的垂直回溯期间,而不是在调用 glXSwapBuffers 之后立即发生。” 关键词是“通常”......基本上glXSwapBuffers 不承诺蹲wrt vsync。去搞清楚。
在我目前解决这个基本问题的尝试中,我目前猜测初始垂直同步时间,然后假设相位等于经过时间 MOD 1/(59.85Hz),这似乎与我当前的显示器同步。但这并不奏效,因为我实际上并不了解初始阶段。所以我得到一滴眼泪。至少它不会四处走动。但我真正需要的是以某种方式测量当前的 vsync 相位。
不,我不想依赖一些 OpenGL 调用来为我做一个 vsync。由于规范中的含糊不清,这使得 OpenGL 实现可以随心所欲地增加延迟。
不,我不想依赖某些 SGI 扩展或其他一些必须安装才能使其工作的东西。这是图形 101。Vsync。只需要一种查询其状态的方法。一些内置的、总是安装的 API 必须有这个。
也许我可以创建一个以某种方式等待 Vsync 的辅助线程,并记录发生这种情况的时间?但请注意以下顺序:
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/fb.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{
int fb = open("/dev/fb0", O_RDWR);
assert(fb != -1);
int zero = 0;
if (ioctl(fb, FBIO_WAITFORVSYNC, &zero) == …
Run Code Online (Sandbox Code Playgroud) 我一直在玩pygame(在Debian/Lenny上).它似乎工作得很好,除了烦人的blits撕裂(全屏或窗口模式).
我正在使用默认的SDL X11驱动程序.谷歌搜索表明SDL的一个已知问题是X11没有提供vsync功能(即使使用FULLSCREEN|DOUBLEBUF|HWSURFACE
标志创建的显示),我应该使用"dga"驱动程序.
但是,跑步
SDL_VIDEODRIVER=dga ./mygame.py
Run Code Online (Sandbox Code Playgroud)
抛出pygame初始化
pygame.error: No available video device
Run Code Online (Sandbox Code Playgroud)
(尽管xdpyinfo
存在XFree86-DGA扩展).
所以:获得无泪vsynced翻转的诀窍是什么?通过让这个dga工作或其他机制?
在Mac OS X上,CVDisplayLink提供了一种可靠地更新屏幕以实现60 fps动画而不会撕裂的好方法.Windows上是否有类似的界面,与OpenGL兼容?
当然可以在等待vsync时阻塞,但是这不能扩展为需要同时进行动画处理的多个窗口.在Windows上,它们都会互相等待(所以每个等待vsync的窗口都会降低到30 fps),这与OS X不同.
例如视频播放器如何实现平滑的屏幕更新?
我正在用C++写一个带OGL/GLFW的游戏.
我的游戏总是以60 fps运行,没有任何屏幕撕裂.在做了一些研究之后,似乎该glfwSwapInterval()
功能应该能够启用/禁用V-sync或60fps上限.
但是,无论我传递给函数的值如何,帧速率都保持锁定在60并且没有任何撕裂.我还检查了linux和nvidia面板上的compositor设置,它们没有任何效果.
这是我认为常见的事情,有没有办法绕过这个fps上限?
我正在开发一个支持多个操作系统和图形后端的图形应用程序。该窗口是使用 GLFW 创建的,并且图形 API 在运行时选择。当在 Windows 上运行程序并使用 OpenGL 时,Vsync 似乎被破坏了。帧速率锁定在 60 fps,但出现屏幕撕裂伪影。根据 GLFW 文档,glfwSwapInterval(0);
应该解锁使用 VSync 的默认帧速率。这按预期工作。使用glfwSwapInterval(1);
时应锁定帧速率以匹配显示器的刷新率。根本不调用glfwSwapInterval();
应该默认使用垂直同步。虽然使用这些调用正确锁定/解锁了帧速率,但我经历了非常有趣的行为。
当glfwSwapInterval();
根本不调用时,垂直同步设置为默认值。但是等待下一帧发生在第一次绘制调用时!人们会认为下一帧的延迟会发生在glfwSwapBuffers()
。无论如何都看不到屏幕伪像。
调用时glfwSwapInterval(1);
,Vsync 被设置,下一帧的延迟发生在glfwSwapBuffers()
!这很好,但是,当显式设置垂直同步时,会出现屏幕撕裂现象。
现在,不要求glfwSwapInterval()
使用 VSync 似乎是一个很棘手的解决方案,但是:
我尝试摆弄 GPU 驱动程序设置并在多台机器上测试代码。如果使用 Windows 和 OpenGL,该问题在不同机器上仍然存在。
如果有人能理解这一点,请分享,或者如果我误解了某些东西,我将非常感谢一些正确方向的指示。
编辑:其他一些细节:撕裂发生在特定的水平线上。框架的其余部分似乎工作正常。
经过更多测试后,似乎一切都在集成显卡上按预期工作。如果我错了请纠正我,但看起来这是一个图形驱动程序问题。
因此,我在窗口应用程序中使用 D3D。
我使用以下参数启动了 D3D:
windowed: true;
backbufferformat: D3DFMT_X8R8G8B8;
presentinterval: D3DPRESENT_INTERVAL_ONE;
swapeffect: DISCARD
Run Code Online (Sandbox Code Playgroud)
每次调用 OnPaint 时,我都会将图像渲染到后缓冲区并将其呈现到前面。
据我所知(MSDN也是这么说的),一旦我设置了D3DPRESENT_INTERVAL_ONE
,vsync就会起作用。
但在这种情况下,水平拖动时图像会撕裂。
(图像上似乎有一条线,线下方的图像显示在监视器上,上面的部分如下。)
一些网站说 D3DPRESENT_INTERVAL_ONE 在窗口应用程序中不起作用。
我怎样才能启用垂直同步?
ps我终于发现D3D垂直同步是启用的,而有些窗口设置不正确,也许窗口本身没有同步。不过,我还没有看过设置。
CompositionTarget.Rendering事件是构建游戏主循环的完美之选。它基本上以垂直同步的速率(通常为 60 Hz)触发。
在渲染合成树中的对象之前发生。将动画和布局应用到合成树后,渲染事件将路由到指定的事件处理程序。
每帧动画操作方法文章对此进行了更多解释。
Note that your event handler method is called after layout has been computed. However, you can modify layout in your event handler method, which means that layout will be computed once more before rendering.
Based on that, the rules for code inside its handler are:
What other gotchas are there? What non-obvious actions cause another layout pass? How much time exactly do I …
我正在尝试移动这张图片:
在我的 PyGame 屏幕上,从右到左,然后再返回,但是随着图像移动,每隔一秒左右,我就会看到屏幕撕裂的闪烁,如下所示:
我正在使用的代码是与此类似的循环:
screen.blit(img, (x,y))
pygame.update((x,y),(w,h))
pygame.draw.rect(screen,(0,0,0),((x,y),(w,h)))
Run Code Online (Sandbox Code Playgroud)
到目前为止,我已尝试以下方法来解决该问题:
创建屏幕时使用HWSURFACE
, FULLSCREEN
,DOUBLEBUF
标志,这没有效果,我也将其调整.update(rect)
为 a .flip()
(因为在使用 时建议这样做DOUBLEBUF
?)
在 GPU 和 CPU 之间分割内存(我在树莓派 2 上运行)我尝试给两者提供更多内存,但没有改变。
设置clock.tick将更新速率限制为60 FPS(也高于和低于),这确实消除了一些撕裂,但不是全部
向左或向右调整每个增量的大小,使增量变小会减少撕裂,但也会降低速度。(不能太慢)
blit
当我读到比绘图更受支持的地方时,虽然我无法确认这一点,但在以前的位置上绘制一个新的黑色表面而不是绘制一个黑色矩形(当移动图像以确保其后面没有痕迹时)HWSURFACE
?- 这没有效果
如果有人有任何其他可以改善情况的解决方案,我将不胜感激。
我宁愿不从 PyGame 更改为其他任何东西(如 pyglet),因为到目前为止我已经使用 PyGame 完成了相当多的实现,但我愿意接受建议。
干杯
编辑
根据要求提供相关代码:
if scanner == True:
clocker.tick(clockspeed)
if x < 11:
slower = 3
if firstTime == True:
img.set_alpha(int(x * 25))
newSurf.set_alpha(int(x * 25))
screen.blit(newSurf,(xText,35))
pygame.display.update((xText,35),((xText + newSurf.get_width()),(50 …
Run Code Online (Sandbox Code Playgroud)