Merge branch 'master' into aot

This commit is contained in:
LDj3SNuD 2020-01-13 01:47:46 +01:00
commit 7d0d9703a1
41 changed files with 402 additions and 255 deletions

View file

@ -1,6 +1,7 @@
using ARMeilleure.State;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
@ -552,6 +553,50 @@ namespace ARMeilleure.Memory
return data;
}
public ReadOnlySpan<byte> GetSpan(ulong address, ulong size)
{
if (IsContiguous(address, size))
{
return new ReadOnlySpan<byte>((void*)Translate((long)address), (int)size);
}
else
{
return ReadBytes((long)address, (long)size);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool IsContiguous(ulong address, ulong size)
{
if (!IsValidPosition((long)address))
{
return false;
}
ulong endVa = (address + size + PageMask) & ~(ulong)PageMask;
address &= ~(ulong)PageMask;
int pages = (int)((endVa - address) / PageSize);
for (int page = 0; page < pages - 1; page++)
{
if (!IsValidPosition((long)address + PageSize))
{
return false;
}
if (GetPtEntry((long)address) + PageSize != GetPtEntry((long)address + PageSize))
{
return false;
}
address += PageSize;
}
return true;
}
public void WriteSByte(long position, sbyte value)
{
WriteByte(position, (byte)value);

View file

@ -78,9 +78,12 @@ namespace ARMeilleure.Translation
{
if (Interlocked.Increment(ref _threadCount) == 1)
{
Thread backgroundTranslatorThread = new Thread(TranslateQueuedSubs);
Thread backgroundTranslatorThread = new Thread(TranslateQueuedSubs)
{
Name = "CPU.BackgroundTranslatorThread",
Priority = ThreadPriority.Lowest
};
backgroundTranslatorThread.Priority = ThreadPriority.Lowest;
backgroundTranslatorThread.Start();
}

View file

@ -70,7 +70,10 @@ namespace Ryujinx.Audio
_context = new AudioContext();
_tracks = new ConcurrentDictionary<int, OpenALAudioTrack>();
_keepPolling = true;
_audioPollerThread = new Thread(AudioPollerWork);
_audioPollerThread = new Thread(AudioPollerWork)
{
Name = "Audio.PollerThread"
};
_audioPollerThread.Start();
}

View file

@ -18,8 +18,13 @@ namespace Ryujinx.Common.Logging
sb.AppendFormat(@"{0:hh\:mm\:ss\.fff}", args.Time);
sb.Append(" | ");
sb.AppendFormat("{0:d4}", args.ThreadId);
sb.Append(' ');
if (args.ThreadName != null)
{
sb.Append(args.ThreadName);
sb.Append(' ');
}
sb.Append(args.Message);
if (args.Data != null)

View file

@ -4,28 +4,28 @@ namespace Ryujinx.Common.Logging
{
public class LogEventArgs : EventArgs
{
public LogLevel Level { get; private set; }
public TimeSpan Time { get; private set; }
public int ThreadId { get; private set; }
public LogLevel Level { get; private set; }
public TimeSpan Time { get; private set; }
public string ThreadName { get; private set; }
public string Message { get; private set; }
public object Data { get; private set; }
public LogEventArgs(LogLevel level, TimeSpan time, int threadId, string message)
public LogEventArgs(LogLevel level, TimeSpan time, string threadName, string message)
{
Level = level;
Time = time;
ThreadId = threadId;
Message = message;
Level = level;
Time = time;
ThreadName = threadName;
Message = message;
}
public LogEventArgs(LogLevel level, TimeSpan time, int threadId, string message, object data)
public LogEventArgs(LogLevel level, TimeSpan time, string threadName, string message, object data)
{
Level = level;
Time = time;
ThreadId = threadId;
Message = message;
Data = data;
Level = level;
Time = time;
ThreadName = threadName;
Message = message;
Data = data;
}
}
}

View file

@ -155,7 +155,7 @@ namespace Ryujinx.Common.Logging
{
if (m_EnabledLevels[(int)logLevel] && m_EnabledClasses[(int)logClass])
{
Updated?.Invoke(null, new LogEventArgs(logLevel, m_Time.Elapsed, Thread.CurrentThread.ManagedThreadId, message));
Updated?.Invoke(null, new LogEventArgs(logLevel, m_Time.Elapsed, Thread.CurrentThread.Name, message));
}
}
@ -163,7 +163,7 @@ namespace Ryujinx.Common.Logging
{
if (m_EnabledLevels[(int)logLevel] && m_EnabledClasses[(int)logClass])
{
Updated?.Invoke(null, new LogEventArgs(logLevel, m_Time.Elapsed, Thread.CurrentThread.ManagedThreadId, message, data));
Updated?.Invoke(null, new LogEventArgs(logLevel, m_Time.Elapsed, Thread.CurrentThread.Name, message, data));
}
}

View file

@ -57,6 +57,7 @@ namespace Ryujinx.Common.Logging
}
});
_messageThread.Name = "Logger.MessageThread";
_messageThread.IsBackground = true;
_messageThread.Start();
}

