Compare commits

..

16 Commits

Author SHA1 Message Date
gdkchan
296c4a3d01 Relax Vulkan requirements (#4282)
* Relax Vulkan requirements

* Fix MaxColorAttachmentIndex

* Fix ColorBlendAttachmentStateCount value mismatch for background pipelines

* Change query capability check to check for pipeline statistics query rather than geometry shader support
2023-01-26 18:34:35 -03:00
riperiperi
e7cf4e6eaf Vulkan: Reset queries on same command buffer (#4329)
* Reset queries on same command buffer

Vulkan seems to complain when the queries are reset on another command buffer. No idea why, the spec really could be written better in this regard. This fixes complaints, and hopefully any implementations that care extensively about them.

This change _guesses_ how many queries need to be reset and resets as many as possible at the same time to avoid splitting render passes. If it resets too many queries, we didn't waste too much time - if it runs out of resets it will batch reset 10 more.

The number of queries reset is the maximum number of queries in the last 3 frames. This has been worked into the AutoFlushCounter so that it only resets up to 32 if it is yet to force a command buffer submission in this attachment.

This is only done for samples passed queries right now, as they have by far the most resets.

* Address Feedback
2023-01-24 13:32:56 -03:00
gdkchan
a1a4771ac1 Remove use of GetFunctionPointerForDelegate to get JIT cache function pointer (#4337)
* Remove use of GetFunctionPointerForDelegate to get JIT cache function pointer

* Rename FuncPtr to FuncPointer
2023-01-23 22:37:53 +00:00
gdkchan
2fd819613f SPIR-V: Change BitfieldExtract and BitfieldInsert for SPIRV-Cross (#4336)
* SPIR-V: Change BitfieldExtract and BitfieldInsert types to make Metal MSL compiler happy

* Shader cache version bump
2023-01-23 19:20:40 -03:00
TSRBerry
ad6ff6ce99 GUI: Add option to register file types (#4250)
* Add FileAssociationHelper.cs

* Add register file types option to gtk

* Add register file types option to avalonia

* Add Windows support to FileAssociationHelper.cs

* linux: Add uninstall support for file types

* Ignore .glade~ backup files

* Rename Register/Unregister methods

* gtk: Add manage file types submenu

* ava: Add manage file types submenu

* windows: Add uninstall support for file types

* Don't invert uninstall condition (formatting change)

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Add IsTypesRegisteredWindows & Fix Windows install function

* Add AreMimeTypesRegisteredLinux()

* Fix wrong indention

Co-authored-by: AcK77 <acoustik666@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-22 17:39:00 +00:00
gnisman
dc30d94852 Handle parsing of corrupt Config.json and prevent crash on launch (#4309)
* Handle parsing of corrupt Config.json and prevent crash on launch

* Implement a cleaner solution to handle empty json object
2023-01-22 17:04:33 +01:00
merry
4f293f8cbe Arm64: Simplify TryEncodeBitMask and use for constants (#4328)
* Arm64: Simplify TryEncodeBitMask

* CodeGenerator: Use TryEncodeBitMask in GenerateConstantCopy

* Ptc: Bump version
2023-01-22 14:15:49 +00:00
merry
32a1cd83fd AvaloniaKeyboardDriver: Swallow TextInput events to avoid bell (#4320) 2023-01-22 11:21:52 +01:00
riperiperi
e3d0ccf8d5 Allow setting texture data from 1x to fix some textures resetting randomly (#2860)
* Allow setting texture data from 1x to fix some textures resetting randomly

Expected targets:

- Deltarune 1+2
- Crash Team Racing
- Those new pokemon games idk

* Allow scaling of MSAA textures, propagate scale on copy.

* Fix Rebase

Oops

* Automatic disable

* A bit more aggressive

* Without the debug log

* Actually decrement the score when writing.
2023-01-22 02:03:30 +00:00
Ac_K
c14844d12c Ava UI: Various Fixes (#4326)
* Ava UI: Various Fixes

* use WriteAllBytes
2023-01-22 01:42:55 +01:00
gdkchan
7fea26e97e Remove use of reflection on GAL multithreading (#4287)
* Introduce new IGALCommand<T> interface and use it

* Remove use of reflection on GAL multithreading

* Unmanaged constraint
2023-01-22 01:07:43 +01:00
dependabot[bot]
7b7f62c776 nuget: bump Microsoft.CodeAnalysis.Analyzers from 3.3.3 to 3.3.4 (#4310)
* nuget: bump Microsoft.CodeAnalysis.Analyzers from 3.3.3 to 3.3.4

Bumps [Microsoft.CodeAnalysis.Analyzers](https://github.com/dotnet/roslyn-analyzers) from 3.3.3 to 3.3.4.
- [Release notes](https://github.com/dotnet/roslyn-analyzers/releases)
- [Changelog](https://github.com/dotnet/roslyn-analyzers/blob/main/PostReleaseActivities.md)
- [Commits](https://github.com/dotnet/roslyn-analyzers/compare/v3.3.3...v3.3.4)

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fixes warning

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-21 20:04:39 +00:00
riperiperi
423dbc8888 Use volatile read/writes for GAL threading (#4327) 2023-01-21 19:49:55 +00:00
gdkchan
6adf15e479 Implement CSET and CSETP shader instructions (#4318)
* Implement CSET and CSETP shader instructions

* Shader cache version bump

* Fix CC.HI
2023-01-21 12:18:05 -03:00
dependabot[bot]
2747f12591 nuget: bump System.IdentityModel.Tokens.Jwt from 6.25.1 to 6.26.0 (#4322)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.25.1 to 6.26.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/commits)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-21 05:24:57 +01:00
Ac_K
a47824f961 Ava UI: Add Notifications and Cleanup (#4275)
* Ava UI: Add Notifications and Cleanup

* Revert notifications on ErrorDialog

* remove unused code from game list views

* Fix cast
2023-01-21 02:57:37 +01:00
152 changed files with 1595 additions and 1284 deletions

3
.gitignore vendored
View File

@@ -170,3 +170,6 @@ launchSettings.json
# NetCore Publishing Profiles
PublishProfiles/
# Glade backup files
*.glade~

View File

@@ -16,4 +16,10 @@
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Ryujinx.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Project>

View File

@@ -1,5 +1,4 @@
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Numerics;
namespace ARMeilleure.CodeGen.Arm64
@@ -32,9 +31,12 @@ namespace ARMeilleure.CodeGen.Arm64
public static bool TryEncodeBitMask(Operand operand, out int immN, out int immS, out int immR)
{
ulong value = operand.Value;
return TryEncodeBitMask(operand.Type, operand.Value, out immN, out immS, out immR);
}
if (operand.Type == OperandType.I32)
public static bool TryEncodeBitMask(OperandType type, ulong value, out int immN, out int immS, out int immR)
{
if (type == OperandType.I32)
{
value |= value << 32;
}
@@ -50,7 +52,7 @@ namespace ARMeilleure.CodeGen.Arm64
// Any value AND all ones will be equal itself, so it's effectively a no-op.
// Any value OR all ones will be equal all ones, so one can just use MOV.
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
if (value == ulong.MaxValue)
if (value == 0 || value == ulong.MaxValue)
{
immN = 0;
immS = 0;
@@ -59,79 +61,18 @@ namespace ARMeilleure.CodeGen.Arm64
return false;
}
int bitLength = CountSequence(value);
// Normalize value, rotating it such that the LSB is 1: Ensures we get a complete element that has not
// been cut-in-half across the word boundary.
int rotation = BitOperations.TrailingZeroCount(value & (value + 1));
ulong rotatedValue = ulong.RotateRight(value, rotation);
if ((value >> bitLength) != 0)
{
bitLength += CountSequence(value >> bitLength);
}
// Now that we have a complete element in the LSB with the LSB = 1, determine size and number of ones
// in element.
int elementSize = BitOperations.TrailingZeroCount(rotatedValue & (rotatedValue + 1));
int onesInElement = BitOperations.TrailingZeroCount(~rotatedValue);
int bitLengthLog2 = BitOperations.Log2((uint)bitLength);
int bitLengthPow2 = 1 << bitLengthLog2;
if (bitLengthPow2 < bitLength)
{
bitLengthLog2++;
bitLengthPow2 <<= 1;
}
int selectedESize = 64;
int repetitions = 1;
int onesCount = BitOperations.PopCount(value);
if (bitLengthPow2 < 64 && (value >> bitLengthPow2) != 0)
{
for (int eSizeLog2 = bitLengthLog2; eSizeLog2 < 6; eSizeLog2++)
{
bool match = true;
int eSize = 1 << eSizeLog2;
ulong mask = (1UL << eSize) - 1;
ulong eValue = value & mask;
for (int e = 1; e < 64 / eSize; e++)
{
if (((value >> (e * eSize)) & mask) != eValue)
{
match = false;
break;
}
}
if (match)
{
selectedESize = eSize;
repetitions = 64 / eSize;
onesCount = BitOperations.PopCount(eValue);
break;
}
}
}
// Find rotation. We have two cases, one where the highest bit is 0
// and one where it is 1.
// If it's 1, we just need to count the number of 1 bits on the MSB to find the right rotation.
// If it's 0, we just need to count the number of 0 bits on the LSB to find the left rotation,
// then we can convert it to the right rotation shift by subtracting the value from the element size.
int rotation;
long vHigh = (long)(value << (64 - selectedESize));
if (vHigh < 0)
{
rotation = BitOperations.LeadingZeroCount(~(ulong)vHigh);
}
else
{
rotation = (selectedESize - BitOperations.TrailingZeroCount(value)) & (selectedESize - 1);
}
// Reconstruct value and see if it matches. If not, we can't encode.
ulong reconstructed = onesCount == 64 ? ulong.MaxValue : RotateRight((1UL << onesCount) - 1, rotation, selectedESize);
for (int bit = 32; bit >= selectedESize; bit >>= 1)
{
reconstructed |= reconstructed << bit;
}
if (reconstructed != value || onesCount == 0)
// Check the value is repeating; also ensures element size is a power of two.
if (ulong.RotateRight(value, elementSize) != value)
{
immN = 0;
immS = 0;
@@ -140,34 +81,11 @@ namespace ARMeilleure.CodeGen.Arm64
return false;
}
immR = rotation;
// immN indicates that there are no repetitions.
// The MSB of immS indicates the amount of repetitions, and the LSB the number of bits set.
if (repetitions == 1)
{
immN = 1;
immS = 0;
}
else
{
immN = 0;
immS = (0xf80 >> BitOperations.Log2((uint)repetitions)) & 0x3f;
}
immS |= onesCount - 1;
immN = (elementSize >> 6) & 1;
immS = (((~elementSize + 1) << 1) | (onesInElement - 1)) & 0x3f;
immR = (elementSize - rotation) & (elementSize - 1);
return true;
}
private static int CountSequence(ulong value)
{
return BitOperations.TrailingZeroCount(value) + BitOperations.TrailingZeroCount(~value);
}
private static ulong RotateRight(ulong bits, int shift, int size)
{
return (bits >> shift) | ((bits << (size - shift)) & (size == 64 ? ulong.MaxValue : (1UL << size) - 1));
}
}
}

View File

@@ -1303,7 +1303,15 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateConstantCopy(CodeGenContext context, Operand dest, ulong value)
{
if (value != 0)
if (value == 0)
{
context.Assembler.Mov(dest, Register(ZrRegister, dest.Type));
}
else if (CodeGenCommon.TryEncodeBitMask(dest.Type, value, out _, out _, out _))
{
context.Assembler.Orr(dest, Register(ZrRegister, dest.Type), Const(dest.Type, (long)value));
}
else
{
int hw = 0;
bool first = true;
@@ -1328,10 +1336,6 @@ namespace ARMeilleure.CodeGen.Arm64
value >>= 16;
}
}
else
{
context.Assembler.Mov(dest, Register(ZrRegister, dest.Type));
}
}
private static void GenerateAtomicCas(

View File

@@ -48,9 +48,21 @@ namespace ARMeilleure.CodeGen
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
public T Map<T>()
{
IntPtr codePtr = JitCache.Map(this);
return MapWithPointer<T>(out _);
}
return Marshal.GetDelegateForFunctionPointer<T>(codePtr);
/// <summary>
/// Maps the <see cref="CompiledFunction"/> onto the <see cref="JitCache"/> and returns a delegate of type
/// <typeparamref name="T"/> pointing to the mapped function.
/// </summary>
/// <typeparam name="T">Type of delegate</typeparam>
/// <param name="codePointer">Pointer to the function code in memory</param>
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
public T MapWithPointer<T>(out IntPtr codePointer)
{
codePointer = JitCache.Map(this);
return Marshal.GetDelegateForFunctionPointer<T>(codePointer);
}
}
}

View File

@@ -191,7 +191,7 @@ namespace ARMeilleure.Instructions
{
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
return (ulong)function.FuncPtr.ToInt64();
return (ulong)function.FuncPointer.ToInt64();
}
public static void InvalidateCacheLine(ulong address)

View File

@@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 4272; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 4328; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
@@ -745,9 +745,9 @@ namespace ARMeilleure.Translation.PTC
bool highCq)
{
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
var gFunc = cFunc.Map<GuestFunction>();
var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer);
return new TranslatedFunction(gFunc, callCounter, guestSize, highCq);
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
}
private void UpdateInfo(InfoEntry infoEntry)

View File

@@ -1,6 +1,5 @@
using ARMeilleure.Common;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Translation
{
@@ -8,18 +7,18 @@ namespace ARMeilleure.Translation
{
private readonly GuestFunction _func; // Ensure that this delegate will not be garbage collected.
public IntPtr FuncPointer { get; }
public Counter<uint> CallCounter { get; }
public ulong GuestSize { get; }
public bool HighCq { get; }
public IntPtr FuncPtr { get; }
public TranslatedFunction(GuestFunction func, Counter<uint> callCounter, ulong guestSize, bool highCq)
public TranslatedFunction(GuestFunction func, IntPtr funcPointer, Counter<uint> callCounter, ulong guestSize, bool highCq)
{
_func = func;
FuncPointer = funcPointer;
CallCounter = callCounter;
GuestSize = guestSize;
HighCq = highCq;
FuncPtr = Marshal.GetFunctionPointerForDelegate(func);
}
public ulong Execute(State.ExecutionContext context)

View File

@@ -211,7 +211,7 @@ namespace ARMeilleure.Translation
if (oldFunc != func)
{
JitCache.Unmap(func.FuncPtr);
JitCache.Unmap(func.FuncPointer);
func = oldFunc;
}
@@ -230,7 +230,7 @@ namespace ARMeilleure.Translation
{
if (FunctionTable.IsValid(guestAddress) && (Optimizations.AllowLcqInFunctionTable || func.HighCq))
{
Volatile.Write(ref FunctionTable.GetValue(guestAddress), (ulong)func.FuncPtr);
Volatile.Write(ref FunctionTable.GetValue(guestAddress), (ulong)func.FuncPointer);
}
}
@@ -292,11 +292,11 @@ namespace ARMeilleure.Translation
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
}
GuestFunction func = compiledFunc.Map<GuestFunction>();
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out IntPtr funcPointer);
Allocators.ResetAll();
return new TranslatedFunction(func, counter, funcSize, highCq);
return new TranslatedFunction(func, funcPointer, counter, funcSize, highCq);
}
private void BackgroundTranslate()
@@ -537,7 +537,7 @@ namespace ARMeilleure.Translation
foreach (var func in functions)
{
JitCache.Unmap(func.FuncPtr);
JitCache.Unmap(func.FuncPointer);
func.CallCounter?.Dispose();
}
@@ -546,7 +546,7 @@ namespace ARMeilleure.Translation
while (_oldFuncs.TryDequeue(out var kv))
{
JitCache.Unmap(kv.Value.FuncPtr);
JitCache.Unmap(kv.Value.FuncPointer);
kv.Value.CallCounter?.Dispose();
}

View File

@@ -20,7 +20,7 @@
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.2.0" />
<PackageVersion Include="LibHac" Version="0.17.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
@@ -44,7 +44,7 @@
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageVersion Include="SPB" Version="0.0.4-build28" />
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.25.1" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.26.0" />
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
<PackageVersion Include="System.Management" Version="7.0.0" />
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />

View File

@@ -231,7 +231,7 @@ namespace Ryujinx.Ava
}
}
private unsafe void Renderer_ScreenCaptured(object sender, ScreenCaptureImageInfo e)
private void Renderer_ScreenCaptured(object sender, ScreenCaptureImageInfo e)
{
if (e.Data.Length > 0 && e.Height > 0 && e.Width > 0)
{
@@ -240,7 +240,7 @@ namespace Ryujinx.Ava
lock (_lockObject)
{
DateTime currentTime = DateTime.Now;
string filename = $"ryujinx_capture_{currentTime}-{currentTime:D2}-{currentTime:D2}_{currentTime:D2}-{currentTime:D2}-{currentTime:D2}.png";
string filename = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png";
string directory = AppDataManager.Mode switch
{

View File

@@ -26,6 +26,9 @@
"MenuBarToolsInstallFirmware": "Install Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Install a firmware from XCI or ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Install a firmware from a directory",
"MenuBarToolsManageFileTypes": "Manage file types",
"MenuBarToolsInstallFileTypes": "Install file types",
"MenuBarToolsUninstallFileTypes": "Uninstall file types",
"MenuBarHelp": "Help",
"MenuBarHelpCheckForUpdates": "Check for Updates",
"MenuBarHelpAbout": "About",
@@ -339,6 +342,10 @@
"DialogFirmwareInstallEmbeddedSuccessMessage": "No installed firmware was found but Ryujinx was able to install firmware {0} from the provided game.\\nThe emulator will now start.",
"DialogFirmwareNoFirmwareInstalledMessage": "No Firmware Installed",
"DialogFirmwareInstalledMessage": "Firmware {0} was installed",
"DialogInstallFileTypesSuccessMessage": "Successfully installed file types!",
"DialogInstallFileTypesErrorMessage": "Failed to install file types.",
"DialogUninstallFileTypesSuccessMessage": "Successfully uninstalled file types!",
"DialogUninstallFileTypesErrorMessage": "Failed to uninstall file types.",
"DialogOpenSettingsWindowLabel": "Open Settings Window",
"DialogControllerAppletTitle": "Controller Applet",
"DialogMessageDialogErrorExceptionMessage": "Error displaying Message Dialog: {0}",
@@ -619,4 +626,4 @@
"UserProfilesRecoverEmptyList": "No profiles to recover",
"UserEditorTitle" : "Edit User",
"UserEditorTitleCreate" : "Create User"
}
}

View File

@@ -1,4 +1,5 @@
using Avalonia.Controls;
using Avalonia.Controls.Notifications;
using Avalonia.Threading;
using LibHac;
using LibHac.Account;
@@ -12,7 +13,6 @@ using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Logging;
@@ -44,14 +44,11 @@ namespace Ryujinx.Ava.Common
_accountManager = accountManager;
}
private static bool TryFindSaveData(string titleName, ulong titleId,
BlitStruct<ApplicationControlProperty> controlHolder, in SaveDataFilter filter, out ulong saveDataId)
private static bool TryFindSaveData(string titleName, ulong titleId, BlitStruct<ApplicationControlProperty> controlHolder, in SaveDataFilter filter, out ulong saveDataId)
{
saveDataId = default;
Result result = _horizonClient.Fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo,
SaveDataSpaceId.User, in filter);
Result result = _horizonClient.Fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, in filter);
if (ResultFs.TargetNotFound.Includes(result))
{
ref ApplicationControlProperty control = ref controlHolder.Value;
@@ -68,17 +65,15 @@ namespace Ryujinx.Ava.Common
control.UserAccountSaveDataSize = 0x4000;
control.UserAccountSaveDataJournalSize = 0x4000;
Logger.Warning?.Print(LogClass.Application,
"No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
Logger.Warning?.Print(LogClass.Application, "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
}
Uid user = new Uid((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
Uid user = new((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new LibHac.Ncm.ApplicationId(titleId), in control, in user);
if (result.IsFailure())
{
Dispatcher.UIThread.Post(async () =>
Dispatcher.UIThread.InvokeAsync(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageCreateSaveErrorMessage, result.ToStringWithName()));
});
@@ -97,7 +92,7 @@ namespace Ryujinx.Ava.Common
return true;
}
Dispatcher.UIThread.Post(async () =>
Dispatcher.UIThread.InvokeAsync(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageFindSaveErrorMessage, result.ToStringWithName()));
});
@@ -105,8 +100,7 @@ namespace Ryujinx.Ava.Common
return false;
}
public static void OpenSaveDir(in SaveDataFilter saveDataFilter, ulong titleId,
BlitStruct<ApplicationControlProperty> controlData, string titleName)
public static void OpenSaveDir(in SaveDataFilter saveDataFilter, ulong titleId, BlitStruct<ApplicationControlProperty> controlData, string titleName)
{
if (!TryFindSaveData(titleName, titleId, controlData, in saveDataFilter, out ulong saveDataId))
{
@@ -147,14 +141,15 @@ namespace Ryujinx.Ava.Common
}
}
public static async Task ExtractSection(NcaSectionType ncaSectionType, string titleFilePath,
int programIndex = 0)
public static async Task ExtractSection(NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0)
{
OpenFolderDialog folderDialog = new() { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] };
OpenFolderDialog folderDialog = new()
{
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
};
string destination = await folderDialog.ShowAsync(_owner);
var cancellationToken = new CancellationTokenSource();
string destination = await folderDialog.ShowAsync(_owner);
var cancellationToken = new CancellationTokenSource();
if (!string.IsNullOrWhiteSpace(destination))
{
@@ -174,133 +169,122 @@ namespace Ryujinx.Ava.Common
cancellationToken.Cancel();
}
});
using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read);
Thread.Sleep(1000);
Nca mainNca = null;
Nca patchNca = null;
using (FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read))
string extension = Path.GetExtension(titleFilePath).ToLower();
if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
{
Nca mainNca = null;
Nca patchNca = null;
PartitionFileSystem pfs;
string extension = Path.GetExtension(titleFilePath).ToLower();
if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
if (extension == ".xci")
{
PartitionFileSystem pfs;
pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure);
}
else
{
pfs = new PartitionFileSystem(file.AsStorage());
}
if (extension == ".xci")
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
{
using var ncaFile = new UniqueRef<IFile>();
pfs.OpenFile(ref ncaFile.Ref(), fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
if (nca.Header.ContentType == NcaContentType.Program)
{
Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage());
pfs = xci.OpenPartition(XciPartitionType.Secure);
}
else
{
pfs = new PartitionFileSystem(file.AsStorage());
}
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
{
using var ncaFile = new UniqueRef<IFile>();
pfs.OpenFile(ref ncaFile.Ref(), fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
if (nca.Header.ContentType == NcaContentType.Program)
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
{
int dataIndex =
Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.GetFsHeader(dataIndex).IsPatchSection())
{
patchNca = nca;
}
else
{
mainNca = nca;
}
patchNca = nca;
}
else
{
mainNca = nca;
}
}
}
else if (extension == ".nca")
{
mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage());
}
}
else if (extension == ".nca")
{
mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage());
}
if (mainNca == null)
if (mainNca == null)
{
Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file");
Dispatcher.UIThread.InvokeAsync(async () =>
{
Logger.Error?.Print(LogClass.Application,
"Extraction failure. The main NCA was not present in the selected file");
Dispatcher.UIThread.InvokeAsync(async () =>
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionMainNcaNotFoundErrorMessage]);
});
return;
}
(Nca updatePatchNca, _) = ApplicationLoader.GetGameUpdateData(_virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), programIndex, out _);
if (updatePatchNca != null)
{
patchNca = updatePatchNca;
}
int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType);
try
{
IFileSystem ncaFileSystem = patchNca != null
? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid)
: mainNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid);
FileSystemClient fsClient = _horizonClient.Fs;
string source = DateTime.Now.ToFileTime().ToString()[10..];
string output = DateTime.Now.ToFileTime().ToString()[10..];
using var uniqueSourceFs = new UniqueRef<IFileSystem>(ncaFileSystem);
using var uniqueOutputFs = new UniqueRef<IFileSystem>(new LocalFileSystem(destination));
fsClient.Register(source.ToU8Span(), ref uniqueSourceFs.Ref());
fsClient.Register(output.ToU8Span(), ref uniqueOutputFs.Ref());
(Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/", cancellationToken.Token);
if (!canceled)
{
if (resultCode.Value.IsFailure())
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionMainNcaNotFoundErrorMessage]);
});
return;
}
Logger.Error?.Print(LogClass.Application, $"LibHac returned error code: {resultCode.Value.ErrorCode}");
(Nca updatePatchNca, _) = ApplicationLoader.GetGameUpdateData(_virtualFileSystem,
mainNca.Header.TitleId.ToString("x16"), programIndex, out _);
if (updatePatchNca != null)
{
patchNca = updatePatchNca;
}
int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType);
try
{
IFileSystem ncaFileSystem = patchNca != null
? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid)
: mainNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid);
FileSystemClient fsClient = _horizonClient.Fs;
string source = DateTime.Now.ToFileTime().ToString()[10..];
string output = DateTime.Now.ToFileTime().ToString()[10..];
using var uniqueSourceFs = new UniqueRef<IFileSystem>(ncaFileSystem);
using var uniqueOutputFs = new UniqueRef<IFileSystem>(new LocalFileSystem(destination));
fsClient.Register(source.ToU8Span(), ref uniqueSourceFs.Ref());
fsClient.Register(output.ToU8Span(), ref uniqueOutputFs.Ref());
(Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/", cancellationToken.Token);
if (!canceled)
{
if (resultCode.Value.IsFailure())
Dispatcher.UIThread.InvokeAsync(async () =>
{
Logger.Error?.Print(LogClass.Application,
$"LibHac returned error code: {resultCode.Value.ErrorCode}");
Dispatcher.UIThread.InvokeAsync(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionCheckLogErrorMessage]);
});
}
else if (resultCode.Value.IsSuccess())
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
await ContentDialogHelper.CreateInfoDialog(
LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage],
"",
LocaleManager.Instance[LocaleKeys.InputDialogOk],
"",
LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle]);
});
}
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionCheckLogErrorMessage]);
});
}
fsClient.Unmount(source.ToU8Span());
fsClient.Unmount(output.ToU8Span());
}
catch (ArgumentException ex)
{
Dispatcher.UIThread.InvokeAsync(async () =>
else if (resultCode.Value.IsSuccess())
{
await ContentDialogHelper.CreateErrorDialog(ex.Message);
});
NotificationHelper.Show(
LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle],
$"{titleName}\n\n{LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage]}",
NotificationType.Information);
}
}
fsClient.Unmount(source.ToU8Span());
fsClient.Unmount(output.ToU8Span());
}
catch (ArgumentException ex)
{
Logger.Error?.Print(LogClass.Application, $"{ex.Message}");
Dispatcher.UIThread.InvokeAsync(async () =>
{
await ContentDialogHelper.CreateErrorDialog(ex.Message);
});
}
});

