SwapChain.Present The GPU device instance has been suspended

177 Views Asked by At

I am trying to make a very simple square render in SharpDX using a WPF window, but when this line of code is executed var response = _swapChain.Present(0, PresentFlags.None); my entire screen starts to flicker with lines of random colors around and my entire system gets messed up for a couple of seconds untill the following exception is thrown:

SharpDX.SharpDXException: 'HRESULT: [0x887A0005], Module: [SharpDX.DXGI], ApiCode: [DXGI_ERROR_DEVICE_REMOVED/DeviceRemoved], Message: The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.

The worst is that I remember rendering a square using SharpDX with another approach this very morning, but for some reason making it this way makes my GPU go boom.

Any ideas about what might be happening?

Here is the code:

MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    private SharpDXRenderer _sharpDXRenderer;

    public MainWindow()
    {
        InitializeComponent();

        Loaded += MainWindow_Loaded;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        _sharpDXRenderer = new SharpDXRenderer(this);

        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }

    private void CompositionTarget_Rendering(object sender, EventArgs e)
    {
        _sharpDXRenderer.Render();
    }
}

SharpDXRenderer.cs

public class SharpDXRenderer : IDisposable
{
    private WindowInteropHelper _interopHelper;
    private Device _device;
    private SwapChain _swapChain;
    private RenderTargetView _renderTargetView;
    private DeviceContext _deviceContext;

    private bool _isRendering;
    private Stopwatch _stopwatch;
    private const int TargetFrameRate = 60; // Set your desired frame rate here
    private const long TargetFrameTime = TimeSpan.TicksPerSecond / TargetFrameRate;

    public SharpDXRenderer(Window window)
    {
        _interopHelper = new WindowInteropHelper(window);

        InitializeDeviceResources();
        CreateRenderTarget();

        _stopwatch = Stopwatch.StartNew();
    }

    private void InitializeDeviceResources()
    {
        var description = new SwapChainDescription()
        {
            BufferCount = 1,
            ModeDescription = new ModeDescription()
            {
                Width = 800,
                Height = 600,
                Format = Format.R8G8B8A8_UNorm,
                RefreshRate = new Rational(60, 1),
            },
            Usage = Usage.RenderTargetOutput,
            SampleDescription = new SampleDescription(1, 0),
            Flags = SwapChainFlags.None,
            SwapEffect = SwapEffect.Discard,
            OutputHandle = _interopHelper.Handle,
            IsWindowed = true,
        };

        Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, description, out _device, out _swapChain);
        _deviceContext = _device.ImmediateContext;
    }

    private void CreateRenderTarget()
    {
        using (var backBuffer = _swapChain.GetBackBuffer<Texture2D>(0))
        {
            _renderTargetView = new RenderTargetView(_device, backBuffer);
        }

        _deviceContext.OutputMerger.SetRenderTargets(_renderTargetView);
    }

    public void Render()
    {
        if(_isRendering)
        {
            return;
        }

        if (_stopwatch.ElapsedTicks >= TargetFrameTime)
        {
            _isRendering = true;
            _deviceContext.ClearRenderTargetView(_renderTargetView, new RawColor4(0, 0, 0, 1)); // Black color

            // Draw a black square
            var vertices = new[]
            {
                new RawVector2(100, 100), // Top-left
                new RawVector2(200, 100), // Top-right
                new RawVector2(200, 200), // Bottom-right
                new RawVector2(100, 200), // Bottom-left
            };

            _deviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;

            using (var vertexBuffer = SharpDX.Direct3D11.Buffer.Create(_device, BindFlags.VertexBuffer, vertices))
            {
                var vertexBufferBinding = new VertexBufferBinding(vertexBuffer, Utilities.SizeOf<RawVector2>(), 0);
                _deviceContext.InputAssembler.SetVertexBuffers(0, vertexBufferBinding);
                _deviceContext.Draw(4, 0);
            }

            var response = _swapChain.Present(0, PresentFlags.None);
            _stopwatch.Restart();
            _isRendering = false;
        }
    }

    public void Dispose()
    {
        _device?.Dispose();
        _swapChain?.Dispose();
        _renderTargetView?.Dispose();
        _deviceContext?.Dispose();
    }
}

Any help will be really appreciated, I am very lost.

0

There are 0 best solutions below