我决定是否将VSync用于我使用OpenGL开发的新游戏.目标是为用户提供最佳游戏体验,并在性能和质量之间取得良好平衡.此游戏旨在在较旧的(英特尔/上网本)计算机和较新的(NVidia/i7桌面)计算机上运行.我知道VSync的目的是防止撕裂; 即使关闭了VSync,我也无法重现这个撕裂问题.提供最佳体验; VSync应该打开还是关闭?
我在禁用DWM的窗口模式下在Direct3D 10上遇到vsync问题.
我们有一个应用程序,它呈现并呈现一些输出.它必须在窗口模式下工作,它必须至少产生稳定的60 fps.一个版本的应用程序使用Direct3D 9和另一个Direct3D 10.当我们在窗口模式下工作时,有时我们有fps减少(它不是"稳定"减少.大多数时候我们产生稳定的60 fps,有时它会突然减少几秒钟,然后回到60帧/秒).在两个版本的应用程序中,fps减少约为10-20 fps.这是不可接受的.
在Windows Vista和Windows 7中,有一种新的图形系统,称为"桌面组合",它改变了应用程序在屏幕上显示像素的方式.桌面组合由桌面窗口管理器(DWM)执行.您知道,当启用DWM时,应用程序将绘制到视频内存中的屏幕外表面,而不是由DWM呈现并在一段时间内显示在显示屏上.所以,我们注意到,当任务管理器中的dwm.exe没有做任何事情(处理时间约为0%)时,我们有fps减少,当dwm.exe需要1-3%的处理时间时,有稳定的60 fps,所有都是好.
我们无法影响它.因此,我们必须关闭DWM才能获得高稳定的fps.当我们关闭它时,一切都好.两个版本的应用程序都有稳定的60 fps.但是DWM在窗口模式下执行vsync,所以当我们关闭它时,我们必须自己做vsync.
但是当我们关闭DWM时,在窗口模式下Direct3D 10中的vsync存在问题.在显示器顶部有图像撕裂.Direc3D 9运行良好.
因此,我们有一个60 Hz刷新率的显示器.
在创建交换链时,我们设置了这样的参数:
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
Run Code Online (Sandbox Code Playgroud)
在演示时我们设置了一个标志来打开vsync:
m_pSwapChain->Present( 1, 0 );
Run Code Online (Sandbox Code Playgroud)
并有下一个vsync问题.有垂直线,从左到右快速移动.并且在显示器的顶部有图像撕裂.
http://bit.ly/POQoFq
起初我们认为,我们做错了什么.所以我用旋转立方体安装了Microsoft的示例"Tutorial 07:Texture Mapping and Constant Buffers".制作更大的立方体,将其放置得更高,使其旋转得更快并得到同样的问题(见图片).
http://bit.ly/SevNqw
http://bit.ly/RSoEhc
http://bit.ly/UjaNPu
所以,在全屏模式下的Direct3D 10上一切都还可以.Vsync工作得很好.在Direct3D 9上也可以,在禁用或启用DWM的情况下,vsync工作正常.在禁用DWM的窗口模式下的Direct3D 10上存在问题.
它在不同的计算机,不同的视频卡(Nvidia 8600 GT,Nvidia 9500 GT,ATI Radeon HD 5870 Eyefinity 6)和不同版本的驱动程序上进行了测试.问题稳定转载.我们正在使用Windows 7.
那么,为什么会出现这样的问题呢?如何解决它以及接下来该做什么?
UPD1.如果上面的图像不可用,则会有一些镜像.
https://dl.dropbox.com/u/20468014/DSC_2287.JPG
https://dl.dropbox.com/u/20468014/DSC_2308.JPG
https://dl.dropbox.com/u/20468014/DSC_2313. JPG
https://dl.dropbox.com/u/20468014/DSC_2319.JPG
UDP2.我还要注意,我正在使用标志WS_POPUP创建窗口以隐藏标题栏(必须隐藏它).图像撕裂出现在不同的地方.它始终位于屏幕的顶部,但它可以是20像素,并且可以是50像素.因此,在创建带有标题栏的窗口时,图像的顶部有时可能根本看不到图像撕裂.
我被屏幕撕裂问题困扰了大约一周。
这是我的问题:我想制作一个程序,可以非常快地显示一系列 PNG 图片(以 30 fps 或更高的速度)。为此,我使用 pygame 库,特别pygame.display.blit是 和pygame.display.flip。
这是代码示例(带有自制延迟函数):
import time
import pygame
screen=pygame.display.set_mode(size, pygame.FULLSCREEN)
nbPicturesToLoad=12
pictures=range(nbPicturesToLoad)
for i in range(nbPicturesToLoad):
pictures[i]=pygame.image.load(pictureName).convert() //Here pictureName depends on the value of i
(...)
for i in range(nbPicturesToLoad):
timer1=time.time()
screen.blit(pictures[i], (0,0))
pygame.display.flip()
timer2=time.time()
timer=timer2-timer1
while(timer<0.03333):
timer2=time.time()
timer=timer2-timer1
Run Code Online (Sandbox Code Playgroud)
计时器允许我在屏幕上具有相同的刷新率。我的问题是,人们可以用自己的眼睛看到存在屏幕撕裂问题(https://en.wikipedia.org/wiki/Screen_tearing)。在 pygame 文档中,他们建议对屏幕初始化使用其他标志(pygame.HWSURFACE and pygame.DOUBLEBUFhttp://www.pygame.org/docs/ref/display ,)y.set_mode。显然这些可以帮助解决屏幕撕裂问题。但是当我使用这些标志时,我看不到屏幕撕裂校正。
我在某处看到 pygame 无法处理 X11 上的垂直同步,这可以解释为什么我认为 HWSURFACE 和 DOUBLEBUF 标志没有区别。
有人在 Raspberry Pi 上遇到过这个垂直同步问题吗?“config.txt”文件中是否有要放入的参数?有谁有办法获得真正的垂直同步信息以避免这些屏幕撕裂效果?
我已经看到 pyglet 可以在创建的窗口中处理垂直同步,但由于未知的原因,我无法在 pyglet …
这解释了VSYNC,但是节奏非常快,我无法找到任何其他好的资源来理解这个主题。
我所理解的是这样的;
VSYNC 发生在每个16ms, 以及所有帧组件上INPUT ANIMATION LAYOUT RECORD DRAW,并且RENDER在这一次只发生 1 次,因此通过 VSYNC,帧渲染是同步的,并且它限制帧在指定时间内重绘。
如果这个理解正确与否,请指导我。
我正在调查Android应用中的帧丢失.它们是不规则的,平均每秒发生一次.我已将有问题的渲染器与一个非常简单的着色器配对,我相信帧渲染时间很短.
当我运行systrace时,我可以看到看起来像丢帧的情况,但原因似乎是HW_VSYNC_0信号偶尔无法翻转(即它在0或1处停留半个周期).我的理解(从这个答案)是这个时钟来自显示硬件,因此应该是常规的.
VSYNC-sf信号无论如何都会继续运行,尽管它偶尔会翻转,大概是在拼命想要恢复同步.
我的问题:这是预期的行为以及导致它发生的原因吗?
我想使用来将小部件的更新同步到屏幕刷新率GdkFrameClock。这是为了在LCD屏幕之外进行视觉刺激响应测量(因此,对于信号的纯度,需要尽可能接近精确的帧同步)。
我已经阅读了该类的文档,但是范围有限。我缺少对GdkFrameClock在GTK世界中的位置的一些总体了解。仔细阅读GitHub上GTK源代码树中的演示对我来说是徒劳的。
假设可以,如何使用(假设开罗)GdkFrameClock的屏幕表示更新GtkDrawingArea与屏幕刷新率同步?
如果不能,目的是GdkFrameClock什么?
在尝试使用OpenGL作为后端为X11制作合成窗口管理器时,我陷入了一个令人讨厌的情况,其中glXSwapBuffers()阻塞,直到vblank渲染合成器对X事件无响应为止,这导致窗口被拖动到光标后方大约滞后于光标一帧。我已经尝试了多线程,但是效果不佳,所以我决定唯一合适的解决方案是使glXSwapBuffers()异步。希望将绘图命令发送到GPU并立即返回而无需等待操作实际完成,而AFAIK在具有DRI2的现代Linux中是可能的。所以我该怎么做?
我正在编写一个简单的 Direct3D 12 应用程序,为 Vulkan 的发布做准备,它在所有方面都按预期工作,但有一个问题:在有边框的窗口中运行会将帧速率限制为 60fps,即使禁用了垂直同步也是如此。让我困惑的是:同一个程序在全屏窗口中的运行速度接近 4000fps。
使用肮脏的自制分析器,我发现挂起发生在我的代码的这一部分中,它会等到最后一帧完成后才开始处理下一帧。
if (m_fence->GetCompletedValue() < endFenceValue)
{
result = m_fence->SetEventOnCompletion(endFenceValue, m_fenceEvent);
if (result != S_OK) return false;
WaitForSingleObject(m_fenceEvent, INFINITE); //Program stalls here
}
//m_fence is a pointer to an ID3D12Fence object
//endFenceValue is an unsigned long long
//m_fenceEvent is a HANDLE
Run Code Online (Sandbox Code Playgroud)
用于呈现渲染帧的代码很普通:
if (m_vsync)
{
result = m_swapChain->Present(1, 0);
if (result != S_OK) return 0;
}
else
{
result = m_swapChain->Present(0, 0);
if (result != S_OK) return 0;
}
//Increase the fence value …Run Code Online (Sandbox Code Playgroud) 我正在使用Vulkan 图形API(通过BGFX)进行渲染。我一直在测量我的电话需要多少(挂钟)时间。
我不明白的是vkAcquireNextImageKHR () 总是很快,而且从不阻塞。即使我禁用超时并使用信号量来等待演示。
演示文稿锁定为 60Hz 显示速率,我看到我的主循环确实以 16.6 或 33.3 毫秒运行。
我不应该在vkAcquireNextImageKHR()通话时长中看到此显示率的等待时间吗?
分析器将这个调用测量为 0.2 毫秒左右,而不是帧的重要部分。
VkResult result = vkAcquireNextImageKHR(
m_device
, m_swapchain
, UINT64_MAX
, renderWait
, VK_NULL_HANDLE
, &m_backBufferColorIdx
);
Run Code Online (Sandbox Code Playgroud)
目标硬件是手持控制台。