View File

@@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Input;
using System;
@@ -30,6 +31,7 @@ namespace Ryujinx.Ava.Input
_control.KeyDown += OnKeyPress;
_control.KeyUp += OnKeyRelease;
_control.TextInput += Control_TextInput;
_control.AddHandler(InputElement.TextInputEvent, Control_LastChanceTextInput, RoutingStrategies.Bubble);
}
private void Control_TextInput(object sender, TextInputEventArgs e)
@@ -37,6 +39,12 @@ namespace Ryujinx.Ava.Input
TextInput?.Invoke(this, e.Text);
}
private void Control_LastChanceTextInput(object sender, TextInputEventArgs e)
{
// Swallow event
e.Handled = true;
}
public event Action<string> OnGamepadConnected
{
add { }

View File

@@ -14,10 +14,8 @@ using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
namespace Ryujinx.Ava
@@ -35,48 +33,6 @@ namespace Ryujinx.Ava
private const uint MB_ICONWARNING = 0x30;
[SupportedOSPlatform("linux")]
static void RegisterMimeTypes()
{
if (ReleaseInformation.IsFlatHubBuild())
{
return;
}
string mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime");
if (!File.Exists(Path.Combine(mimeDbPath, "packages", "Ryujinx.xml")))
{
string mimeTypesFile = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "mime", "Ryujinx.xml");
using Process mimeProcess = new();
mimeProcess.StartInfo.FileName = "xdg-mime";
mimeProcess.StartInfo.Arguments = $"install --novendor --mode user {mimeTypesFile}";
mimeProcess.Start();
mimeProcess.WaitForExit();
if (mimeProcess.ExitCode != 0)
{
Logger.Error?.PrintMsg(LogClass.Application, $"Unable to install mime types. Make sure xdg-utils is installed. Process exited with code: {mimeProcess.ExitCode}");
return;
}
using Process updateMimeProcess = new();
updateMimeProcess.StartInfo.FileName = "update-mime-database";
updateMimeProcess.StartInfo.Arguments = mimeDbPath;
updateMimeProcess.Start();
updateMimeProcess.WaitForExit();
if (updateMimeProcess.ExitCode != 0)
{
Logger.Error?.PrintMsg(LogClass.Application, $"Could not update local mime database. Process exited with code: {updateMimeProcess.ExitCode}");
}
}
}
public static void Main(string[] args)
{
Version = ReleaseInformation.GetVersion();
@@ -139,12 +95,6 @@ namespace Ryujinx.Ava
// Initialize the logger system.
LoggerModule.Initialize();
// Register mime types on linux.
if (OperatingSystem.IsLinux())
{
RegisterMimeTypes();
}
// Initialize Discord integration.
DiscordIntegrationModule.Initialize();

View File

@@ -14,7 +14,7 @@
Focusable="True">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<MenuFlyout x:Key="GameContextMenu" Opened="MenuBase_OnMenuOpened">
<MenuFlyout x:Key="GameContextMenu">
<MenuItem
Command="{Binding ToggleFavorite}"
Header="{locale:Locale GameListContextMenuToggleFavorite}"
@@ -22,14 +22,17 @@
<Separator />
<MenuItem
Command="{Binding OpenUserSaveDirectory}"
IsEnabled="{Binding EnabledUserSaveDirectory}"
Header="{locale:Locale GameListContextMenuOpenUserSaveDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenUserSaveDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenDeviceSaveDirectory}"
IsEnabled="{Binding EnabledDeviceSaveDirectory}"
Header="{locale:Locale GameListContextMenuOpenDeviceSaveDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenDeviceSaveDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenBcatSaveDirectory}"
IsEnabled="{Binding EnabledBcatSaveDirectory}"
Header="{locale:Locale GameListContextMenuOpenBcatSaveDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenBcatSaveDirectoryToolTip}" />
<Separator />

View File

@@ -1,9 +1,7 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using LibHac.Common;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ui.App.Common;
@@ -13,16 +11,25 @@ namespace Ryujinx.Ava.UI.Controls
{
public partial class GameGridView : UserControl
{
private ApplicationData _selectedApplication;
public static readonly RoutedEvent<ApplicationOpenedEventArgs> ApplicationOpenedEvent =
RoutedEvent.Register<GameGridView, ApplicationOpenedEventArgs>(nameof(ApplicationOpened), RoutingStrategies.Bubble);
public event EventHandler<ApplicationOpenedEventArgs> ApplicationOpened
{
add { AddHandler(ApplicationOpenedEvent, value); }
add { AddHandler(ApplicationOpenedEvent, value); }
remove { RemoveHandler(ApplicationOpenedEvent, value); }
}
public GameGridView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public void GameList_DoubleTapped(object sender, RoutedEventArgs args)
{
if (sender is ListBox listBox)
@@ -38,46 +45,13 @@ namespace Ryujinx.Ava.UI.Controls
{
if (sender is ListBox listBox)
{
_selectedApplication = listBox.SelectedItem as ApplicationData;
(DataContext as MainWindowViewModel).GridSelectedApplication = _selectedApplication;
(DataContext as MainWindowViewModel).GridSelectedApplication = listBox.SelectedItem as ApplicationData;
}
}
public ApplicationData SelectedApplication => _selectedApplication;
public GameGridView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void SearchBox_OnKeyUp(object sender, KeyEventArgs e)
{
(DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text;
}
private void MenuBase_OnMenuOpened(object sender, EventArgs e)
{
var selection = SelectedApplication;
if (selection != null)
{
if (sender is ContextMenu menu)
{
bool canHaveUserSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.UserAccountSaveDataSize > 0;
bool canHaveDeviceSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.DeviceSaveDataSize > 0;
bool canHaveBcatSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
((menu.Items as AvaloniaList<object>)[2] as MenuItem).IsEnabled = canHaveUserSave;
((menu.Items as AvaloniaList<object>)[3] as MenuItem).IsEnabled = canHaveDeviceSave;
((menu.Items as AvaloniaList<object>)[4] as MenuItem).IsEnabled = canHaveBcatSave;
}
}
}
}
}

View File

@@ -13,7 +13,7 @@
mc:Ignorable="d">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<MenuFlyout x:Key="GameContextMenu" Opened="MenuBase_OnMenuOpened">
<MenuFlyout x:Key="GameContextMenu">
<MenuItem
Command="{Binding ToggleFavorite}"
Header="{locale:Locale GameListContextMenuToggleFavorite}"
@@ -21,14 +21,17 @@
<Separator />
<MenuItem
Command="{Binding OpenUserSaveDirectory}"
IsEnabled="{Binding EnabledUserSaveDirectory}"
Header="{locale:Locale GameListContextMenuOpenUserSaveDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenUserSaveDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenDeviceSaveDirectory}"
IsEnabled="{Binding EnabledDeviceSaveDirectory}"
Header="{locale:Locale GameListContextMenuOpenDeviceSaveDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenDeviceSaveDirectoryToolTip}" />
<MenuItem
Command="{Binding OpenBcatSaveDirectory}"
IsEnabled="{Binding EnabledBcatSaveDirectory}"
Header="{locale:Locale GameListContextMenuOpenBcatSaveDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenBcatSaveDirectoryToolTip}" />
<Separator />

View File

@@ -1,9 +1,7 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using LibHac.Common;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ui.App.Common;
@@ -13,16 +11,25 @@ namespace Ryujinx.Ava.UI.Controls
{
public partial class GameListView : UserControl
{
private ApplicationData _selectedApplication;
public static readonly RoutedEvent<ApplicationOpenedEventArgs> ApplicationOpenedEvent =
RoutedEvent.Register<GameGridView, ApplicationOpenedEventArgs>(nameof(ApplicationOpened), RoutingStrategies.Bubble);
public event EventHandler<ApplicationOpenedEventArgs> ApplicationOpened
{
add { AddHandler(ApplicationOpenedEvent, value); }
add { AddHandler(ApplicationOpenedEvent, value); }
remove { RemoveHandler(ApplicationOpenedEvent, value); }
}
public GameListView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public void GameList_DoubleTapped(object sender, RoutedEventArgs args)
{
if (sender is ListBox listBox)
@@ -38,46 +45,13 @@ namespace Ryujinx.Ava.UI.Controls
{
if (sender is ListBox listBox)
{
_selectedApplication = listBox.SelectedItem as ApplicationData;
(DataContext as MainWindowViewModel).ListSelectedApplication = _selectedApplication;
(DataContext as MainWindowViewModel).ListSelectedApplication = listBox.SelectedItem as ApplicationData;
}
}
public ApplicationData SelectedApplication => _selectedApplication;
public GameListView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void SearchBox_OnKeyUp(object sender, KeyEventArgs e)
{
(DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text;
}
private void MenuBase_OnMenuOpened(object sender, EventArgs e)
{
var selection = SelectedApplication;
if (selection != null)
{
if (sender is ContextMenu menu)
{
bool canHaveUserSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.UserAccountSaveDataSize > 0;
bool canHaveDeviceSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.DeviceSaveDataSize > 0;
bool canHaveBcatSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
((menu.Items as AvaloniaList<object>)[2] as MenuItem).IsEnabled = canHaveUserSave;
((menu.Items as AvaloniaList<object>)[3] as MenuItem).IsEnabled = canHaveDeviceSave;
((menu.Items as AvaloniaList<object>)[4] as MenuItem).IsEnabled = canHaveBcatSave;
}
}
}
}
}

View File

@@ -0,0 +1,65 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Notifications;
using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Helpers
{
public static class NotificationHelper
{
private const int MaxNotifications = 4;
private const int NotificationDelayInMs = 5000;
private static WindowNotificationManager _notificationManager;
private static readonly ManualResetEvent _templateAppliedEvent = new(false);
private static readonly BlockingCollection<Notification> _notifications = new();
public static void SetNotificationManager(Window host)
{
_notificationManager = new WindowNotificationManager(host)
{
Position = NotificationPosition.BottomRight,
MaxItems = MaxNotifications,
Margin = new Thickness(0, 0, 15, 40)
};
_notificationManager.TemplateApplied += (sender, args) =>
{
_templateAppliedEvent.Set();
};
Task.Run(async () =>
{
_templateAppliedEvent.WaitOne();
foreach (var notification in _notifications.GetConsumingEnumerable())
{
Dispatcher.UIThread.Post(() =>
{
_notificationManager.Show(notification);
});
await Task.Delay(NotificationDelayInMs / MaxNotifications);
}
});
}
public static void Show(string title, string text, NotificationType type, bool waitingExit = false, Action onClick = null, Action onClose = null)
{
var delay = waitingExit ? TimeSpan.FromMilliseconds(0) : TimeSpan.FromMilliseconds(NotificationDelayInMs);
_notifications.Add(new Notification(title, text, type, delay, onClick, onClose));
}
public static void ShowError(string message)
{
Show(LocaleManager.Instance[LocaleKeys.DialogErrorTitle], $"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}", NotificationType.Error);
}
}
}

View File

@@ -140,68 +140,75 @@ namespace Ryujinx.Ava.UI.Renderer
{
if (VisualRoot != null)
{
Point rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), VisualRoot).Value;
Pointer pointer = new(0, PointerType.Mouse, true);
switch (msg)
if (msg == WindowsMessages.LBUTTONDOWN ||
msg == WindowsMessages.RBUTTONDOWN ||
msg == WindowsMessages.LBUTTONUP ||
msg == WindowsMessages.RBUTTONUP ||
msg == WindowsMessages.MOUSEMOVE)
{
case WindowsMessages.LBUTTONDOWN:
case WindowsMessages.RBUTTONDOWN:
{
bool isLeft = msg == WindowsMessages.LBUTTONDOWN;
RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed);
Point rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), VisualRoot).Value;
Pointer pointer = new(0, PointerType.Mouse, true);
var evnt = new PointerPressedEventArgs(
this,
pointer,
VisualRoot,
rootVisualPosition,
(ulong)Environment.TickCount64,
properties,
KeyModifiers.None);
switch (msg)
{
case WindowsMessages.LBUTTONDOWN:
case WindowsMessages.RBUTTONDOWN:
{
bool isLeft = msg == WindowsMessages.LBUTTONDOWN;
RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed);
RaiseEvent(evnt);
var evnt = new PointerPressedEventArgs(
this,
pointer,
VisualRoot,
rootVisualPosition,
(ulong)Environment.TickCount64,
properties,
KeyModifiers.None);
break;
}
case WindowsMessages.LBUTTONUP:
case WindowsMessages.RBUTTONUP:
{
bool isLeft = msg == WindowsMessages.LBUTTONUP;
RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased);
RaiseEvent(evnt);
var evnt = new PointerReleasedEventArgs(
this,
pointer,
VisualRoot,
rootVisualPosition,
(ulong)Environment.TickCount64,
properties,
KeyModifiers.None,
isLeft ? MouseButton.Left : MouseButton.Right);
break;
}
case WindowsMessages.LBUTTONUP:
case WindowsMessages.RBUTTONUP:
{
bool isLeft = msg == WindowsMessages.LBUTTONUP;
RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased);
RaiseEvent(evnt);
var evnt = new PointerReleasedEventArgs(
this,
pointer,
VisualRoot,
rootVisualPosition,
(ulong)Environment.TickCount64,
properties,
KeyModifiers.None,
isLeft ? MouseButton.Left : MouseButton.Right);
break;
}
case WindowsMessages.MOUSEMOVE:
{
var evnt = new PointerEventArgs(
PointerMovedEvent,
this,
pointer,
VisualRoot,
rootVisualPosition,
(ulong)Environment.TickCount64,
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.Other),
KeyModifiers.None);
RaiseEvent(evnt);
RaiseEvent(evnt);
break;
}
case WindowsMessages.MOUSEMOVE:
{
var evnt = new PointerEventArgs(
PointerMovedEvent,
this,
pointer,
VisualRoot,
rootVisualPosition,
(ulong)Environment.TickCount64,
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.Other),
KeyModifiers.None);
break;
}
RaiseEvent(evnt);
break;
}
}
}
}

