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