Compare commits

..

4 Commits

Author SHA1 Message Date
Mary-nyan
09c9686498 misc: Use official names for NVDEC registers (#4192)
* misc: Uses official names for NVDEC registers

* Address gdkchan's comment

* Address comments
2023-01-02 14:48:46 +00:00
Mary-nyan
b6614c6ad5 chore: Update tests dependencies (#3978)
* chore: Update tests dependencies

* Apply TSR Berry suggestion to add a GC.SuppressFinalize in MemoryBlock.cs

* Ensure we wait for the test thread to be dead on PartialUnmap

* Use platform attribute for os specific tests

* Make P/Invoke methods private

* Downgrade NUnit3TestAdapter to 4.1.0

* test: Disable warning about platform compat for ThreadLocalMap()

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2023-01-01 17:35:29 +01:00
Emmanuel Hansen
b1d4b174a6 fix typo in left joycon sl binding (#4195) 2023-01-01 15:46:02 +01:00
Andrew Glaze
2b23463daa Filter hidden game files from the Game List (#4051)
* Filter “._” files from the game list

* Filter all hidden files from the game list

* Fix style

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

* merge OR expression into a pattern

* migrate from GetFiles/Directories to Enumerate

* Remove GetFilesInDirectory()

* Update Ryujinx.Ui.Common/App/ApplicationLibrary.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* add error handeling

* code cleanup

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-29 16:52:30 +01:00
15 changed files with 134 additions and 197 deletions

View File

@@ -25,7 +25,7 @@
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NUnit" Version="3.13.3" /> <PackageVersion Include="NUnit" Version="3.13.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="3.17.0" /> <PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageVersion Include="OpenTK.Core" Version="4.7.5" /> <PackageVersion Include="OpenTK.Core" Version="4.7.5" />
<PackageVersion Include="OpenTK.Graphics" Version="4.7.5" /> <PackageVersion Include="OpenTK.Graphics" Version="4.7.5" />
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.5" /> <PackageVersion Include="OpenTK.OpenAL" Version="4.7.5" />

View File

@@ -639,14 +639,14 @@
Width="20" Width="20"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{locale:Locale ControllerSettingsRightSL}" Text="{locale:Locale ControllerSettingsLeftSL}"
TextAlignment="Center" /> TextAlignment="Center" />
<ToggleButton <ToggleButton
Width="90" Width="90"
Height="27" Height="27"
HorizontalAlignment="Stretch"> HorizontalAlignment="Stretch">
<TextBlock <TextBlock
Text="{Binding Configuration.RightButtonSl, Mode=TwoWay, Converter={StaticResource Key}}" Text="{Binding Configuration.LeftButtonSl, Mode=TwoWay, Converter={StaticResource Key}}"
TextAlignment="Center" /> TextAlignment="Center" />
</ToggleButton> </ToggleButton>
</StackPanel> </StackPanel>

View File

@@ -27,7 +27,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll")] [LibraryImport("kernel32.dll")]
public static partial int GetCurrentThreadId(); private static partial int GetCurrentThreadId();
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]
@@ -36,7 +36,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs (UnmanagedType.Bool)] [return: MarshalAs (UnmanagedType.Bool)]
public static partial bool CloseHandle(IntPtr hObject); private static partial bool CloseHandle(IntPtr hObject);
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]
@@ -160,4 +160,4 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
} }
} }
} }
} }

View File

@@ -106,7 +106,7 @@ namespace Ryujinx.Graphics.Host1x
private void Method1(int data) private void Method1(int data)
{ {
_commandQueue.Add(new MethodCallAction(_currentContextId, (int)_state.State.Method0 * 4, data)); _commandQueue.Add(new MethodCallAction(_currentContextId, (int)_state.State.Method0 * sizeof(uint), data));
} }
private void Process(CommandAction cmdAction) private void Process(CommandAction cmdAction)

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.Nvdec namespace Ryujinx.Graphics.Nvdec
{ {
public enum CodecId public enum ApplicationId
{ {
Mpeg = 1, Mpeg = 1,
Vc1 = 2, Vc1 = 2,
@@ -8,6 +8,7 @@
Mpeg4 = 4, Mpeg4 = 4,
Vp8 = 5, Vp8 = 5,
Hevc = 7, Hevc = 7,
Vp9 = 9 Vp9 = 9,
HevcParser = 12,
} }
} }

