コード例 #1
0
    public static IDXGIAdapter1 *GetLatestDxgiAdapter(IDXGIAdapter1 *dxgiAdapter, out uint dxgiAdapterVersion)
    {
        IDXGIAdapter1 *result;

        if (dxgiAdapter->QueryInterface(__uuidof <IDXGIAdapter4>(), (void **)&result).SUCCEEDED)
        {
            dxgiAdapterVersion = 4;
            _ = dxgiAdapter->Release();
        }
        else if (dxgiAdapter->QueryInterface(__uuidof <IDXGIAdapter3>(), (void **)&result).SUCCEEDED)
        {
            dxgiAdapterVersion = 3;
            _ = dxgiAdapter->Release();
        }
        else if (dxgiAdapter->QueryInterface(__uuidof <IDXGIAdapter2>(), (void **)&result).SUCCEEDED)
        {
            dxgiAdapterVersion = 2;
            _ = dxgiAdapter->Release();
        }
        else
        {
            dxgiAdapterVersion = 1;
            result             = dxgiAdapter;
        }

        return(result);
    }
コード例 #2
0
    protected override void CreateDeviceDependentResources()
    {
        _dxgiFactory = CreateDxgiFactory();
        _dxgiAdapter = GetDxgiAdapter();
        _d3dDevice   = CreateD3DDevice(out _immediateContext);

        CreateAssets();

        ID3D11Device *CreateD3DDevice(out ID3D11DeviceContext *pImmediateContext)
        {
            ID3D11Device *       d3dDevice;
            ID3D11DeviceContext *immediateContext;

            var featureLevel = D3D_FEATURE_LEVEL_11_0;

            ThrowIfFailed(D3D11CreateDevice((IDXGIAdapter *)DxgiAdapter, D3D_DRIVER_TYPE_HARDWARE, Software: HMODULE.NULL, Flags: 0, &featureLevel, FeatureLevels: 1, D3D11_SDK_VERSION, &d3dDevice, pFeatureLevel: null, &immediateContext));

            pImmediateContext = immediateContext;
            return(d3dDevice);
        }

        IDXGIFactory1 *CreateDxgiFactory()
        {
            IDXGIFactory1 *dxgiFactory;

            ThrowIfFailed(CreateDXGIFactory1(__uuidof <IDXGIFactory1>(), (void **)&dxgiFactory));
            return(dxgiFactory);
        }

        IDXGIAdapter1 *GetDxgiAdapter()
        {
            return(UseWarpDevice ? throw new NotImplementedException("WARP Device not supported for D3D11.") : GetHardwareAdapter(_dxgiFactory));
        }
    }
コード例 #3
0
        ValueList <GraphicsAdapter> GetAdapters(IDXGIFactory3 *dxgiFactory)
        {
            IDXGIAdapter1 *dxgiAdapter1 = null;

            var adapters = new ValueList <GraphicsAdapter>();
            var index    = 0u;

            do
            {
                var result = dxgiFactory->EnumAdapters1(index, &dxgiAdapter1);

                if (result.FAILED)
                {
                    if (result != DXGI_ERROR_NOT_FOUND)
                    {
                        ReleaseIfNotNull(dxgiAdapter1);
                        ExceptionUtilities.ThrowExternalException(nameof(IDXGIFactory1.EnumAdapters1), result);
                    }
                    index = 0;
                }
                else
                {
                    var adapter = new GraphicsAdapter(this, dxgiAdapter1);
                    adapters.Add(adapter);

                    index++;
                    dxgiAdapter1 = null;
                }
            }while (index != 0);

            return(adapters);
        }
コード例 #4
0
        internal D3D12GraphicsAdapter(D3D12GraphicsProvider provider, IDXGIAdapter1 *dxgiAdapter)
            : base(provider)
        {
            ThrowIfNull(dxgiAdapter, nameof(dxgiAdapter));

            _dxgiAdapter = dxgiAdapter;

            _dxgiAdapterDesc = new ValueLazy <DXGI_ADAPTER_DESC1>(GetDxgiAdapterDesc);
            _name            = new ValueLazy <string>(GetName);

            _ = _state.Transition(to: Initialized);
        }
