1

I’m developing a WPF application showing a 3D scene. While I use the Viewport3D control to display 2D WPF controls within that scene, I use native Direct3D 11 in a transparent overlay window for complex animated 3D geometries. This works fine.

The one and only problem is, that currently there may be a significant delay because the Direct3D overlay window is not synchronized with the WPF Viewport3D. It becomes only visible when the camera is moved around because then the Viewport3D rendering has to be updated just like the Direct3D rendering. Ideally, the Direct3D buffer should be swapped immediately after the WPF buffer.

My question: Is there any way to execute code just after the Viewport3D presents its contents? Or at least close to that moment? Does not have to be a clean solution – I could also live with a dirty native hack …

I managed to create a method which gets called from RenderContent of the (internal) Viewport3DVisual class, but this is executed more often than the actual present to screen and probably not on the render thread.

Athafoud
  • 2,898
  • 3
  • 40
  • 58
  • 1
    You should share the code that you tried to solve your problem. If it has any issue with it, you will get suggestions/answer here. – Kamalesh Wankhede Aug 30 '16 at 14:13
  • You may want to update Viewport3D after you changed something in D3D. Why not? – Sergey.quixoticaxis.Ivanov Aug 30 '16 at 14:17
  • @sergey Well, the problem if I do it that way around is that it will take some time until the Viewport3D has finished rendering and finally presents an update – actually, WPF might start to render multiple times without presenting anything at all to the front buffer. Hence the Viewport3D still displays an outdated scene, while the updated Direct3D overlay is already visible. That is also the reason why my hook on `RenderContent` is not a good solution, rendering is not necessarily close to the next present to the front buffer in WPF. – Johannes Viehmann Aug 30 '16 at 15:41
  • @user12572 The problem is not really in my code, my code works as I expect it. The question is where / how to call the D3D overlay render method so that it has always a minimal delay to the Viewport3D present to front buffer … – Johannes Viehmann Aug 30 '16 at 15:52

1 Answers1

0

Ok, I found the solution by myself. It is possible to add an event handler to the internal RenderComplete event of the internal MediaContext class using reflection:

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 ) } );