View File

@@ -1,16 +0,0 @@
namespace Ryujinx.Graphics.Nvdec
{
public readonly struct FrameDecodedEventArgs
{
public CodecId CodecId { get; }
public uint LumaOffset { get; }
public uint ChromaOffset { get; }
internal FrameDecodedEventArgs(CodecId codecId, uint lumaOffset, uint chromaOffset)
{
CodecId = codecId;
LumaOffset = lumaOffset;
ChromaOffset = chromaOffset;
}
}
}

View File

@@ -12,18 +12,18 @@ namespace Ryujinx.Graphics.Nvdec
public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state) public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
{ {
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset); PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
H264PictureInfo info = pictureInfo.Convert(); H264PictureInfo info = pictureInfo.Convert();
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetBitstreamOffset, (int)pictureInfo.BitstreamSize); ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize);
int width = (int)pictureInfo.PicWidthInMbs * MbSizeInPixels; int width = (int)pictureInfo.PicWidthInMbs * MbSizeInPixels;
int height = (int)pictureInfo.PicHeightInMbs * MbSizeInPixels; int height = (int)pictureInfo.PicHeightInMbs * MbSizeInPixels;
int surfaceIndex = (int)pictureInfo.OutputSurfaceIndex; int surfaceIndex = (int)pictureInfo.OutputSurfaceIndex;
uint lumaOffset = state.SetSurfaceLumaOffset[surfaceIndex]; uint lumaOffset = state.SetPictureLumaOffset[surfaceIndex];
uint chromaOffset = state.SetSurfaceChromaOffset[surfaceIndex]; uint chromaOffset = state.SetPictureChromaOffset[surfaceIndex];
Decoder decoder = context.GetH264Decoder(); Decoder decoder = context.GetH264Decoder();

View File

@@ -58,24 +58,24 @@ namespace Ryujinx.Graphics.Nvdec
private void Execute(int data) private void Execute(int data)
{ {
Decode((CodecId)_state.State.SetCodecID); Decode((ApplicationId)_state.State.SetApplicationId);
} }
private void Decode(CodecId codecId) private void Decode(ApplicationId applicationId)
{ {
switch (codecId) switch (applicationId)
{ {
case CodecId.H264: case ApplicationId.H264:
H264Decoder.Decode(_currentContext, _rm, ref _state.State); H264Decoder.Decode(_currentContext, _rm, ref _state.State);
break; break;
case CodecId.Vp8: case ApplicationId.Vp8:
Vp8Decoder.Decode(_currentContext, _rm, ref _state.State); Vp8Decoder.Decode(_currentContext, _rm, ref _state.State);
break; break;
case CodecId.Vp9: case ApplicationId.Vp9:
Vp9Decoder.Decode(_rm, ref _state.State); Vp9Decoder.Decode(_rm, ref _state.State);
break; break;
default: default:
Logger.Error?.Print(LogClass.Nvdec, $"Unsupported codec \"{codecId}\"."); Logger.Error?.Print(LogClass.Nvdec, $"Unsupported codec \"{applicationId}\".");
break; break;
} }
} }

View File

@@ -2,43 +2,62 @@
namespace Ryujinx.Graphics.Nvdec namespace Ryujinx.Graphics.Nvdec
{ {
// Note: Most of those names are not official.
struct NvdecRegisters struct NvdecRegisters
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649
public Array64<uint> Reserved0; public Array64<uint> Reserved0;
public Array64<uint> Reserved100; public uint Nop;
public uint SetCodecID; public Array63<uint> Reserved104;
public Array63<uint> Reserved204; public uint SetApplicationId;
public uint SetWatchdogTimer;
public Array14<uint> Reserved208;
public uint SemaphoreA;
public uint SemaphoreB;
public uint SemaphoreC;
public uint CtxSaveArea;
public Array44<uint> Reserved254;
public uint Execute; public uint Execute;
public Array63<uint> Reserved304; public uint SemaphoreD;
public uint SetPlatformID; public Array62<uint> Reserved308;
public uint SetPictureInfoOffset; public uint SetControlParams;
public uint SetBitstreamOffset; public uint SetDrvPicSetupOffset;
public uint SetFrameNumber; public uint SetInBufBaseOffset;
public uint SetH264SliceDataOffsetsOffset; // Also used by VC1 public uint SetPictureIndex;
public uint SetH264MvDumpOffset; // Also used by VC1 public uint SetSliceOffsetsBufOffset; // Also used by VC1
public uint Unknown418; // Used by VC1 public uint SetColocDataOffset; // Also used by VC1
public uint Unknown41C; public uint SetHistoryOffset; // Used by VC1
public uint Unknown420; // Used by VC1 public uint SetDisplayBufSize;
public uint SetFrameStatsOffset; public uint SetHistogramOffset; // Used by VC1
public uint SetH264LastSurfaceLumaOffset; public uint SetNvDecStatusOffset;
public uint SetH264LastSurfaceChromaOffset; public uint SetDisplayBufLumaOffset;
public Array17<uint> SetSurfaceLumaOffset; public uint SetDisplayBufChromaOffset;
public Array17<uint> SetSurfaceChromaOffset; public Array17<uint> SetPictureLumaOffset;
public uint Unknown4B8; public Array17<uint> SetPictureChromaOffset;
public uint Unknown4BC; public uint SetPicScratchBufOffset;
public uint SetExternalMvBufferOffset;
public uint SetCryptoData0Offset; public uint SetCryptoData0Offset;
public uint SetCryptoData1Offset; public uint SetCryptoData1Offset;
public Array62<uint> Unknown4C8; public Array14<uint> Unknown4C8;
public uint SetVp9EntropyProbsOffset; public uint H264SetMbHistBufOffset;
public uint SetVp9BackwardUpdatesOffset; public Array15<uint> Unknown504;
public uint SetVp9LastFrameSegMapOffset; public uint Vp8SetProbDataOffset;
public uint SetVp9CurrFrameSegMapOffset; public uint Vp8SetHeaderPartitionBufBaseOffset;
public uint Unknown5D0; public Array14<uint> Unknown548;
public uint SetVp9LastFrameMvsOffset; public uint HevcSetScalingListOffset;
public uint SetVp9CurrFrameMvsOffset; public uint HevcSetTileSizesOffset;
public uint Unknown5DC; public uint HevcSetFilterBufferOffset;
public uint HevcSetSaoBufferOffset;
public uint HevcSetSliceInfoBufferOffset;
public uint HevcSetSliceGroupIndex;
public Array10<uint> Unknown598;
public uint Vp9SetProbTabBufOffset;
public uint Vp9SetCtxCounterBufOffset;
public uint Vp9SetSegmentReadBufOffset;
public uint Vp9SetSegmentWriteBufOffset;
public uint Vp9SetTileSizeBufOffset;
public uint Vp9SetColMvWriteBufOffset;
public uint Vp9SetColMvReadBufOffset;
public uint Vp9SetFilterBufferOffset;
#pragma warning restore CS0649 #pragma warning restore CS0649
} }
} }

View File

@@ -10,8 +10,8 @@ namespace Ryujinx.Graphics.Nvdec
{ {
public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state) public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
{ {
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset); PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetBitstreamOffset, (int)pictureInfo.VLDBufferSize); ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.VLDBufferSize);
Decoder decoder = context.GetVp8Decoder(); Decoder decoder = context.GetVp8Decoder();
@@ -19,8 +19,8 @@ namespace Ryujinx.Graphics.Nvdec
Vp8PictureInfo info = pictureInfo.Convert(); Vp8PictureInfo info = pictureInfo.Convert();
uint lumaOffset = state.SetSurfaceLumaOffset[3]; uint lumaOffset = state.SetPictureLumaOffset[3];
uint chromaOffset = state.SetSurfaceChromaOffset[3]; uint chromaOffset = state.SetPictureChromaOffset[3];
if (decoder.Decode(ref info, outputSurface, bitstream)) if (decoder.Decode(ref info, outputSurface, bitstream))
{ {

View File

@@ -17,18 +17,18 @@ namespace Ryujinx.Graphics.Nvdec
public unsafe static void Decode(ResourceManager rm, ref NvdecRegisters state) public unsafe static void Decode(ResourceManager rm, ref NvdecRegisters state)
{ {
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset); PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
EntropyProbs entropy = rm.Gmm.DeviceRead<EntropyProbs>(state.SetVp9EntropyProbsOffset); EntropyProbs entropy = rm.Gmm.DeviceRead<EntropyProbs>(state.Vp9SetProbTabBufOffset);
ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size) ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size)
{ {
return rm.Cache.Get(_decoder, lumaOffset, chromaOffset, size.Width, size.Height); return rm.Cache.Get(_decoder, lumaOffset, chromaOffset, size.Width, size.Height);
} }
ISurface lastSurface = Rent(state.SetSurfaceLumaOffset[0], state.SetSurfaceChromaOffset[0], pictureInfo.LastFrameSize); ISurface lastSurface = Rent(state.SetPictureLumaOffset[0], state.SetPictureChromaOffset[0], pictureInfo.LastFrameSize);
ISurface goldenSurface = Rent(state.SetSurfaceLumaOffset[1], state.SetSurfaceChromaOffset[1], pictureInfo.GoldenFrameSize); ISurface goldenSurface = Rent(state.SetPictureLumaOffset[1], state.SetPictureChromaOffset[1], pictureInfo.GoldenFrameSize);
ISurface altSurface = Rent(state.SetSurfaceLumaOffset[2], state.SetSurfaceChromaOffset[2], pictureInfo.AltFrameSize); ISurface altSurface = Rent(state.SetPictureLumaOffset[2], state.SetPictureChromaOffset[2], pictureInfo.AltFrameSize);
ISurface currentSurface = Rent(state.SetSurfaceLumaOffset[3], state.SetSurfaceChromaOffset[3], pictureInfo.CurrentFrameSize); ISurface currentSurface = Rent(state.SetPictureLumaOffset[3], state.SetPictureChromaOffset[3], pictureInfo.CurrentFrameSize);
Vp9PictureInfo info = pictureInfo.Convert(); Vp9PictureInfo info = pictureInfo.Convert();
@@ -38,31 +38,31 @@ namespace Ryujinx.Graphics.Nvdec
entropy.Convert(ref info.Entropy); entropy.Convert(ref info.Entropy);
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetBitstreamOffset, (int)pictureInfo.BitstreamSize); ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize);
ReadOnlySpan<Vp9MvRef> mvsIn = ReadOnlySpan<Vp9MvRef>.Empty; ReadOnlySpan<Vp9MvRef> mvsIn = ReadOnlySpan<Vp9MvRef>.Empty;
if (info.UsePrevInFindMvRefs) if (info.UsePrevInFindMvRefs)
{ {
mvsIn = GetMvsInput(rm.Gmm, pictureInfo.CurrentFrameSize, state.SetVp9LastFrameMvsOffset); mvsIn = GetMvsInput(rm.Gmm, pictureInfo.CurrentFrameSize, state.Vp9SetColMvReadBufOffset);
} }
int miCols = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Width, 8); int miCols = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Width, 8);
int miRows = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Height, 8); int miRows = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Height, 8);
using var mvsRegion = rm.Gmm.GetWritableRegion(ExtendOffset(state.SetVp9CurrFrameMvsOffset), miRows * miCols * 16); using var mvsRegion = rm.Gmm.GetWritableRegion(ExtendOffset(state.Vp9SetColMvWriteBufOffset), miRows * miCols * 16);
Span<Vp9MvRef> mvsOut = MemoryMarshal.Cast<byte, Vp9MvRef>(mvsRegion.Memory.Span); Span<Vp9MvRef> mvsOut = MemoryMarshal.Cast<byte, Vp9MvRef>(mvsRegion.Memory.Span);
uint lumaOffset = state.SetSurfaceLumaOffset[3]; uint lumaOffset = state.SetPictureLumaOffset[3];
uint chromaOffset = state.SetSurfaceChromaOffset[3]; uint chromaOffset = state.SetPictureChromaOffset[3];
if (_decoder.Decode(ref info, currentSurface, bitstream, mvsIn, mvsOut)) if (_decoder.Decode(ref info, currentSurface, bitstream, mvsIn, mvsOut))
{ {
SurfaceWriter.Write(rm.Gmm, currentSurface, lumaOffset, chromaOffset); SurfaceWriter.Write(rm.Gmm, currentSurface, lumaOffset, chromaOffset);
} }
WriteBackwardUpdates(rm.Gmm, state.SetVp9BackwardUpdatesOffset, ref info.BackwardUpdateCounts); WriteBackwardUpdates(rm.Gmm, state.Vp9SetCtxCounterBufOffset, ref info.BackwardUpdateCounts);
rm.Cache.Put(lastSurface); rm.Cache.Put(lastSurface);
rm.Cache.Put(goldenSurface); rm.Cache.Put(goldenSurface);

View File

@@ -39,14 +39,10 @@ namespace Ryujinx.Memory.Tests
} }
[Test] [Test]
// Memory aliasing tests fail on CI at the moment.
[Platform(Exclude = "MacOsX")]
public void Test_Alias() public void Test_Alias()
{ {
if (OperatingSystem.IsMacOS())
{
// Memory aliasing tests fail on CI at the moment.
return;
}
using MemoryBlock backing = new MemoryBlock(0x10000, MemoryAllocationFlags.Mirrorable); using MemoryBlock backing = new MemoryBlock(0x10000, MemoryAllocationFlags.Mirrorable);
using MemoryBlock toAlias = new MemoryBlock(0x10000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible); using MemoryBlock toAlias = new MemoryBlock(0x10000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
@@ -58,14 +54,10 @@ namespace Ryujinx.Memory.Tests
} }
[Test] [Test]
// Memory aliasing tests fail on CI at the moment.
[Platform(Exclude = "MacOsX")]
public void Test_AliasRandom() public void Test_AliasRandom()
{ {
if (OperatingSystem.IsMacOS())
{
// Memory aliasing tests fail on CI at the moment.
return;
}
using MemoryBlock backing = new MemoryBlock(0x80000, MemoryAllocationFlags.Mirrorable); using MemoryBlock backing = new MemoryBlock(0x80000, MemoryAllocationFlags.Mirrorable);
using MemoryBlock toAlias = new MemoryBlock(0x80000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible); using MemoryBlock toAlias = new MemoryBlock(0x80000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
@@ -94,14 +86,10 @@ namespace Ryujinx.Memory.Tests
} }
[Test] [Test]
// Memory aliasing tests fail on CI at the moment.
[Platform(Exclude = "MacOsX")]
public void Test_AliasMapLeak() public void Test_AliasMapLeak()
{ {
if (OperatingSystem.IsMacOS())
{
// Memory aliasing tests fail on CI at the moment.
return;
}
ulong pageSize = 4096; ulong pageSize = 4096;
ulong size = 100000 * pageSize; // The mappings limit on Linux is usually around 65K, so let's make sure we are above that. ulong size = 100000 * pageSize; // The mappings limit on Linux is usually around 65K, so let's make sure we are above that.

View File

@@ -379,7 +379,12 @@ namespace Ryujinx.Memory
/// <remarks> /// <remarks>
/// It's an error to use the memory block after disposal. /// It's an error to use the memory block after disposal.
/// </remarks> /// </remarks>
public void Dispose() => FreeMemory(); public void Dispose()
{
FreeMemory();
GC.SuppressFinalize(this);
}
~MemoryBlock() => FreeMemory(); ~MemoryBlock() => FreeMemory();

View File

@@ -9,6 +9,7 @@ using Ryujinx.Memory.Tests;
using Ryujinx.Memory.Tracking; using Ryujinx.Memory.Tracking;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
@@ -57,14 +58,10 @@ namespace Ryujinx.Tests.Memory
} }
[Test] [Test]
// Memory aliasing tests fail on CI at the moment.
[Platform(Exclude = "MacOsX")]
public void PartialUnmap([Values] bool readOnly) public void PartialUnmap([Values] bool readOnly)
{ {
if (OperatingSystem.IsMacOS())
{
// Memory aliasing tests fail on CI at the moment.
return;
}
// Set up an address space to test partial unmapping. // Set up an address space to test partial unmapping.
// Should register the signal handler to deal with this on Windows. // Should register the signal handler to deal with this on Windows.
ulong vaSize = 0x100000; ulong vaSize = 0x100000;
@@ -78,11 +75,13 @@ namespace Ryujinx.Tests.Memory
ref var state = ref PartialUnmapState.GetRef(); ref var state = ref PartialUnmapState.GetRef();
Thread testThread = null;
bool shouldAccess = true;
try try
{ {
// Globally reset the struct for handling partial unmap races. // Globally reset the struct for handling partial unmap races.
PartialUnmapState.Reset(); PartialUnmapState.Reset();
bool shouldAccess = true;
bool error = false; bool error = false;
// Create a large mapping. // Create a large mapping.
@@ -93,8 +92,6 @@ namespace Ryujinx.Tests.Memory
memory.Reprotect(0, vaSize, MemoryPermission.Read); memory.Reprotect(0, vaSize, MemoryPermission.Read);
} }
Thread testThread;
if (readOnly) if (readOnly)
{ {
// Write a value to the physical memory, then try to read it repeately from virtual. // Write a value to the physical memory, then try to read it repeately from virtual.
@@ -193,6 +190,10 @@ namespace Ryujinx.Tests.Memory
} }
finally finally
{ {
// In case something failed, we want to ensure the test thread is dead before disposing of the memory.
shouldAccess = false;
testThread?.Join();
exceptionHandler.Dispose(); exceptionHandler.Dispose();
unusedMainMemory.Dispose(); unusedMainMemory.Dispose();
memory.Dispose(); memory.Dispose();
@@ -201,13 +202,10 @@ namespace Ryujinx.Tests.Memory
} }
[Test] [Test]
// Memory aliasing tests fail on CI at the moment.
[Platform(Exclude = "MacOsX")]
public unsafe void PartialUnmapNative() public unsafe void PartialUnmapNative()
{ {
if (OperatingSystem.IsMacOS())
{
// Memory aliasing tests fail on CI at the moment.
return;
}
// Set up an address space to test partial unmapping. // Set up an address space to test partial unmapping.
// Should register the signal handler to deal with this on Windows. // Should register the signal handler to deal with this on Windows.
@@ -284,26 +282,17 @@ namespace Ryujinx.Tests.Memory
} }
[Test] [Test]
// Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming.
[Platform("Win")]
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
public void ThreadLocalMap() public void ThreadLocalMap()
{ {
if (!OperatingSystem.IsWindows())
{
// Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming.
return;
}
PartialUnmapState.Reset(); PartialUnmapState.Reset();
ref var state = ref PartialUnmapState.GetRef(); ref var state = ref PartialUnmapState.GetRef();
bool running = true; bool running = true;
var testThread = new Thread(() => var testThread = new Thread(() =>
{ {
if (!OperatingSystem.IsWindows())
{
// Need this here to avoid a warning.
return;
}
PartialUnmapState.GetRef().RetryFromAccessViolation(); PartialUnmapState.GetRef().RetryFromAccessViolation();
while (running) while (running)
{ {
@@ -330,14 +319,10 @@ namespace Ryujinx.Tests.Memory
} }
[Test] [Test]
// Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming.
[Platform("Win")]
public unsafe void ThreadLocalMapNative() public unsafe void ThreadLocalMapNative()
{ {
if (!OperatingSystem.IsWindows())
{
// Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming.
return;
}
EnsureTranslator(); EnsureTranslator();
PartialUnmapState.Reset(); PartialUnmapState.Reset();
@@ -481,4 +466,4 @@ namespace Ryujinx.Tests.Memory
Assert.False(error); Assert.False(error);
} }
} }
} }

View File

@@ -68,53 +68,6 @@ namespace Ryujinx.Ui.App.Common
_cancellationToken?.Cancel(); _cancellationToken?.Cancel();
} }
public IEnumerable<string> GetFilesInDirectory(string directory)
{
Stack<string> stack = new Stack<string>();
stack.Push(directory);
while (stack.Count > 0)
{
string dir = stack.Pop();
string[] content = Array.Empty<string>();
try
{
content = Directory.GetFiles(dir, "*");
}
catch (UnauthorizedAccessException)
{
Logger.Warning?.Print(LogClass.Application, $"Failed to get access to directory: \"{dir}\"");
}
if (content.Length > 0)
{
foreach (string file in content)
{
yield return file;
}
}
try
{
content = Directory.GetDirectories(dir);
}
catch (UnauthorizedAccessException)
{
Logger.Warning?.Print(LogClass.Application, $"Failed to get access to directory: \"{dir}\"");
}
if (content.Length > 0)
{
foreach (string subdir in content)
{
stack.Push(subdir);
}
}
}
}
public void ReadControlData(IFileSystem controlFs, Span<byte> outProperty) public void ReadControlData(IFileSystem controlFs, Span<byte> outProperty)
{ {
using var controlFile = new UniqueRef<IFile>(); using var controlFile = new UniqueRef<IFile>();
@@ -151,26 +104,28 @@ namespace Ryujinx.Ui.App.Common
continue; continue;
} }
foreach (string app in GetFilesInDirectory(appDir)) try
{ {
if (_cancellationToken.Token.IsCancellationRequested) foreach (string app in Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories))
{ {
return; if (_cancellationToken.Token.IsCancellationRequested)
} {
return;
string extension = Path.GetExtension(app).ToLower(); }
if ((extension == ".nsp") || string extension = Path.GetExtension(app).ToLower();
(extension == ".pfs0") ||
(extension == ".xci") || if (!File.GetAttributes(app).HasFlag(FileAttributes.Hidden) && extension is ".nsp" or ".pfs0" or ".xci" or ".nca" or ".nro" or ".nso")
(extension == ".nca") || {
(extension == ".nro") || applications.Add(app);
(extension == ".nso")) numApplicationsFound++;
{ }
applications.Add(app);
numApplicationsFound++;
} }
} }
catch (UnauthorizedAccessException)
{
Logger.Warning?.Print(LogClass.Application, $"Failed to get access to directory: \"{appDir}\"");
}
} }
// Loops through applications list, creating a struct and then firing an event containing the struct for each application // Loops through applications list, creating a struct and then firing an event containing the struct for each application