Browse Source

Added Win32PlatformOptions.GraphicsAdapterSelectionCallback (#17079)

pull/17107/head
Nikita Tsukanov 2 years ago
committed by GitHub
parent
commit
49ab0b36e5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      src/Avalonia.Base/Platform/PlatformGraphicsDeviceAdapterDescription.cs
  2. 40
      src/Windows/Avalonia.Win32/OpenGl/Angle/AngleWin32EglDisplay.cs
  3. 10
      src/Windows/Avalonia.Win32/Win32PlatformOptions.cs

8
src/Avalonia.Base/Platform/PlatformGraphicsDeviceAdapterDescription.cs

@ -0,0 +1,8 @@
namespace Avalonia.Platform;
public class PlatformGraphicsDeviceAdapterDescription
{
public string? Description { get; set; }
public byte[]? DeviceLuid { get; set; }
public byte[]? DeviceUuid { get; set; }
}

40
src/Windows/Avalonia.Win32/OpenGl/Angle/AngleWin32EglDisplay.cs

@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Win32.DirectX;
using MicroCom.Runtime;
using static Avalonia.OpenGL.Egl.EglConsts;
@ -63,31 +64,50 @@ namespace Avalonia.Win32.OpenGl.Angle
{
using var factory = MicroComRuntime.CreateProxyFor<IDXGIFactory1>(pDxgiFactory, true);
var selectionCallback = AvaloniaLocator.Current.GetService<Win32PlatformOptions>()
?.GraphicsAdapterSelectionCallback;
void* pAdapter = null;
var applyArmAdrenoBlacklist = RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
// As for now, we only need to redefine default adapter only on ARM64 just in case of Adreno GPU.
var redefineDefaultAdapter = RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
var redefineDefaultAdapter =
selectionCallback != null
|| applyArmAdrenoBlacklist;
if (redefineDefaultAdapter)
{
ushort adapterIndex = 0;
var adapters = new List<(IDXGIAdapter1 adapter, string name)>();
var adapters = new List<(IDXGIAdapter1 adapter, PlatformGraphicsDeviceAdapterDescription desc)>();
while (factory.EnumAdapters1(adapterIndex, &pAdapter) == 0)
{
var adapter = MicroComRuntime.CreateProxyFor<IDXGIAdapter1>(pAdapter, true);
var desc = adapter.Desc1;
var name = Marshal.PtrToStringUni(new IntPtr(desc.Description))!.ToLowerInvariant();
adapters.Add((adapter, name));
var name = Marshal.PtrToStringUni(new IntPtr(desc.Description))?.ToLowerInvariant();
var luid = BitConverter.GetBytes(desc.AdapterLuid);
adapters.Add((adapter, new() { Description = name, DeviceLuid = luid }));
adapterIndex++;
}
if (adapters.Count == 0)
throw new OpenGlException("No adapters found");
chosenAdapter = adapters
.OrderByDescending(x =>
// Put adreno in lower priority - it's broken in Avalonia.
x.name.Contains("adreno") ? -1 : 0)
.First().adapter
.CloneReference();
if (applyArmAdrenoBlacklist && adapters.Count > 1)
{
for (var c = adapters.Count - 1; c >= 0; c--)
if (adapters[c].desc.Description?.Contains("adreno") == true)
{
adapters[c].adapter.Dispose();
adapters.RemoveAt(c);
}
}
var chosenAdapterIndex = 0;
if (selectionCallback != null)
chosenAdapterIndex = selectionCallback(adapters.Select(a => a.desc).ToArray());
chosenAdapter = adapters[chosenAdapterIndex].adapter.CloneReference();
foreach (var a in adapters)
a.adapter.Dispose();

10
src/Windows/Avalonia.Win32/Win32PlatformOptions.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Avalonia.OpenGL;
using Avalonia.Platform;
@ -168,4 +169,11 @@ public class Win32PlatformOptions
/// Gets or sets the application's DPI awareness.
/// </summary>
public Win32DpiAwareness DpiAwareness { get; set; } = Win32DpiAwareness.PerMonitorDpiAware;
/// <summary>
/// Specifies a callback method to be called when compositor needs to create a platform graphics device
/// Currently is only called for AngleEgl rendering mode when DirectX 11 is used
/// </summary>
public Func<IReadOnlyList<PlatformGraphicsDeviceAdapterDescription>, int>?
GraphicsAdapterSelectionCallback { get; set; }
}

Loading…
Cancel
Save