SwapChain Present Issue

Started by
1 comment, last by Curin 7 years ago

Hey everyone,
I'm having a small problem when attempting to move to a UWP code base for SharpDX. I've fixed all problems so far but it errors out with:
"The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action."
on the following line from TestImageSource.cs in the Present() Function:


            _chain.Present(1, PresentFlags.None, new PresentParameters());

I do know that the Swapchain.Present() suggests using Swapchain.Present1(), but that isn't an available function in any Swapchain version.

Thanks for any help,
Curin

MainPage.cs:
[spoiler]


public sealed partial class MainPage : Page
    {
        private TestImageSource _source;
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void SwapChainPanel_OnLoaded(object sender, RoutedEventArgs e)
        {
            _source = new TestImageSource(SwapChainPanel);

            CompositionTarget.Rendering += CompositionTarget_Rendering;
        }

        private void CompositionTarget_Rendering(object sender, object e)
        {
            _source.List.ClearRenderTargetView(_source._cpuHandle, SharpDX.Color.CornflowerBlue);
            _source.Present();
        }
    }

[/spoiler]

TestImageSource.cs:
[spoiler]


using System;
using System.Threading;
using Windows.ApplicationModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using SharpDX;
using SharpDX.Direct3D12;
using SharpDX.DXGI;
using Device = SharpDX.Direct3D12.Device;
using DXGIDevice = SharpDX.DXGI.Device3;
using Adapter = SharpDX.DXGI.Adapter3;
using Resource = SharpDX.Direct3D12.Resource;
using SwapChain = SharpDX.DXGI.SwapChain3;
using Factory = SharpDX.DXGI.Factory4;
using FeatureLevel = SharpDX.Direct3D.FeatureLevel;

...

public class TestImageSource
    {
        const byte FRAMECOUNT = 2;
        private static Factory _fact = new Factory();

        private long _currentFence;

        private Device _devD3D;
        private DescriptorHeap _rtvHeap;
        private CommandQueue _queue;
        private SwapChain _chain;
        private Adapter _adapt;
        private Resource[] _rtv = new Resource[FRAMECOUNT];
        private CommandList _ComList;
        private Fence _fen;
        private AutoResetEvent _event;
        private DXGIDevice _devDXGI;
        private SwapChainPanel _swapPanel;

        private int _width;
        private int _height;
        private int _rtvDescSize;
        private float _pixelSize;

        private int _frameIndex;
        public CpuDescriptorHandle _cpuHandle;
        private SwapChainDescription1 _chainDesc;
        private DescriptorHeapDescription _rtvHeapDesc;
        private bool _isUsingWarp;

        public GraphicsCommandList List;
        public CommandAllocator Allocator;

        public TestImageSource(SwapChainPanel swapPanel)
        {
            _swapPanel = swapPanel;
            _pixelSize = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi/96.0f;
            _width = (int)(swapPanel.RenderSize.Width * _pixelSize);
            _height = (int)(swapPanel.RenderSize.Height * _pixelSize);

            CreateDeviceResources();

            Application.Current.Suspending += OnSuspending;
        }

        private void CreateDeviceResources()
        {
            LoadPipeline();
            LoadAssets();
        }

        private void LoadPipeline()
        {
            if (_devD3D == null)
            {
                try
                {
                    _isUsingWarp = false;
                    using (SharpDX.DXGI.Adapter adapt = _fact.GetAdapter(0))
                        _adapt = adapt.QueryInterface<Adapter>();
                    _devD3D = new Device(_adapt, FeatureLevel.Level_12_1);
                }
                finally 
                {
                    _isUsingWarp = true;
                    using (SharpDX.DXGI.Adapter adapt = _fact.GetWarpAdapter())
                        _adapt = adapt.QueryInterface<Adapter>();
                    _devD3D = new Device(_adapt, FeatureLevel.Level_12_1);
                }
            }

            _queue = _devD3D.CreateCommandQueue(new CommandQueueDescription(CommandListType.Direct));

            _chainDesc = new SwapChainDescription1()
            {
                AlphaMode = AlphaMode.Ignore,
                BufferCount = FRAMECOUNT,
                Format = Format.B8G8R8A8_UNorm,
                Height = _height,
                Width = _width,
                SampleDescription = new SampleDescription(1, 0),
                Scaling = Scaling.Stretch,
                Stereo = false,
                SwapEffect = SwapEffect.FlipSequential,
                Usage = Usage.BackBuffer | Usage.RenderTargetOutput
            };

            _devDXGI = new Device3(_devD3D.NativePointer);

            using (Factory3 fact = _adapt.GetParent<Factory3>())
                using (SwapChain1 chain = new SwapChain1(fact, _queue, ref _chainDesc))
                    _chain = chain.QueryInterface<SwapChain3>();

            using (ISwapChainPanelNative nativeObject = ComObject.As<ISwapChainPanelNative>(_swapPanel))
                nativeObject.SwapChain = _chain;

            _rtvHeapDesc = new DescriptorHeapDescription()
            {
                DescriptorCount = FRAMECOUNT,
                Type = DescriptorHeapType.RenderTargetView,
                Flags = DescriptorHeapFlags.None
            };

            _rtvHeap = _devD3D.CreateDescriptorHeap(_rtvHeapDesc);
            _rtvDescSize = _devD3D.GetDescriptorHandleIncrementSize(DescriptorHeapType.RenderTargetView);

            _cpuHandle = _rtvHeap.CPUDescriptorHandleForHeapStart;

            Allocator = _devD3D.CreateCommandAllocator(CommandListType.Direct);
            List = _devD3D.CreateCommandList(CommandListType.Direct, Allocator, null);
        }

        private void LoadAssets()
        {
            _fen = _devD3D.CreateFence(0, FenceFlags.None);
            _currentFence = 1;

            _event = new AutoResetEvent(false);
            WaitForPrevFrame();
        }

        private void WaitForPrevFrame()
        {
            long localFence = _currentFence;
            _queue.Signal(_fen, localFence);
            _currentFence++;

            if (_fen.CompletedValue < localFence)
            {
                _fen.SetEventOnCompletion(localFence, _event.GetSafeWaitHandle().DangerousGetHandle());
                _event.WaitOne();
            }

            _frameIndex = _chain.CurrentBackBufferIndex;
            _cpuHandle = _rtvHeap.CPUDescriptorHandleForHeapStart;
            _cpuHandle += _frameIndex * _rtvDescSize;

            
        }

        public void Present()
        {
            _queue.ExecuteCommandList(List);
            _chain.Present(1, PresentFlags.None, new PresentParameters());

            WaitForPrevFrame();
        }

        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            throw new NotImplementedException();
        }
    }
}

[/spoiler]

Advertisement

This is likely unrelated to the Present call. If you're using D3D12, it's more likely that you have an error somewhere else which is just getting reported out of Present. Are you running with the D3D12 debug layer? How about the GPU-based validation layer? Most likely it would report what's causing your problem.

Thank you very much Jesse. I hadn't turned on the Debug layer as I was doing quick tests and forgot. It led me to realize I forgot a bunch of steps that I had put in different spots of my old code, like creating my rendertargets, not just their heaps, and reseting the command list and allocator every frame.

Appreciate your Help,

Curin

This topic is closed to new replies.

Advertisement