コード例 #5
0
    protected override void DestroyDeviceDependentResources()
    {
        DestroyAssets();

        DestroyImmediateContext();
        DestroyD3DDevice();
        DestroyDxgiAdapter();
        DestroyDxgiFactory();

        void DestroyD3DDevice()
        {
            var d3dDevice = _d3dDevice;

            if (d3dDevice != null)
            {
                _d3dDevice = null;
                _          = d3dDevice->Release();
            }
        }

        void DestroyDxgiAdapter()
        {
            var dxgiAdapter = _dxgiAdapter;

            if (dxgiAdapter != null)
            {
                _dxgiAdapter = null;
                _            = dxgiAdapter->Release();
            }
        }

        void DestroyDxgiFactory()
        {
            var dxgiFactory = _dxgiFactory;

            if (dxgiFactory != null)
            {
                _dxgiFactory = null;
                _            = dxgiFactory->Release();
            }
        }

        void DestroyImmediateContext()
        {
            var immediateContext = _immediateContext;

            if (immediateContext != null)
            {
                _immediateContext = null;
                _ = immediateContext->Release();
            }
        }
    }
コード例 #6
0
ファイル: GraphicsAdapter.cs プロジェクト: john-h-k/terrafx
        /// <summary>Initializes a new instance of the <see cref="GraphicsAdapter" /> class.</summary>
        /// <param name="graphicsProvider">The <see cref="GraphicsProvider" /> for the instance.</param>
        /// <param name="adapter">The <see cref="IDXGIAdapter1" /> for the instance.</param>
        /// <exception cref="ExternalException">The call to <see cref="IDXGIAdapter1.GetDesc1(DXGI_ADAPTER_DESC1*)" /> failed.</exception>
        internal GraphicsAdapter(GraphicsProvider graphicsProvider, IDXGIAdapter1 *adapter)
        {
            _graphicsProvider = graphicsProvider;
            _adapter          = adapter;

            DXGI_ADAPTER_DESC1 desc;

            ThrowExternalExceptionIfFailed(nameof(IDXGIAdapter1.GetDesc1), adapter->GetDesc1(&desc));

            _deviceName = Marshal.PtrToStringUni((IntPtr)desc.Description);
            _vendorId   = desc.VendorId;
            _deviceId   = desc.DeviceId;

            _state.Transition(to: Initialized);
        }
コード例 #7
0
    internal GraphicsAdapter(GraphicsService service, IDXGIAdapter1 *dxgiAdapter) : base(service)
    {
        dxgiAdapter = GetLatestDxgiAdapter(dxgiAdapter, out _dxgiAdapterVersion);
        _dxgiAdapter.Attach(dxgiAdapter);

        DXGI_ADAPTER_DESC1 dxgiAdapterDesc;

        ThrowExternalExceptionIfFailed(dxgiAdapter->GetDesc1(&dxgiAdapterDesc));

        _description = GetUtf16Span(dxgiAdapterDesc.Description, 128).GetString() ?? string.Empty;
        _pciDeviceId = dxgiAdapterDesc.DeviceId;
        _pciVendorId = dxgiAdapterDesc.VendorId;

        SetName(_description);

        _devices      = new ValueList <GraphicsDevice>();
        _devicesMutex = new ValueMutex();
    }
