当帧开始时,我会进行逻辑更新并在此之后进行渲染。在我的渲染代码中,我做通常的事情。我通过调用 Draw 设置了几个状态、缓冲、纹理和结束。
m_deviceContext->Draw(
nbVertices,
0);
Run Code Online (Sandbox Code Playgroud)
在帧结束时,我调用present 来显示渲染帧。
// Present the back buffer to the screen since rendering is complete.
if(m_vsync_enabled)
{
// Lock to screen refresh rate.
m_swapChain->Present(1, 0);
}
else
{
// Present as fast as possible.
m_swapChain->Present(0, 0);
}
Run Code Online (Sandbox Code Playgroud)
平时的东西。现在,当我调用 Draw 时,根据 MSDN
Draw 将工作提交给渲染管道。
这是否意味着数据被发送到 GPU 并且主线程(称为 Draw 的线程)继续?还是等待渲染完成?
在我看来,只有 Present 函数应该让主线程等待渲染完成。
有许多调用可以触发 GPU 开始工作,Draw
其中之一。其他的包括Dispatch
、CopyResource
等。 MSDN 文档试图说的是像PSSetShader
. IASetPrimitiveTopology
等在您调用 之前不会真正执行任何操作Draw
。
当您调用Present
它时,它被视为“帧结束”的隐式指示器,但您的程序通常可以在第一帧完成并显示之前继续为下一帧设置渲染调用。默认情况下,Windows 将允许您在Present
调用时阻塞 CPU 线程之前最多提前 3 帧排队,以让 GPU 赶上进度——在实时渲染中,您通常不希望输入和渲染之间的延迟是真的高的。
然而,事实是,GPU/CPU 同步很复杂,而且 Direct3D 运行时也在增加请求以最小化内核调用开销,因此在许多 Draw 提交到命令队列后,实际工作可能会发生。这篇旧文章让您了解这是如何工作的。在现代 GPU 上,您还可以进行各种内存操作,用于在内存中进行分页、设置物理视频内存区域等。
顺便说一句,所有这些“魔法”在 Direct3D 12 中都不存在,但这意味着应用程序必须在“正确”的时间做所有事情,以确保它既高效又实用。程序员更直接地构建命令队列,触发各种像素和计算 GPU 引擎上的工作,并完成所有由 Direct3 11 的运行时更加抽象和自动处理的混乱工作。尽管如此,最终视频驱动程序是真正与硬件对话的驱动程序,因此它们也可以进行其他类型的优化。
这里要记住的一般经验法则:
归档时间: |
|
查看次数: |
2061 次 |
最近记录: |