在DirectX 11中渲染

时间:2015-06-24 07:43:49

标签: directx-11

当帧开始时,我会进行逻辑更新并在此之后进行渲染。 在我的渲染代码中,我做通常的事情。我设置了几个状态,buffors,纹理,并通过调用Draw来结束。

m_deviceContext->Draw(
        nbVertices,
        0);

在帧结束时,我调用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);
}

通常的东西。现在,当我打电话给Draw时,根据MSDN

  

Draw将工作提交给渲染管道。

这是否意味着数据被发送到GPU并且主线程(名为Draw)继续?还是等待渲染完成?

在我看来,只有Present函数才能使主线程等待渲染完成。

1 个答案:

答案 0 :(得分:3)

有许多调用可以触发GPU开始工作,Draw是一个。其他内容包括DispatchCopyResource等.MSDN文档试图说的是像PSSetShader这样的内容。在致电IASetPrimitiveTopology之前,Draw等并没有做任何事情。

当您致电Present时,该Present被视为框架结束的隐含指示符'但是你的程序通常可以继续在第一帧完成和显示之前为下一帧设置渲染调用。默认情况下,Windows会让您在at 12:00 the schedule is : first_task:eating:fruit second_task:rest:onehour third_task:watching:horrorfilm at 18:00 the schedule is : first_task:eating:vegetals second_task:rest:threehours third_task:watching:manga at 22:00 the schedule is : first_task:eating:nothing second_task:rest:sevenhours third_task:watching:nothing 调用阻塞CPU线程之前最多排队3帧,让GPU赶上 - 实时渲染您通常不想要延迟在输入和渲染之间真的很高。

然而,事实是,GPU / CPU同步很复杂,Direct3D运行时也在为最小化内核调用开销的请求提供支持,因此在将许多Draw提交到命令队列后,实际工作可能会受到影响。 This old article为您提供了如何工作的风格。在现代GPU上,您还可以使用各种内存操作在内存中进行分页,设置物理视频内存区域等。

顺便说一句,所有这些'魔术'与Direct3D 12不存在但这意味着应用程序必须在“正确”的情况下执行所有操作。确保它既高效又实用的时间。程序员更直接地构建命令队列,触发各种像素和计算GPU引擎的工作,以及完成由Direct3 11的运行时稍微抽象和自动处理的所有混乱的东西。即使如此,最终视频驱动程序实际上是与硬件通信的驱动程序,因此它们也可以进行其他类型的优化。

这里要记住一般的经验法则:

  • 创建资源非常昂贵,特别是运行时着色器编译(通过HLSL编译器)和运行时着色器blob优化(通过驱动程序)
  • 将资源复制到GPU(即从CPU内存加载纹理数据)需要供应有限的总线带宽:更喜欢将纹理,VB和IB数据保存在您重复使用的静态缓冲区中。
  • 从GPU复制资源(即将GPU内存移动到CPU内存)使用的反向通道比转到GPU要慢:尽量避免需要从GPU回读
  • 每次Draw调用提交更大的几何体块有助于分摊开销(即,对于10,000个三角形调用绘制一次,使用相同的状态/着色器比调用绘制10次,每个1000个三角形,每次更改状态/着色器)要快得多。