コード例 #8
0
        private ImmutableArray <GraphicsAdapter> GetGraphicsAdapters()
        {
            IDXGIAdapter1 *adapter          = null;
            var            graphicsAdapters = ImmutableArray.CreateBuilder <GraphicsAdapter>();

            try
            {
                var index = 0u;

                while (true)
                {
                    var hr = Factory->EnumAdapters1(index, &adapter);

                    if (FAILED(hr))
                    {
                        if (hr == DXGI_ERROR_NOT_FOUND)
                        {
                            break;
                        }

                        ThrowExternalException(nameof(IDXGIFactory1.EnumAdapters1), hr);
                    }

                    var graphicsAdapter = new GraphicsAdapter(this, adapter);
                    graphicsAdapters.Add(graphicsAdapter);
                    adapter = null;

                    index++;
                }
            }
            finally
            {
                // We explicitly set adapter to null in the enumeration above so that we only
                // release in the case of an exception being thrown.

                if (adapter != null)
                {
                    _ = adapter->Release();
                }
            }

            return(graphicsAdapters.ToImmutable());
        }
コード例 #9
0
 protected abstract bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter);
コード例 #10
0
        protected override unsafe bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter)
        {
            var iid = IID_ID3D12Device;

            return(SUCCEEDED(D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, &iid, null)));
        }
コード例 #11
0
        protected override void DestroyDeviceDependentResources()
        {
            DestroyAssets();

            DestroyGraphicsCommandLists();
            DestroyPipelineState();
            DestroyRootSignature();

            DestroyFenceEvent();
            DestroyFence();

            DestroyCommandAllocators();

            DestroyDescriptorHeaps();

            DestroyCommandQueue();
            DestroyD3DDevice();
            DestroyDxgiAdapter();
            DestroyDxgiFactory();

            void DestroyCommandAllocators()
            {
                for (var i = 0; i < _commandAllocators.Length; i++)
                {
                    var commandAllocator = _commandAllocators[i];

                    if (commandAllocator != null)
                    {
                        _commandAllocators[i] = null;
                        _ = commandAllocator->Release();
                    }
                }
            }

            void DestroyCommandQueue()
            {
                var commandQueue = _commandQueue;

                if (commandQueue != null)
                {
                    _commandQueue = null;
                    _             = commandQueue->Release();
                }
            }

            void DestroyD3DDevice()
            {
                var d3dDevice = _d3dDevice;

                if (d3dDevice != null)
                {
                    _d3dDevice = null;
                    _          = d3dDevice->Release();
                }
            }

            void DestroyDxgiAdapter()
            {
                var dxgiAdapter = _dxgiAdapter;

                if (dxgiAdapter != null)
                {
                    _dxgiAdapter = null;
                    _            = dxgiAdapter->Release();
                }
            }

            void DestroyDxgiFactory()
            {
                var dxgiFactory = _dxgiFactory;

                if (dxgiFactory != null)
                {
                    _dxgiFactory = null;
                    _            = dxgiFactory->Release();
                }
            }

            void DestroyFence()
            {
                var fence = _fence;

                if (fence != null)
                {
                    _fence = null;
                    _      = fence->Release();
                }
            }

            void DestroyFenceEvent()
            {
                var fenceEvent = _fenceEvent;

                if (fenceEvent != IntPtr.Zero)
                {
                    _fenceEvent = IntPtr.Zero;
                    _           = CloseHandle(_fenceEvent);
                }
            }

            void DestroyGraphicsCommandLists()
            {
                for (var i = 0; i < _graphicsCommandLists.Length; i++)
                {
                    var graphicsCommandList = _graphicsCommandLists[i];

                    if (graphicsCommandList != null)
                    {
                        _graphicsCommandLists[i] = null;
                        _ = graphicsCommandList->Release();
                    }
                }
            }

            void DestroyPipelineState()
            {
                var pipelineState = _pipelineState;

                if (pipelineState != null)
                {
                    _pipelineState = null;
                    _ = pipelineState->Release();
                }
            }

            void DestroyRootSignature()
            {
                var rootSignature = _rootSignature;

                if (rootSignature != null)
                {
                    _rootSignature = null;
                    _ = rootSignature->Release();
                }
            }
        }
