/// <summary>
        /// Function to add the WARP software device.
        /// </summary>
        /// <param name="index">Index of the device.</param>
        /// <param name="factory">The factory used to query the adapter.</param>
        /// <param name="log">The log interface used to send messages to a debug log.</param>
        /// <returns>The video adapter used for WARP software rendering.</returns>
        private static VideoAdapterInfo GetWARPSoftwareDevice(int index, Factory5 factory, IGorgonLog log)
        {
            D3D11.DeviceCreationFlags flags = D3D11.DeviceCreationFlags.None;

            if (GorgonGraphics.IsDebugEnabled)
            {
                flags = D3D11.DeviceCreationFlags.Debug;
            }

            using (Adapter warp = factory.GetWarpAdapter())
                using (Adapter4 warpAdapter4 = warp.QueryInterface <Adapter4>())
                    using (var D3DDevice = new D3D11.Device(warpAdapter4, flags))
                        using (D3D11.Device5 D3DDevice5 = D3DDevice.QueryInterface <D3D11.Device5>())
                        {
                            FeatureSet?featureSet = GetFeatureLevel(D3DDevice5);

                            if (featureSet == null)
                            {
                                log.Print("WARNING: The WARP software adapter does not support the minimum feature set of 12.0. This device will be excluded.", LoggingLevel.All);
                                return(null);
                            }

                            var result = new VideoAdapterInfo(index, warpAdapter4, featureSet.Value, new Dictionary <string, VideoOutputInfo>(), VideoDeviceType.Software);

                            PrintLog(result, log);

                            return(result);
                        }
        }
        /// <summary>
        /// Function to print device log information.
        /// </summary>
        /// <param name="device">Device to print.</param>
        /// <param name="log">The log interface to output debug messages.</param>
        private static void PrintLog(VideoAdapterInfo device, IGorgonLog log)
        {
            log.Print($"Device found: {device.Name}", LoggingLevel.Simple);
            log.Print("===================================================================", LoggingLevel.Simple);
            log.Print($"Supported feature set: {device.FeatureSet}", LoggingLevel.Simple);
            log.Print($"Video memory: {(device.Memory.Video).FormatMemory()}", LoggingLevel.Simple);
            log.Print($"System memory: {(device.Memory.System).FormatMemory()}", LoggingLevel.Intermediate);
            log.Print($"Shared memory: {(device.Memory.Shared).FormatMemory()}", LoggingLevel.Intermediate);
            log.Print($"Device ID: 0x{device.PciInfo.DeviceID.FormatHex()}", LoggingLevel.Verbose);
            log.Print($"Sub-system ID: 0x{device.PciInfo.SubSystemID.FormatHex()}", LoggingLevel.Verbose);
            log.Print($"Vendor ID: 0x{device.PciInfo.VendorID.FormatHex()}", LoggingLevel.Verbose);
            log.Print($"Revision: {device.PciInfo.Revision}", LoggingLevel.Verbose);
            log.Print($"Unique ID: 0x{device.Luid.FormatHex()}", LoggingLevel.Verbose);
            log.Print("===================================================================", LoggingLevel.Simple);

            foreach (IGorgonVideoOutputInfo output in device.Outputs)
            {
                log.Print($"Found output '{output.Name}'.", LoggingLevel.Simple);
                log.Print("===================================================================", LoggingLevel.Verbose);
                log.Print($"Output bounds: ({output.DesktopBounds.Left}x{output.DesktopBounds.Top})-({output.DesktopBounds.Right}x{output.DesktopBounds.Bottom})",
                          LoggingLevel.Verbose);
                log.Print($"Monitor handle: 0x{output.MonitorHandle.FormatHex()}", LoggingLevel.Verbose);
                log.Print($"Attached to desktop: {output.IsAttachedToDesktop}", LoggingLevel.Verbose);
                log.Print($"Monitor rotation: {output.Rotation}", LoggingLevel.Verbose);
                log.Print("===================================================================", LoggingLevel.Simple);

                log.Print($"Retrieving video modes for output '{output.Name}'...", LoggingLevel.Simple);
                log.Print("===================================================================", LoggingLevel.Simple);

                foreach (GorgonVideoMode mode in output.VideoModes)
                {
                    log.Print($"{mode.ToString().PadRight(70)}\tScaling: {mode.Scaling.ToString().PadRight(20)}Scanline Order: {mode.ScanlineOrder.ToString().PadRight(25)}Stereo: {mode.SupportsStereo}",
                              LoggingLevel.Verbose);
                }

                log.Print("===================================================================", LoggingLevel.Verbose);
                log.Print($"Found {output.VideoModes.Count} video modes for output '{output.Name}'.", LoggingLevel.Simple);
                log.Print("===================================================================", LoggingLevel.Simple);
            }
        }
        /// <summary>
        /// Function to perform an enumeration of the video adapters attached to the system and populate this list.
        /// </summary>
        /// <param name="enumerateWARPDevice"><b>true</b> to enumerate the WARP software device, or <b>false</b> to exclude it.</param>
        /// <param name="log">The log that will capture debug logging messages.</param>
        /// <remarks>
        /// <para>
        /// Use this method to populate a list with information about the video adapters installed in the system.
        /// </para>
        /// <para>
        /// You may include the WARP device, which is a software based device that emulates most of the functionality of a video adapter, by setting the <paramref name="enumerateWARPDevice"/> to <b>true</b>.
        /// </para>
        /// <para>
        /// Gorgon requires a video adapter that is capable of supporting Direct 3D 12.0 at minimum. If no suitable devices are found installed in the computer, then the resulting list will be empty.
        /// </para>
        /// </remarks>
        public static IReadOnlyList <IGorgonVideoAdapterInfo> Enumerate(bool enumerateWARPDevice, IGorgonLog log)
        {
            var devices = new List <IGorgonVideoAdapterInfo>();

            if (log == null)
            {
                log = GorgonLog.NullLog;
            }

            using (var factory2 = new Factory2(GorgonGraphics.IsDebugEnabled))
                using (Factory5 factory5 = factory2.QueryInterface <Factory5>())
                {
                    int adapterCount = factory5.GetAdapterCount1();

                    log.Print("Enumerating video adapters...", LoggingLevel.Simple);

                    // Begin gathering device information.
                    for (int i = 0; i < adapterCount; i++)
                    {
                        // Get the video adapter information.
                        using (Adapter1 adapter1 = factory5.GetAdapter1(i))
                            using (Adapter4 adapter = adapter1.QueryInterface <Adapter4>())
                            {
                                // ReSharper disable BitwiseOperatorOnEnumWithoutFlags
                                if (((adapter.Desc3.Flags & AdapterFlags3.Remote) == AdapterFlags3.Remote) ||
                                    ((adapter.Desc3.Flags & AdapterFlags3.Software) == AdapterFlags3.Software))
                                {
                                    continue;
                                }
                                // ReSharper restore BitwiseOperatorOnEnumWithoutFlags

                                D3D11.DeviceCreationFlags flags = D3D11.DeviceCreationFlags.None;

                                if (GorgonGraphics.IsDebugEnabled)
                                {
                                    flags = D3D11.DeviceCreationFlags.Debug;
                                }

                                // We create a D3D device here to filter out unsupported video modes from the format list.
                                using (var D3DDevice = new D3D11.Device(adapter, flags, D3D.FeatureLevel.Level_12_1, D3D.FeatureLevel.Level_12_0))
                                    using (D3D11.Device5 D3DDevice5 = D3DDevice.QueryInterface <D3D11.Device5>())
                                    {
                                        D3DDevice5.DebugName = "Output enumerator device.";

                                        FeatureSet?featureSet = GetFeatureLevel(D3DDevice5);

                                        // Do not enumerate this device if its feature set is not supported.
                                        if (featureSet == null)
                                        {
                                            log.Print("This video adapter is not supported by Gorgon and will be skipped.", LoggingLevel.Verbose);
                                            continue;
                                        }

                                        Dictionary <string, VideoOutputInfo> outputs = GetOutputs(D3DDevice5, adapter, adapter.GetOutputCount(), log);

                                        if (outputs.Count <= 0)
                                        {
                                            log.Print($"WARNING: Video adapter {adapter.Description1.Description.Replace("\0", string.Empty)} has no outputs. Full screen mode will not be possible.",
                                                      LoggingLevel.Verbose);
                                        }

                                        var videoAdapter = new VideoAdapterInfo(i, adapter, featureSet.Value, outputs, VideoDeviceType.Hardware);

                                        devices.Add(videoAdapter);
                                        PrintLog(videoAdapter, log);
                                    }
                            }
                    }

                    // Get software devices.
                    if (!enumerateWARPDevice)
                    {
                        return(devices);
                    }

                    VideoAdapterInfo device = GetWARPSoftwareDevice(devices.Count, factory5, log);

                    if (device != null)
                    {
                        devices.Add(device);
                    }
                }

            log.Print("Found {0} video adapters.", LoggingLevel.Simple, devices.Count);

            return(devices);
        }