原文链接:https://stackoverflow.com/questions/49244480/correct-way-to-wait-for-vblank-on-windows-10-in-windowed-mode

What is the correct way to wait for VBLANK to present on windows 10 in windowed mode? Currently I'm doing the following:

D3DKMTWaitForVerticalBlankEvent(&waitData);
swapchain->Present(0, 0);

However this leads to occasional stutter. My current theory on the stutter is the following:
DWM completes composition at some time before the VBLANK event and then during the VBLANK interval, DWM tries to write to the front buffer as fast as possible. Therefore if Present is called in the VBLANK interval it possibly occurs after the DWM has written to the front buffer. This is the picture in my head:

So a more correct method would be call Present(1, 0) before VBLANK to queue the window's back buffer with DWM. Then call D3DKMTWaitForVerticalBlankEvent to wait until the next VBLANK. That is:

swapchain->Present(1, 0);
D3DKMTWaitForVerticalBlankEvent(&waitData);

With corresponding picture:  This second method seems to work perfectly, there is no longer any stutter.

My question is: What is the correct way to present in the VBLANK interval and is my theory correct or is there something more complicated/simple happening? Also are there any resources to learn more about this interaction?

Potentially helpful links:
MSDN Present
DXGI Best Practices
DXGI Waitable Swap Chain
D3DKMTWaitForVerticalBlankEvent

Edit: Not sure if this should be an answer or edit. After some googling I found this explanation by Nicholas Steel which seems align with my theory

There is no sure fire way to detect exactly when VBlank will occur because Windows doesn't expose a VBlank interrupt, and displays/GPU aren't necessarily required to generate one anyway (in addition, 'current scanline' information as given by e.g. IDirect3DDevice9::GetRasterStatus may not be accurate). As a result, programs generally poll for VBlank or rely on Direct3D/OpenGL to do it for them.

Programs present video frames during VBlank to avoid tearing, since the monitor will happily switch to the new frame mid-draw. With the compositor in Windows Vista and later versions of Windows, these programs will still detect VBlank and only present frames during it, as they think they are presenting video frames directly, when in reality the video frames are feeding into the compositor first. Frames sent to the compositor (from any running programs on the PC) will be queued up by the compositor, and merged together to be swapped/copied into place during VBlank.

Problems that can occur with this system:

1) A program polling for VBlank may miss composition. This will cause the frame to be queued up for the next composition, meaning the previous frame will be shown twice as long.

2) Worse, the next frame may not miss composition, and end up overwriting the previously queued up frame - so you end up with a duplicate frame followed by a skipped frame.

3) The program's VSync implementation may naturally fail to detect VBlank (which has only a short duration), causing it to wait until the next VBlank and risk problems 1 and/or 2.

4) These problems may even combine to generate a 'perfect storm' of duplicate and/or missed frames.

As you can see, this polling setup is not ideal, and far worse when a compositor is present. There are multiple problems that can cause a new video frame to fail to be displayed, causing a previous frame to be displayed for longer than intended and potentially skipping the new frame altogether!

The solution is to work with the compositor instead of against it. Present a new video frame immediately and afterward, call a command that will block until the compositor has completed it's task (DwmFlush). This will ensure that at most 1 new video frame is presented to the compositor between each VBlank period. As long as the compositor is active, you also won't have to worry about polling for VBlank yourself anymore.

So the best thing to do is:

if (DWM.isEnabled())
{ present(); DwmFlush();
}
else
{waitForVBlank(); present();
}

Another edit: For future readers there is are two other ways to wait for VBLANK that I wasn't aware of they are IDXGIOutput::WaitForVBlank and IDirectDraw7::WaitForVerticalBlank the latter being deprecated.

winapidirectxdirect3ddwmdxgi

Share

Improve this question

Follow

edited Mar 19 '18 at 9:57

asked Mar 12 '18 at 21:12

Cairn O.

43333 silver badges1414 bronze badges

  • Does WaitForVBlank work in windows mode? I would guess it only works in full screen. – tofutim Aug 15 '18 at 17:49

add a comment

1 Answer

ActiveOldestVotes

2

Why are you trying to wait for VBLANK in windowed mode? DWM will ensure that the composited surface will flip in the VBLANK region.

When you say "DWM completes composition at some time before the VBLANK event", what would make DWM initiate composition? It does not happen after any app presents, or after the app in focus presents. Composition actually begins when the VBLANK occurs. It may finish and flip the composited surface within the VBLANK, or it may end up actually flipping in the next VBLANK (so you may end up with an extra frame duration in latency). That isn't in your control though - it depends on the duration of the composition and not on your app's present.

In a windowed app, when you call present, that just flips your app's swapchain - it does not flip the surface that is displayed. DWM will handle that. So "As long as the compositor is active, you also won't have to worry about polling for VBlank yourself anymore."