コード例 #12
0
        protected override void CreateDeviceDependentResources()
        {
            _dxgiFactory  = CreateDxgiFactory();
            _dxgiAdapter  = GetDxgiAdapter();
            _d3dDevice    = CreateD3DDevice();
            _commandQueue = CreateCommandQueue();

            CreateDescriptorHeaps();

            for (int i = 0; i < FrameCount; i++)
            {
                _commandAllocators[i] = CreateCommandAllocator();
            }

            _fence       = CreateFence();
            _fenceValues = CreateFenceValues();
            _fenceEvent  = CreateFenceEvent();

            _rootSignature        = CreateRootSignature();
            _pipelineState        = CreatePipelineState();
            _graphicsCommandLists = CreateGraphicsCommandLists();

            ThrowIfFailed(nameof(ID3D12CommandAllocator.Reset), CommandAllocator->Reset());
            ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Reset), GraphicsCommandList->Reset(CommandAllocator, PipelineState));

            CreateAssets();

            ID3D12CommandAllocator *CreateCommandAllocator()
            {
                ID3D12CommandAllocator *commandAllocator;

                var iid = IID_ID3D12CommandAllocator;

                ThrowIfFailed(nameof(ID3D12Device.CreateCommandAllocator), D3DDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, &iid, (void **)&commandAllocator));

                return(commandAllocator);
            }

            ID3D12CommandQueue *CreateCommandQueue()
            {
                var queueDesc = new D3D12_COMMAND_QUEUE_DESC();

                ID3D12CommandQueue *commandQueue;

                var iid = IID_ID3D12CommandQueue;

                ThrowIfFailed(nameof(ID3D12Device.CreateCommandQueue), D3DDevice->CreateCommandQueue(&queueDesc, &iid, (void **)&commandQueue));

                return(commandQueue);
            }

            ID3D12Device *CreateD3DDevice()
            {
                ID3D12Device *d3dDevice;

                var iid = IID_ID3D12Device;

                ThrowIfFailed(nameof(D3D12CreateDevice), D3D12CreateDevice((IUnknown *)_dxgiAdapter, D3D_FEATURE_LEVEL_11_0, &iid, (void **)&d3dDevice));

                return(d3dDevice);
            }

            IDXGIFactory4 *CreateDxgiFactory()
            {
                var dxgiFactoryFlags = TryEnableDebugLayer() ? DXGI_CREATE_FACTORY_DEBUG : 0u;

                IDXGIFactory4 *dxgiFactory;

                var iid = IID_IDXGIFactory4;

                ThrowIfFailed(nameof(CreateDXGIFactory2), CreateDXGIFactory2(dxgiFactoryFlags, &iid, (void **)&dxgiFactory));

                return(dxgiFactory);
            }

            ID3D12Fence *CreateFence()
            {
                ID3D12Fence *fence;

                var iid = IID_ID3D12Fence;

                ThrowIfFailed(nameof(ID3D12Device.CreateFence), D3DDevice->CreateFence(InitialValue: 0, D3D12_FENCE_FLAG_NONE, &iid, (void **)&fence));

                return(fence);
            }

            IntPtr CreateFenceEvent()
            {
                var fenceEvent = CreateEventW(lpEventAttributes: null, bManualReset: FALSE, bInitialState: FALSE, lpName: null);

                if (fenceEvent == IntPtr.Zero)
                {
                    var hr = Marshal.GetHRForLastWin32Error();
                    Marshal.ThrowExceptionForHR(hr);
                }

                return(fenceEvent);
            }

            ulong[] CreateFenceValues()
            {
                var fenceValues = new ulong[FrameCount];

                fenceValues[0] = 1;
                return(fenceValues);
            }

            ID3D12GraphicsCommandList *[] CreateGraphicsCommandLists()
            {
                var graphicsCommandLists = new ID3D12GraphicsCommandList *[FrameCount];

                for (uint i = 0u; i < FrameCount; i++)
                {
                    ID3D12GraphicsCommandList *graphicsCommandList;

                    var iid = IID_ID3D12GraphicsCommandList;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), D3DDevice->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocators[i], PipelineState, &iid, (void **)&graphicsCommandList));

                    ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), graphicsCommandList->Close());
                    graphicsCommandLists[i] = graphicsCommandList;
                }

                return(graphicsCommandLists);
            }

            IDXGIAdapter1 *GetDxgiAdapter()
            {
                if (UseWarpDevice)
                {
                    IDXGIAdapter1 *adapter;

                    var iid = IID_IDXGIAdapter;
                    ThrowIfFailed(nameof(IDXGIFactory4.EnumWarpAdapter), _dxgiFactory->EnumWarpAdapter(&iid, (void **)&adapter));

                    return(adapter);
                }
                else
                {
                    return(GetHardwareAdapter((IDXGIFactory1 *)_dxgiFactory));
                }
            }

            bool TryEnableDebugLayer()
            {
#if DEBUG
                // Enable the debug layer (requires the Graphics Tools "optional feature").
                // NOTE: Enabling the debug layer after device creation will invalidate the active device.

                using ComPtr <ID3D12Debug> debugController = null;
                var iid = IID_ID3D12Debug;

                if (SUCCEEDED(D3D12GetDebugInterface(&iid, (void **)&debugController)))
                {
                    debugController.Get()->EnableDebugLayer();
                    return(true);
                }
#endif

                return(false);
            }
        }
