Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4c3f09644a | ||
|
e187a8870a | ||
|
a64fee29dc |
@@ -321,17 +321,15 @@ namespace Ryujinx.Ava
|
||||
_viewModel.IsGameRunning = true;
|
||||
|
||||
var activeProcess = Device.Processes.ActiveApplication;
|
||||
var nacp = activeProcess.ApplicationControlProperties;
|
||||
int desiredLanguage = (int)Device.System.State.DesiredTitleLanguage;
|
||||
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(nacp.Title[desiredLanguage].NameString.ToString()) ? string.Empty : $" - {nacp.Title[desiredLanguage].NameString.ToString()}";
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(nacp.DisplayVersionString.ToString()) ? string.Empty : $" v{nacp.DisplayVersionString.ToString()}";
|
||||
string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})";
|
||||
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}";
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}";
|
||||
string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})";
|
||||
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
|
||||
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
_viewModel.Title = $"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
|
||||
_viewModel.Title = $"Ryujinx {Program.Version} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
|
||||
});
|
||||
|
||||
_viewModel.SetUIProgressHandlers(Device);
|
||||
|
@@ -23,10 +23,11 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
|
||||
private ContentDialog _host;
|
||||
|
||||
public SwkbdAppletDialog(string mainText, string secondaryText, string placeholder)
|
||||
public SwkbdAppletDialog(string mainText, string secondaryText, string placeholder, string message)
|
||||
{
|
||||
MainText = mainText;
|
||||
SecondaryText = secondaryText;
|
||||
Message = message ?? "";
|
||||
DataContext = this;
|
||||
_placeholder = placeholder;
|
||||
InitializeComponent();
|
||||
@@ -54,10 +55,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
|
||||
UserResult result = UserResult.Cancel;
|
||||
|
||||
SwkbdAppletDialog content = new SwkbdAppletDialog(args.HeaderText, args.SubtitleText, args.GuideText)
|
||||
{
|
||||
Message = args.InitialText ?? ""
|
||||
};
|
||||
SwkbdAppletDialog content = new SwkbdAppletDialog(args.HeaderText, args.SubtitleText, args.GuideText, args.InitialText);
|
||||
|
||||
string input = string.Empty;
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
@@ -7,12 +8,26 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
internal class AutoFlushCounter
|
||||
{
|
||||
// How often to flush on framebuffer change.
|
||||
private readonly static long FramebufferFlushTimer = Stopwatch.Frequency / 1000;
|
||||
private readonly static long FramebufferFlushTimer = Stopwatch.Frequency / 1000; // (1ms)
|
||||
|
||||
// How often to flush on draw when fast flush mode is enabled.
|
||||
private readonly static long DrawFlushTimer = Stopwatch.Frequency / 666; // (1.5ms)
|
||||
|
||||
// Average wait time that triggers fast flush mode to be entered.
|
||||
private readonly static long FastFlushEnterThreshold = Stopwatch.Frequency / 666; // (1.5ms)
|
||||
|
||||
// Average wait time that triggers fast flush mode to be exited.
|
||||
private readonly static long FastFlushExitThreshold = Stopwatch.Frequency / 10000; // (0.1ms)
|
||||
|
||||
// Number of frames to average waiting times over.
|
||||
private const int SyncWaitAverageCount = 20;
|
||||
|
||||
private const int MinDrawCountForFlush = 10;
|
||||
private const int MinConsecutiveQueryForFlush = 10;
|
||||
private const int InitialQueryCountForFlush = 32;
|
||||
|
||||
private readonly VulkanRenderer _gd;
|
||||
|
||||
private long _lastFlush;
|
||||
private ulong _lastDrawCount;
|
||||
private bool _hasPendingQuery;
|
||||
@@ -23,6 +38,16 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private int _queryCountHistoryIndex;
|
||||
private int _remainingQueries;
|
||||
|
||||
private long[] _syncWaitHistory = new long[SyncWaitAverageCount];
|
||||
private int _syncWaitHistoryIndex;
|
||||
|
||||
private bool _fastFlushMode;
|
||||
|
||||
public AutoFlushCounter(VulkanRenderer gd)
|
||||
{
|
||||
_gd = gd;
|
||||
}
|
||||
|
||||
public void RegisterFlush(ulong drawCount)
|
||||
{
|
||||
_lastFlush = Stopwatch.GetTimestamp();
|
||||
@@ -69,6 +94,32 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return _hasPendingQuery;
|
||||
}
|
||||
|
||||
public bool ShouldFlushDraw(ulong drawCount)
|
||||
{
|
||||
if (_fastFlushMode)
|
||||
{
|
||||
long draws = (long)(drawCount - _lastDrawCount);
|
||||
|
||||
if (draws < MinDrawCountForFlush)
|
||||
{
|
||||
if (draws == 0)
|
||||
{
|
||||
_lastFlush = Stopwatch.GetTimestamp();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
long flushTimeout = DrawFlushTimer;
|
||||
|
||||
long now = Stopwatch.GetTimestamp();
|
||||
|
||||
return now > _lastFlush + flushTimeout;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ShouldFlushAttachmentChange(ulong drawCount)
|
||||
{
|
||||
_queryCount = 0;
|
||||
@@ -102,11 +153,27 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void Present()
|
||||
{
|
||||
// Query flush prediction.
|
||||
|
||||
_queryCountHistoryIndex = (_queryCountHistoryIndex + 1) % 3;
|
||||
|
||||
_remainingQueries = _queryCountHistory.Max() + 10;
|
||||
|
||||
_queryCountHistory[_queryCountHistoryIndex] = 0;
|
||||
|
||||
// Fast flush mode toggle.
|
||||
|
||||
_syncWaitHistory[_syncWaitHistoryIndex] = _gd.SyncManager.GetAndResetWaitTicks();
|
||||
|
||||
_syncWaitHistoryIndex = (_syncWaitHistoryIndex + 1) % SyncWaitAverageCount;
|
||||
|
||||
long averageWait = (long)_syncWaitHistory.Average();
|
||||
|
||||
if (_fastFlushMode ? averageWait < FastFlushExitThreshold : averageWait > FastFlushEnterThreshold)
|
||||
{
|
||||
_fastFlushMode = !_fastFlushMode;
|
||||
Logger.Debug?.PrintMsg(LogClass.Gpu, $"Switched fast flush mode: ({_fastFlushMode})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -86,7 +86,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Gd = gd;
|
||||
Device = device;
|
||||
|
||||
AutoFlush = new AutoFlushCounter();
|
||||
AutoFlush = new AutoFlushCounter(gd);
|
||||
|
||||
var pipelineCacheCreateInfo = new PipelineCacheCreateInfo()
|
||||
{
|
||||
@@ -1562,6 +1562,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
private void RecreatePipelineIfNeeded(PipelineBindPoint pbp)
|
||||
{
|
||||
if (AutoFlush.ShouldFlushDraw(DrawCount))
|
||||
{
|
||||
Gd.FlushAllCommands();
|
||||
}
|
||||
|
||||
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
||||
|
||||
// Commit changes to the support buffer before drawing.
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Silk.NET.Vulkan;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
@@ -26,6 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private readonly Device _device;
|
||||
private List<SyncHandle> _handles;
|
||||
private ulong FlushId;
|
||||
private long WaitTicks;
|
||||
|
||||
public SyncManager(VulkanRenderer gd, Device device)
|
||||
{
|
||||
@@ -130,6 +132,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return;
|
||||
}
|
||||
|
||||
long beforeTicks = Stopwatch.GetTimestamp();
|
||||
|
||||
if (result.NeedsFlush(FlushId))
|
||||
{
|
||||
_gd.InterruptAction(() =>
|
||||
@@ -142,12 +146,14 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
|
||||
bool signaled = result.Signalled || result.Waitable.WaitForFences(_gd.Api, _device, 1000000000);
|
||||
|
||||
if (!signaled)
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.Gpu, $"VK Sync Object {result.ID} failed to signal within 1000ms. Continuing...");
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitTicks += Stopwatch.GetTimestamp() - beforeTicks;
|
||||
result.Signalled = true;
|
||||
}
|
||||
}
|
||||
@@ -188,5 +194,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long GetAndResetWaitTicks()
|
||||
{
|
||||
long result = WaitTicks;
|
||||
WaitTicks = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
internal PipelineLayoutCache PipelineLayoutCache { get; private set; }
|
||||
internal BackgroundResources BackgroundResources { get; private set; }
|
||||
internal Action<Action> InterruptAction { get; private set; }
|
||||
internal SyncManager SyncManager { get; private set; }
|
||||
|
||||
internal BufferManager BufferManager { get; private set; }
|
||||
|
||||
@@ -58,7 +59,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
private VulkanDebugMessenger _debugMessenger;
|
||||
private Counters _counters;
|
||||
private SyncManager _syncManager;
|
||||
|
||||
private PipelineFull _pipeline;
|
||||
|
||||
@@ -327,7 +327,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
BufferManager = new BufferManager(this, _device);
|
||||
|
||||
_syncManager = new SyncManager(this, _device);
|
||||
SyncManager = new SyncManager(this, _device);
|
||||
_pipeline = new PipelineFull(this, _device);
|
||||
_pipeline.Initialize();
|
||||
|
||||
@@ -436,7 +436,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
internal void RegisterFlush()
|
||||
{
|
||||
_syncManager.RegisterFlush();
|
||||
SyncManager.RegisterFlush();
|
||||
}
|
||||
|
||||
public PinnedSpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
|
||||
@@ -696,7 +696,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void PreFrame()
|
||||
{
|
||||
_syncManager.Cleanup();
|
||||
SyncManager.Cleanup();
|
||||
}
|
||||
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, bool hostReserved)
|
||||
@@ -736,7 +736,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void CreateSync(ulong id, bool strict)
|
||||
{
|
||||
_syncManager.Create(id, strict);
|
||||
SyncManager.Create(id, strict);
|
||||
}
|
||||
|
||||
public IProgram LoadProgramBinary(byte[] programBinary, bool isFragment, ShaderInfo info)
|
||||
@@ -746,12 +746,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void WaitSync(ulong id)
|
||||
{
|
||||
_syncManager.Wait(id);
|
||||
SyncManager.Wait(id);
|
||||
}
|
||||
|
||||
public ulong GetCurrentSync()
|
||||
{
|
||||
return _syncManager.GetCurrent();
|
||||
return SyncManager.GetCurrent();
|
||||
}
|
||||
|
||||
public void SetInterruptAction(Action<Action> interruptAction)
|
||||
|
@@ -5,6 +5,7 @@ using Ryujinx.Cpu;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders.Processes
|
||||
{
|
||||
@@ -21,8 +22,9 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
public readonly ApplicationControlProperty ApplicationControlProperties;
|
||||
|
||||
public readonly ulong ProcessId;
|
||||
public string Name;
|
||||
public ulong ProgramId;
|
||||
public readonly string Name;
|
||||
public readonly string DisplayVersion;
|
||||
public readonly ulong ProgramId;
|
||||
public readonly string ProgramIdText;
|
||||
public readonly bool Is64Bit;
|
||||
public readonly bool DiskCacheEnabled;
|
||||
@@ -52,20 +54,17 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
{
|
||||
ulong programId = metaLoader.GetProgramId();
|
||||
|
||||
if (ApplicationControlProperties.Title.ItemsRo.Length > 0)
|
||||
{
|
||||
var langIndex = ApplicationControlProperties.Title.ItemsRo.Length > (int)titleLanguage ? (int)titleLanguage : 0;
|
||||
Name = ApplicationControlProperties.Title[(int)titleLanguage].NameString.ToString();
|
||||
|
||||
Name = ApplicationControlProperties.Title[langIndex].NameString.ToString();
|
||||
}
|
||||
else
|
||||
if (string.IsNullOrWhiteSpace(Name))
|
||||
{
|
||||
Name = metaLoader.GetProgramName();
|
||||
Name = ApplicationControlProperties.Title.ItemsRo.ToArray().FirstOrDefault(x => x.Name[0] != 0).NameString.ToString();
|
||||
}
|
||||
|
||||
ProgramId = programId;
|
||||
ProgramIdText = $"{programId:x16}";
|
||||
Is64Bit = metaLoader.IsProgram64Bit();
|
||||
DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString();
|
||||
ProgramId = programId;
|
||||
ProgramIdText = $"{programId:x16}";
|
||||
Is64Bit = metaLoader.IsProgram64Bit();
|
||||
}
|
||||
|
||||
DiskCacheEnabled = diskCacheEnabled;
|
||||
@@ -85,20 +84,11 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
}
|
||||
|
||||
// TODO: LibHac npdm currently doesn't support version field.
|
||||
string version;
|
||||
|
||||
if (ProgramId > 0x0100000000007FFF)
|
||||
{
|
||||
version = ApplicationControlProperties.DisplayVersionString.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
version = device.System.ContentManager.GetCurrentFirmwareVersion().VersionString;
|
||||
}
|
||||
string version = ProgramId > 0x0100000000007FFF ? DisplayVersion : device.System.ContentManager.GetCurrentFirmwareVersion()?.VersionString ?? "?";
|
||||
|
||||
Logger.Info?.Print(LogClass.Loader, $"Application Loaded: {Name} v{version} [{ProgramIdText}] [{(Is64Bit ? "64-bit" : "32-bit")}]");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -496,15 +496,13 @@ namespace Ryujinx.Ui
|
||||
parent.Present();
|
||||
|
||||
var activeProcess = Device.Processes.ActiveApplication;
|
||||
var nacp = activeProcess.ApplicationControlProperties;
|
||||
int desiredLanguage = (int)Device.System.State.DesiredTitleLanguage;
|
||||
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(nacp.Title[desiredLanguage].NameString.ToString()) ? string.Empty : $" - {nacp.Title[desiredLanguage].NameString.ToString()}";
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(nacp.DisplayVersionString.ToString()) ? string.Empty : $" v{nacp.DisplayVersionString.ToString()}";
|
||||
string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})";
|
||||
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
|
||||
string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}";
|
||||
string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}";
|
||||
string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})";
|
||||
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
|
||||
|
||||
parent.Title = $"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
|
||||
parent.Title = $"Ryujinx {Program.Version} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
|
||||
});
|
||||
|
||||
Thread renderLoopThread = new Thread(Render)
|
||||
|
Reference in New Issue
Block a user