如何在等待垂直同步时执行操作?
我希望能够加载/下载一堆资源并通知用户当前正在加载的文件,但我不能在每个文件开始加载后绘制一个框架,因为垂直同步将等到它可以绘制一个框架继续之前的帧(将负载限制为低于 60/秒)。
有没有办法检查设备是否准备好绘制(没有 hacky“已经过去了 1/60 秒?),这样我就可以执行操作直到它准备好?我不介意通知是否跳过在准备绘制之前完成的文件,但我想最大限度地提高加载速度,同时仍然能够通知用户
此外,我想避免暂时禁用垂直同步,因为我不想导致。一张显卡如果计算机加载速度非常快,则 300FPS 会严重降低。
I want to be able to load/download a bunch of resources and notify the user of the file that's currently being loaded, but I can't just draw a frame after each file starts loading because v-sync will wait until it can draw a frame before it continues (bottle-necking the loads to less than 60/second).
Is there a way to check whether the device is ready to draw or not (without hacky "has 1/60th of a second passed yet?), so I can perform actions until it's ready? I don't mind if the notification skips over files that finished before it's ready to draw, but I want to maximize the speed of the loads while still being able to notify the user.
Also, I'd like to avoid disabling v-sync even temporarily because I don't want to cause a graphic card crippling 300FPS rate if the computer loads really quickly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有指定您正在使用哪个版本的 Direct3D。使用 D3D9,您可以将 D3DPRESENT_DONOTWAIT 传递给 Present() 调用,如果硬件正忙于处理或等待垂直同步间隔,它将返回 D3DERR_WASSTILLDRAWING。这意味着,如果您启用了垂直同步,则在主循环中,只要您加载了一个文件,您就可以使用 DONOTWAIT 标志调用 Present,如果它返回 WASSTILLDRAWING,则加载另一个文件。
请注意,您需要获取交换链并在交换链上调用 Present(),而不是直接在设备上调用 Present() 才能将此标志传递给 Present,或者您可以在创建时在 D3DPRESENT_PARAMETERS 结构中设置它设备或创建 IDirect3DDevice9Ex 而不是 IDirect3DDevice9 设备并调用 PresentEx() 而不是 Present()。
但这并不能解决文件加载时间超过一帧的问题 - 如果您有一个需要很长时间处理的文件,您的帧速率将会下降。在我看来,这个问题的更好解决方案是将尽可能多的 IO 移动到另一个线程(在 D3D9 中,您仍然需要在主线程上创建 D3D 资源),然后只传递当前文件的名称被处理到您的主/渲染线程以在每次呈现帧时显示。
You don't specify which version of Direct3D you're using. With D3D9 you can pass D3DPRESENT_DONOTWAIT to your Present() call and it will return D3DERR_WASSTILLDRAWING if the hardware is busy processing or waiting for a vertical sync interval. This means if you have vsync enabled, in your main loop you can just call Present with the DONOTWAIT flag whenever you've loaded a file and load another if it returns WASSTILLDRAWING.
Note that you need to get the swap chain and call Present() on the swap chain rather than calling Present() directly on the device to be able to pass this flag to present, or you can set it in the D3DPRESENT_PARAMETERS structure when you create the device or create an IDirect3DDevice9Ex instead of an IDirect3DDevice9 device and call PresentEx() instead of Present().
This doesn't solve the problem of files that take longer than a frame to load however - your frame rate will drop if you have a file that takes a long time to process. A better solution to this problem in my opinion would be to move as much of your IO as possible to another thread (in D3D9 you will still have to create D3D resources on your main thread however) and just pass the name of the file that's currently being processed to your main / render thread to display each time you present a frame.