View File

@@ -5,7 +5,7 @@ using Avalonia.Media;
using Avalonia.Threading;
using DynamicData;
using DynamicData.Binding;
using LibHac.Bcat;
using LibHac.Common;
using LibHac.Fs;
using LibHac.FsSystem;
using LibHac.Tools.Fs;
@@ -344,6 +344,12 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public bool EnabledUserSaveDirectory => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
public bool EnabledDeviceSaveDirectory => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
public bool EnabledBcatSaveDirectory => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
public string LoadHeading
{
get => _loadHeading;
@@ -677,6 +683,11 @@ namespace Ryujinx.Ava.UI.ViewModels
get => ConsoleHelper.SetConsoleWindowStateSupported;
}
public bool ManageFileTypesVisible
{
get => FileAssociationHelper.IsTypeAssociationSupported;
}
public ObservableCollection<ApplicationData> Applications
{
get => _applications;
@@ -735,19 +746,14 @@ namespace Ryujinx.Ava.UI.ViewModels
{
get
{
switch (ConfigurationState.Instance.Ui.GridSize)
return ConfigurationState.Instance.Ui.GridSize.Value switch
{
case 1:
return 78;
case 2:
return 100;
case 3:
return 120;
case 4:
return 140;
default:
return 16;
}
1 => 78,
2 => 100,
3 => 120,
4 => 140,
_ => 16,
};
}
}
@@ -755,19 +761,14 @@ namespace Ryujinx.Ava.UI.ViewModels
{
get
{
switch (ConfigurationState.Instance.Ui.GridSize)
return ConfigurationState.Instance.Ui.GridSize.Value switch
{
case 1:
return 120;
case 2:
return ShowNames ? 210 : 150;
case 3:
return ShowNames ? 240 : 180;
case 4:
return ShowNames ? 280 : 220;
default:
return 16;
}
1 => 120,
2 => ShowNames ? 210 : 150,
3 => ShowNames ? 240 : 180,
4 => ShowNames ? 280 : 220,
_ => 16,
};
}
}
@@ -1091,35 +1092,27 @@ namespace Ryujinx.Ava.UI.ViewModels
}));
}
private void OpenSaveDirectory(in SaveDataFilter filter, ApplicationData data, ulong titleId)
{
ApplicationHelper.OpenSaveDir(in filter, titleId, data.ControlHolder, data.TitleName);
}
private async void ExtractLogo()
{
var selection = SelectedApplication;
if (selection != null)
if (SelectedApplication != null)
{
await ApplicationHelper.ExtractSection(NcaSectionType.Logo, selection.Path);
await ApplicationHelper.ExtractSection(NcaSectionType.Logo, SelectedApplication.Path, SelectedApplication.TitleName);
}
}
private async void ExtractRomFs()
{
var selection = SelectedApplication;
if (selection != null)
if (SelectedApplication != null)
{
await ApplicationHelper.ExtractSection(NcaSectionType.Data, selection.Path);
await ApplicationHelper.ExtractSection(NcaSectionType.Data, SelectedApplication.Path, SelectedApplication.TitleName);
}
}
private async void ExtractExeFs()
{
var selection = SelectedApplication;
if (selection != null)
if (SelectedApplication != null)
{
await ApplicationHelper.ExtractSection(NcaSectionType.Code, selection.Path);
await ApplicationHelper.ExtractSection(NcaSectionType.Code, SelectedApplication.Path, SelectedApplication.TitleName);
}
}
@@ -1487,56 +1480,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public void OpenDeviceSaveDirectory()
{
ApplicationData selection = SelectedApplication;
if (selection != null)
{
Task.Run(() =>
{
if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
{
async void Action()
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
}
Dispatcher.UIThread.Post(Action);
return;
}
var saveDataFilter = SaveDataFilter.Make(titleIdNumber, SaveDataType.Device, userId: default, saveDataId: default, index: default);
OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
});
}
}
public void OpenBcatSaveDirectory()
{
ApplicationData selection = SelectedApplication;
if (selection != null)
{
Task.Run(() =>
{
if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
{
async void Action()
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
}
Dispatcher.UIThread.Post(Action);
return;
}
var saveDataFilter = SaveDataFilter.Make(titleIdNumber, SaveDataType.Bcat, userId: default, saveDataId: default, index: default);
OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
});
}
}
public void ToggleFavorite()
{
ApplicationData selection = SelectedApplication;
@@ -1555,37 +1498,45 @@ namespace Ryujinx.Ava.UI.ViewModels
public void OpenUserSaveDirectory()
{
ApplicationData selection = SelectedApplication;
if (selection != null)
OpenSaveDirectory(SaveDataType.Account, userId: new UserId((ulong)AccountManager.LastOpenedUser.UserId.High, (ulong)AccountManager.LastOpenedUser.UserId.Low));
}
public void OpenDeviceSaveDirectory()
{
OpenSaveDirectory(SaveDataType.Device, userId: default);
}
public void OpenBcatSaveDirectory()
{
OpenSaveDirectory(SaveDataType.Bcat, userId: default);
}
private void OpenSaveDirectory(SaveDataType saveDataType, UserId userId)
{
if (SelectedApplication != null)
{
Task.Run(() =>
if (!ulong.TryParse(SelectedApplication.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
{
if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
Dispatcher.UIThread.InvokeAsync(async () =>
{
async void Action()
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
}
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
});
Dispatcher.UIThread.Post(Action);
return;
}
return;
}
var saveDataFilter = SaveDataFilter.Make(titleIdNumber, saveDataType, userId, saveDataId: default, index: default);
UserId userId = new((ulong)AccountManager.LastOpenedUser.UserId.High, (ulong)AccountManager.LastOpenedUser.UserId.Low);
SaveDataFilter saveDataFilter = SaveDataFilter.Make(titleIdNumber, saveType: default, userId, saveDataId: default, index: default);
OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
});
ApplicationHelper.OpenSaveDir(in saveDataFilter, titleIdNumber, SelectedApplication.ControlHolder, SelectedApplication.TitleName);
}
}
public void OpenModsDirectory()
{
ApplicationData selection = SelectedApplication;
if (selection != null)
if (SelectedApplication != null)
{
string modsBasePath = VirtualFileSystem.ModLoader.GetModsBasePath();
string titleModsPath = VirtualFileSystem.ModLoader.GetTitleDir(modsBasePath, selection.TitleId);
string titleModsPath = VirtualFileSystem.ModLoader.GetTitleDir(modsBasePath, SelectedApplication.TitleId);
OpenHelper.OpenFolder(titleModsPath);
}
@@ -1593,12 +1544,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public void OpenSdModsDirectory()
{
ApplicationData selection = SelectedApplication;
if (selection != null)
if (SelectedApplication != null)
{
string sdModsBasePath = VirtualFileSystem.ModLoader.GetSdModsBasePath();
string titleModsPath = VirtualFileSystem.ModLoader.GetTitleDir(sdModsBasePath, selection.TitleId);
string titleModsPath = VirtualFileSystem.ModLoader.GetTitleDir(sdModsBasePath, SelectedApplication.TitleId);
OpenHelper.OpenFolder(titleModsPath);
}
@@ -1614,25 +1563,17 @@ namespace Ryujinx.Ava.UI.ViewModels
public async void OpenDownloadableContentManager()
{
ApplicationData selection = SelectedApplication;
if (selection != null)
if (SelectedApplication != null)
{
if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
await new DownloadableContentManagerWindow(VirtualFileSystem, ulong.Parse(selection.TitleId, NumberStyles.HexNumber), selection.TitleName).ShowDialog(desktop.MainWindow);
}
await new DownloadableContentManagerWindow(VirtualFileSystem, ulong.Parse(SelectedApplication.TitleId, NumberStyles.HexNumber), SelectedApplication.TitleName).ShowDialog(TopLevel as Window);
}
}
public async void OpenCheatManager()
{
ApplicationData selection = SelectedApplication;
if (selection != null)
if (SelectedApplication != null)
{
if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
await new CheatWindow(VirtualFileSystem, selection.TitleId, selection.TitleName).ShowDialog(desktop.MainWindow);
}
await new CheatWindow(VirtualFileSystem, SelectedApplication.TitleId, SelectedApplication.TitleName).ShowDialog(TopLevel as Window);
}
}

