Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
eb2cc159fa | ||
|
bb89e36fd8 | ||
|
de3134adbe |
@@ -7,9 +7,7 @@ using ICSharpCode.SharpZipLib.Zip;
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Ryujinx.Ava;
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Ui.Common.Helper;
|
using Ryujinx.Ui.Common.Helper;
|
||||||
@@ -32,7 +30,6 @@ namespace Ryujinx.Modules
|
|||||||
internal static class Updater
|
internal static class Updater
|
||||||
{
|
{
|
||||||
private const string GitHubApiURL = "https://api.github.com";
|
private const string GitHubApiURL = "https://api.github.com";
|
||||||
internal static bool Running;
|
|
||||||
|
|
||||||
private static readonly string HomeDir = AppDomain.CurrentDomain.BaseDirectory;
|
private static readonly string HomeDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
private static readonly string UpdateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
private static readonly string UpdateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
|
||||||
@@ -43,20 +40,19 @@ namespace Ryujinx.Modules
|
|||||||
private static string _platformExt;
|
private static string _platformExt;
|
||||||
private static string _buildUrl;
|
private static string _buildUrl;
|
||||||
private static long _buildSize;
|
private static long _buildSize;
|
||||||
|
private static bool _updateSuccessful;
|
||||||
|
private static bool _running;
|
||||||
|
|
||||||
private static readonly string[] WindowsDependencyDirs = Array.Empty<string>();
|
private static readonly string[] WindowsDependencyDirs = Array.Empty<string>();
|
||||||
|
|
||||||
public static bool UpdateSuccessful { get; private set; }
|
public static async Task BeginParse(Window mainWindow, bool showVersionUpToDate)
|
||||||
|
|
||||||
public static async Task BeginParse(MainWindow mainWindow, bool showVersionUpToDate)
|
|
||||||
{
|
{
|
||||||
if (Running)
|
if (_running)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Running = true;
|
_running = true;
|
||||||
mainWindow.ViewModel.CanUpdate = false;
|
|
||||||
|
|
||||||
// Detect current platform
|
// Detect current platform
|
||||||
if (OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsMacOS())
|
||||||
@@ -82,21 +78,25 @@ namespace Ryujinx.Modules
|
|||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Application, "Failed to convert the current Ryujinx version!");
|
Logger.Error?.Print(LogClass.Application, "Failed to convert the current Ryujinx version!");
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(async () =>
|
Dispatcher.UIThread.Post(async () =>
|
||||||
{
|
{
|
||||||
await ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage],
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_running = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get latest version number from GitHub API
|
// Get latest version number from GitHub API
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (HttpClient jsonClient = ConstructHttpClient())
|
using HttpClient jsonClient = ConstructHttpClient();
|
||||||
{
|
|
||||||
string buildInfoURL = $"{GitHubApiURL}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
|
|
||||||
|
|
||||||
|
string buildInfoURL = $"{GitHubApiURL}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
|
||||||
string fetchedJson = await jsonClient.GetStringAsync(buildInfoURL);
|
string fetchedJson = await jsonClient.GetStringAsync(buildInfoURL);
|
||||||
JObject jsonRoot = JObject.Parse(fetchedJson);
|
JObject jsonRoot = JObject.Parse(fetchedJson);
|
||||||
JToken assets = jsonRoot["assets"];
|
JToken assets = jsonRoot["assets"];
|
||||||
@@ -123,6 +123,8 @@ namespace Ryujinx.Modules
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_running = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,18 +143,22 @@ namespace Ryujinx.Modules
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_running = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Application, exception.Message);
|
Logger.Error?.Print(LogClass.Application, exception.Message);
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(async () =>
|
Dispatcher.UIThread.Post(async () =>
|
||||||
{
|
{
|
||||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]);
|
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_running = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,11 +169,16 @@ namespace Ryujinx.Modules
|
|||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!");
|
Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!");
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(async () =>
|
Dispatcher.UIThread.Post(async () =>
|
||||||
{
|
{
|
||||||
await ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_running = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +192,7 @@ namespace Ryujinx.Modules
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Running = false;
|
_running = false;
|
||||||
mainWindow.ViewModel.CanUpdate = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -210,7 +220,8 @@ namespace Ryujinx.Modules
|
|||||||
Dispatcher.UIThread.Post(async () =>
|
Dispatcher.UIThread.Post(async () =>
|
||||||
{
|
{
|
||||||
// Show a message asking the user if they want to update
|
// Show a message asking the user if they want to update
|
||||||
var shouldUpdate = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
var shouldUpdate = await ContentDialogHelper.CreateChoiceDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
||||||
LocaleManager.Instance[LocaleKeys.RyujinxUpdaterMessage],
|
LocaleManager.Instance[LocaleKeys.RyujinxUpdaterMessage],
|
||||||
$"{Program.Version} -> {newVersion}");
|
$"{Program.Version} -> {newVersion}");
|
||||||
|
|
||||||
@@ -218,12 +229,16 @@ namespace Ryujinx.Modules
|
|||||||
{
|
{
|
||||||
UpdateRyujinx(mainWindow, _buildUrl);
|
UpdateRyujinx(mainWindow, _buildUrl);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_running = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HttpClient ConstructHttpClient()
|
private static HttpClient ConstructHttpClient()
|
||||||
{
|
{
|
||||||
HttpClient result = new HttpClient();
|
HttpClient result = new();
|
||||||
|
|
||||||
// Required by GitHub to interract with APIs.
|
// Required by GitHub to interract with APIs.
|
||||||
result.DefaultRequestHeaders.Add("User-Agent", "Ryujinx-Updater/1.0.0");
|
result.DefaultRequestHeaders.Add("User-Agent", "Ryujinx-Updater/1.0.0");
|
||||||
@@ -233,7 +248,7 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
public static async void UpdateRyujinx(Window parent, string downloadUrl)
|
public static async void UpdateRyujinx(Window parent, string downloadUrl)
|
||||||
{
|
{
|
||||||
UpdateSuccessful = false;
|
_updateSuccessful = false;
|
||||||
|
|
||||||
// Empty update dir, although it shouldn't ever have anything inside it
|
// Empty update dir, although it shouldn't ever have anything inside it
|
||||||
if (Directory.Exists(UpdateDir))
|
if (Directory.Exists(UpdateDir))
|
||||||
@@ -245,17 +260,16 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
string updateFile = Path.Combine(UpdateDir, "update.bin");
|
string updateFile = Path.Combine(UpdateDir, "update.bin");
|
||||||
|
|
||||||
var taskDialog = new TaskDialog()
|
TaskDialog taskDialog = new()
|
||||||
{
|
{
|
||||||
Header = LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
Header = LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
||||||
SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
|
SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
|
||||||
IconSource = new SymbolIconSource { Symbol = Symbol.Download },
|
IconSource = new SymbolIconSource { Symbol = Symbol.Download },
|
||||||
Buttons = { },
|
Buttons = { },
|
||||||
ShowProgressBar = true
|
ShowProgressBar = true,
|
||||||
|
XamlRoot = parent
|
||||||
};
|
};
|
||||||
|
|
||||||
taskDialog.XamlRoot = parent;
|
|
||||||
|
|
||||||
taskDialog.Opened += (s, e) =>
|
taskDialog.Opened += (s, e) =>
|
||||||
{
|
{
|
||||||
if (_buildSize >= 0)
|
if (_buildSize >= 0)
|
||||||
@@ -270,7 +284,7 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
await taskDialog.ShowAsync(true);
|
await taskDialog.ShowAsync(true);
|
||||||
|
|
||||||
if (UpdateSuccessful)
|
if (_updateSuccessful)
|
||||||
{
|
{
|
||||||
var shouldRestart = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
var shouldRestart = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterCompleteMessage],
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterCompleteMessage],
|
||||||
@@ -305,8 +319,8 @@ namespace Ryujinx.Modules
|
|||||||
int totalProgressPercentage = 0;
|
int totalProgressPercentage = 0;
|
||||||
int[] progressPercentage = new int[ConnectionCount];
|
int[] progressPercentage = new int[ConnectionCount];
|
||||||
|
|
||||||
List<byte[]> list = new List<byte[]>(ConnectionCount);
|
List<byte[]> list = new(ConnectionCount);
|
||||||
List<WebClient> webClients = new List<WebClient>(ConnectionCount);
|
List<WebClient> webClients = new(ConnectionCount);
|
||||||
|
|
||||||
for (int i = 0; i < ConnectionCount; i++)
|
for (int i = 0; i < ConnectionCount; i++)
|
||||||
{
|
{
|
||||||
@@ -317,9 +331,9 @@ namespace Ryujinx.Modules
|
|||||||
{
|
{
|
||||||
#pragma warning disable SYSLIB0014
|
#pragma warning disable SYSLIB0014
|
||||||
// TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient.
|
// TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient.
|
||||||
using (WebClient client = new WebClient())
|
using WebClient client = new();
|
||||||
#pragma warning restore SYSLIB0014
|
#pragma warning restore SYSLIB0014
|
||||||
{
|
|
||||||
webClients.Add(client);
|
webClients.Add(client);
|
||||||
|
|
||||||
if (i == ConnectionCount - 1)
|
if (i == ConnectionCount - 1)
|
||||||
@@ -405,20 +419,18 @@ namespace Ryujinx.Modules
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void DoUpdateWithSingleThreadWorker(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
private static void DoUpdateWithSingleThreadWorker(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||||
{
|
{
|
||||||
using (HttpClient client = new HttpClient())
|
using HttpClient client = new();
|
||||||
{
|
|
||||||
// We do not want to timeout while downloading
|
// We do not want to timeout while downloading
|
||||||
client.Timeout = TimeSpan.FromDays(1);
|
client.Timeout = TimeSpan.FromDays(1);
|
||||||
|
|
||||||
using (HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result)
|
using (HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result)
|
||||||
using (Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result)
|
using (Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result)
|
||||||
{
|
{
|
||||||
using (Stream updateFileStream = File.Open(updateFile, FileMode.Create))
|
using Stream updateFileStream = File.Open(updateFile, FileMode.Create);
|
||||||
{
|
|
||||||
long totalBytes = response.Content.Headers.ContentLength.Value;
|
long totalBytes = response.Content.Headers.ContentLength.Value;
|
||||||
long byteWritten = 0;
|
long byteWritten = 0;
|
||||||
|
|
||||||
@@ -440,11 +452,9 @@ namespace Ryujinx.Modules
|
|||||||
updateFileStream.Write(buffer, 0, readSize);
|
updateFileStream.Write(buffer, 0, readSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
InstallUpdate(taskDialog, updateFile);
|
InstallUpdate(taskDialog, updateFile);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static double GetPercentage(double value, double max)
|
private static double GetPercentage(double value, double max)
|
||||||
@@ -454,8 +464,11 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
private static void DoUpdateWithSingleThread(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
private static void DoUpdateWithSingleThread(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||||
{
|
{
|
||||||
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(taskDialog, downloadUrl, updateFile));
|
Thread worker = new(() => DoUpdateWithSingleThreadWorker(taskDialog, downloadUrl, updateFile))
|
||||||
worker.Name = "Updater.SingleThreadWorker";
|
{
|
||||||
|
Name = "Updater.SingleThreadWorker"
|
||||||
|
};
|
||||||
|
|
||||||
worker.Start();
|
worker.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,10 +496,10 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
if (OperatingSystem.IsLinux())
|
if (OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
using (Stream inStream = File.OpenRead(updateFile))
|
using Stream inStream = File.OpenRead(updateFile);
|
||||||
using (Stream gzipStream = new GZipInputStream(inStream))
|
using GZipInputStream gzipStream = new(inStream);
|
||||||
using (TarInputStream tarStream = new TarInputStream(gzipStream, Encoding.ASCII))
|
using TarInputStream tarStream = new(gzipStream, Encoding.ASCII);
|
||||||
{
|
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
TarEntry tarEntry;
|
TarEntry tarEntry;
|
||||||
@@ -516,12 +529,11 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
taskDialog.SetProgressBarState(100, TaskDialogProgressState.Normal);
|
taskDialog.SetProgressBarState(100, TaskDialogProgressState.Normal);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using (Stream inStream = File.OpenRead(updateFile))
|
using Stream inStream = File.OpenRead(updateFile);
|
||||||
using (ZipFile zipFile = new ZipFile(inStream))
|
using ZipFile zipFile = new(inStream);
|
||||||
{
|
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
double count = 0;
|
double count = 0;
|
||||||
@@ -549,7 +561,6 @@ namespace Ryujinx.Modules
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Delete downloaded zip
|
// Delete downloaded zip
|
||||||
File.Delete(updateFile);
|
File.Delete(updateFile);
|
||||||
@@ -594,21 +605,24 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
SetFileExecutable(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx"));
|
SetFileExecutable(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx"));
|
||||||
|
|
||||||
UpdateSuccessful = true;
|
_updateSuccessful = true;
|
||||||
|
|
||||||
taskDialog.Hide();
|
taskDialog.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
public static bool CanUpdate(bool showWarnings)
|
||||||
public static bool CanUpdate(bool showWarnings, StyleableWindow parent)
|
|
||||||
{
|
{
|
||||||
#if !DISABLE_UPDATER
|
#if !DISABLE_UPDATER
|
||||||
if (RuntimeInformation.OSArchitecture != Architecture.X64)
|
if (RuntimeInformation.OSArchitecture != Architecture.X64)
|
||||||
{
|
{
|
||||||
if (showWarnings)
|
if (showWarnings)
|
||||||
{
|
{
|
||||||
ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedMessage],
|
Dispatcher.UIThread.Post(async () =>
|
||||||
|
{
|
||||||
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedMessage],
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedSubMessage]);
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedSubMessage]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -618,8 +632,12 @@ namespace Ryujinx.Modules
|
|||||||
{
|
{
|
||||||
if (showWarnings)
|
if (showWarnings)
|
||||||
{
|
{
|
||||||
ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetMessage],
|
Dispatcher.UIThread.Post(async () =>
|
||||||
|
{
|
||||||
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetMessage],
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetSubMessage]);
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetSubMessage]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -629,8 +647,12 @@ namespace Ryujinx.Modules
|
|||||||
{
|
{
|
||||||
if (showWarnings)
|
if (showWarnings)
|
||||||
{
|
{
|
||||||
ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildMessage],
|
Dispatcher.UIThread.Post(async () =>
|
||||||
|
{
|
||||||
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildMessage],
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]);
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -642,18 +664,27 @@ namespace Ryujinx.Modules
|
|||||||
{
|
{
|
||||||
if (ReleaseInformation.IsFlatHubBuild())
|
if (ReleaseInformation.IsFlatHubBuild())
|
||||||
{
|
{
|
||||||
ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle], LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage]);
|
Dispatcher.UIThread.Post(async () =>
|
||||||
|
{
|
||||||
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle], LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]);
|
Dispatcher.UIThread.Post(async () =>
|
||||||
|
{
|
||||||
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
|
LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
|
||||||
|
|
||||||
// NOTE: This method should always reflect the latest build layout.s
|
// NOTE: This method should always reflect the latest build layout.s
|
||||||
private static IEnumerable<string> EnumerateFilesToDelete()
|
private static IEnumerable<string> EnumerateFilesToDelete()
|
||||||
@@ -677,7 +708,7 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
private static void MoveAllFilesOver(string root, string dest, TaskDialog taskDialog)
|
private static void MoveAllFilesOver(string root, string dest, TaskDialog taskDialog)
|
||||||
{
|
{
|
||||||
var total = Directory.GetFiles(root, "*", SearchOption.AllDirectories).Length;
|
int total = Directory.GetFiles(root, "*", SearchOption.AllDirectories).Length;
|
||||||
foreach (string directory in Directory.GetDirectories(root))
|
foreach (string directory in Directory.GetDirectories(root))
|
||||||
{
|
{
|
||||||
string dirName = Path.GetFileName(directory);
|
string dirName = Path.GetFileName(directory);
|
||||||
@@ -694,6 +725,7 @@ namespace Ryujinx.Modules
|
|||||||
foreach (string file in Directory.GetFiles(root))
|
foreach (string file in Directory.GetFiles(root))
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
File.Move(file, Path.Combine(dest, Path.GetFileName(file)), true);
|
File.Move(file, Path.Combine(dest, Path.GetFileName(file)), true);
|
||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
|
@@ -88,7 +88,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
private float _volume;
|
private float _volume;
|
||||||
private string _backendText;
|
private string _backendText;
|
||||||
|
|
||||||
private bool _canUpdate;
|
private bool _canUpdate = true;
|
||||||
private Cursor _cursor;
|
private Cursor _cursor;
|
||||||
private string _title;
|
private string _title;
|
||||||
private string _currentEmulatedGamePath;
|
private string _currentEmulatedGamePath;
|
||||||
@@ -177,11 +177,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
public bool CanUpdate
|
public bool CanUpdate
|
||||||
{
|
{
|
||||||
get => _canUpdate;
|
get => _canUpdate && EnableNonGameRunningControls && Modules.Updater.CanUpdate(false);
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_canUpdate = value;
|
_canUpdate = value;
|
||||||
|
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -165,7 +165,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
|
|
||||||
public async void CheckForUpdates(object sender, RoutedEventArgs e)
|
public async void CheckForUpdates(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (Updater.CanUpdate(true, Window))
|
if (Updater.CanUpdate(true))
|
||||||
{
|
{
|
||||||
await Updater.BeginParse(Window, true);
|
await Updater.BeginParse(Window, true);
|
||||||
}
|
}
|
||||||
|
@@ -271,7 +271,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
ViewModel.LoadApplication(_launchPath, _startFullscreen);
|
ViewModel.LoadApplication(_launchPath, _startFullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false, this))
|
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
|
||||||
{
|
{
|
||||||
Updater.BeginParse(this, false).ContinueWith(task =>
|
Updater.BeginParse(this, false).ContinueWith(task =>
|
||||||
{
|
{
|
||||||
|
@@ -28,6 +28,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public readonly bool SupportsExtendedDynamicState;
|
public readonly bool SupportsExtendedDynamicState;
|
||||||
public readonly bool SupportsMultiView;
|
public readonly bool SupportsMultiView;
|
||||||
public readonly bool SupportsNullDescriptors;
|
public readonly bool SupportsNullDescriptors;
|
||||||
|
public readonly bool SupportsPreciseOcclusionQueries;
|
||||||
public readonly bool SupportsPushDescriptors;
|
public readonly bool SupportsPushDescriptors;
|
||||||
public readonly bool SupportsTransformFeedback;
|
public readonly bool SupportsTransformFeedback;
|
||||||
public readonly bool SupportsTransformFeedbackQueries;
|
public readonly bool SupportsTransformFeedbackQueries;
|
||||||
@@ -53,6 +54,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
bool supportsPushDescriptors,
|
bool supportsPushDescriptors,
|
||||||
bool supportsTransformFeedback,
|
bool supportsTransformFeedback,
|
||||||
bool supportsTransformFeedbackQueries,
|
bool supportsTransformFeedbackQueries,
|
||||||
|
bool supportsPreciseOcclusionQueries,
|
||||||
bool supportsGeometryShader,
|
bool supportsGeometryShader,
|
||||||
uint minSubgroupSize,
|
uint minSubgroupSize,
|
||||||
uint maxSubgroupSize,
|
uint maxSubgroupSize,
|
||||||
@@ -74,6 +76,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SupportsPushDescriptors = supportsPushDescriptors;
|
SupportsPushDescriptors = supportsPushDescriptors;
|
||||||
SupportsTransformFeedback = supportsTransformFeedback;
|
SupportsTransformFeedback = supportsTransformFeedback;
|
||||||
SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries;
|
SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries;
|
||||||
|
SupportsPreciseOcclusionQueries = supportsPreciseOcclusionQueries;
|
||||||
SupportsGeometryShader = supportsGeometryShader;
|
SupportsGeometryShader = supportsGeometryShader;
|
||||||
MinSubgroupSize = minSubgroupSize;
|
MinSubgroupSize = minSubgroupSize;
|
||||||
MaxSubgroupSize = maxSubgroupSize;
|
MaxSubgroupSize = maxSubgroupSize;
|
||||||
|
@@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
foreach (var queryPool in _activeQueries)
|
foreach (var queryPool in _activeQueries)
|
||||||
{
|
{
|
||||||
Gd.Api.CmdResetQueryPool(CommandBuffer, queryPool, 0, 1);
|
Gd.Api.CmdResetQueryPool(CommandBuffer, queryPool, 0, 1);
|
||||||
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, 0);
|
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Restore();
|
Restore();
|
||||||
@@ -255,7 +255,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, 0);
|
Gd.Api.CmdBeginQuery(CommandBuffer, pool, 0, Gd.Capabilities.SupportsPreciseOcclusionQueries ? QueryControlFlags.PreciseBit : 0);
|
||||||
|
|
||||||
_activeQueries.Add(pool);
|
_activeQueries.Add(pool);
|
||||||
}
|
}
|
||||||
|
@@ -416,6 +416,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
IndependentBlend = true,
|
IndependentBlend = true,
|
||||||
LogicOp = supportedFeatures.LogicOp,
|
LogicOp = supportedFeatures.LogicOp,
|
||||||
MultiViewport = true,
|
MultiViewport = true,
|
||||||
|
OcclusionQueryPrecise = supportedFeatures.OcclusionQueryPrecise,
|
||||||
PipelineStatisticsQuery = supportedFeatures.PipelineStatisticsQuery,
|
PipelineStatisticsQuery = supportedFeatures.PipelineStatisticsQuery,
|
||||||
SamplerAnisotropy = true,
|
SamplerAnisotropy = true,
|
||||||
ShaderClipDistance = true,
|
ShaderClipDistance = true,
|
||||||
|
@@ -270,6 +270,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
supportedExtensions.Contains(KhrPushDescriptor.ExtensionName),
|
supportedExtensions.Contains(KhrPushDescriptor.ExtensionName),
|
||||||
supportsTransformFeedback,
|
supportsTransformFeedback,
|
||||||
propertiesTransformFeedback.TransformFeedbackQueries,
|
propertiesTransformFeedback.TransformFeedbackQueries,
|
||||||
|
features2.Features.OcclusionQueryPrecise,
|
||||||
supportedFeatures.GeometryShader,
|
supportedFeatures.GeometryShader,
|
||||||
propertiesSubgroupSizeControl.MinSubgroupSize,
|
propertiesSubgroupSizeControl.MinSubgroupSize,
|
||||||
propertiesSubgroupSizeControl.MaxSubgroupSize,
|
propertiesSubgroupSizeControl.MaxSubgroupSize,
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
|
using Silk.NET.Vulkan.Extensions.KHR;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using VkFormat = Silk.NET.Vulkan.Format;
|
using VkFormat = Silk.NET.Vulkan.Format;
|
||||||
@@ -49,13 +50,19 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void RecreateSwapchain()
|
private void RecreateSwapchain()
|
||||||
{
|
{
|
||||||
|
var oldSwapchain = _swapchain;
|
||||||
|
int imageCount = _swapchainImageViews.Length;
|
||||||
_vsyncModeChanged = false;
|
_vsyncModeChanged = false;
|
||||||
|
|
||||||
for (int i = 0; i < _swapchainImageViews.Length; i++)
|
for (int i = 0; i < imageCount; i++)
|
||||||
{
|
{
|
||||||
_swapchainImageViews[i].Dispose();
|
_swapchainImageViews[i].Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy old Swapchain.
|
||||||
|
_gd.Api.DeviceWaitIdle(_device);
|
||||||
|
_gd.SwapchainApi.DestroySwapchain(_device, oldSwapchain, Span<AllocationCallbacks>.Empty);
|
||||||
|
|
||||||
CreateSwapchain();
|
CreateSwapchain();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +122,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PreTransform = capabilities.CurrentTransform,
|
PreTransform = capabilities.CurrentTransform,
|
||||||
CompositeAlpha = CompositeAlphaFlagsKHR.OpaqueBitKhr,
|
CompositeAlpha = CompositeAlphaFlagsKHR.OpaqueBitKhr,
|
||||||
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
|
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
|
||||||
Clipped = true,
|
Clipped = true
|
||||||
OldSwapchain = oldSwapchain
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_gd.SwapchainApi.CreateSwapchain(_device, swapchainCreateInfo, null, out _swapchain).ThrowOnError();
|
_gd.SwapchainApi.CreateSwapchain(_device, swapchainCreateInfo, null, out _swapchain).ThrowOnError();
|
||||||
|
Reference in New Issue
Block a user