gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 12:47:36 26 4
gpt4 key购买 nike

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

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

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

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

谢谢。

最佳答案

CompositionTarget.Rendering event在 WPF 将要呈现时调用,因此您应该在此时执行 Lock()Unlock()。在 Unlock() 之后,您可以开始下一次渲染。

您还应该检查 RenderingTime,因为该事件可能每帧触发多次。尝试这样的事情:

private void HandleWpfCompositionTargetRendering(object sender, EventArgs e)
{
RenderingEventArgs rea = e as RenderingEventArgs;

// It's possible for Rendering to call back twice in the same frame
// so only render when we haven't already rendered in this frame.
if (this.lastRenderTime == rea.RenderingTime)
return;

if (this.renderIsFinished)
{
// Lock();
// SetBackBuffer(...);
// AddDirtyRect(...);
// Unlock();

this.renderIsFinished = false;
// Fire event to start new render
// the event needs to set this.renderIsFinished = true when the render is done

// Remember last render time
this.lastRenderTime = rea.RenderingTime;
}
}

更新以解决评论

您确定存在竞争条件吗? This page表示当您调用 Unlock() 时后台缓冲区会被复制。

如果真的存在竞争条件,在渲染代码周围放置 Lock/Unlock 怎么样? This page表示 Lock() 将阻塞直到复制完成。

关于c# - 如何检测 WPF 控件何时被重绘?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16482841/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com