View File

@@ -21,8 +21,9 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SpanHelpers = LibHac.Common.SpanHelpers;
using System.Text;
using Path = System.IO.Path;
using SpanHelpers = LibHac.Common.SpanHelpers;
namespace Ryujinx.Ava.UI.ViewModels;
@@ -90,6 +91,8 @@ public class TitleUpdateViewModel : BaseModel
Selected = "",
Paths = new List<string>()
};
Save();
}
LoadUpdates();
@@ -102,6 +105,9 @@ public class TitleUpdateViewModel : BaseModel
AddUpdate(path);
}
// NOTE: Save the list again to remove leftovers.
Save();
TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == _titleUpdateWindowData.Selected, null);
SelectedUpdate = selected;
@@ -223,4 +229,22 @@ public class TitleUpdateViewModel : BaseModel
SortUpdates();
}
public void Save()
{
_titleUpdateWindowData.Paths.Clear();
_titleUpdateWindowData.Selected = "";
foreach (TitleUpdateModel update in TitleUpdates)
{
_titleUpdateWindowData.Paths.Add(update.Path);
if (update == SelectedUpdate)
{
_titleUpdateWindowData.Selected = update.Path;
}
}
File.WriteAllBytes(_titleUpdateJsonPath, Encoding.UTF8.GetBytes(JsonHelper.Serialize(_titleUpdateWindowData, true)));
}
}

