等待VBLANK在窗口模式下呈现在 Windows 10上的正确方法是什么?目前我正在做以下事情:
D3DKMTWaitForVerticalBlankEvent(&waitData);
swapchain->Present(0,0);

然而,这会导致偶尔的口吃.我目前关于口吃的理论如下:
DWM在VBLANK事件之前的某个时间完成合成,然后在VBLANK间隔期间,DWM尝试尽可能快地写入前端缓冲区.因此,如果在VBLANK间隔中调用Present,则可能在DWM写入前缓冲区后发生.这是我头脑中的画面:

因此,更正确的方法是在VBLANK之前调用Present(1,0)以使用DWM对窗口的后缓冲区进行排队.然后调用D3DKMTWaitForVerticalBlankEvent等到下一个VBLANK.那是:

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

有相应的图片:

第二种方法看起来很完美,不再有任何口吃.

我的问题是:
什么是在VBLANK间隔中呈现的正确方法
我的理论是正确的还是有更复杂/更简单的事情发生?
还有什么资源可以了解这种互动的更多信息吗?

潜在有用的链接:
MSDN Present
DXGI Best Practices
DXGI Waitable Swap Chain
D3DKMTWaitForVerticalBlankEvent

编辑:
不确定这应该是答案还是编辑.
经过一些谷歌搜索后,我发现this explanation by Nicholas Steel似乎与我的理论一致

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.

所以最好的办法是:

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

另一个编辑:
对于未来的读者,还有另外两种等待VBLANK的方法我不知道它们是IdxgiOutput :: WaitForVBlank和IDirectDraw7 :: WaitForVerticalBlank后者被弃用了.

你为什么要在窗口模式下等待VBLANK? DWM将确保合成曲面将在VBLANK区域中翻转.

当您说“DWM在VBLANK事件之前的某个时间完成合成”时,什么会使DWM启动合成?在任何应用程序呈现之后,或在关注的应用程序呈现之后,它不会发生.组合实际上在VBLANK发生时开始.它可能会完成并翻转VBLANK中的合成曲面,或者最终可能会在下一个VBLANK中翻转(因此您可能会在延迟时间内获得额外的帧持续时间).这不是你的控制 – 它取决于合成的持续时间而不是你的应用程序的存在.

在一个带窗口的应用程序中,当你调用present时,它只是翻转你的应用程序的交换链 – 它不会翻转显示的表面. DWM将处理这个问题.所以“只要合成器处于活动状态,你也不必担心自己的VBlank轮询了.”

然而,使用DwmFlush()来实现“在每个VBlank周期之间向合成器呈现最多1个新视频帧”不一定是期望的.除非你肯定只想在每个监视周期显示1帧,否则你可以这样做(虽然我不确定DwmFlush()是否是最优雅的方法).但在大多数情况下,我不认为强制执行该限制是可取的.

winapi – 在窗口模式下在Windows 10上等待VBLANK的正确方法的更多相关文章

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. js中‘!.’是什么意思

  3. InnoDB 和 MyISAM 引擎恢复数据库,使用 .frm、.ibd文件恢复数据库

  4. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  5. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  6. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  7. 宝塔Linux的FTP连接不上的解决方法

    宝塔Linux的FTP连接不上的解决方法常见的几个可能,建议先排查。1.注意内网IP和外网IP2.检查ftp服务是否启动 (面板首页即可看到)3.检查防火墙20端口 ftp 21端口及被动端口39000 - 40000是否放行 (如是腾讯云/阿里云等还需检查安全组)4.是否主动/被动模式都不能连接5.新建一个用户看是否能连接6.修改ftp配置文件 将ForcePassiveIP前面的#去掉 将19

  8. 扩展element-ui el-upload组件,实现复制粘贴上传图片文件,带图片预览功能

  9. 微信小程序canvas实现水平、垂直居中效果

    这篇文章主要介绍了小程序中canvas实现水平、垂直居中效果,本文图文实例代码相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

  10. 使用HTML5做的导航条详细步骤

    这篇文章主要介绍了用HTML5做的导航条详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部