View file

@ -8,8 +8,8 @@ namespace Ryujinx.Graphics.GAL
byte[] GetData(int offset, int size);
void SetData(Span<byte> data);
void SetData(ReadOnlySpan<byte> data);
void SetData(int offset, Span<byte> data);
void SetData(int offset, ReadOnlySpan<byte> data);
}
}

View file

@ -4,6 +4,8 @@ namespace Ryujinx.Graphics.GAL
{
public interface IPipeline
{
void Barrier();
void ClearRenderTargetColor(int index, uint componentMask, ColorF color);
void ClearRenderTargetDepthStencil(

View file

@ -18,8 +18,6 @@ namespace Ryujinx.Graphics.GAL
ISampler CreateSampler(SamplerCreateInfo info);
ITexture CreateTexture(TextureCreateInfo info);
void FlushPipelines();
Capabilities GetCapabilities();
ulong GetCounter(CounterType type);

View file

@ -11,6 +11,6 @@ namespace Ryujinx.Graphics.GAL
byte[] GetData();
void SetData(Span<byte> data);
void SetData(ReadOnlySpan<byte> data);
}
}

View file

@ -77,7 +77,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
sbDescAddress += (ulong)sbDescOffset;
Span<byte> sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10);
ReadOnlySpan<byte> sbDescriptorData = _context.PhysicalMemory.GetSpan(sbDescAddress, 0x10);
SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];

View file

@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
ulong srcAddress = srcBaseAddress + (ulong)srcOffset;
ulong dstAddress = dstBaseAddress + (ulong)dstOffset;
Span<byte> pixel = _context.PhysicalMemory.Read(srcAddress, (ulong)srcBpp);
ReadOnlySpan<byte> pixel = _context.PhysicalMemory.GetSpan(srcAddress, (ulong)srcBpp);
_context.PhysicalMemory.Write(dstAddress, pixel);
}

View file

@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
sbDescAddress += (ulong)sbDescOffset;
Span<byte> sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10);
ReadOnlySpan<byte> sbDescriptorData = _context.PhysicalMemory.GetSpan(sbDescAddress, 0x10);
SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
ulong address = Address + (ulong)(uint)id * DescriptorSize;
Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
ReadOnlySpan<byte> data = Context.PhysicalMemory.GetSpan(address, DescriptorSize);
SamplerDescriptor descriptor = MemoryMarshal.Cast<byte, SamplerDescriptor>(data)[0];

View file

@ -304,7 +304,7 @@ namespace Ryujinx.Graphics.Gpu.Image
return;
}
Span<byte> data = _context.PhysicalMemory.Read(Address, Size);
ReadOnlySpan<byte> data = _context.PhysicalMemory.GetSpan(Address, Size);
if (Info.IsLinear)
{

View file

@ -197,7 +197,7 @@ namespace Ryujinx.Graphics.Gpu.Image
address = bufferManager.GetGraphicsUniformBufferAddress(stageIndex, binding.CbufSlot);
}
packedId = MemoryMarshal.Cast<byte, int>(_context.PhysicalMemory.Read(address + (ulong)binding.CbufOffset * 4, 4))[0];
packedId = MemoryMarshal.Cast<byte, int>(_context.PhysicalMemory.GetSpan(address + (ulong)binding.CbufOffset * 4, 4))[0];
}
else
{
@ -321,7 +321,7 @@ namespace Ryujinx.Graphics.Gpu.Image
address += (uint)wordOffset * 4;
return BitConverter.ToInt32(_context.PhysicalMemory.Read(address, 4));
return BitConverter.ToInt32(_context.PhysicalMemory.GetSpan(address, 4));
}
/// <summary>

View file

@ -85,7 +85,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
ulong address = Address + (ulong)(uint)id * DescriptorSize;
Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
ReadOnlySpan<byte> data = Context.PhysicalMemory.GetSpan(address, DescriptorSize);
return MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];
}
@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (texture != null)
{
Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
ReadOnlySpan<byte> data = Context.PhysicalMemory.GetSpan(address, DescriptorSize);
TextureDescriptor descriptor = MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];