However, using DwmFlush() to achieve "at most 1 new video frame is presented to the compositor between each VBlank period" is not necessarily desirable. Unless you definitely want to just show 1 frame each monitor cycle, then you can do that (though I'm not sure if DwmFlush() is the most elegant approach). But in most cases, I don't think enforcing that limit is desirable.



Share

Improve this answer

Follow

answered Mar 18 '18 at 16:30

Alan Daniels

2933 bronze badges

  • The reason to wait for VBLANK is described in the second paragraph of this article docs.microsoft.com/en-us/windows/uwp/gaming/… – Cairn O. Mar 19 '18 at 2:51

  • I'm aware that the DWM will ensure no tearing, the problem is submitting multiple frames to DWM before the flip, 1 frame per VBLANK is preferable. – Cairn O. Mar 19 '18 at 2:53

  • In that article, they mention waiting until the previous present is done. This means that the GPU is still rendering / processing the previous commands. If the GPU is busy, then it makes sense to wait before queuing more rendering because the new frame will start rendering at the same time (in both cases after the previous one finishes), but if you wait, you can start the render with a more recent state. – Alan Daniels Mar 24 '18 at 0:19

  • So it's not tied to VBLANK/VSYNC. Submitting multiple frames is not necessarily a bad thing - plenty of games do that. If you want to enforce 1 frame per cycle, you should just be able to set the app flip mode to VSYNC (rather than an immediate mode), or do this DwmFlush() thing. – Alan Daniels Mar 24 '18 at 0:25

add a comment

Correct way to wait for VBLANK on windows 10 in windowed mode相关推荐

  1. mac 制作usb启动盘_如何使用Mac制作Windows 10 USB-从Mac终端构建可启动的ISO

    mac 制作usb启动盘 Most new PCs don't come with DVD drives anymore. So it can be a pain to install Windows ...

  2. win10图标重建缓存_如何在Windows 10中重建损坏的图标缓存

    win10图标重建缓存 The icons that Windows uses for your documents and programs are saved in an icon cache, ...

  3. 如何在Windows 10上使用手写输入

    Windows 10's handwriting keyboard allows you to enter text into any application with a pen or other ...

  4. imagick php7.0,Installing Imagick for PHP 7 on Windows 10

    转自 http://herbmiller.me/2016/06/16/installing-imagick-php-7/ If you're running PHP 7 on Windows and ...

  5. windows10墙纸_如何根据一天中的时间更改Windows 10的墙纸

    windows10墙纸 Apple's macOS 10.14 Mojave offers "Dynamic Desktop" wallpapers that change bas ...

  6. Windows 10下编译安装Hadoop2.6

    转自:https://www.linuxidc.com/Linux/2016-08/134131.htm Windows 10下安装Hadoop2.6,Windows10下编译64位Hadoop2.x ...

  7. mysql数据库解压安装教程_MySQL数据库之windows 10下解压版MySql安装配置方法教程...

    本文主要向大家介绍了MySQL数据库之windows 10下解压版MySql安装配置方法教程 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. windows 10 下安装解压版的 ...

  8. w ndows连接USB不正常,Raspberry Pi Zero W 连接电脑 – 针对Windows 10 缺少RNDIS驱动

    在网上有很多关于Raspberry Pi Zero连接电脑的帖子,但是发现在windows 10 系统上发现没有发现RNDIS 驱动,这个驱动在其他系统上会自动安装,但是在windows 10 上显示 ...

  9. Windows 10完美识别3TB硬盘实录

    京东上买了一块3TB希捷酷鱼硬盘,已经安装到PC机箱中,操作系统是Windows 10. 启动Windows 10,进入操作系统,没有识别出该盘,系统也没有报错.为了让windows 10识别并格式化 ...

  10. windows和linux添加引导文件,Linux与Windows 10用grub引导教程-Go语言中文社区

    前言 去年暑假的时候,写了一篇如何装 Linux 和 Windows 10 双系统的文章发在了简书上,我写这篇文章的原因是当初装双系统确实是折腾了许久,网上也找不到一篇详尽的教程.由于去年对于写教程还 ...

最新文章

  1. python template engine
  2. HP LINUX打印机驱动安装步骤
  3. Atitit 高级人员要看哪些源码 目录 1. Ati看过的源码 1 1.1. Ui类 1 1.2. Mvc类 1 1.3. 数据库类 1 1.4. 算法类 1 2. 看源码的意义 2 2.1. 一
  4. Java比较器-学习
  5. 敏感词库php数组,PHP 实现敏感词 / 停止词 过滤(附敏感词库),敏感类词语大全...
  6. autojs 复制到粘贴板_JS复制到剪贴板示例代码
  7. 计算机科学与技术专业支部,计算机科学与技术专业学生党支部成员组成
  8. Django 链接sqlserver 简单教程
  9. 潮汐监测站点 api数据接口
  10. 词语语义的相关关系和相似关系量化
  11. 开发者数据库规范 - 团队协作
  12. 怎么在ppt中加入html5,怎样在PPT中插入html网页.ppt
  13. Cell:首次揭示肿瘤胞内菌在癌症转移过程中的作用
  14. Homebrew error: Another active Homebrew process is already in progress
  15. linux下w5500驱动程序,W5500驱动函数库.pdf
  16. daemon tools ultra 6虚拟光驱软件
  17. SQLite,嵌入式数据库
  18. 遇到不认识的字怎么键盘输入
  19. 顶级操盘手是怎样准确把握入场时机的
  20. LOAD RESUME YES DSNIDLDU:5016

热门文章

  1. 使用 teredo 穿透NAT访问 ipv6
  2. 2022-2027年中国百元酒店行业市场全景评估及发展战略规划报告
  3. 导出指定layer或指定区域layout的GDS
  4. “标注神器”——Zeplin使用教程(Ps版)
  5. Java开发中存在这样的代码,反而影响整体整洁和可读性
  6. 光伏发电量和用电量的概率预测研究综述(1)
  7. Vim 文件浏览器(Netrw)
  8. Ubuntu下ATI显卡风扇转速调节脚本
  9. Http格林尼治时间和毫秒的相互转化EEE, dd MMM y HH:mm:ss 'GMT'
  10. 最新!2016中国城市GDP排名出炉