コード例 #13
0
        protected override unsafe bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter)
        {
            var featureLevel = D3D_FEATURE_LEVEL_11_0;

            return(SUCCEEDED(D3D11CreateDevice((IDXGIAdapter *)adapter, D3D_DRIVER_TYPE_HARDWARE, Software: IntPtr.Zero, Flags: 0, &featureLevel, FeatureLevels: 1, D3D11_SDK_VERSION, ppDevice: null, pFeatureLevel: null, ppImmediateContext: null)));
        }
コード例 #14
0
 protected override unsafe bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter)
 {
     return(D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, __uuidof <ID3D12Device>(), null).SUCCEEDED);
 }
コード例 #15
0
        public static SystemParameters Create()
        {
            var(width, height, _) = GetDisplays().First(d => d.IsPrimary);

            /*using var f = new SharpDX.DXGI.Factory1();
             * var video_memory = f.Adapters1.Select(a =>
             *  Math.Max(a.Description.DedicatedSystemMemory, (long)a.Description.DedicatedVideoMemory)).Max();*/

            var dxgiMemory = 0UL;

            unsafe
            {
                using var api = DXGI.GetApi();

                IDXGIFactory1 *factory1 = default;

                try
                {
                    //https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-createdxgifactory1
                    SilkMarshal.ThrowHResult(api.CreateDXGIFactory1(SilkMarshal.GuidPtrOf <IDXGIFactory1>(), (void **)&factory1));

                    uint i = 0u;
                    while (true)
                    {
                        IDXGIAdapter1 *adapter1 = default;

                        //https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgifactory1-enumadapters1
                        var res = factory1->EnumAdapters1(i, &adapter1);

                        var exception = Marshal.GetExceptionForHR(res);
                        if (exception != null)
                        {
                            break;
                        }

                        AdapterDesc1 adapterDesc = default;

                        //https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiadapter1-getdesc1
                        SilkMarshal.ThrowHResult(adapter1->GetDesc1(&adapterDesc));

                        var systemMemory = (ulong)adapterDesc.DedicatedSystemMemory;
                        var videoMemory  = (ulong)adapterDesc.DedicatedVideoMemory;

                        var maxMemory = Math.Max(systemMemory, videoMemory);
                        if (maxMemory > dxgiMemory)
                        {
                            dxgiMemory = maxMemory;
                        }

                        adapter1->Release();
                        i++;
                    }
                }
                catch (Exception e)
                {
                    Utils.ErrorThrow(e);
                }
                finally
                {
                    if (factory1->LpVtbl != (void **)IntPtr.Zero)
                    {
                        factory1->Release();
                    }
                }
            }

            var memory = Utils.GetMemoryStatus();

            return(new SystemParameters
            {
                ScreenWidth = width,
                ScreenHeight = height,
                VideoMemorySize = (long)dxgiMemory,
                SystemMemorySize = (long)memory.ullTotalPhys,
                SystemPageSize = (long)memory.ullTotalPageFile - (long)memory.ullTotalPhys
            });
        }
コード例 #16
0
        protected override void CreateDeviceDependentResources()
        {
            _dxgiFactory = CreateDxgiFactory();
            _dxgiAdapter = GetDxgiAdapter();
            _d3dDevice   = CreateD3DDevice();
            StartInfoPump();
            _commandQueue = CreateCommandQueue();

            CreateDescriptorHeaps();

            for (int i = 0; i < FrameCount; i++)
            {
                _commandAllocators[i] = CreateCommandAllocator();
            }

            _fence       = CreateFence();
            _fenceValues = CreateFenceValues();
            _fenceEvent  = CreateFenceEvent();

            _rootSignature        = CreateRootSignature();
            _pipelineState        = CreatePipelineState();
            _graphicsCommandLists = CreateGraphicsCommandLists();

            SilkMarshal.ThrowHResult(CommandAllocator->Reset());
            SilkMarshal.ThrowHResult(GraphicsCommandList->Reset(CommandAllocator, PipelineState));

            CreateAssets();

            ID3D12CommandAllocator *CreateCommandAllocator()
            {
                ID3D12CommandAllocator *commandAllocator;

                var iid = ID3D12CommandAllocator.Guid;

                SilkMarshal.ThrowHResult
                (
                    D3DDevice->CreateCommandAllocator
                        (CommandListType.CommandListTypeDirect, &iid, (void **)&commandAllocator)
                );

                return(commandAllocator);
            }

            ID3D12CommandQueue *CreateCommandQueue()
            {
                var queueDesc = new CommandQueueDesc();

                ID3D12CommandQueue *commandQueue;

                var iid = ID3D12CommandQueue.Guid;

                SilkMarshal.ThrowHResult(D3DDevice->CreateCommandQueue(&queueDesc, &iid, (void **)&commandQueue));

                return(commandQueue);
            }

            ID3D12Device *CreateD3DDevice()
            {
                ID3D12Device *d3dDevice;

                var iid = ID3D12Device.Guid;

                SilkMarshal.ThrowHResult
                (
                    D3D12.CreateDevice
                        ((IUnknown *)_dxgiAdapter, D3DFeatureLevel.D3DFeatureLevel110, &iid, (void **)&d3dDevice)
                );

                return(d3dDevice);
            }

            IDXGIFactory4 *CreateDxgiFactory()
            {
                var dxgiFactoryFlags = TryEnableDebugLayer() ? 0x01 : 0u;

                IDXGIFactory4 *dxgiFactory;

                var iid = IDXGIFactory4.Guid;

                SilkMarshal.ThrowHResult(Dxgi.CreateDXGIFactory2(dxgiFactoryFlags, &iid, (void **)&dxgiFactory));

                return(dxgiFactory);
            }

            ID3D12Fence *CreateFence()
            {
                ID3D12Fence *fence;

                var iid = ID3D12Fence.Guid;

                SilkMarshal.ThrowHResult
                    (D3DDevice->CreateFence(InitialValue: 0, FenceFlags.FenceFlagNone, &iid, (void **)&fence));

                return(fence);
            }

            IntPtr CreateFenceEvent()
            {
                var fenceEvent = SilkMarshal.CreateWindowsEvent(null, false, false, null);

                if (fenceEvent == IntPtr.Zero)
                {
                    var hr = Marshal.GetHRForLastWin32Error();
                    Marshal.ThrowExceptionForHR(hr);
                }

                return(fenceEvent);
            }

            ulong[] CreateFenceValues()
            {
                var fenceValues = new ulong[FrameCount];

                fenceValues[0] = 1;
                return(fenceValues);
            }

            ID3D12GraphicsCommandList *[] CreateGraphicsCommandLists()
            {
                var graphicsCommandLists = new ID3D12GraphicsCommandList *[FrameCount];

                for (uint i = 0u; i < FrameCount; i++)
                {
                    ID3D12GraphicsCommandList *graphicsCommandList;

                    var iid = ID3D12GraphicsCommandList.Guid;
                    SilkMarshal.ThrowHResult
                    (
                        D3DDevice->CreateCommandList
                        (
                            nodeMask: 0, CommandListType.CommandListTypeDirect, _commandAllocators[i], PipelineState,
                            &iid, (void **)&graphicsCommandList
                        )
                    );

                    SilkMarshal.ThrowHResult(graphicsCommandList->Close());
                    graphicsCommandLists[i] = graphicsCommandList;
                }

                return(graphicsCommandLists);
            }

            IDXGIAdapter1 *GetDxgiAdapter()
            {
                if (UseWarpDevice)
                {
                    IDXGIAdapter1 *adapter;

                    var iid = IDXGIAdapter.Guid;
                    SilkMarshal.ThrowHResult(_dxgiFactory->EnumWarpAdapter(&iid, (void **)&adapter));

                    return(adapter);
                }
                else
                {
                    return(GetHardwareAdapter((IDXGIFactory1 *)_dxgiFactory));
                }
            }

            bool TryEnableDebugLayer()
            {
#if DEBUG
                // Enable the debug layer (requires the Graphics Tools "optional feature").
                // NOTE: Enabling the debug layer after device creation will invalidate the active device.

                using ComPtr <ID3D12Debug> debugController = null;
                var iid = ID3D12Debug.Guid;
                var hr  = D3D12.GetDebugInterface(&iid, (void **)&debugController);

                if (HResult.IndicatesSuccess(hr))
                {
                    debugController.Get().EnableDebugLayer();
                    Log.LogInformation("Debug layer enabled");
                    return(_debug = true);
                }
                else
                {
                    Log.LogWarning
                    (
                        Marshal.GetExceptionForHR(hr),
                        $"Failed to enable debug layer, failed with result {hr} (0x{hr:x8})"
                    );
                }
#endif

                return(false);
            }

            void StartInfoPump()
            {
#if DEBUG
                if (!_debug)
                {
                    Log.LogInformation("Skipped creation of info pump due to the debug layer not being enabled.");
                    return;
                }

                var iid = ID3D12InfoQueue.Guid;
                fixed(ID3D12InfoQueue ** @out = &_infoQueue)
                {
                    SilkMarshal.ThrowHResult(D3DDevice->QueryInterface(&iid, (void **)@out));
                }

                _infoPumpCancellationToken = new();
                _infoPump = Task.Run
                            (
                    () =>
                {
                    Log.LogInformation("Info queue pump started");
                    while (!_infoPumpCancellationToken.Token.IsCancellationRequested)
                    {
                        var numMessages = _infoQueue->GetNumStoredMessages();
                        if (numMessages == 0)
                        {
                            continue;
                        }

                        for (var i = 0ul; i < numMessages; i++)
                        {
                            nuint msgByteLength;
                            SilkMarshal.ThrowHResult(_infoQueue->GetMessageA(i, null, &msgByteLength));
                            using var memory = GlobalMemory.Allocate((int)msgByteLength);
                            SilkMarshal.ThrowHResult
                            (
                                _infoQueue->GetMessageA(i, memory.AsPtr <Message>(), &msgByteLength)
                            );

                            ref var msg   = ref memory.AsRef <Message>();
                            var descBytes = new Span <byte>(msg.PDescription, (int)msg.DescriptionByteLength);
                            var desc      = Encoding.UTF8.GetString(descBytes[..^ 1]);
                            var eid       = new EventId((int)msg.ID, msg.ID.ToString()["MessageID".Length..]);