如何检测 WPF 控件何时被重绘?

Asi*_*sik 6 c# directx wpf

我正在使用 D3DImage 显示一系列帧,这些帧依次渲染到同一个 Direct3D Surface 上。我目前的逻辑是:

  • 显示最后渲染的帧(即D3DImage.Lock()/AddDirtyRect()/Unlock())
  • 开始渲染下一帧
  • 等待下一帧准备好并显示它
  • 显示最后渲染的帧
  • ...

这种方法的问题在于,当我们在 D3DImage 上调用 Unlock() 后,图像实际上并未被复制,它只是计划在下一个 WPF 渲染时复制。因此,我们有可能在 WPF 有机会显示新帧之前在 Direct3D 表面上渲染它。最终结果是我们在显示屏上看到丢失的帧。

现在,我正在尝试使用单独的 Direct3D 纹理进行渲染,并在显示之前执行到“显示纹理”的复制,这提供了更好的结果,但会产生大量开销。最好能够知道 D3DImage 何时完成刷新并立即开始渲染下一帧。这可能吗,如果可以的话怎么办?或者你有更好的主意吗?

谢谢。

Asi*_*sik 0

为了与 UI 并行渲染,看起来最干净的方法是渲染到一个单独的 D3D 表面,并在调用 Lock( 之间将其复制到显示表面(即传递给 SetBackBuffer 的表面)) )和解锁()。所以算法就变成了:

  1. 复制并显示最后渲染的帧,即
    • Lock()
    • 从渲染复制到显示表面
    • SetBackBuffer(displaySurface)
    • AddDirtyRect()
    • Unlock()
  2. 将新的渲染安排到渲染表面
  3. 等待它完成并且时机合适即可显示它
  4. 转到1

D3DImage 的文档明确指出

当 D3DImage 解锁时,请勿更新 Direct3D 表面。

这里的痛点是复制,这可能是昂贵的(即,如果硬件繁忙,则>2ms)。为了在 D3DImage 解锁时使用显示表面(避免渲染时可能代价高昂的操作),人们必须诉诸反汇编和反射来挂钩 D3DImage 自己的渲染...