View file

@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
int offset = (int)(mAddress - Address);
HostBuffer.SetData(offset, _context.PhysicalMemory.Read(mAddress, mSize));
HostBuffer.SetData(offset, _context.PhysicalMemory.GetSpan(mAddress, mSize));
}
}
@ -157,7 +157,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary>
public void Invalidate()
{
HostBuffer.SetData(0, _context.PhysicalMemory.Read(Address, Size));
HostBuffer.SetData(0, _context.PhysicalMemory.GetSpan(Address, Size));
}
/// <summary>

View file

@ -27,23 +27,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <returns>Byte array with the data</returns>
public byte[] ReadBytes(ulong gpuVa, ulong size)
{
return Read(gpuVa, size).ToArray();
return GetSpan(gpuVa, size).ToArray();
}
/// <summary>
/// Reads data from GPU mapped memory.
/// Gets a read-only span of data from GPU mapped memory.
/// This reads as much data as possible, up to the specified maximum size.
/// </summary>
/// <param name="gpuVa">GPU virtual address where the data is located</param>
/// <param name="maxSize">Maximum size of the data</param>
/// <returns>The data at the specified memory location</returns>
public Span<byte> Read(ulong gpuVa, ulong maxSize)
/// <returns>The span of the data at the specified memory location</returns>
public ReadOnlySpan<byte> GetSpan(ulong gpuVa, ulong maxSize)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
ulong size = Math.Min(_context.MemoryManager.GetSubSize(gpuVa), maxSize);
return _context.PhysicalMemory.Read(processVa, size);
return _context.PhysicalMemory.GetSpan(processVa, size);
}
/// <summary>
@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong size = (uint)Marshal.SizeOf<T>();
return MemoryMarshal.Cast<byte, T>(_context.PhysicalMemory.Read(processVa, size))[0];
return MemoryMarshal.Cast<byte, T>(_context.PhysicalMemory.GetSpan(processVa, size))[0];
}
/// <summary>
@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
return BitConverter.ToInt32(_context.PhysicalMemory.Read(processVa, 4));
return BitConverter.ToInt32(_context.PhysicalMemory.GetSpan(processVa, 4));
}
/// <summary>
@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
return BitConverter.ToUInt64(_context.PhysicalMemory.Read(processVa, 8));
return BitConverter.ToUInt64(_context.PhysicalMemory.GetSpan(processVa, 8));
}
/// <summary>

View file

@ -22,14 +22,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
/// <summary>
/// Reads data from the application process.
/// Gets a span of data from the application process.
/// </summary>
/// <param name="address">Address to be read</param>
/// <param name="size">Size in bytes to be read</param>
/// <returns>The data at the specified memory location</returns>
public Span<byte> Read(ulong address, ulong size)
/// <param name="address">Start address of the range</param>
/// <param name="size">Size in bytes to be range</param>
/// <returns>A read only span of the data at the specified memory location</returns>
public ReadOnlySpan<byte> GetSpan(ulong address, ulong size)
{
return _cpuMemory.ReadBytes((long)address, (long)size);
return _cpuMemory.GetSpan(address, size);
}
/// <summary>
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary>
/// <param name="address">Address to write into</param>
/// <param name="data">Data to be written</param>
public void Write(ulong address, Span<byte> data)
public void Write(ulong address, ReadOnlySpan<byte> data)
{
_cpuMemory.WriteBytes((long)address, data.ToArray());
}

View file

@ -154,7 +154,7 @@ namespace Ryujinx.Graphics.Gpu
{
_context.Methods.PerformDeferredDraws();
_context.Renderer.FlushPipelines();
_context.Renderer.Pipeline.Barrier();
break;
}

View file

@ -265,7 +265,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
ShaderProgram program;
Span<byte> code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize);
ReadOnlySpan<byte> code = _context.MemoryAccessor.GetSpan(gpuVa, MaxProgramSize);
program = Translator.Translate(code, callbacks, DefaultFlags | TranslationFlags.Compute);
@ -319,8 +319,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
if (gpuVaA != 0)
{
Span<byte> codeA = _context.MemoryAccessor.Read(gpuVaA, MaxProgramSize);
Span<byte> codeB = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize);
ReadOnlySpan<byte> codeA = _context.MemoryAccessor.GetSpan(gpuVaA, MaxProgramSize);
ReadOnlySpan<byte> codeB = _context.MemoryAccessor.GetSpan(gpuVa, MaxProgramSize);
program = Translator.Translate(codeA, codeB, callbacks, DefaultFlags);
@ -340,7 +340,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
else
{
Span<byte> code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize);
ReadOnlySpan<byte> code = _context.MemoryAccessor.GetSpan(gpuVa, MaxProgramSize);
program = Translator.Translate(code, callbacks, DefaultFlags);

