I have realtime graphics in WPF application with DirectX on SharpDX. I use Direct2D1, Direct Composition, SwapCain. Its perfectly works with 1 object on window, but if i add more one (9), then there are problems: in debug after 1-2 min or if I actively move window between monitors, I catch Access Violation exception or Device Removed, in release I catch it once after deploy. I try recreate device after removing, but it dont work.
public class DirectX
{
public BitmapProperties1 BitmapProperties1 { get; private set; }
public SharpDX.Direct2D1.Factory1 Factory1 { get; private set; }
private SharpDX.DXGI.Device _genericDevice;
private SharpDX.DirectComposition.Visual _visual;
private Target _target;
private SharpDX.DirectComposition.Device _compDevice;
private SharpDX.Direct3D11.Device d11Device;
private IntPtr _hwnd;
public Result? DeviceRemovedReason => d11Device?.DeviceRemovedReason;
public DirectX(Window window)
{
_hwnd = new WindowInteropHelper(window).Handle;
InitilizeDevices();
}
private bool _isRefreshed = false;
public void InitilizeDevices()
{
var creationFlags = SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport;
var factory1Flags = DebugLevel.None;
#if DEBUG
creationFlags |= SharpDX.Direct3D11.DeviceCreationFlags.Debug;
factory1Flags = DebugLevel.Information;
#endif
SharpDX.Direct3D.FeatureLevel[] featureLevels =
{
SharpDX.Direct3D.FeatureLevel.Level_11_1,
SharpDX.Direct3D.FeatureLevel.Level_11_0,
SharpDX.Direct3D.FeatureLevel.Level_10_1,
SharpDX.Direct3D.FeatureLevel.Level_10_0,
SharpDX.Direct3D.FeatureLevel.Level_9_3,
SharpDX.Direct3D.FeatureLevel.Level_9_2,
SharpDX.Direct3D.FeatureLevel.Level_9_1,
};
if (d11Device != null)
Utilities.Dispose(ref d11Device);
d11Device = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, creationFlags, featureLevels);
Factory1 = new SharpDX.Direct2D1.Factory2(FactoryType.MultiThreaded, factory1Flags);
if (_genericDevice != null)
Utilities.Dispose(ref _genericDevice);
_genericDevice = d11Device.QueryInterface<SharpDX.DXGI.Device>();
if (_compDevice != null)
Utilities.Dispose(ref _compDevice);
_compDevice = new SharpDX.DirectComposition.Device(_genericDevice);
BitmapProperties1 = new BitmapProperties1(new SharpDX.Direct2D1.PixelFormat(Format.R8G8B8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Ignore), Factory1.DesktopDpi.Width, Factory1.DesktopDpi.Height, BitmapOptions.CannotDraw | BitmapOptions.Target);
if (_visual == null)
_visual = new SharpDX.DirectComposition.Visual(_compDevice);
if (_target == null)
_target = Target.FromHwnd(_compDevice, _hwnd, true);
_target.Root = _visual;
_compDevice.Commit();
}
public void CreateSwapChainAndDeviceContext(int width, int height, float offsetX, float offsetY, out SwapChain1 swapChain, out DeviceContext deviceContext)
{
var desc = new SwapChainDescription1()
{
BufferCount = 2,
Width = width,
Height = height,
Format = Format.R8G8B8A8_UNorm,
SampleDescription = new SampleDescription(1, 0),
SwapEffect = SwapEffect.FlipSequential,
Usage = Usage.RenderTargetOutput
};
swapChain = new SwapChain1(new SharpDX.DXGI.Factory2(), _genericDevice, ref desc);
var visual = new SharpDX.DirectComposition.Visual(_compDevice)
{
Content = swapChain,
};
visual.SetOffsetX(offsetX);
visual.SetOffsetY(offsetY);
_visual.AddVisual(visual, true, null);
_compDevice.Commit();
using (var d2Device = new SharpDX.Direct2D1.Device(Factory1, _genericDevice))
deviceContext = new DeviceContext(d2Device, DeviceContextOptions.None) { AntialiasMode = AntialiasMode.Aliased };
}
}
In control:
public void Init(float offsetX, float offsetY, DirectX directX)
{
_directX = directX;
_offsetX = offsetX;
_offsetY = offsetY;
Stopwatch = new Stopwatch();
_directX.CreateSwapChainAndDeviceContext((int)ActualWidth, (int)ActualHeight, _offsetX, _offsetY, out swapchain, out deviceContext);
brush = new SharpDX.Direct2D1.SolidColorBrush(deviceContext, new Color4(1f, 0f, 0, 1f));
stop = false;
var thread = new Thread(new ThreadStart(Render));
thread.Start();
}
public Action RefreshAction { get; set; } // call InitializeDevices in DirectX
Random rand = new Random();
public bool stop;
SharpDX.DXGI.SwapChain1 swapchain;
SharpDX.Direct2D1.SolidColorBrush brush;
DeviceContext deviceContext;
SharpDX.DXGI.Surface2 backBuffer;
Stopwatch Stopwatch;
object _lock = new object();
DirectX _directX;
private void Render()
{
while (!stop)
{
Stopwatch.Start();
try
{
backBuffer = swapchain.GetBackBuffer<SharpDX.DXGI.Surface2>(0);
var bitmap1 = new SharpDX.Direct2D1.Bitmap1(deviceContext, backBuffer, _directX.BitmapProperties1);
deviceContext.Target = bitmap1;
deviceContext.BeginDraw();
deviceContext.Clear(SharpDX.Color.Green);
using (var geometry = new SharpDX.Direct2D1.PathGeometry(_directX.Factory1))
{
using (var path = geometry.Open())
{
double angle = 10 * Math.PI * (rand.NextDouble() - 0.5);
sin.Add(100 + 10 * Math.Sin(angle));
sin.RemoveAt(0);
path.BeginFigure(new Vector2(0, (float)sin[0]), FigureBegin.Hollow);
for (int k = 1; k < 100; k++)
{
path.AddLine(new Vector2(k * 5, (float)sin[k]));
}
path.EndFigure(FigureEnd.Open);
path.Close();
}
deviceContext.DrawGeometry(geometry, brush, 1);
}
deviceContext.DrawEllipse(new SharpDX.Direct2D1.Ellipse(new Vector2(100, 100), 20, 20), brush);
deviceContext.EndDraw();
swapchain.Present(1, PresentFlags.None);
bitmap1.Dispose();
backBuffer.Dispose();
}
catch (SharpDXException ex) when ((uint)ex.HResult == 0x8899000C || (uint)ex.HResult == 0x887A0020 || (uint)ex.HResult == 0x887A0005)
{
Console.WriteLine(_directX?.DeviceRemovedReason);
Console.WriteLine(ex);
if (!stop)
RefreshAction();
return;
}
catch (AccessViolationException ex)
{
Console.WriteLine(ex);
}
Stopwatch.Stop();
Stopwatch.Reset();
if (Stopwatch.ElapsedMilliseconds < 20)
Thread.Sleep(20 - (int)Stopwatch.ElapsedMilliseconds);
}
}
User contributions licensed under CC BY-SA 3.0