Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cee667b491 | ||
|
94a64f2aea | ||
|
2355c2af62 |
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Deutsch",
|
||||||
"MenuBarFileOpenApplet": "Applet öffnen",
|
"MenuBarFileOpenApplet": "Applet öffnen",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii Editor Applet im Standalone Modus",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii Editor Applet im Standalone Modus",
|
||||||
"SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff",
|
"SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Ελληνικά",
|
||||||
"MenuBarFileOpenApplet": "Άνοιγμα Applet",
|
"MenuBarFileOpenApplet": "Άνοιγμα Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
|
||||||
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",
|
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "English (US)",
|
||||||
"MenuBarFileOpenApplet": "Open Applet",
|
"MenuBarFileOpenApplet": "Open Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode",
|
||||||
"SettingsTabInputDirectMouseAccess": "Direct Mouse Access",
|
"SettingsTabInputDirectMouseAccess": "Direct Mouse Access",
|
||||||
@@ -611,3 +612,4 @@
|
|||||||
"Recover": "Recover",
|
"Recover": "Recover",
|
||||||
"UserProfilesRecoverHeading" : "Saves were found for the following accounts"
|
"UserProfilesRecoverHeading" : "Saves were found for the following accounts"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Español (ES)",
|
||||||
"MenuBarFileOpenApplet": "Abrir applet",
|
"MenuBarFileOpenApplet": "Abrir applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo",
|
||||||
"SettingsTabInputDirectMouseAccess": "Acceso directo al ratón",
|
"SettingsTabInputDirectMouseAccess": "Acceso directo al ratón",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Français",
|
||||||
"MenuBarFileOpenApplet": "Ouvrir Applet",
|
"MenuBarFileOpenApplet": "Ouvrir Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'Applet Mii Editor en mode Standalone",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'Applet Mii Editor en mode Standalone",
|
||||||
"SettingsTabInputDirectMouseAccess": "Accès direct à la souris",
|
"SettingsTabInputDirectMouseAccess": "Accès direct à la souris",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Italiano",
|
||||||
"MenuBarFileOpenApplet": "Apri Applet",
|
"MenuBarFileOpenApplet": "Apri Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Apri l'applet Mii Editor in modalità Standalone",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Apri l'applet Mii Editor in modalità Standalone",
|
||||||
"SettingsTabInputDirectMouseAccess": "Accesso diretto al mouse",
|
"SettingsTabInputDirectMouseAccess": "Accesso diretto al mouse",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "日本語",
|
||||||
"MenuBarFileOpenApplet": "アプレットを開く",
|
"MenuBarFileOpenApplet": "アプレットを開く",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
|
||||||
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
|
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "한국어",
|
||||||
"MenuBarFileOpenApplet": "애플릿 열기",
|
"MenuBarFileOpenApplet": "애플릿 열기",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기",
|
||||||
"SettingsTabInputDirectMouseAccess": "직접 마우스 접속",
|
"SettingsTabInputDirectMouseAccess": "직접 마우스 접속",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Polski",
|
||||||
"MenuBarFileOpenApplet": "Otwórz Aplet",
|
"MenuBarFileOpenApplet": "Otwórz Aplet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie Indywidualnym",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie Indywidualnym",
|
||||||
"SettingsTabInputDirectMouseAccess": "Bezpośredni Dostęp do Myszy",
|
"SettingsTabInputDirectMouseAccess": "Bezpośredni Dostęp do Myszy",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Português (BR)",
|
||||||
"MenuBarFileOpenApplet": "Abrir Applet",
|
"MenuBarFileOpenApplet": "Abrir Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abrir editor Mii em modo avulso",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abrir editor Mii em modo avulso",
|
||||||
"SettingsTabInputDirectMouseAccess": "Acesso direto ao mouse",
|
"SettingsTabInputDirectMouseAccess": "Acesso direto ao mouse",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Русский",
|
||||||
"MenuBarFileOpenApplet": "Открыть апплет",
|
"MenuBarFileOpenApplet": "Открыть апплет",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открыть апплет Mii Editor в автономном режиме.",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открыть апплет Mii Editor в автономном режиме.",
|
||||||
"SettingsTabInputDirectMouseAccess": "Прямой доступ с помощью мыши",
|
"SettingsTabInputDirectMouseAccess": "Прямой доступ с помощью мыши",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Türkçe",
|
||||||
"MenuBarFileOpenApplet": "Applet'i Aç",
|
"MenuBarFileOpenApplet": "Applet'i Aç",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Mii Editör Applet'ini Bağımsız Mod'da Aç",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Mii Editör Applet'ini Bağımsız Mod'da Aç",
|
||||||
"SettingsTabInputDirectMouseAccess": "Doğrudan Mouse Erişimi",
|
"SettingsTabInputDirectMouseAccess": "Doğrudan Mouse Erişimi",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "Yкраїнська",
|
||||||
"MenuBarFileOpenApplet": "Відкрити аплет",
|
"MenuBarFileOpenApplet": "Відкрити аплет",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрийте аплет Mii Editor в автономному режимі",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрийте аплет Mii Editor в автономному режимі",
|
||||||
"SettingsTabInputDirectMouseAccess": "Прямий доступ мишею",
|
"SettingsTabInputDirectMouseAccess": "Прямий доступ мишею",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "简体中文",
|
||||||
"MenuBarFileOpenApplet": "打开小程序",
|
"MenuBarFileOpenApplet": "打开小程序",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序",
|
||||||
"SettingsTabInputDirectMouseAccess": "直通鼠标操作",
|
"SettingsTabInputDirectMouseAccess": "直通鼠标操作",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Language": "繁體中文",
|
||||||
"MenuBarFileOpenApplet": "打開小程式",
|
"MenuBarFileOpenApplet": "打開小程式",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打開獨立的 Mii 小程式",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打開獨立的 Mii 小程式",
|
||||||
"SettingsTabInputDirectMouseAccess": "直通滑鼠操作",
|
"SettingsTabInputDirectMouseAccess": "直通滑鼠操作",
|
||||||
|
@@ -6,7 +6,6 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Common.Locale
|
namespace Ryujinx.Ava.Common.Locale
|
||||||
{
|
{
|
||||||
|
@@ -145,6 +145,7 @@
|
|||||||
<None Remove="Assets\Locales\pt_BR.json" />
|
<None Remove="Assets\Locales\pt_BR.json" />
|
||||||
<None Remove="Assets\Locales\ru_RU.json" />
|
<None Remove="Assets\Locales\ru_RU.json" />
|
||||||
<None Remove="Assets\Locales\tr_TR.json" />
|
<None Remove="Assets\Locales\tr_TR.json" />
|
||||||
|
<None Remove="Assets\Locales\uk_UA.json" />
|
||||||
<None Remove="Assets\Locales\zh_CN.json" />
|
<None Remove="Assets\Locales\zh_CN.json" />
|
||||||
<None Remove="Assets\Locales\zh_TW.json" />
|
<None Remove="Assets\Locales\zh_TW.json" />
|
||||||
<None Remove="Assets\Styles\Styles.xaml" />
|
<None Remove="Assets\Styles\Styles.xaml" />
|
||||||
@@ -165,6 +166,7 @@
|
|||||||
<EmbeddedResource Include="Assets\Locales\pt_BR.json" />
|
<EmbeddedResource Include="Assets\Locales\pt_BR.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\ru_RU.json" />
|
<EmbeddedResource Include="Assets\Locales\ru_RU.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\tr_TR.json" />
|
<EmbeddedResource Include="Assets\Locales\tr_TR.json" />
|
||||||
|
<EmbeddedResource Include="Assets\Locales\uk_UA.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\zh_CN.json" />
|
<EmbeddedResource Include="Assets\Locales\zh_CN.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\zh_TW.json" />
|
<EmbeddedResource Include="Assets\Locales\zh_TW.json" />
|
||||||
<EmbeddedResource Include="Assets\Styles\Styles.xaml" />
|
<EmbeddedResource Include="Assets\Styles\Styles.xaml" />
|
||||||
|
@@ -77,63 +77,7 @@
|
|||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}">
|
<MenuItem Name="ChangeLanguageMenuItem" Header="{locale:Locale MenuBarOptionsChangeLanguage}">
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="de_DE"
|
|
||||||
Header="Deutsch" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="en_US"
|
|
||||||
Header="English (US)" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="es_ES"
|
|
||||||
Header="Español (ES)" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="fr_FR"
|
|
||||||
Header="Français" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="it_IT"
|
|
||||||
Header="Italiano" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="pt_BR"
|
|
||||||
Header="Português (BR)" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="tr_TR"
|
|
||||||
Header="Türkçe" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="el_GR"
|
|
||||||
Header="Ελληνικά" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="pl_PL"
|
|
||||||
Header="Polski" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="ru_RU"
|
|
||||||
Header="Русский" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="zh_CN"
|
|
||||||
Header="简体中文" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="zh_TW"
|
|
||||||
Header="繁體中文" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="ja_JP"
|
|
||||||
Header="日本語" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="ko_KR"
|
|
||||||
Header="한국어" />
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
@@ -1,13 +1,20 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
|
||||||
using Ryujinx.Ava.UI.Windows;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
using LibHac.Ncm;
|
using LibHac.Ncm;
|
||||||
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.UI.Windows;
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Main
|
namespace Ryujinx.Ava.UI.Views.Main
|
||||||
{
|
{
|
||||||
@@ -19,13 +26,47 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
public MainMenuBarView()
|
public MainMenuBarView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
List<MenuItem> menuItems = new();
|
||||||
|
|
||||||
|
string localePath = "Ryujinx.Ava/Assets/Locales";
|
||||||
|
string localeExt = ".json";
|
||||||
|
|
||||||
|
string[] localesPath = EmbeddedResources.GetAllAvailableResources(localePath, localeExt);
|
||||||
|
|
||||||
|
Array.Sort(localesPath);
|
||||||
|
|
||||||
|
foreach (string locale in localesPath)
|
||||||
|
{
|
||||||
|
string languageCode = Path.GetFileNameWithoutExtension(locale).Split('.').Last();
|
||||||
|
string languageJson = EmbeddedResources.ReadAllText($"{localePath}/{languageCode}{localeExt}");
|
||||||
|
var strings = JsonHelper.Deserialize<Dictionary<string, string>>(languageJson);
|
||||||
|
|
||||||
|
if (!strings.TryGetValue("Language", out string languageName))
|
||||||
|
{
|
||||||
|
languageName = languageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem menuItem = new()
|
||||||
|
{
|
||||||
|
Header = languageName,
|
||||||
|
Command = MiniCommand.Create(() =>
|
||||||
|
{
|
||||||
|
ViewModel.ChangeLanguage(languageCode);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
menuItems.Add(menuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangeLanguageMenuItem.Items = menuItems.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnAttachedToVisualTree(e);
|
base.OnAttachedToVisualTree(e);
|
||||||
|
|
||||||
if (this.VisualRoot is MainWindow window)
|
if (VisualRoot is MainWindow window)
|
||||||
{
|
{
|
||||||
Window = window;
|
Window = window;
|
||||||
}
|
}
|
||||||
|
@@ -81,7 +81,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
private void PrintHeading()
|
private void PrintHeading()
|
||||||
{
|
{
|
||||||
Heading.Text = string.Format(LocaleManager.Instance[LocaleKeys.GameUpdateWindowHeading], _titleUpdates.Count, _titleName, _titleId.ToString("X16"));
|
Heading.Text = string.Format(LocaleManager.Instance[LocaleKeys.GameUpdateWindowHeading], _titleUpdates.Count - 1, _titleName, _titleId.ToString("X16"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadUpdates()
|
private void LoadUpdates()
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -127,6 +128,13 @@ namespace Ryujinx.Common
|
|||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string[] GetAllAvailableResources(string path, string ext = "")
|
||||||
|
{
|
||||||
|
return ResolveManifestPath(path).Item1.GetManifestResourceNames()
|
||||||
|
.Where(r => r.EndsWith(ext))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
private static (Assembly, string) ResolveManifestPath(string filename)
|
private static (Assembly, string) ResolveManifestPath(string filename)
|
||||||
{
|
{
|
||||||
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
|
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
@@ -13,6 +14,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
private const int MaxCapacity = 2048;
|
private const int MaxCapacity = 2048;
|
||||||
|
|
||||||
private readonly LinkedList<Texture> _textures;
|
private readonly LinkedList<Texture> _textures;
|
||||||
|
private readonly ConcurrentQueue<Texture> _deferredRemovals;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the automatic deletion cache.
|
/// Creates a new instance of the automatic deletion cache.
|
||||||
@@ -20,6 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
public AutoDeleteCache()
|
public AutoDeleteCache()
|
||||||
{
|
{
|
||||||
_textures = new LinkedList<Texture>();
|
_textures = new LinkedList<Texture>();
|
||||||
|
_deferredRemovals = new ConcurrentQueue<Texture>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -56,6 +59,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
oldestTexture.CacheNode = null;
|
oldestTexture.CacheNode = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_deferredRemovals.Count > 0)
|
||||||
|
{
|
||||||
|
while (_deferredRemovals.TryDequeue(out Texture textureToRemove))
|
||||||
|
{
|
||||||
|
Remove(textureToRemove, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -84,6 +95,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a texture from the cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="texture">The texture to be removed from the cache</param>
|
||||||
|
/// <param name="flush">True to remove the texture if it was on the cache</param>
|
||||||
|
/// <returns>True if the texture was found and removed, false otherwise</returns>
|
||||||
public bool Remove(Texture texture, bool flush)
|
public bool Remove(Texture texture, bool flush)
|
||||||
{
|
{
|
||||||
if (texture.CacheNode == null)
|
if (texture.CacheNode == null)
|
||||||
@@ -104,6 +121,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return texture.DecrementReferenceCount();
|
return texture.DecrementReferenceCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queues removal of a texture from the cache in a thread safe way.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="texture">The texture to be removed from the cache</param>
|
||||||
|
public void RemoveDeferred(Texture texture)
|
||||||
|
{
|
||||||
|
_deferredRemovals.Enqueue(texture);
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerator<Texture> GetEnumerator()
|
public IEnumerator<Texture> GetEnumerator()
|
||||||
{
|
{
|
||||||
return _textures.GetEnumerator();
|
return _textures.GetEnumerator();
|
||||||
|
@@ -1676,6 +1676,13 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoveFromPools(true);
|
RemoveFromPools(true);
|
||||||
|
|
||||||
|
// We only want to remove if there's no mapped region of the texture that was modified by the GPU,
|
||||||
|
// otherwise we could lose data.
|
||||||
|
if (!Group.AnyModified(this))
|
||||||
|
{
|
||||||
|
_physicalMemory.TextureCache.QueueAutoDeleteCacheRemoval(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -1165,6 +1165,19 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queues the removal of a texture from the auto delete cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This function is thread safe and can be called from any thread.
|
||||||
|
/// The texture will be deleted on the next time the cache is used.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="texture">The texture to be removed</param>
|
||||||
|
public void QueueAutoDeleteCacheRemoval(Texture texture)
|
||||||
|
{
|
||||||
|
_cache.RemoveDeferred(texture);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes all textures and samplers in the cache.
|
/// Disposes all textures and samplers in the cache.
|
||||||
/// It's an error to use the texture cache after disposal.
|
/// It's an error to use the texture cache after disposal.
|
||||||
|
@@ -434,6 +434,32 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a texture was modified by the GPU.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="texture">The texture to be checked</param>
|
||||||
|
/// <returns>True if any region of the texture was modified by the GPU, false otherwise</returns>
|
||||||
|
public bool AnyModified(Texture texture)
|
||||||
|
{
|
||||||
|
bool anyModified = false;
|
||||||
|
|
||||||
|
EvaluateRelevantHandles(texture, (baseHandle, regionCount, split) =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < regionCount; i++)
|
||||||
|
{
|
||||||
|
TextureGroupHandle group = _handles[baseHandle + i];
|
||||||
|
|
||||||
|
if (group.Modified)
|
||||||
|
{
|
||||||
|
anyModified = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return anyModified;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flush modified ranges for a given texture.
|
/// Flush modified ranges for a given texture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Reference in New Issue
Block a user