View file

@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <param name="compute">True for compute shader code, false for graphics shader code</param>
/// <param name="fullPath">Output path for the shader code with header included</param>
/// <param name="codePath">Output path for the shader code without header</param>
public void Dump(Span<byte> code, bool compute, out string fullPath, out string codePath)
public void Dump(ReadOnlySpan<byte> code, bool compute, out string fullPath, out string codePath)
{
_dumpPath = GraphicsConfig.ShadersDumpPath;

View file

@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.OpenGL
return data;
}
public void SetData(Span<byte> data)
public void SetData(ReadOnlySpan<byte> data)
{
unsafe
{
@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.OpenGL
}
}
public void SetData(int offset, Span<byte> data)
public void SetData(int offset, ReadOnlySpan<byte> data)
{
GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle);

View file

@ -37,6 +37,11 @@ namespace Ryujinx.Graphics.OpenGL
_clipDepthMode = ClipDepthMode.NegativeOneToOne;
}
public void Barrier()
{
GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits);
}
public void ClearRenderTargetColor(int index, uint componentMask, ColorF color)
{
GL.ColorMask(
@ -165,26 +170,35 @@ namespace Ryujinx.Graphics.OpenGL
int firstVertex,
int firstInstance)
{
// TODO: Instanced rendering.
int quadsCount = (vertexCount - 2) / 2;
int[] firsts = new int[quadsCount];
int[] counts = new int[quadsCount];
firsts[0] = firstVertex;
counts[0] = 4;
for (int quadIndex = 1; quadIndex < quadsCount; quadIndex++)
if (firstInstance != 0 || instanceCount != 1)
{
firsts[quadIndex] = firstVertex + quadIndex * 2;
counts[quadIndex] = 4;
for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
{
GL.DrawArraysInstancedBaseInstance(PrimitiveType.TriangleFan, firstVertex + quadIndex * 2, 4, instanceCount, firstInstance);
}
}
else
{
int[] firsts = new int[quadsCount];
int[] counts = new int[quadsCount];
GL.MultiDrawArrays(
PrimitiveType.TriangleFan,
firsts,
counts,
quadsCount);
firsts[0] = firstVertex;
counts[0] = 4;
for (int quadIndex = 1; quadIndex < quadsCount; quadIndex++)
{
firsts[quadIndex] = firstVertex + quadIndex * 2;
counts[quadIndex] = 4;
}
GL.MultiDrawArrays(
PrimitiveType.TriangleFan,
firsts,
counts,
quadsCount);
}
}
private void DrawImpl(
@ -277,31 +291,75 @@ namespace Ryujinx.Graphics.OpenGL
int firstVertex,
int firstInstance)
{
// TODO: Instanced rendering.
int quadsCount = indexCount / 4;
IntPtr[] indices = new IntPtr[quadsCount];
int[] counts = new int[quadsCount];
int[] baseVertices = new int[quadsCount];
for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
if (firstInstance != 0 || instanceCount != 1)
{
indices[quadIndex] = indexBaseOffset + quadIndex * 4 * indexElemSize;
counts[quadIndex] = 4;
baseVertices[quadIndex] = firstVertex;
if (firstVertex != 0 && firstInstance != 0)
{
for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
{
GL.DrawElementsInstancedBaseVertexBaseInstance(
PrimitiveType.TriangleFan,
4,
_elementsType,
indexBaseOffset + quadIndex * 4 * indexElemSize,
instanceCount,
firstVertex,
firstInstance);
}
}
else if (firstInstance != 0)
{
for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
{
GL.DrawElementsInstancedBaseInstance(
PrimitiveType.TriangleFan,
4,
_elementsType,
indexBaseOffset + quadIndex * 4 * indexElemSize,
instanceCount,
firstInstance);
}
}
else
{
for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
{
GL.DrawElementsInstanced(
PrimitiveType.TriangleFan,
4,
_elementsType,
indexBaseOffset + quadIndex * 4 * indexElemSize,
instanceCount);
}
}
}
else
{
IntPtr[] indices = new IntPtr[quadsCount];
GL.MultiDrawElementsBaseVertex(
PrimitiveType.TriangleFan,
counts,
_elementsType,
indices,
quadsCount,
baseVertices);
int[] counts = new int[quadsCount];
int[] baseVertices = new int[quadsCount];
for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++)
{
indices[quadIndex] = indexBaseOffset + quadIndex * 4 * indexElemSize;
counts[quadIndex] = 4;
baseVertices[quadIndex] = firstVertex;
}
GL.MultiDrawElementsBaseVertex(
PrimitiveType.TriangleFan,
counts,
_elementsType,
indices,
quadsCount,
baseVertices);
}
}
private void DrawQuadStripIndexedImpl(

View file

@ -55,11 +55,6 @@ namespace Ryujinx.Graphics.OpenGL
return new TextureStorage(this, info).CreateDefaultView();
}
public void FlushPipelines()
{
GL.Finish();
}
public Capabilities GetCapabilities()
{
return new Capabilities(

View file

@ -217,7 +217,7 @@ namespace Ryujinx.Graphics.OpenGL
}
}
public void SetData(Span<byte> data)
public void SetData(ReadOnlySpan<byte> data)
{
unsafe
{

View file

@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
_opActivators = new ConcurrentDictionary<Type, OpActivator>();
}
public static Block[] Decode(Span<byte> code, ulong headerSize)
public static Block[] Decode(ReadOnlySpan<byte> code, ulong headerSize)
{
List<Block> blocks = new List<Block>();
@ -214,10 +214,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
private static void FillBlock(
Span<byte> code,
Block block,
ulong limitAddress,
ulong startAddress)
ReadOnlySpan<byte> code,
Block block,
ulong limitAddress,
ulong startAddress)
{
ulong address = block.Address;

View file

@ -76,9 +76,9 @@ namespace Ryujinx.Graphics.Shader.Translation
public bool OmapSampleMask { get; }
public bool OmapDepth { get; }
public ShaderHeader(Span<byte> code)
public ShaderHeader(ReadOnlySpan<byte> code)
{
Span<int> header = MemoryMarshal.Cast<byte, int>(code);
ReadOnlySpan<int> header = MemoryMarshal.Cast<byte, int>(code);
int commonWord0 = header[0];
int commonWord1 = header[1];

View file

@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{
private const int HeaderSize = 0x50;
public static Span<byte> ExtractCode(Span<byte> code, bool compute, out int headerSize)
public static ReadOnlySpan<byte> ExtractCode(ReadOnlySpan<byte> code, bool compute, out int headerSize)
{
headerSize = compute ? 0 : HeaderSize;
@ -38,14 +38,14 @@ namespace Ryujinx.Graphics.Shader.Translation
return code.Slice(0, headerSize + (int)endAddress);
}
public static ShaderProgram Translate(Span<byte> code, TranslatorCallbacks callbacks, TranslationFlags flags)
public static ShaderProgram Translate(ReadOnlySpan<byte> code, TranslatorCallbacks callbacks, TranslationFlags flags)
{
Operation[] ops = DecodeShader(code, callbacks, flags, out ShaderConfig config, out int size);
return Translate(ops, config, size);
}
public static ShaderProgram Translate(Span<byte> vpACode, Span<byte> vpBCode, TranslatorCallbacks callbacks, TranslationFlags flags)
public static ShaderProgram Translate(ReadOnlySpan<byte> vpACode, ReadOnlySpan<byte> vpBCode, TranslatorCallbacks callbacks, TranslationFlags flags)
{
Operation[] vpAOps = DecodeShader(vpACode, callbacks, flags, out _, out _);
Operation[] vpBOps = DecodeShader(vpBCode, callbacks, flags, out ShaderConfig config, out int sizeB);
@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Shader.Translation
}
private static Operation[] DecodeShader(
Span<byte> code,
ReadOnlySpan<byte> code,
TranslatorCallbacks callbacks,
TranslationFlags flags,
out ShaderConfig config,

View file

@ -28,6 +28,8 @@ namespace Ryujinx.HLE.FileSystem.Content
private Switch _device;
private readonly object _lock = new object();
public ContentManager(Switch device)
{
_contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>();
@ -58,139 +60,151 @@ namespace Ryujinx.HLE.FileSystem.Content
public void LoadEntries(bool ignoreMissingFonts = false)
{
_contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>();
_locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>();
foreach (StorageId storageId in Enum.GetValues(typeof(StorageId)))
lock (_lock)
{
string contentDirectory = null;
string contentPathString = null;
string registeredDirectory = null;
_contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>();
_locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>();
try
foreach (StorageId storageId in Enum.GetValues(typeof(StorageId)))
{
contentPathString = LocationHelper.GetContentRoot(storageId);
contentDirectory = LocationHelper.GetRealPath(_device.FileSystem, contentPathString);
registeredDirectory = Path.Combine(contentDirectory, "registered");
}
catch (NotSupportedException)
{
continue;
}
string contentDirectory = null;
string contentPathString = null;
string registeredDirectory = null;
Directory.CreateDirectory(registeredDirectory);
LinkedList<LocationEntry> locationList = new LinkedList<LocationEntry>();
void AddEntry(LocationEntry entry)
{
locationList.AddLast(entry);
}
foreach (string directoryPath in Directory.EnumerateDirectories(registeredDirectory))
{
if (Directory.GetFiles(directoryPath).Length > 0)
try
{
string ncaName = new DirectoryInfo(directoryPath).Name.Replace(".nca", string.Empty);
contentPathString = LocationHelper.GetContentRoot(storageId);
contentDirectory = LocationHelper.GetRealPath(_device.FileSystem, contentPathString);
registeredDirectory = Path.Combine(contentDirectory, "registered");
}
catch (NotSupportedException)
{
continue;
}
using (FileStream ncaFile = new FileStream(Directory.GetFiles(directoryPath)[0], FileMode.Open, FileAccess.Read))
Directory.CreateDirectory(registeredDirectory);
LinkedList<LocationEntry> locationList = new LinkedList<LocationEntry>();
void AddEntry(LocationEntry entry)
{
locationList.AddLast(entry);
}
foreach (string directoryPath in Directory.EnumerateDirectories(registeredDirectory))
{
if (Directory.GetFiles(directoryPath).Length > 0)
{
Nca nca = new Nca(_device.System.KeySet, ncaFile.AsStorage());
string ncaName = new DirectoryInfo(directoryPath).Name.Replace(".nca", string.Empty);
string switchPath = contentPathString + ":/" + ncaFile.Name.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar);
using (FileStream ncaFile = File.OpenRead(Directory.GetFiles(directoryPath)[0]))
{
Nca nca = new Nca(_device.System.KeySet, ncaFile.AsStorage());
// Change path format to switch's
switchPath = switchPath.Replace('\\', '/');
string switchPath = contentPathString + ":/" + ncaFile.Name.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar);
LocationEntry entry = new LocationEntry(switchPath,
0,
(long)nca.Header.TitleId,
nca.Header.ContentType);
// Change path format to switch's
switchPath = switchPath.Replace('\\', '/');
AddEntry(entry);
LocationEntry entry = new LocationEntry(switchPath,
0,
(long)nca.Header.TitleId,
nca.Header.ContentType);
_contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
AddEntry(entry);
_contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
}
}
}
foreach (string filePath in Directory.EnumerateFiles(contentDirectory))
{
if (Path.GetExtension(filePath) == ".nca")
{
string ncaName = Path.GetFileNameWithoutExtension(filePath);
using (FileStream ncaFile = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
Nca nca = new Nca(_device.System.KeySet, ncaFile.AsStorage());
string switchPath = contentPathString + ":/" + filePath.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar);
// Change path format to switch's
switchPath = switchPath.Replace('\\', '/');
LocationEntry entry = new LocationEntry(switchPath,
0,
(long)nca.Header.TitleId,
nca.Header.ContentType);
AddEntry(entry);
_contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
}
}
}
if (_locationEntries.ContainsKey(storageId) && _locationEntries[storageId]?.Count == 0)
{
_locationEntries.Remove(storageId);
}
if (!_locationEntries.ContainsKey(storageId))
{
_locationEntries.Add(storageId, locationList);
}
}
foreach (string filePath in Directory.EnumerateFiles(contentDirectory))
{
if (Path.GetExtension(filePath) == ".nca")
{
string ncaName = Path.GetFileNameWithoutExtension(filePath);
TimeManager.Instance.InitializeTimeZone(_device);
using (FileStream ncaFile = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
Nca nca = new Nca(_device.System.KeySet, ncaFile.AsStorage());
string switchPath = contentPathString + ":/" + filePath.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar);
// Change path format to switch's
switchPath = switchPath.Replace('\\', '/');
LocationEntry entry = new LocationEntry(switchPath,
0,
(long)nca.Header.TitleId,
nca.Header.ContentType);
AddEntry(entry);
_contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
}
}
}
if (_locationEntries.ContainsKey(storageId) && _locationEntries[storageId]?.Count == 0)
{
_locationEntries.Remove(storageId);
}
if (!_locationEntries.ContainsKey(storageId))
{
_locationEntries.Add(storageId, locationList);
}
_device.System.Font.Initialize(this, ignoreMissingFonts);
}
TimeManager.Instance.InitializeTimeZone(_device);
_device.System.Font.Initialize(this, ignoreMissingFonts);
}
public void ClearEntry(long titleId, NcaContentType contentType, StorageId storageId)
{
RemoveLocationEntry(titleId, contentType, storageId);
lock (_lock)
{
RemoveLocationEntry(titleId, contentType, storageId);
}
}
public void RefreshEntries(StorageId storageId, int flag)
{
LinkedList<LocationEntry> locationList = _locationEntries[storageId];
LinkedListNode<LocationEntry> locationEntry = locationList.First;
while (locationEntry != null)
lock (_lock)
{
LinkedListNode<LocationEntry> nextLocationEntry = locationEntry.Next;
LinkedList<LocationEntry> locationList = _locationEntries[storageId];
LinkedListNode<LocationEntry> locationEntry = locationList.First;
if (locationEntry.Value.Flag == flag)
while (locationEntry != null)
{
locationList.Remove(locationEntry.Value);
}
LinkedListNode<LocationEntry> nextLocationEntry = locationEntry.Next;
locationEntry = nextLocationEntry;
if (locationEntry.Value.Flag == flag)
{
locationList.Remove(locationEntry.Value);
}
locationEntry = nextLocationEntry;
}
}
}
public bool HasNca(string ncaId, StorageId storageId)
{
if (_contentDictionary.ContainsValue(ncaId))
lock (_lock)
{
var content = _contentDictionary.FirstOrDefault(x => x.Value == ncaId);
long titleId = (long)content.Key.Item1;
if (_contentDictionary.ContainsValue(ncaId))
{
var content = _contentDictionary.FirstOrDefault(x => x.Value == ncaId);
long titleId = (long)content.Key.Item1;
NcaContentType contentType = content.Key.type;
StorageId storage = GetInstalledStorage(titleId, contentType, storageId);
NcaContentType contentType = content.Key.type;
StorageId storage = GetInstalledStorage(titleId, contentType, storageId);
return storage == storageId;
return storage == storageId;
}
}
return false;
@ -198,9 +212,12 @@ namespace Ryujinx.HLE.FileSystem.Content
public UInt128 GetInstalledNcaId(long titleId, NcaContentType contentType)
{
if (_contentDictionary.ContainsKey(((ulong)titleId, contentType)))
lock (_lock)
{
return new UInt128(_contentDictionary[((ulong)titleId, contentType)]);
if (_contentDictionary.ContainsKey(((ulong)titleId, contentType)))
{
return new UInt128(_contentDictionary[((ulong)titleId, contentType)]);
}
}
return new UInt128();
@ -208,19 +225,25 @@ namespace Ryujinx.HLE.FileSystem.Content
public StorageId GetInstalledStorage(long titleId, NcaContentType contentType, StorageId storageId)
{
LocationEntry locationEntry = GetLocation(titleId, contentType, storageId);
lock (_lock)
{
LocationEntry locationEntry = GetLocation(titleId, contentType, storageId);
return locationEntry.ContentPath != null ?
LocationHelper.GetStorageId(locationEntry.ContentPath) : StorageId.None;
return locationEntry.ContentPath != null ?
LocationHelper.GetStorageId(locationEntry.ContentPath) : StorageId.None;
}
}
public string GetInstalledContentPath(long titleId, StorageId storageId, NcaContentType contentType)
{
LocationEntry locationEntry = GetLocation(titleId, contentType, storageId);
if (VerifyContentType(locationEntry, contentType))
lock (_lock)
{
return locationEntry.ContentPath;
LocationEntry locationEntry = GetLocation(titleId, contentType, storageId);
if (VerifyContentType(locationEntry, contentType))
{
return locationEntry.ContentPath;
}
}
return string.Empty;
@ -228,14 +251,17 @@ namespace Ryujinx.HLE.FileSystem.Content
public void RedirectLocation(LocationEntry newEntry, StorageId storageId)
{
LocationEntry locationEntry = GetLocation(newEntry.TitleId, newEntry.ContentType, storageId);
if (locationEntry.ContentPath != null)
lock (_lock)
{
RemoveLocationEntry(newEntry.TitleId, newEntry.ContentType, storageId);
}
LocationEntry locationEntry = GetLocation(newEntry.TitleId, newEntry.ContentType, storageId);
AddLocationEntry(newEntry, storageId);
if (locationEntry.ContentPath != null)
{
RemoveLocationEntry(newEntry.TitleId, newEntry.ContentType, storageId);
}
AddLocationEntry(newEntry, storageId);
}
}
private bool VerifyContentType(LocationEntry locationEntry, NcaContentType contentType)
@ -827,28 +853,31 @@ namespace Ryujinx.HLE.FileSystem.Content
{
LoadEntries(true);
var locationEnties = _locationEntries[StorageId.NandSystem];
foreach (var entry in locationEnties)
lock (_lock)
{
if (entry.ContentType == NcaContentType.Data)
var locationEnties = _locationEntries[StorageId.NandSystem];
foreach (var entry in locationEnties)
{
var path = _device.FileSystem.SwitchPathToSystemPath(entry.ContentPath);
using (IStorage ncaStorage = File.Open(path, FileMode.Open).AsStorage())
if (entry.ContentType == NcaContentType.Data)
{
Nca nca = new Nca(_device.System.KeySet, ncaStorage);
var path = _device.FileSystem.SwitchPathToSystemPath(entry.ContentPath);
if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data)
using (FileStream fileStream = File.OpenRead(path))
{
var romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel);
Nca nca = new Nca(_device.System.KeySet, fileStream.AsStorage());
if (romfs.OpenFile(out IFile systemVersionFile, "/file", OpenMode.Read).IsSuccess())
if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data)
{
return new SystemVersion(systemVersionFile.AsStream());
}
}
var romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel);
if (romfs.OpenFile(out IFile systemVersionFile, "/file", OpenMode.Read).IsSuccess())
{
return new SystemVersion(systemVersionFile.AsStream());
}
}
}
}
}
}

