mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Software rendering - Fixed memory leak
Rendering - Swap back and forth between software and GPU without crash
This commit is contained in:
parent
97668ee932
commit
c444ff4e59
@ -9,6 +9,7 @@ namespace Artemis.Core
|
|||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private SKRect _lastBounds;
|
private SKRect _lastBounds;
|
||||||
private SKRect _lastParentBounds;
|
private SKRect _lastParentBounds;
|
||||||
|
private GRContext? _lastGraphicsContext;
|
||||||
public SKSurface? Surface { get; private set; }
|
public SKSurface? Surface { get; private set; }
|
||||||
public SKPaint? Paint { get; private set; }
|
public SKPaint? Paint { get; private set; }
|
||||||
public SKPath? Path { get; private set; }
|
public SKPath? Path { get; private set; }
|
||||||
@ -27,7 +28,7 @@ namespace Artemis.Core
|
|||||||
if (IsOpen)
|
if (IsOpen)
|
||||||
throw new ArtemisCoreException("Cannot open render context because it is already open");
|
throw new ArtemisCoreException("Cannot open render context because it is already open");
|
||||||
|
|
||||||
if (path.Bounds != _lastBounds || (parent != null && parent.Bounds != _lastParentBounds))
|
if (path.Bounds != _lastBounds || (parent != null && parent.Bounds != _lastParentBounds) || _lastGraphicsContext != Constants.ManagedGraphicsContext?.GraphicsContext)
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
|
||||||
if (!_valid || Surface == null)
|
if (!_valid || Surface == null)
|
||||||
@ -53,6 +54,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
_lastParentBounds = parent?.Bounds ?? new SKRect();
|
_lastParentBounds = parent?.Bounds ?? new SKRect();
|
||||||
_lastBounds = path.Bounds;
|
_lastBounds = path.Bounds;
|
||||||
|
_lastGraphicsContext = Constants.ManagedGraphicsContext?.GraphicsContext;
|
||||||
_valid = true;
|
_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +72,14 @@ namespace Artemis.Core
|
|||||||
throw new ObjectDisposedException("Renderer");
|
throw new ObjectDisposedException("Renderer");
|
||||||
|
|
||||||
Surface?.Canvas.Restore();
|
Surface?.Canvas.Restore();
|
||||||
|
|
||||||
|
// Looks like every part of the paint needs to be disposed :(
|
||||||
|
Paint?.ColorFilter?.Dispose();
|
||||||
|
Paint?.ImageFilter?.Dispose();
|
||||||
|
Paint?.MaskFilter?.Dispose();
|
||||||
|
Paint?.PathEffect?.Dispose();
|
||||||
Paint?.Dispose();
|
Paint?.Dispose();
|
||||||
|
|
||||||
Paint = null;
|
Paint = null;
|
||||||
|
|
||||||
IsOpen = false;
|
IsOpen = false;
|
||||||
|
|||||||
@ -51,6 +51,8 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value};
|
UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value};
|
||||||
Surface.RegisterUpdateTrigger(UpdateTrigger);
|
Surface.RegisterUpdateTrigger(UpdateTrigger);
|
||||||
|
|
||||||
|
Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimerUpdateTrigger UpdateTrigger { get; }
|
public TimerUpdateTrigger UpdateTrigger { get; }
|
||||||
@ -66,6 +68,11 @@ namespace Artemis.Core.Services
|
|||||||
_texture?.Invalidate();
|
_texture?.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UtilitiesOnShutdownRequested(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
IsRenderPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void SurfaceOnLayoutChanged(SurfaceLayoutChangedEventArgs args)
|
private void SurfaceOnLayoutChanged(SurfaceLayoutChangedEventArgs args)
|
||||||
{
|
{
|
||||||
UpdateLedGroup();
|
UpdateLedGroup();
|
||||||
@ -115,6 +122,11 @@ namespace Artemis.Core.Services
|
|||||||
DeviceAdded?.Invoke(this, e);
|
DeviceAdded?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_texture?.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
public IReadOnlyCollection<ArtemisDevice> EnabledDevices => _enabledDevices.AsReadOnly();
|
public IReadOnlyCollection<ArtemisDevice> EnabledDevices => _enabledDevices.AsReadOnly();
|
||||||
public IReadOnlyCollection<ArtemisDevice> Devices => _devices.AsReadOnly();
|
public IReadOnlyCollection<ArtemisDevice> Devices => _devices.AsReadOnly();
|
||||||
public IReadOnlyDictionary<Led, ArtemisLed> LedMap => new ReadOnlyDictionary<Led, ArtemisLed>(_ledMap);
|
public IReadOnlyDictionary<Led, ArtemisLed> LedMap => new ReadOnlyDictionary<Led, ArtemisLed>(_ledMap);
|
||||||
@ -195,11 +207,6 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
_texture?.Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Surface.UnregisterUpdateTrigger(UpdateTrigger);
|
Surface.UnregisterUpdateTrigger(UpdateTrigger);
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"Artemis.UI": {
|
"Artemis.UI": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "--force-elevation"
|
"commandLineArgs": "--force-elevation --pcmr"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,9 +33,7 @@
|
|||||||
<Run Text="FPS: " />
|
<Run Text="FPS: " />
|
||||||
<Run FontWeight="Bold" Text="{Binding CurrentFps}" />
|
<Run FontWeight="Bold" Text="{Binding CurrentFps}" />
|
||||||
<Run Text="at" />
|
<Run Text="at" />
|
||||||
<Run Text="{Binding RenderWidth}" /><Run Text="x" />
|
<Run Text="{Binding RenderWidth}" /><Run Text="x" /><Run Text="{Binding RenderHeight}" />
|
||||||
<Run Text="{Binding RenderHeight}" />
|
|
||||||
|
|
||||||
<Run Text="- Renderer:"></Run>
|
<Run Text="- Renderer:"></Run>
|
||||||
<Run Text="{Binding Renderer}"></Run>
|
<Run Text="{Binding Renderer}"></Run>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|||||||
@ -21,6 +21,8 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
private int _renderHeight;
|
private int _renderHeight;
|
||||||
private string _frameTargetPath;
|
private string _frameTargetPath;
|
||||||
private string _renderer;
|
private string _renderer;
|
||||||
|
private int _frames;
|
||||||
|
private DateTime _frameCountStart;
|
||||||
|
|
||||||
public RenderDebugViewModel(ICoreService coreService)
|
public RenderDebugViewModel(ICoreService coreService)
|
||||||
{
|
{
|
||||||
@ -76,8 +78,6 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
{
|
{
|
||||||
_coreService.FrameRendered += CoreServiceOnFrameRendered;
|
_coreService.FrameRendered += CoreServiceOnFrameRendered;
|
||||||
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
||||||
|
|
||||||
Renderer = Constants.ManagedGraphicsContext != null ? Constants.ManagedGraphicsContext.GetType().Name : "Software";
|
|
||||||
base.OnActivate();
|
base.OnActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,15 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
|
|
||||||
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||||
{
|
{
|
||||||
CurrentFps = Math.Round(1.0 / e.DeltaTime, 2);
|
if (DateTime.Now - _frameCountStart >= TimeSpan.FromSeconds(1))
|
||||||
|
{
|
||||||
|
CurrentFps = _frames;
|
||||||
|
Renderer = Constants.ManagedGraphicsContext != null ? Constants.ManagedGraphicsContext.GetType().Name : "Software";
|
||||||
|
|
||||||
|
_frames = 0;
|
||||||
|
_frameCountStart = DateTime.Now;
|
||||||
|
}
|
||||||
|
_frames++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,6 +28,7 @@ namespace Artemis.UI.Services
|
|||||||
private bool _registeredBuiltInDataModelDisplays;
|
private bool _registeredBuiltInDataModelDisplays;
|
||||||
private bool _registeredBuiltInDataModelInputs;
|
private bool _registeredBuiltInDataModelInputs;
|
||||||
private bool _registeredBuiltInPropertyEditors;
|
private bool _registeredBuiltInPropertyEditors;
|
||||||
|
private VulkanContext _vulkanContext;
|
||||||
|
|
||||||
public RegistrationService(ILogger logger,
|
public RegistrationService(ILogger logger,
|
||||||
ICoreService coreService,
|
ICoreService coreService,
|
||||||
@ -128,7 +129,8 @@ namespace Artemis.UI.Services
|
|||||||
_rgbService.UpdateGraphicsContext(null);
|
_rgbService.UpdateGraphicsContext(null);
|
||||||
break;
|
break;
|
||||||
case "Vulkan":
|
case "Vulkan":
|
||||||
_rgbService.UpdateGraphicsContext(new VulkanContext());
|
_vulkanContext ??= new VulkanContext();
|
||||||
|
_rgbService.UpdateGraphicsContext(_vulkanContext);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|||||||
@ -8,27 +8,24 @@ namespace Artemis.UI.SkiaSharp.Vulkan
|
|||||||
{
|
{
|
||||||
internal sealed class Win32VkContext : VkContext
|
internal sealed class Win32VkContext : VkContext
|
||||||
{
|
{
|
||||||
private static readonly NativeWindow window = new NativeWindow();
|
public NativeWindow Window { get; }
|
||||||
|
|
||||||
public Win32VkContext()
|
public Win32VkContext()
|
||||||
{
|
{
|
||||||
|
Window = new NativeWindow();
|
||||||
Instance = Instance.Create(null, new[] {"VK_KHR_surface", "VK_KHR_win32_surface"});
|
Instance = Instance.Create(null, new[] {"VK_KHR_surface", "VK_KHR_win32_surface"});
|
||||||
|
|
||||||
PhysicalDevice = Instance.EnumeratePhysicalDevices().First();
|
PhysicalDevice = Instance.EnumeratePhysicalDevices().First();
|
||||||
|
Surface = Instance.CreateWin32Surface(Kernel32.CurrentModuleHandle, Window.Handle);
|
||||||
Surface = Instance.CreateWin32Surface(Kernel32.CurrentModuleHandle, window.Handle);
|
|
||||||
|
|
||||||
(GraphicsFamily, PresentFamily) = FindQueueFamilies();
|
(GraphicsFamily, PresentFamily) = FindQueueFamilies();
|
||||||
|
|
||||||
DeviceQueueCreateInfo[]? queueInfos = new[]
|
DeviceQueueCreateInfo[] queueInfos =
|
||||||
{
|
{
|
||||||
new DeviceQueueCreateInfo { QueueFamilyIndex = GraphicsFamily, QueuePriorities = new[] { 1f } },
|
new() {QueueFamilyIndex = GraphicsFamily, QueuePriorities = new[] {1f}},
|
||||||
new DeviceQueueCreateInfo { QueueFamilyIndex = PresentFamily, QueuePriorities = new[] { 1f } },
|
new() {QueueFamilyIndex = PresentFamily, QueuePriorities = new[] {1f}}
|
||||||
};
|
};
|
||||||
Device = PhysicalDevice.CreateDevice(queueInfos, null, null);
|
Device = PhysicalDevice.CreateDevice(queueInfos, null, null);
|
||||||
|
|
||||||
GraphicsQueue = Device.GetQueue(GraphicsFamily, 0);
|
GraphicsQueue = Device.GetQueue(GraphicsFamily, 0);
|
||||||
|
|
||||||
PresentQueue = Device.GetQueue(PresentFamily, 0);
|
PresentQueue = Device.GetQueue(PresentFamily, 0);
|
||||||
|
|
||||||
GetProc = (name, instanceHandle, deviceHandle) =>
|
GetProc = (name, instanceHandle, deviceHandle) =>
|
||||||
@ -54,9 +51,15 @@ namespace Artemis.UI.SkiaSharp.Vulkan
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
base.Dispose();
|
||||||
|
Window.DestroyHandle();
|
||||||
|
}
|
||||||
|
|
||||||
private (uint, uint) FindQueueFamilies()
|
private (uint, uint) FindQueueFamilies()
|
||||||
{
|
{
|
||||||
QueueFamilyProperties[]? queueFamilyProperties = PhysicalDevice.GetQueueFamilyProperties();
|
QueueFamilyProperties[] queueFamilyProperties = PhysicalDevice.GetQueueFamilyProperties();
|
||||||
|
|
||||||
var graphicsFamily = queueFamilyProperties
|
var graphicsFamily = queueFamilyProperties
|
||||||
.Select((properties, index) => new {properties, index})
|
.Select((properties, index) => new {properties, index})
|
||||||
|
|||||||
@ -50,14 +50,13 @@ namespace Artemis.UI.SkiaSharp
|
|||||||
{
|
{
|
||||||
throw new ArtemisGraphicsContextException("Failed to create Vulkan graphics context", e);
|
throw new ArtemisGraphicsContextException("Failed to create Vulkan graphics context", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsContext.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_vulkanBackendContext?.Dispose();
|
|
||||||
_vulkanContext?.Dispose();
|
|
||||||
GraphicsContext?.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GRContext GraphicsContext { get; }
|
public GRContext GraphicsContext { get; }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user