如何将 Direct3D 11 覆盖与 WPF Viewport3D 同步?

How to synchronize Direct3D 11 overlay with WPF Viewport3D?

我正在开发一个显示 3D 场景的 WPF 应用程序。当我使用 Viewport3D 控件在该场景中显示 2D WPF 控件时,我在透明覆盖 window 中使用本机 Direct3D 11 来处理复杂的动画 3D 几何图形。这很好用。

唯一的问题是,由于 Direct3D 覆盖 window 与 WPF Viewport3D 不同步,目前可能会有明显的延迟。它仅在相机四处移动时才可见,因为那时 Viewport3D 渲染必须像 Direct3D 渲染一样更新。理想情况下,Direct3D 缓冲区应在 WPF 缓冲区之后立即交换。

我的问题:有什么方法可以在 Viewport3D 显示其内容后立即执行代码?或者至少接近那个时刻? 不一定是一个干净的解决方案——我也可以忍受一个肮脏的本地 hack …

我设法创建了一个从(内部)Viewport3DVisual class 的 RenderContent 调用的方法,但这比实际呈现在屏幕上的执行频率更高,而且可能不在渲染线程上。

好的,我自己找到了解决方案。可以使用反射将事件处理程序添加到内部 MediaContext class 的内部 RenderComplete 事件:

Assembly oAssemblyPresentationCore = typeof( Visual ).Assembly;
Type oTypeMediaContext = oAssemblyPresentationCore.GetType( "System.Windows.Media.MediaContext" );
MethodInfo oMethodInfoGetMediaContextFromDispatcher = oTypeMediaContext.GetMethod( "From", BindingFlags.Static | BindingFlags.NonPublic );
object oMediaContext = oMethodInfoGetMediaContextFromDispatcher.Invoke( null, new object[] { oViewport3D.Dispatcher } );
EventInfo oEventInfoRenderComplete = oMediaContext.GetType().GetEvent( "RenderComplete", BindingFlags.NonPublic | BindingFlags.Instance );
oEventInfoRenderComplete.GetAddMethod( true ).Invoke( oMediaContext, new object[] { new EventHandler( EventHandlerRendered ) } );