Attempting a "minimum viable" SharpDX 12 setup; error 0x887A0005 "device removed"

1

The goal: Write "minimum viable", no frills or extras code that sets up SharpDX 12 (a C# wrapper around DirectX 12), creates a window, and executes a present loop that clears the screen to RGBA (0, 0, 1, 1).

The expectation: Having followed a DirectX 12 setup tutorial as best as I can, I would then get a window with a blue background.

The outcome: On the second run through the loop, on the line "swapChain.Present(1, SharpDX.DXGI.PresentFlags.None);" The error message "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.

at SharpDX.Result.CheckError() at SharpDX.DXGI.SwapChain.Present(Int32 syncInterval, PresentFlags flags) at DirectX12BlueScreen.Program.Main(String[] args) in *\DirectX12BlueScreen\DirectX12BlueScreen\Program.cs:line 114" printed to the console window (which I am using for debug output)

What I am looking for: Why the error is happening (the device has certainly not been removed); what part of my code is causing the error; and a solution to the problem, if the preceding two pieces of information do not supply that information.

As the full code is 165 lines, I have posted the loop here, and the full code in a pastebin: https://pastebin.com/vctaYkNC

while(form.Visible)
{
    commandAllocator[0].Reset();
    commandList.Reset(commandAllocator[0], null);
    commandList.SetViewport(viewport: viewport);
    commandList.SetScissorRectangles(rectangle: scissorsRectangle);
    commandList.ResourceBarrierTransition(
        resource: renderTargets[0],
        stateBefore: ResourceStates.Present,
        stateAfter: ResourceStates.RenderTarget);
    commandList.ClearRenderTargetView(
        renderTargetView:
        rtvDescriptorHeap.CPUDescriptorHandleForHeapStart,
        colorRGBA: new RawColor4(0f, 0f, 1f, 1f));
    commandList.ResourceBarrierTransition(
        resource: renderTargets[0],
        stateBefore: ResourceStates.RenderTarget,
        stateAfter: ResourceStates.Present);
    commandList.Close();
    commandQueue.ExecuteCommandList(commandList);
    swapChain.Present(1, SharpDX.DXGI.PresentFlags.None);
    Application.DoEvents();
}

Edit: Using information supplied by PhillipH, I now have a more accurate error readout: "System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception. at SharpDX.Direct3D12.GraphicsCommandList.ClearRenderTargetView(CpuDescriptorHandle renderTargetView, RawColor4 colorRGBA, Int32 numRects, RawRectangle[] rectsRef) at SharpDX.Direct3D12.GraphicsCommandList.ClearRenderTargetView(CpuDescriptorHandle renderTargetView, RawColor4 colorRGBA) at DirectX12BlueScreen.Program.Main(String[] args) in *\DirectX12BlueScreen\DirectX12BlueScreen\Program.cs:line 138"

c#
windows
winforms
sharpdx
directx-12
asked on Stack Overflow Jun 25, 2017 by Narf the Mouse • edited Jun 25, 2017 by Narf the Mouse

1 Answer

0

I was not setting up the render targets correctly, and I wasn't using fences at all. I was using SwapChain rather than SwapChain3, and so couldn't get the current buffer index. The correct code has been put into a pastebin for future reference.

It successfully rendered as intended for three minutes, so I think I can call this one resolved.

Thanks to PhillipH, without whose help I'd still be wondering how to get good error messages.

https://pastebin.com/Ku7wqHpJ

The working render loop:

while (form.Visible)
{
    commandAllocator[0].Reset();
    commandList.Reset(commandAllocator[0], null);
    commandList.ResourceBarrierTransition(
        resource: renderTargets[currentBufferIndex],
        stateBefore: ResourceStates.Present,
        stateAfter: ResourceStates.RenderTarget);
    renderTargetView =
        rtvDescriptorHeap.CPUDescriptorHandleForHeapStart +
        currentBufferIndex *
        renderTargetViewHeapSize;
    commandList.ClearRenderTargetView(
        renderTargetView: renderTargetView,
        colorRGBA: new RawColor4(0f, 0f, 1f, 1f));
    commandList.ResourceBarrierTransition(
        resource: renderTargets[currentBufferIndex],
        stateBefore: ResourceStates.RenderTarget,
        stateAfter: ResourceStates.Present);
    commandList.Close();
    commandQueue.ExecuteCommandList(commandList);
    swapChain.Present(1, SharpDX.DXGI.PresentFlags.None);
    long fenceToWaitFor = fenceValue;
    commandQueue.Signal(fence[0], fenceValue);
    ++fenceValue;
    if (fence[0].CompletedValue < fenceValue)
    {
        fence[0].SetEventOnCompletion(fenceToWaitFor,
            fenceEvent.SafeWaitHandle.DangerousGetHandle());
        fenceEvent.WaitOne();
        fenceEvent.Reset();
    }

    currentBufferIndex = swapChain.CurrentBackBufferIndex;
    Application.DoEvents();
}
answered on Stack Overflow Jun 25, 2017 by Narf the Mouse

User contributions licensed under CC BY-SA 3.0