View File

@@ -77,8 +77,7 @@
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Name="ChangeLanguageMenuItem" Header="{locale:Locale MenuBarOptionsChangeLanguage}">
</MenuItem>
<MenuItem Name="ChangeLanguageMenuItem" Header="{locale:Locale MenuBarOptionsChangeLanguage}" />
<Separator />
<MenuItem
Click="OpenSettings"
@@ -141,6 +140,10 @@
<MenuItem Command="{ReflectionBinding InstallFirmwareFromFile}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromFile}" />
<MenuItem Command="{ReflectionBinding InstallFirmwareFromFolder}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" />
</MenuItem>
<MenuItem Header="{locale:Locale MenuBarToolsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}">
<MenuItem Header="{locale:Locale MenuBarToolsInstallFileTypes}" Click="InstallFileTypes_Click"/>
<MenuItem Header="{locale:Locale MenuBarToolsUninstallFileTypes}" Click="UninstallFileTypes_Click"/>
</MenuItem>
</MenuItem>
<MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarHelp}">
<MenuItem
@@ -157,4 +160,4 @@
</MenuItem>
</Menu>
</DockPanel>
</UserControl>
</UserControl>

View File

@@ -3,6 +3,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using LibHac.FsSystem;
using LibHac.Ncm;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
@@ -10,6 +11,7 @@ using Ryujinx.Common;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS;
using Ryujinx.Modules;
using Ryujinx.Ui.Common.Helper;
using System;
using System.Collections.Generic;
using System.IO;
@@ -163,6 +165,32 @@ namespace Ryujinx.Ava.UI.Views.Main
}
}
private async void InstallFileTypes_Click(object sender, RoutedEventArgs e)
{
if (FileAssociationHelper.Install())
{
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage],
string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
}
else
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesErrorMessage]);
}
}
private async void UninstallFileTypes_Click(object sender, RoutedEventArgs e)
{
if (FileAssociationHelper.Uninstall())
{
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage],
string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
}
else
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesErrorMessage]);
}
}
public async void CheckForUpdates(object sender, RoutedEventArgs e)
{
if (Updater.CanUpdate(true))

View File

@@ -104,6 +104,8 @@ namespace Ryujinx.Ava.UI.Windows
ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
ViewModel.ReloadGameList += ReloadGameList;
NotificationHelper.SetNotificationManager(this);
}
private void IsActiveChanged(bool obj)

View File

