Search code examples
wpfdirectxdirect3ddispatcherd3dimage

D3DImage.Lock() causes the dispatcher to process and fire other events


I wrote a WPF application that uses D3dImage class, I subscribed to CompositionTarget.Rendering event and I update the content displayed with the following instructions

D3DImageInstance.Lock();
D3DImageInstance.SetBackBuffer(...);
D3DImageInstance.AddDirtyRect(new Int32Rect(0, 0, Width, Height));
D3DImageInstance.Unlock();

My problem is that if the Window is resized, during the Lock() call the resize event is fired and the program execution jumps to the handler of the event, as shown in the following stack trace:

    D3DWPFImageSource.Initialize(D3DImageExtManager d3dImageManager, int width, int height, SharpDX.Direct3D11.Texture2D backBufferTexture, SharpDX.Direct3D11.Texture2DDescription textureDesc, int renderSurfaceCount) Line 61    C#
    D3DRenderContextWPF.InitResourceBuffers(System.Drawing.Size size) Line 4407 C#
    D3DRenderContextWPF.Resize(System.Drawing.Size size) Line 4589  C#
    Workspace.OnResize(System.EventArgs e) Line 3875    C#
    WorkspaceBase.CreateAndBindTargets() Line 1670  C#
    WorkspaceBase.OnRenderSizeChanged(System.Windows.SizeChangedInfo sizeInfo) Line 1845    C#
    [External Code] 
>   D3DImageInstance.Lock();
    D3DImageExtManager.UpdateBackBufferCommand.Update(SharpDX.Direct3D11.Device device, SharpDX.Direct3D11.DeviceContext context, SharpDX.Direct3D11.Texture2D wpfSharedSurface, System.IntPtr sharedSurfacePtr) Line 222   C#
    D3DImageExtManager.CompositionTargetOnRendering(object sender, System.EventArgs eventArgs) Line 156 C#
    D3DRenderContextWPF.OnRendering() Line 4491 C#
    WorkspaceBase.OnRendering(object sender, System.EventArgs e) Line 1785  C#
    [External Code]

In the resize handler I re-initialize the graphics resource, which leads to an inconsistent state when the program execution goes back on the Rendering handler.

Is this normal behavior? It depends only on the Lock() call? What is the right approach to manage this case?

Thanks


Solution

  • Solved by calling Dispatcher.DisableProcessing() to prevent events processing during the rendering routine

    using System.Windows.Threading.Dispatcher.CurrentDispatcher.DisableProcessing())  
    {
        D3DImageInstance.Lock();
        D3DImageInstance.SetBackBuffer(...);
        D3DImageInstance.AddDirtyRect(new Int32Rect(0, 0, Width, Height));
        D3DImageInstance.Unlock();
    }