SwapChain.Present GPU 设备实例已暂停

SwapChain.Present The GPU device instance has been suspended

提问人:Pakoco 提问时间:5/12/2023 更新时间:5/12/2023 访问量:122

问:

我正在尝试使用 WPF 窗口在 SharpDX 中制作非常简单的方形渲染,但是当执行这行代码时,我的整个屏幕开始闪烁,周围有随机颜色的行,我的整个系统被搞砸了几秒钟,直到抛出以下异常:var response = _swapChain.Present(0, PresentFlags.None);

SharpDX.SharpDXException:'HRESULT:[0x887A0005],模块:[SharpDX.DXGI],ApiCode:[DXGI_ERROR_DEVICE_REMOVED/DeviceRemoved],消息:GPU 设备实例已挂起。使用 GetDeviceRemovedReason 确定相应的操作。

最糟糕的是,我记得今天早上用另一种方法用 SharpDX 渲染了一个正方形,但由于某种原因,这样做会让我的 GPU 蓬勃发展。

关于可能发生的事情的任何想法?

代码如下:

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

夏普DXRenderer.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();
    }
}

任何帮助将不胜感激,我非常迷茫。

C# WPF、 DirectX、DirectX-11 SharpDX

评论

0赞 Simon Mourier 5/12/2023
此处删除的设备是由驱动程序级别的争用超时引起的。WPF 有自己的交换链(基于 DX9),因此,这是行不通的。使用 WPF 时,使用 DirectX 的唯一官方方法是 D3DImage learn.microsoft.com/en-us/dotnet/api/...(这有很大的缺点,就像基于 DX9 一样)。WPF 现在是旧版(如 SharpDX)。我的建议是将 UWP 或 WinUI3 与 SwapChainPanel (learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/...) 一起使用,这正是为此而设计的。

答: 暂无答案