@@ -60,24 +60,7 @@ namespace Ryujinx.Ava.UI.Windows
public void Save(object sender, RoutedEventArgs e)
{
ViewModel._titleUpdateWindowData.Paths.Clear();
ViewModel._titleUpdateWindowData.Selected = "";
foreach (TitleUpdateModel update in ViewModel.TitleUpdates)
{
ViewModel._titleUpdateWindowData.Paths.Add(update.Path);
if (update == ViewModel.SelectedUpdate)
{
ViewModel._titleUpdateWindowData.Selected = update.Path;
}
}
using (FileStream titleUpdateJsonStream = File.Create(ViewModel._titleUpdateJsonPath, 4096, FileOptions.WriteThrough))
{
titleUpdateJsonStream.Write(Encoding.UTF8.GetBytes(JsonHelper.Serialize(ViewModel._titleUpdateWindowData, true)));
}
ViewModel.Save();
if (VisualRoot is MainWindow window)
{

View File

@@ -7,9 +7,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Commands.Sampler;
using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
using Ryujinx.Graphics.GAL.Multithreading.Commands.Window;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -30,207 +28,115 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public static int GetMaxCommandSize()
{
Assembly assembly = typeof(CommandHelper).Assembly;
IEnumerable<Type> commands = assembly.GetTypes().Where(type => typeof(IGALCommand).IsAssignableFrom(type) && type.IsValueType);
int maxSize = commands.Max(command =>
{
MethodInfo method = typeof(Unsafe).GetMethod(nameof(Unsafe.SizeOf));
MethodInfo generic = method.MakeGenericMethod(command);
int size = (int)generic.Invoke(null, null);
return size;
});
InitLookup();
return maxSize + 1; // 1 byte reserved for command size.
return InitLookup() + 1; // 1 byte reserved for command size.
}
private static void InitLookup()
private static int InitLookup()
{
_lookup[(int)CommandType.Action] = (memory, threaded, renderer) =>
ActionCommand.Run(ref GetCommand<ActionCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CreateBuffer] = (memory, threaded, renderer) =>
CreateBufferCommand.Run(ref GetCommand<CreateBufferCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CreateProgram] = (memory, threaded, renderer) =>
CreateProgramCommand.Run(ref GetCommand<CreateProgramCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CreateSampler] = (memory, threaded, renderer) =>
CreateSamplerCommand.Run(ref GetCommand<CreateSamplerCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CreateSync] = (memory, threaded, renderer) =>
CreateSyncCommand.Run(ref GetCommand<CreateSyncCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CreateTexture] = (memory, threaded, renderer) =>
CreateTextureCommand.Run(ref GetCommand<CreateTextureCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.GetCapabilities] = (memory, threaded, renderer) =>
GetCapabilitiesCommand.Run(ref GetCommand<GetCapabilitiesCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.PreFrame] = (memory, threaded, renderer) =>
PreFrameCommand.Run(ref GetCommand<PreFrameCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.ReportCounter] = (memory, threaded, renderer) =>
ReportCounterCommand.Run(ref GetCommand<ReportCounterCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.ResetCounter] = (memory, threaded, renderer) =>
ResetCounterCommand.Run(ref GetCommand<ResetCounterCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.UpdateCounters] = (memory, threaded, renderer) =>
UpdateCountersCommand.Run(ref GetCommand<UpdateCountersCommand>(memory), threaded, renderer);
int maxCommandSize = 0;
_lookup[(int)CommandType.BufferDispose] = (memory, threaded, renderer) =>
BufferDisposeCommand.Run(ref GetCommand<BufferDisposeCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.BufferGetData] = (memory, threaded, renderer) =>
BufferGetDataCommand.Run(ref GetCommand<BufferGetDataCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.BufferSetData] = (memory, threaded, renderer) =>
BufferSetDataCommand.Run(ref GetCommand<BufferSetDataCommand>(memory), threaded, renderer);
void Register<T>(CommandType commandType) where T : unmanaged, IGALCommand, IGALCommand<T>
{
maxCommandSize = Math.Max(maxCommandSize, Unsafe.SizeOf<T>());
_lookup[(int)commandType] = (memory, threaded, renderer) => T.Run(ref GetCommand<T>(memory), threaded, renderer);
}
_lookup[(int)CommandType.CounterEventDispose] = (memory, threaded, renderer) =>
CounterEventDisposeCommand.Run(ref GetCommand<CounterEventDisposeCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CounterEventFlush] = (memory, threaded, renderer) =>
CounterEventFlushCommand.Run(ref GetCommand<CounterEventFlushCommand>(memory), threaded, renderer);
Register<ActionCommand>(CommandType.Action);
Register<CreateBufferCommand>(CommandType.CreateBuffer);
Register<CreateProgramCommand>(CommandType.CreateProgram);
Register<CreateSamplerCommand>(CommandType.CreateSampler);
Register<CreateSyncCommand>(CommandType.CreateSync);
Register<CreateTextureCommand>(CommandType.CreateTexture);
Register<GetCapabilitiesCommand>(CommandType.GetCapabilities);
Register<PreFrameCommand>(CommandType.PreFrame);
Register<ReportCounterCommand>(CommandType.ReportCounter);
Register<ResetCounterCommand>(CommandType.ResetCounter);
Register<UpdateCountersCommand>(CommandType.UpdateCounters);
_lookup[(int)CommandType.ProgramDispose] = (memory, threaded, renderer) =>
ProgramDisposeCommand.Run(ref GetCommand<ProgramDisposeCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.ProgramGetBinary] = (memory, threaded, renderer) =>
ProgramGetBinaryCommand.Run(ref GetCommand<ProgramGetBinaryCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.ProgramCheckLink] = (memory, threaded, renderer) =>
ProgramCheckLinkCommand.Run(ref GetCommand<ProgramCheckLinkCommand>(memory), threaded, renderer);
Register<BufferDisposeCommand>(CommandType.BufferDispose);
Register<BufferGetDataCommand>(CommandType.BufferGetData);
Register<BufferSetDataCommand>(CommandType.BufferSetData);
_lookup[(int)CommandType.SamplerDispose] = (memory, threaded, renderer) =>
SamplerDisposeCommand.Run(ref GetCommand<SamplerDisposeCommand>(memory), threaded, renderer);
Register<CounterEventDisposeCommand>(CommandType.CounterEventDispose);
Register<CounterEventFlushCommand>(CommandType.CounterEventFlush);
_lookup[(int)CommandType.TextureCopyTo] = (memory, threaded, renderer) =>
TextureCopyToCommand.Run(ref GetCommand<TextureCopyToCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureCopyToScaled] = (memory, threaded, renderer) =>
TextureCopyToScaledCommand.Run(ref GetCommand<TextureCopyToScaledCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureCopyToSlice] = (memory, threaded, renderer) =>
TextureCopyToSliceCommand.Run(ref GetCommand<TextureCopyToSliceCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureCreateView] = (memory, threaded, renderer) =>
TextureCreateViewCommand.Run(ref GetCommand<TextureCreateViewCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureGetData] = (memory, threaded, renderer) =>
TextureGetDataCommand.Run(ref GetCommand<TextureGetDataCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureGetDataSlice] = (memory, threaded, renderer) =>
TextureGetDataSliceCommand.Run(ref GetCommand<TextureGetDataSliceCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureRelease] = (memory, threaded, renderer) =>
TextureReleaseCommand.Run(ref GetCommand<TextureReleaseCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureSetData] = (memory, threaded, renderer) =>
TextureSetDataCommand.Run(ref GetCommand<TextureSetDataCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureSetDataSlice] = (memory, threaded, renderer) =>
TextureSetDataSliceCommand.Run(ref GetCommand<TextureSetDataSliceCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureSetDataSliceRegion] = (memory, threaded, renderer) =>
TextureSetDataSliceRegionCommand.Run(ref GetCommand<TextureSetDataSliceRegionCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureSetStorage] = (memory, threaded, renderer) =>
TextureSetStorageCommand.Run(ref GetCommand<TextureSetStorageCommand>(memory), threaded, renderer);
Register<ProgramDisposeCommand>(CommandType.ProgramDispose);
Register<ProgramGetBinaryCommand>(CommandType.ProgramGetBinary);
Register<ProgramCheckLinkCommand>(CommandType.ProgramCheckLink);
_lookup[(int)CommandType.WindowPresent] = (memory, threaded, renderer) =>
WindowPresentCommand.Run(ref GetCommand<WindowPresentCommand>(memory), threaded, renderer);
Register<SamplerDisposeCommand>(CommandType.SamplerDispose);
_lookup[(int)CommandType.Barrier] = (memory, threaded, renderer) =>
BarrierCommand.Run(ref GetCommand<BarrierCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.BeginTransformFeedback] = (memory, threaded, renderer) =>
BeginTransformFeedbackCommand.Run(ref GetCommand<BeginTransformFeedbackCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.ClearBuffer] = (memory, threaded, renderer) =>
ClearBufferCommand.Run(ref GetCommand<ClearBufferCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.ClearRenderTargetColor] = (memory, threaded, renderer) =>
ClearRenderTargetColorCommand.Run(ref GetCommand<ClearRenderTargetColorCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.ClearRenderTargetDepthStencil] = (memory, threaded, renderer) =>
ClearRenderTargetDepthStencilCommand.Run(ref GetCommand<ClearRenderTargetDepthStencilCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CommandBufferBarrier] = (memory, threaded, renderer) =>
CommandBufferBarrierCommand.Run(ref GetCommand<CommandBufferBarrierCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.CopyBuffer] = (memory, threaded, renderer) =>
CopyBufferCommand.Run(ref GetCommand<CopyBufferCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.DispatchCompute] = (memory, threaded, renderer) =>
DispatchComputeCommand.Run(ref GetCommand<DispatchComputeCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.Draw] = (memory, threaded, renderer) =>
DrawCommand.Run(ref GetCommand<DrawCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.DrawIndexed] = (memory, threaded, renderer) =>
DrawIndexedCommand.Run(ref GetCommand<DrawIndexedCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.DrawIndexedIndirect] = (memory, threaded, renderer) =>
DrawIndexedIndirectCommand.Run(ref GetCommand<DrawIndexedIndirectCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.DrawIndexedIndirectCount] = (memory, threaded, renderer) =>
DrawIndexedIndirectCountCommand.Run(ref GetCommand<DrawIndexedIndirectCountCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.DrawIndirect] = (memory, threaded, renderer) =>
DrawIndirectCommand.Run(ref GetCommand<DrawIndirectCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.DrawIndirectCount] = (memory, threaded, renderer) =>
DrawIndirectCountCommand.Run(ref GetCommand<DrawIndirectCountCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.DrawTexture] = (memory, threaded, renderer) =>
DrawTextureCommand.Run(ref GetCommand<DrawTextureCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.EndHostConditionalRendering] = (memory, threaded, renderer) =>
EndHostConditionalRenderingCommand.Run(renderer);
_lookup[(int)CommandType.EndTransformFeedback] = (memory, threaded, renderer) =>
EndTransformFeedbackCommand.Run(ref GetCommand<EndTransformFeedbackCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetAlphaTest] = (memory, threaded, renderer) =>
SetAlphaTestCommand.Run(ref GetCommand<SetAlphaTestCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetBlendState] = (memory, threaded, renderer) =>
SetBlendStateCommand.Run(ref GetCommand<SetBlendStateCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetDepthBias] = (memory, threaded, renderer) =>
SetDepthBiasCommand.Run(ref GetCommand<SetDepthBiasCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetDepthClamp] = (memory, threaded, renderer) =>
SetDepthClampCommand.Run(ref GetCommand<SetDepthClampCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetDepthMode] = (memory, threaded, renderer) =>
SetDepthModeCommand.Run(ref GetCommand<SetDepthModeCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetDepthTest] = (memory, threaded, renderer) =>
SetDepthTestCommand.Run(ref GetCommand<SetDepthTestCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetFaceCulling] = (memory, threaded, renderer) =>
SetFaceCullingCommand.Run(ref GetCommand<SetFaceCullingCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetFrontFace] = (memory, threaded, renderer) =>
SetFrontFaceCommand.Run(ref GetCommand<SetFrontFaceCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetStorageBuffers] = (memory, threaded, renderer) =>
SetStorageBuffersCommand.Run(ref GetCommand<SetStorageBuffersCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetTransformFeedbackBuffers] = (memory, threaded, renderer) =>
SetTransformFeedbackBuffersCommand.Run(ref GetCommand<SetTransformFeedbackBuffersCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetUniformBuffers] = (memory, threaded, renderer) =>
SetUniformBuffersCommand.Run(ref GetCommand<SetUniformBuffersCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetImage] = (memory, threaded, renderer) =>
SetImageCommand.Run(ref GetCommand<SetImageCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetIndexBuffer] = (memory, threaded, renderer) =>
SetIndexBufferCommand.Run(ref GetCommand<SetIndexBufferCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetLineParameters] = (memory, threaded, renderer) =>
SetLineParametersCommand.Run(ref GetCommand<SetLineParametersCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetLogicOpState] = (memory, threaded, renderer) =>
SetLogicOpStateCommand.Run(ref GetCommand<SetLogicOpStateCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetMultisampleState] = (memory, threaded, renderer) =>
SetMultisampleStateCommand.Run(ref GetCommand<SetMultisampleStateCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetPatchParameters] = (memory, threaded, renderer) =>
SetPatchParametersCommand.Run(ref GetCommand<SetPatchParametersCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetPointParameters] = (memory, threaded, renderer) =>
SetPointParametersCommand.Run(ref GetCommand<SetPointParametersCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetPolygonMode] = (memory, threaded, renderer) =>
SetPolygonModeCommand.Run(ref GetCommand<SetPolygonModeCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetPrimitiveRestart] = (memory, threaded, renderer) =>
SetPrimitiveRestartCommand.Run(ref GetCommand<SetPrimitiveRestartCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetPrimitiveTopology] = (memory, threaded, renderer) =>
SetPrimitiveTopologyCommand.Run(ref GetCommand<SetPrimitiveTopologyCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetProgram] = (memory, threaded, renderer) =>
SetProgramCommand.Run(ref GetCommand<SetProgramCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetRasterizerDiscard] = (memory, threaded, renderer) =>
SetRasterizerDiscardCommand.Run(ref GetCommand<SetRasterizerDiscardCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetRenderTargetColorMasks] = (memory, threaded, renderer) =>
SetRenderTargetColorMasksCommand.Run(ref GetCommand<SetRenderTargetColorMasksCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetRenderTargetScale] = (memory, threaded, renderer) =>
SetRenderTargetScaleCommand.Run(ref GetCommand<SetRenderTargetScaleCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetRenderTargets] = (memory, threaded, renderer) =>
SetRenderTargetsCommand.Run(ref GetCommand<SetRenderTargetsCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetScissor] = (memory, threaded, renderer) =>
SetScissorsCommand.Run(ref GetCommand<SetScissorsCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetStencilTest] = (memory, threaded, renderer) =>
SetStencilTestCommand.Run(ref GetCommand<SetStencilTestCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetTextureAndSampler] = (memory, threaded, renderer) =>
SetTextureAndSamplerCommand.Run(ref GetCommand<SetTextureAndSamplerCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetUserClipDistance] = (memory, threaded, renderer) =>
SetUserClipDistanceCommand.Run(ref GetCommand<SetUserClipDistanceCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetVertexAttribs] = (memory, threaded, renderer) =>
SetVertexAttribsCommand.Run(ref GetCommand<SetVertexAttribsCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetVertexBuffers] = (memory, threaded, renderer) =>
SetVertexBuffersCommand.Run(ref GetCommand<SetVertexBuffersCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.SetViewports] = (memory, threaded, renderer) =>
SetViewportsCommand.Run(ref GetCommand<SetViewportsCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureBarrier] = (memory, threaded, renderer) =>
TextureBarrierCommand.Run(ref GetCommand<TextureBarrierCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TextureBarrierTiled] = (memory, threaded, renderer) =>
TextureBarrierTiledCommand.Run(ref GetCommand<TextureBarrierTiledCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TryHostConditionalRendering] = (memory, threaded, renderer) =>
TryHostConditionalRenderingCommand.Run(ref GetCommand<TryHostConditionalRenderingCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.TryHostConditionalRenderingFlush] = (memory, threaded, renderer) =>
TryHostConditionalRenderingFlushCommand.Run(ref GetCommand<TryHostConditionalRenderingFlushCommand>(memory), threaded, renderer);
_lookup[(int)CommandType.UpdateRenderScale] = (memory, threaded, renderer) =>
UpdateRenderScaleCommand.Run(ref GetCommand<UpdateRenderScaleCommand>(memory), threaded, renderer);
Register<TextureCopyToCommand>(CommandType.TextureCopyTo);
Register<TextureCopyToScaledCommand>(CommandType.TextureCopyToScaled);
Register<TextureCopyToSliceCommand>(CommandType.TextureCopyToSlice);
Register<TextureCreateViewCommand>(CommandType.TextureCreateView);
Register<TextureGetDataCommand>(CommandType.TextureGetData);
Register<TextureGetDataSliceCommand>(CommandType.TextureGetDataSlice);
Register<TextureReleaseCommand>(CommandType.TextureRelease);
Register<TextureSetDataCommand>(CommandType.TextureSetData);
Register<TextureSetDataSliceCommand>(CommandType.TextureSetDataSlice);
Register<TextureSetDataSliceRegionCommand>(CommandType.TextureSetDataSliceRegion);
Register<TextureSetStorageCommand>(CommandType.TextureSetStorage);
Register<WindowPresentCommand>(CommandType.WindowPresent);
Register<BarrierCommand>(CommandType.Barrier);
Register<BeginTransformFeedbackCommand>(CommandType.BeginTransformFeedback);
Register<ClearBufferCommand>(CommandType.ClearBuffer);
Register<ClearRenderTargetColorCommand>(CommandType.ClearRenderTargetColor);
Register<ClearRenderTargetDepthStencilCommand>(CommandType.ClearRenderTargetDepthStencil);
Register<CommandBufferBarrierCommand>(CommandType.CommandBufferBarrier);
Register<CopyBufferCommand>(CommandType.CopyBuffer);
Register<DispatchComputeCommand>(CommandType.DispatchCompute);
Register<DrawCommand>(CommandType.Draw);
Register<DrawIndexedCommand>(CommandType.DrawIndexed);
Register<DrawIndexedIndirectCommand>(CommandType.DrawIndexedIndirect);
Register<DrawIndexedIndirectCountCommand>(CommandType.DrawIndexedIndirectCount);
Register<DrawIndirectCommand>(CommandType.DrawIndirect);
Register<DrawIndirectCountCommand>(CommandType.DrawIndirectCount);
Register<DrawTextureCommand>(CommandType.DrawTexture);
Register<EndHostConditionalRenderingCommand>(CommandType.EndHostConditionalRendering);
Register<EndTransformFeedbackCommand>(CommandType.EndTransformFeedback);
Register<SetAlphaTestCommand>(CommandType.SetAlphaTest);
Register<SetBlendStateCommand>(CommandType.SetBlendState);
Register<SetDepthBiasCommand>(CommandType.SetDepthBias);
Register<SetDepthClampCommand>(CommandType.SetDepthClamp);
Register<SetDepthModeCommand>(CommandType.SetDepthMode);
Register<SetDepthTestCommand>(CommandType.SetDepthTest);
Register<SetFaceCullingCommand>(CommandType.SetFaceCulling);
Register<SetFrontFaceCommand>(CommandType.SetFrontFace);
Register<SetStorageBuffersCommand>(CommandType.SetStorageBuffers);
Register<SetTransformFeedbackBuffersCommand>(CommandType.SetTransformFeedbackBuffers);
Register<SetUniformBuffersCommand>(CommandType.SetUniformBuffers);
Register<SetImageCommand>(CommandType.SetImage);
Register<SetIndexBufferCommand>(CommandType.SetIndexBuffer);
Register<SetLineParametersCommand>(CommandType.SetLineParameters);
Register<SetLogicOpStateCommand>(CommandType.SetLogicOpState);
Register<SetMultisampleStateCommand>(CommandType.SetMultisampleState);
Register<SetPatchParametersCommand>(CommandType.SetPatchParameters);
Register<SetPointParametersCommand>(CommandType.SetPointParameters);
Register<SetPolygonModeCommand>(CommandType.SetPolygonMode);
Register<SetPrimitiveRestartCommand>(CommandType.SetPrimitiveRestart);
Register<SetPrimitiveTopologyCommand>(CommandType.SetPrimitiveTopology);
Register<SetProgramCommand>(CommandType.SetProgram);
Register<SetRasterizerDiscardCommand>(CommandType.SetRasterizerDiscard);
Register<SetRenderTargetColorMasksCommand>(CommandType.SetRenderTargetColorMasks);
Register<SetRenderTargetScaleCommand>(CommandType.SetRenderTargetScale);
Register<SetRenderTargetsCommand>(CommandType.SetRenderTargets);
Register<SetScissorsCommand>(CommandType.SetScissor);
Register<SetStencilTestCommand>(CommandType.SetStencilTest);
Register<SetTextureAndSamplerCommand>(CommandType.SetTextureAndSampler);
Register<SetUserClipDistanceCommand>(CommandType.SetUserClipDistance);
Register<SetVertexAttribsCommand>(CommandType.SetVertexAttribs);
Register<SetVertexBuffersCommand>(CommandType.SetVertexBuffers);
Register<SetViewportsCommand>(CommandType.SetViewports);
Register<TextureBarrierCommand>(CommandType.TextureBarrier);
Register<TextureBarrierTiledCommand>(CommandType.TextureBarrierTiled);
Register<TryHostConditionalRenderingCommand>(CommandType.TryHostConditionalRendering);
Register<TryHostConditionalRenderingFlushCommand>(CommandType.TryHostConditionalRenderingFlush);
Register<UpdateRenderScaleCommand>(CommandType.UpdateRenderScale);
return maxCommandSize;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct BarrierCommand : IGALCommand
struct BarrierCommand : IGALCommand, IGALCommand<BarrierCommand>
{
public CommandType CommandType => CommandType.Barrier;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct BeginTransformFeedbackCommand : IGALCommand
struct BeginTransformFeedbackCommand : IGALCommand, IGALCommand<BeginTransformFeedbackCommand>
{
public CommandType CommandType => CommandType.BeginTransformFeedback;
private PrimitiveTopology _topology;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
{
struct BufferDisposeCommand : IGALCommand
struct BufferDisposeCommand : IGALCommand, IGALCommand<BufferDisposeCommand>
{
public CommandType CommandType => CommandType.BufferDispose;
private BufferHandle _buffer;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
{
struct BufferGetDataCommand : IGALCommand
struct BufferGetDataCommand : IGALCommand, IGALCommand<BufferGetDataCommand>
{
public CommandType CommandType => CommandType.BufferGetData;
private BufferHandle _buffer;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
{
struct BufferSetDataCommand : IGALCommand
struct BufferSetDataCommand : IGALCommand, IGALCommand<BufferSetDataCommand>
{
public CommandType CommandType => CommandType.BufferSetData;
private BufferHandle _buffer;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct ClearBufferCommand : IGALCommand
struct ClearBufferCommand : IGALCommand, IGALCommand<ClearBufferCommand>
{
public CommandType CommandType => CommandType.ClearBuffer;
private BufferHandle _destination;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct ClearRenderTargetColorCommand : IGALCommand
struct ClearRenderTargetColorCommand : IGALCommand, IGALCommand<ClearRenderTargetColorCommand>
{
public CommandType CommandType => CommandType.ClearRenderTargetColor;
private int _index;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct ClearRenderTargetDepthStencilCommand : IGALCommand
struct ClearRenderTargetDepthStencilCommand : IGALCommand, IGALCommand<ClearRenderTargetDepthStencilCommand>
{
public CommandType CommandType => CommandType.ClearRenderTargetDepthStencil;
private int _layer;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct CommandBufferBarrierCommand : IGALCommand
struct CommandBufferBarrierCommand : IGALCommand, IGALCommand<CommandBufferBarrierCommand>
{
public CommandType CommandType => CommandType.CommandBufferBarrier;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct CopyBufferCommand : IGALCommand
struct CopyBufferCommand : IGALCommand, IGALCommand<CopyBufferCommand>
{
public CommandType CommandType => CommandType.CopyBuffer;
private BufferHandle _source;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.CounterEvent
{
struct CounterEventDisposeCommand : IGALCommand
struct CounterEventDisposeCommand : IGALCommand, IGALCommand<CounterEventDisposeCommand>
{
public CommandType CommandType => CommandType.CounterEventDispose;
private TableRef<ThreadedCounterEvent> _event;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.CounterEvent
{
struct CounterEventFlushCommand : IGALCommand
struct CounterEventFlushCommand : IGALCommand, IGALCommand<CounterEventFlushCommand>
{
public CommandType CommandType => CommandType.CounterEventFlush;
private TableRef<ThreadedCounterEvent> _event;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DispatchComputeCommand : IGALCommand
struct DispatchComputeCommand : IGALCommand, IGALCommand<DispatchComputeCommand>
{
public CommandType CommandType => CommandType.DispatchCompute;
private int _groupsX;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DrawIndexedCommand : IGALCommand
struct DrawIndexedCommand : IGALCommand, IGALCommand<DrawIndexedCommand>
{
public CommandType CommandType => CommandType.DrawIndexed;
private int _indexCount;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DrawCommand : IGALCommand
struct DrawCommand : IGALCommand, IGALCommand<DrawCommand>
{
public CommandType CommandType => CommandType.Draw;
private int _vertexCount;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DrawIndexedIndirectCommand : IGALCommand
struct DrawIndexedIndirectCommand : IGALCommand, IGALCommand<DrawIndexedIndirectCommand>
{
public CommandType CommandType => CommandType.DrawIndexedIndirect;
private BufferRange _indirectBuffer;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DrawIndexedIndirectCountCommand : IGALCommand
struct DrawIndexedIndirectCountCommand : IGALCommand, IGALCommand<DrawIndexedIndirectCountCommand>
{
public CommandType CommandType => CommandType.DrawIndexedIndirectCount;
private BufferRange _indirectBuffer;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DrawIndirectCommand : IGALCommand
struct DrawIndirectCommand : IGALCommand, IGALCommand<DrawIndirectCommand>
{
public CommandType CommandType => CommandType.DrawIndirect;
private BufferRange _indirectBuffer;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DrawIndirectCountCommand : IGALCommand
struct DrawIndirectCountCommand : IGALCommand, IGALCommand<DrawIndirectCountCommand>
{
public CommandType CommandType => CommandType.DrawIndirectCount;
private BufferRange _indirectBuffer;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct DrawTextureCommand : IGALCommand
struct DrawTextureCommand : IGALCommand, IGALCommand<DrawTextureCommand>
{
public CommandType CommandType => CommandType.DrawTexture;
private TableRef<ITexture> _texture;

View File

@@ -1,10 +1,10 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct EndHostConditionalRenderingCommand : IGALCommand
struct EndHostConditionalRenderingCommand : IGALCommand, IGALCommand<EndHostConditionalRenderingCommand>
{
public CommandType CommandType => CommandType.EndHostConditionalRendering;
public static void Run(IRenderer renderer)
public static void Run(ref EndHostConditionalRenderingCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
renderer.Pipeline.EndHostConditionalRendering();
}

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct EndTransformFeedbackCommand : IGALCommand
struct EndTransformFeedbackCommand : IGALCommand, IGALCommand<EndTransformFeedbackCommand>
{
public CommandType CommandType => CommandType.EndTransformFeedback;

View File

@@ -4,4 +4,9 @@
{
CommandType CommandType { get; }
}
interface IGALCommand<T> where T : IGALCommand
{
abstract static void Run(ref T command, ThreadedRenderer threaded, IRenderer renderer);
}
}

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Program
{
struct ProgramCheckLinkCommand : IGALCommand
struct ProgramCheckLinkCommand : IGALCommand, IGALCommand<ProgramCheckLinkCommand>
{
public CommandType CommandType => CommandType.ProgramCheckLink;
private TableRef<ThreadedProgram> _program;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Program
{
struct ProgramDisposeCommand : IGALCommand
struct ProgramDisposeCommand : IGALCommand, IGALCommand<ProgramDisposeCommand>
{
public CommandType CommandType => CommandType.ProgramDispose;
private TableRef<ThreadedProgram> _program;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Program
{
struct ProgramGetBinaryCommand : IGALCommand
struct ProgramGetBinaryCommand : IGALCommand, IGALCommand<ProgramGetBinaryCommand>
{
public CommandType CommandType => CommandType.ProgramGetBinary;
private TableRef<ThreadedProgram> _program;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct ActionCommand : IGALCommand
struct ActionCommand : IGALCommand, IGALCommand<ActionCommand>
{
public CommandType CommandType => CommandType.Action;
private TableRef<Action> _action;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct CreateBufferCommand : IGALCommand
struct CreateBufferCommand : IGALCommand, IGALCommand<CreateBufferCommand>
{
public CommandType CommandType => CommandType.CreateBuffer;
private BufferHandle _threadedHandle;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources.Programs;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct CreateProgramCommand : IGALCommand
struct CreateProgramCommand : IGALCommand, IGALCommand<CreateProgramCommand>
{
public CommandType CommandType => CommandType.CreateProgram;
private TableRef<IProgramRequest> _request;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct CreateSamplerCommand : IGALCommand
struct CreateSamplerCommand : IGALCommand, IGALCommand<CreateSamplerCommand>
{
public CommandType CommandType => CommandType.CreateSampler;
private TableRef<ThreadedSampler> _sampler;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct CreateSyncCommand : IGALCommand
struct CreateSyncCommand : IGALCommand, IGALCommand<CreateSyncCommand>
{
public CommandType CommandType => CommandType.CreateSync;
private ulong _id;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct CreateTextureCommand : IGALCommand
struct CreateTextureCommand : IGALCommand, IGALCommand<CreateTextureCommand>
{
public CommandType CommandType => CommandType.CreateTexture;
private TableRef<ThreadedTexture> _texture;

View File

@@ -2,7 +2,7 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct GetCapabilitiesCommand : IGALCommand
struct GetCapabilitiesCommand : IGALCommand, IGALCommand<GetCapabilitiesCommand>
{
public CommandType CommandType => CommandType.GetCapabilities;
private TableRef<ResultBox<Capabilities>> _result;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct PreFrameCommand : IGALCommand
struct PreFrameCommand : IGALCommand, IGALCommand<PreFrameCommand>
{
public CommandType CommandType => CommandType.PreFrame;

View File

@@ -4,7 +4,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct ReportCounterCommand : IGALCommand
struct ReportCounterCommand : IGALCommand, IGALCommand<ReportCounterCommand>
{
public CommandType CommandType => CommandType.ReportCounter;
private TableRef<ThreadedCounterEvent> _event;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct ResetCounterCommand : IGALCommand
struct ResetCounterCommand : IGALCommand, IGALCommand<ResetCounterCommand>
{
public CommandType CommandType => CommandType.ResetCounter;
private CounterType _type;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{
struct UpdateCountersCommand : IGALCommand
struct UpdateCountersCommand : IGALCommand, IGALCommand<UpdateCountersCommand>
{
public CommandType CommandType => CommandType.UpdateCounters;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Sampler
{
struct SamplerDisposeCommand : IGALCommand
struct SamplerDisposeCommand : IGALCommand, IGALCommand<SamplerDisposeCommand>
{
public CommandType CommandType => CommandType.SamplerDispose;
private TableRef<ThreadedSampler> _sampler;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetAlphaTestCommand : IGALCommand
struct SetAlphaTestCommand : IGALCommand, IGALCommand<SetAlphaTestCommand>
{
public CommandType CommandType => CommandType.SetAlphaTest;
private bool _enable;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetBlendStateCommand : IGALCommand
struct SetBlendStateCommand : IGALCommand, IGALCommand<SetBlendStateCommand>
{
public CommandType CommandType => CommandType.SetBlendState;
private int _index;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetDepthBiasCommand : IGALCommand
struct SetDepthBiasCommand : IGALCommand, IGALCommand<SetDepthBiasCommand>
{
public CommandType CommandType => CommandType.SetDepthBias;
private PolygonModeMask _enables;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetDepthClampCommand : IGALCommand
struct SetDepthClampCommand : IGALCommand, IGALCommand<SetDepthClampCommand>
{
public CommandType CommandType => CommandType.SetDepthClamp;
private bool _clamp;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetDepthModeCommand : IGALCommand
struct SetDepthModeCommand : IGALCommand, IGALCommand<SetDepthModeCommand>
{
public CommandType CommandType => CommandType.SetDepthMode;
private DepthMode _mode;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetDepthTestCommand : IGALCommand
struct SetDepthTestCommand : IGALCommand, IGALCommand<SetDepthTestCommand>
{
public CommandType CommandType => CommandType.SetDepthTest;
private DepthTestDescriptor _depthTest;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetFaceCullingCommand : IGALCommand
struct SetFaceCullingCommand : IGALCommand, IGALCommand<SetFaceCullingCommand>
{
public CommandType CommandType => CommandType.SetFaceCulling;
private bool _enable;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetFrontFaceCommand : IGALCommand
struct SetFrontFaceCommand : IGALCommand, IGALCommand<SetFrontFaceCommand>
{
public CommandType CommandType => CommandType.SetFrontFace;
private FrontFace _frontFace;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetImageCommand : IGALCommand
struct SetImageCommand : IGALCommand, IGALCommand<SetImageCommand>
{
public CommandType CommandType => CommandType.SetImage;
private int _binding;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetIndexBufferCommand : IGALCommand
struct SetIndexBufferCommand : IGALCommand, IGALCommand<SetIndexBufferCommand>
{
public CommandType CommandType => CommandType.SetIndexBuffer;
private BufferRange _buffer;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetLineParametersCommand : IGALCommand
struct SetLineParametersCommand : IGALCommand, IGALCommand<SetLineParametersCommand>
{
public CommandType CommandType => CommandType.SetLineParameters;
private float _width;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetLogicOpStateCommand : IGALCommand
struct SetLogicOpStateCommand : IGALCommand, IGALCommand<SetLogicOpStateCommand>
{
public CommandType CommandType => CommandType.SetLogicOpState;
private bool _enable;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetMultisampleStateCommand : IGALCommand
struct SetMultisampleStateCommand : IGALCommand, IGALCommand<SetMultisampleStateCommand>
{
public CommandType CommandType => CommandType.SetMultisampleState;
private MultisampleDescriptor _multisample;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetPatchParametersCommand : IGALCommand
struct SetPatchParametersCommand : IGALCommand, IGALCommand<SetPatchParametersCommand>
{
public CommandType CommandType => CommandType.SetPatchParameters;
private int _vertices;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetPointParametersCommand : IGALCommand
struct SetPointParametersCommand : IGALCommand, IGALCommand<SetPointParametersCommand>
{
public CommandType CommandType => CommandType.SetPointParameters;
private float _size;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetPolygonModeCommand : IGALCommand
struct SetPolygonModeCommand : IGALCommand, IGALCommand<SetPolygonModeCommand>
{
public CommandType CommandType => CommandType.SetPolygonMode;
private PolygonMode _frontMode;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetPrimitiveRestartCommand : IGALCommand
struct SetPrimitiveRestartCommand : IGALCommand, IGALCommand<SetPrimitiveRestartCommand>
{
public CommandType CommandType => CommandType.SetPrimitiveRestart;
private bool _enable;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetPrimitiveTopologyCommand : IGALCommand
struct SetPrimitiveTopologyCommand : IGALCommand, IGALCommand<SetPrimitiveTopologyCommand>
{
public CommandType CommandType => CommandType.SetPrimitiveTopology;
private PrimitiveTopology _topology;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetProgramCommand : IGALCommand
struct SetProgramCommand : IGALCommand, IGALCommand<SetProgramCommand>
{
public CommandType CommandType => CommandType.SetProgram;
private TableRef<IProgram> _program;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetRasterizerDiscardCommand : IGALCommand
struct SetRasterizerDiscardCommand : IGALCommand, IGALCommand<SetRasterizerDiscardCommand>
{
public CommandType CommandType => CommandType.SetRasterizerDiscard;
private bool _discard;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetRenderTargetColorMasksCommand : IGALCommand
struct SetRenderTargetColorMasksCommand : IGALCommand, IGALCommand<SetRenderTargetColorMasksCommand>
{
public CommandType CommandType => CommandType.SetRenderTargetColorMasks;
private SpanRef<uint> _componentMask;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetRenderTargetScaleCommand : IGALCommand
struct SetRenderTargetScaleCommand : IGALCommand, IGALCommand<SetRenderTargetScaleCommand>
{
public CommandType CommandType => CommandType.SetRenderTargetScale;
private float _scale;

View File

@@ -4,7 +4,7 @@ using System.Linq;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetRenderTargetsCommand : IGALCommand
struct SetRenderTargetsCommand : IGALCommand, IGALCommand<SetRenderTargetsCommand>
{
public CommandType CommandType => CommandType.SetRenderTargets;
private TableRef<ITexture[]> _colors;

View File

@@ -2,7 +2,7 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetScissorsCommand : IGALCommand
struct SetScissorsCommand : IGALCommand, IGALCommand<SetScissorsCommand>
{
public CommandType CommandType => CommandType.SetScissor;
private SpanRef<Rectangle<int>> _scissors;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetStencilTestCommand : IGALCommand
struct SetStencilTestCommand : IGALCommand, IGALCommand<SetStencilTestCommand>
{
public CommandType CommandType => CommandType.SetStencilTest;
private StencilTestDescriptor _stencilTest;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetStorageBuffersCommand : IGALCommand
struct SetStorageBuffersCommand : IGALCommand, IGALCommand<SetStorageBuffersCommand>
{
public CommandType CommandType => CommandType.SetStorageBuffers;
private SpanRef<BufferAssignment> _buffers;

View File

@@ -4,7 +4,7 @@ using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetTextureAndSamplerCommand : IGALCommand
struct SetTextureAndSamplerCommand : IGALCommand, IGALCommand<SetTextureAndSamplerCommand>
{
public CommandType CommandType => CommandType.SetTextureAndSampler;
private ShaderStage _stage;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetTransformFeedbackBuffersCommand : IGALCommand
struct SetTransformFeedbackBuffersCommand : IGALCommand, IGALCommand<SetTransformFeedbackBuffersCommand>
{
public CommandType CommandType => CommandType.SetTransformFeedbackBuffers;
private SpanRef<BufferRange> _buffers;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetUniformBuffersCommand : IGALCommand
struct SetUniformBuffersCommand : IGALCommand, IGALCommand<SetUniformBuffersCommand>
{
public CommandType CommandType => CommandType.SetUniformBuffers;
private SpanRef<BufferAssignment> _buffers;

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetUserClipDistanceCommand : IGALCommand
struct SetUserClipDistanceCommand : IGALCommand, IGALCommand<SetUserClipDistanceCommand>
{
public CommandType CommandType => CommandType.SetUserClipDistance;
private int _index;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetVertexAttribsCommand : IGALCommand
struct SetVertexAttribsCommand : IGALCommand, IGALCommand<SetVertexAttribsCommand>
{
public CommandType CommandType => CommandType.SetVertexAttribs;
private SpanRef<VertexAttribDescriptor> _vertexAttribs;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetVertexBuffersCommand : IGALCommand
struct SetVertexBuffersCommand : IGALCommand, IGALCommand<SetVertexBuffersCommand>
{
public CommandType CommandType => CommandType.SetVertexBuffers;
private SpanRef<VertexBufferDescriptor> _vertexBuffers;

View File

@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetViewportsCommand : IGALCommand
struct SetViewportsCommand : IGALCommand, IGALCommand<SetViewportsCommand>
{
public CommandType CommandType => CommandType.SetViewports;
private SpanRef<Viewport> _viewports;

View File

@@ -3,7 +3,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Resources;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
struct TextureCopyToCommand : IGALCommand
struct TextureCopyToCommand : IGALCommand, IGALCommand<TextureCopyToCommand>
{
public CommandType CommandType => CommandType.TextureCopyTo;
private TableRef<ThreadedTexture> _texture;

Some files were not shown because too many files have changed in this diff Show More