Kill command - stop emulation
This commit is contained in:
parent
38c15faacf
commit
055ac70eaa
6 changed files with 29 additions and 24 deletions
|
@ -1076,9 +1076,11 @@ namespace Ryujinx.UI
|
|||
RendererWidget.WaitEvent.WaitOne();
|
||||
|
||||
RendererWidget.Start();
|
||||
_pauseEmulation.Sensitive = false;
|
||||
_resumeEmulation.Sensitive = false;
|
||||
UpdateMenuItem.Sensitive = true;
|
||||
|
||||
_emulationContext.Dispose();
|
||||
_deviceExitStatus.Set();
|
||||
|
||||
// NOTE: Everything that is here will not be executed when you close the UI.
|
||||
Application.Invoke(delegate
|
||||
|
@ -1173,7 +1175,7 @@ namespace Ryujinx.UI
|
|||
RendererWidget.Exit();
|
||||
|
||||
// Wait for the other thread to dispose the HLE context before exiting.
|
||||
_deviceExitStatus.WaitOne();
|
||||
_emulationContext.ExitStatus.WaitOne();
|
||||
RendererWidget.Dispose();
|
||||
}
|
||||
}
|
||||
|
@ -1511,9 +1513,6 @@ namespace Ryujinx.UI
|
|||
UpdateGameMetadata(_emulationContext.Processes.ActiveApplication.ProgramIdText);
|
||||
}
|
||||
|
||||
_pauseEmulation.Sensitive = false;
|
||||
_resumeEmulation.Sensitive = false;
|
||||
UpdateMenuItem.Sensitive = true;
|
||||
RendererWidget?.Exit();
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ namespace Ryujinx.UI
|
|||
|
||||
public static event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
|
||||
|
||||
private bool _isActive;
|
||||
private bool _isStopped;
|
||||
|
||||
private bool _toggleFullscreen;
|
||||
|
@ -459,7 +458,7 @@ namespace Ryujinx.UI
|
|||
|
||||
(Toplevel as MainWindow)?.ActivatePauseMenu();
|
||||
|
||||
while (_isActive)
|
||||
while (Device.IsActive)
|
||||
{
|
||||
if (_isStopped)
|
||||
{
|
||||
|
@ -519,7 +518,7 @@ namespace Ryujinx.UI
|
|||
{
|
||||
_chrono.Restart();
|
||||
|
||||
_isActive = true;
|
||||
Device.IsActive = true;
|
||||
|
||||
Gtk.Window parent = Toplevel as Gtk.Window;
|
||||
|
||||
|
@ -573,9 +572,9 @@ namespace Ryujinx.UI
|
|||
|
||||
_isStopped = true;
|
||||
|
||||
if (_isActive)
|
||||
if (Device.IsActive)
|
||||
{
|
||||
_isActive = false;
|
||||
Device.IsActive = false;
|
||||
|
||||
_exitEvent.WaitOne();
|
||||
_exitEvent.Dispose();
|
||||
|
@ -584,7 +583,7 @@ namespace Ryujinx.UI
|
|||
|
||||
private void NvidiaStutterWorkaround()
|
||||
{
|
||||
while (_isActive)
|
||||
while (Device.IsActive)
|
||||
{
|
||||
// When NVIDIA Threaded Optimization is on, the driver will snapshot all threads in the system whenever the application creates any new ones.
|
||||
// The ThreadPool has something called a "GateThread" which terminates itself after some inactivity.
|
||||
|
@ -603,7 +602,7 @@ namespace Ryujinx.UI
|
|||
|
||||
public void MainLoop()
|
||||
{
|
||||
while (_isActive)
|
||||
while (Device.IsActive)
|
||||
{
|
||||
UpdateFrame();
|
||||
|
||||
|
@ -616,7 +615,7 @@ namespace Ryujinx.UI
|
|||
|
||||
private bool UpdateFrame()
|
||||
{
|
||||
if (!_isActive)
|
||||
if (!Device.IsActive)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -218,6 +218,8 @@ namespace Ryujinx.HLE.Debugger
|
|||
}
|
||||
case 'k':
|
||||
Logger.Notice.Print(LogClass.GdbStub, "Kill request received");
|
||||
Device.IsActive = false;
|
||||
Device.ExitStatus.WaitOne();
|
||||
Reply("");
|
||||
break;
|
||||
case 'm':
|
||||
|
|
|
@ -311,7 +311,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
if (Owner != null && Owner.PinnedThreads[KernelStatic.GetCurrentThread().CurrentCore] == this)
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
if (Owner != null && currentThread != null && Owner.PinnedThreads[currentThread.CurrentCore] == this)
|
||||
{
|
||||
Owner.UnpinThread(this);
|
||||
}
|
||||
|
@ -366,7 +368,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
ThreadSchedState state = PrepareForTermination();
|
||||
|
||||
if (state != ThreadSchedState.TerminationPending)
|
||||
if (KernelStatic.GetCurrentThread() == this && state != ThreadSchedState.TerminationPending)
|
||||
{
|
||||
KernelContext.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ using Ryujinx.HLE.Loaders.Processes;
|
|||
using Ryujinx.HLE.UI;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.HLE
|
||||
{
|
||||
|
@ -27,11 +28,14 @@ namespace Ryujinx.HLE
|
|||
public TamperMachine TamperMachine { get; }
|
||||
public IHostUIHandler UIHandler { get; }
|
||||
public Debugger.Debugger Debugger { get; }
|
||||
public ManualResetEvent ExitStatus { get; }
|
||||
|
||||
public bool EnableDeviceVsync { get; set; } = true;
|
||||
|
||||
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
public Switch(HLEConfiguration configuration)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
||||
|
@ -56,6 +60,7 @@ namespace Ryujinx.HLE
|
|||
Hid = new Hid(this, System.HidStorage);
|
||||
Processes = new ProcessLoader(this);
|
||||
TamperMachine = new TamperMachine();
|
||||
ExitStatus = new ManualResetEvent(false);
|
||||
|
||||
System.InitializeServices();
|
||||
System.State.SetLanguage(Configuration.SystemLanguage);
|
||||
|
@ -157,6 +162,7 @@ namespace Ryujinx.HLE
|
|||
FileSystem.Dispose();
|
||||
Memory.Dispose();
|
||||
Debugger.Dispose();
|
||||
ExitStatus.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,6 @@ namespace Ryujinx.Ava
|
|||
CursorStates.CursorIsVisible : CursorStates.CursorIsHidden;
|
||||
|
||||
private bool _isStopped;
|
||||
private bool _isActive;
|
||||
private bool _renderingStarted;
|
||||
|
||||
private readonly ManualResetEvent _gpuDoneEvent;
|
||||
|
@ -427,8 +426,6 @@ namespace Ryujinx.Ava
|
|||
|
||||
RendererHost.BoundsChanged += Window_BoundsChanged;
|
||||
|
||||
_isActive = true;
|
||||
|
||||
_renderingThread.Start();
|
||||
|
||||
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
||||
|
@ -497,7 +494,7 @@ namespace Ryujinx.Ava
|
|||
|
||||
public void Stop()
|
||||
{
|
||||
_isActive = false;
|
||||
Device.IsActive = false;
|
||||
}
|
||||
|
||||
private void Exit()
|
||||
|
@ -510,14 +507,14 @@ namespace Ryujinx.Ava
|
|||
}
|
||||
|
||||
_isStopped = true;
|
||||
_isActive = false;
|
||||
Device.IsActive = false;
|
||||
}
|
||||
|
||||
public void DisposeContext()
|
||||
{
|
||||
Dispose();
|
||||
|
||||
_isActive = false;
|
||||
Device.IsActive = false;
|
||||
|
||||
// NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
|
||||
// We only need to wait for all commands submitted during the main gpu loop to be processed.
|
||||
|
@ -950,7 +947,7 @@ namespace Ryujinx.Ava
|
|||
|
||||
private void MainLoop()
|
||||
{
|
||||
while (_isActive)
|
||||
while (Device.IsActive)
|
||||
{
|
||||
UpdateFrame();
|
||||
|
||||
|
@ -1001,7 +998,7 @@ namespace Ryujinx.Ava
|
|||
|
||||
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
|
||||
|
||||
while (_isActive)
|
||||
while (Device.IsActive)
|
||||
{
|
||||
_ticks += _chrono.ElapsedTicks;
|
||||
|
||||
|
@ -1100,7 +1097,7 @@ namespace Ryujinx.Ava
|
|||
|
||||
private bool UpdateFrame()
|
||||
{
|
||||
if (!_isActive)
|
||||
if (!Device.IsActive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue