Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
09c9686498 | ||
|
b6614c6ad5 | ||
|
b1d4b174a6 | ||
|
2b23463daa |
@@ -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" />
|
||||||
|
@@ -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>
|
||||||
|
@@ -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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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)
|
||||||
|
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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))
|
||||||
{
|
{
|
||||||
|
@@ -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);
|
||||||
|
@@ -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.
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user