View file

@ -33,7 +33,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
_keepRunning = true;
Thread work = new Thread(WaitAndCheckScheduledObjects);
Thread work = new Thread(WaitAndCheckScheduledObjects)
{
Name = "HLE.TimeManager"
};
work.Start();
}

View file

@ -17,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
public void StartAutoPreemptionThread()
{
Thread preemptionThread = new Thread(PreemptCurrentThread);
Thread preemptionThread = new Thread(PreemptCurrentThread)
{
Name = "HLE.PreemptionThread"
};
_keepPreempting = true;

View file

@ -159,7 +159,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
is64Bits = true;
}
HostThread = new Thread(customHostThreadStart == null ? () => ThreadStart(entrypoint) : customHostThreadStart);
HostThread = new Thread(customHostThreadStart ?? (() => ThreadStart(entrypoint)));
Context = new ARMeilleure.State.ExecutionContext();
@ -185,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
ThreadUid = System.GetThreadUid();
HostThread.Name = $"Host Thread (thread id {ThreadUid})";
HostThread.Name = $"HLE.HostThread.{ThreadUid}";
_hasBeenInitialized = true;

View file

@ -55,7 +55,10 @@ namespace Ryujinx.Profiler
_cleanupRunning = true;
// Create cleanup thread.
_cleanupThread = new Thread(CleanupLoop);
_cleanupThread = new Thread(CleanupLoop)
{
Name = "Profiler.CleanupThread"
};
_cleanupThread.Start();
}

