aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Ava/AppHost.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Ava/AppHost.cs')
-rw-r--r--Ryujinx.Ava/AppHost.cs92
1 files changed, 36 insertions, 56 deletions
diff --git a/Ryujinx.Ava/AppHost.cs b/Ryujinx.Ava/AppHost.cs
index 7e3cddc8..7cf5934a 100644
--- a/Ryujinx.Ava/AppHost.cs
+++ b/Ryujinx.Ava/AppHost.cs
@@ -1,6 +1,5 @@
using ARMeilleure.Translation;
using ARMeilleure.Translation.PTC;
-using Avalonia;
using Avalonia.Input;
using Avalonia.Threading;
using LibHac.Tools.FsSystem;
@@ -12,10 +11,8 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input;
-using Ryujinx.Ava.Ui.Backend.Vulkan;
using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models;
-using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Ava.Ui.Windows;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
@@ -39,6 +36,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
+using SPB.Graphics.Vulkan;
using System;
using System.Diagnostics;
using System.IO;
@@ -58,24 +56,24 @@ namespace Ryujinx.Ava
{
private const int CursorHideIdleTime = 8; // Hide Cursor seconds
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
+ private const int TargetFps = 60;
- private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
+ private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
+ private readonly long _ticksPerFrame;
+ private readonly Stopwatch _chrono;
private readonly AccountManager _accountManager;
private readonly UserChannelPersistence _userChannelPersistence;
-
private readonly InputManager _inputManager;
-
- private readonly IKeyboard _keyboardInterface;
-
private readonly MainWindow _parent;
-
+ private readonly IKeyboard _keyboardInterface;
private readonly GraphicsDebugLevel _glLogLevel;
private bool _hideCursorOnIdle;
private bool _isStopped;
private bool _isActive;
private long _lastCursorMoveTime;
+ private long _ticks = 0;
private KeyboardHotkeyState _prevHotkeyState;
@@ -93,7 +91,7 @@ namespace Ryujinx.Ava
public event EventHandler AppExit;
public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
- public RendererControl Renderer { get; }
+ public RendererHost Renderer { get; }
public VirtualFileSystem VirtualFileSystem { get; }
public ContentManager ContentManager { get; }
public Switch Device { get; set; }
@@ -111,7 +109,7 @@ namespace Ryujinx.Ava
private object _lockObject = new();
public AppHost(
- RendererControl renderer,
+ RendererHost renderer,
InputManager inputManager,
string applicationPath,
VirtualFileSystem virtualFileSystem,
@@ -128,7 +126,7 @@ namespace Ryujinx.Ava
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
_lastCursorMoveTime = Stopwatch.GetTimestamp();
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
- _inputManager.SetMouseDriver(new AvaloniaMouseDriver(renderer));
+ _inputManager.SetMouseDriver(new AvaloniaMouseDriver(_parent, renderer));
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
NpadManager = _inputManager.CreateNpadManager();
@@ -138,6 +136,9 @@ namespace Ryujinx.Ava
VirtualFileSystem = virtualFileSystem;
ContentManager = contentManager;
+ _chrono = new Stopwatch();
+ _ticksPerFrame = Stopwatch.Frequency / TargetFps;
+
if (ApplicationPath.StartsWith("@SystemContent"))
{
ApplicationPath = _parent.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
@@ -177,7 +178,7 @@ namespace Ryujinx.Ava
if (_renderer != null)
{
double scale = _parent.PlatformImpl.RenderScaling;
- _renderer.Window.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
+ _renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
}
}
@@ -335,8 +336,6 @@ namespace Ryujinx.Ava
return;
}
- AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface.Display.ChangeVSyncMode(true);
-
_isStopped = true;
_isActive = false;
}
@@ -376,6 +375,8 @@ namespace Ryujinx.Ava
_gpuCancellationTokenSource.Cancel();
_gpuCancellationTokenSource.Dispose();
+
+ _chrono.Stop();
}
public void DisposeGpu()
@@ -389,8 +390,7 @@ namespace Ryujinx.Ava
Renderer?.MakeCurrent();
Device.DisposeGpu();
-
- Renderer?.DestroyBackgroundContext();
+
Renderer?.MakeCurrent(null);
}
@@ -596,16 +596,11 @@ namespace Ryujinx.Ava
IRenderer renderer;
- if (Program.UseVulkan)
+ if (Renderer.IsVulkan)
{
- var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
+ string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
- renderer = new VulkanRenderer(vulkan.Instance.InternalHandle,
- vulkan.MainSurface.Device.InternalHandle,
- vulkan.PhysicalDevice.InternalHandle,
- vulkan.MainSurface.Device.Queue.InternalHandle,
- vulkan.PhysicalDevice.QueueFamilyIndex,
- vulkan.MainSurface.Device.Lock);
+ renderer = new VulkanRenderer(Renderer.CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
}
else
{
@@ -778,11 +773,7 @@ namespace Ryujinx.Ava
{
Width = (int)e.Width;
Height = (int)e.Height;
-
- if (!Program.UseVulkan)
- {
- SetRendererWindowSize(e);
- }
+ SetRendererWindowSize(e);
}
private void MainLoop()
@@ -822,12 +813,10 @@ namespace Ryujinx.Ava
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
- (_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
+ (_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext(Renderer.GetContext()));
Renderer.MakeCurrent();
- AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
-
Device.Gpu.Renderer.Initialize(_glLogLevel);
Width = (int)Renderer.Bounds.Width;
@@ -835,16 +824,20 @@ namespace Ryujinx.Ava
_renderer.Window.SetSize((int)(Width * _parent.PlatformImpl.RenderScaling), (int)(Height * _parent.PlatformImpl.RenderScaling));
+ _chrono.Start();
+
Device.Gpu.Renderer.RunLoop(() =>
{
Device.Gpu.SetGpuThread();
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
Translator.IsReadyForTranslation.Set();
- Renderer.Start();
-
while (_isActive)
{
+ _ticks += _chrono.ElapsedTicks;
+
+ _chrono.Restart();
+
if (Device.WaitFifo())
{
Device.Statistics.RecordFifoStart();
@@ -860,19 +853,20 @@ namespace Ryujinx.Ava
_parent.SwitchToGameControl();
}
- Device.PresentFrame(Present);
+ Device.PresentFrame(() => Renderer?.SwapBuffers());
}
- }
- Renderer.Stop();
+ if (_ticks >= _ticksPerFrame)
+ {
+ UpdateStatus();
+ }
+ }
});
Renderer?.MakeCurrent(null);
-
- Renderer.SizeChanged -= Window_SizeChanged;
}
- private void Present(object image)
+ public void UpdateStatus()
{
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance["Docked"] : LocaleManager.Instance["Handheld"];
@@ -886,24 +880,12 @@ namespace Ryujinx.Ava
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.EnableDeviceVsync,
Device.GetVolume(),
- Program.UseVulkan ? "Vulkan" : "OpenGL",
+ Renderer.IsVulkan ? "Vulkan" : "OpenGL",
dockedMode,
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
LocaleManager.Instance["Game"] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
-
- if (Program.UseVulkan)
- {
- var platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
- if (platformInterface.MainSurface.Display.IsSurfaceChanged())
- {
- SetRendererWindowSize(new Size(Width, Height));
- return;
- }
- }
-
- Renderer.Present(image);
}
public async Task ShowExitPrompt()
@@ -985,8 +967,6 @@ namespace Ryujinx.Ava
case KeyboardHotkeyState.ToggleVSync:
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
- AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
-
break;
case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true;