View file

@ -21,7 +21,10 @@ namespace Ryujinx.Profiler.UI
{
_profilerRunning = true;
_prevTime = 0;
_profileThread = new Thread(ProfileLoop);
_profileThread = new Thread(ProfileLoop)
{
Name = "Profiler.ProfileThread"
};
_profileThread.Start();
}
}
@ -60,7 +63,10 @@ namespace Ryujinx.Profiler.UI
using (_window = new ProfileWindow())
{
// Create thread for render loop
_renderThread = new Thread(RenderLoop);
_renderThread = new Thread(RenderLoop)
{
Name = "Profiler.RenderThread"
};
_renderThread.Start();
while (_profilerRunning)

View file

@ -1,9 +0,0 @@
namespace Ryujinx.Ui
{
internal struct AboutInfo
{
public string InstallVersion;
public string InstallCommit;
public string InstallBranch;
}
}

View file

@ -13,8 +13,6 @@ namespace Ryujinx.Ui
{
public class AboutWindow : Window
{
private static AboutInfo AboutInformation { get; set; }
#pragma warning disable CS0649
#pragma warning disable IDE0044
[GUI] Window _aboutWin;

View file

@ -120,7 +120,10 @@ namespace Ryujinx.Ui
Context.MakeCurrent(null);
// OpenTK doesn't like sleeps in its thread, to avoid this a renderer thread is created
_renderThread = new Thread(RenderLoop);
_renderThread = new Thread(RenderLoop)
{
Name = "GUI.RenderThread"
};
_renderThread.Start();

View file

@ -656,6 +656,7 @@ namespace Ryujinx.Ui
}
});
thread.Name = "GUI.FirmwareInstallerThread";
thread.Start();
}
else