Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
b1bd6a50b5 | |||
70895bdb04 | |||
830cbf91bb | |||
9a9349f0f4 | |||
46cc7b55f0 | |||
dd8f97ab9e | |||
633c5ec330 |
@ -14,10 +14,11 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
public byte Kind;
|
public byte Kind;
|
||||||
public byte Type;
|
public byte Type;
|
||||||
public byte SymbolType;
|
public byte SymbolType;
|
||||||
|
public byte Padding; // Unused space.
|
||||||
public ushort AssignmentsCount;
|
public ushort AssignmentsCount;
|
||||||
public ushort AssignmentsCapacity;
|
public ushort AssignmentsCapacity;
|
||||||
public ushort UsesCount;
|
public uint UsesCount;
|
||||||
public ushort UsesCapacity;
|
public uint UsesCapacity;
|
||||||
public Operation* Assignments;
|
public Operation* Assignments;
|
||||||
public Operation* Uses;
|
public Operation* Uses;
|
||||||
public ulong Value;
|
public ulong Value;
|
||||||
@ -84,11 +85,11 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
{
|
{
|
||||||
Debug.Assert(Kind != OperandKind.Memory);
|
Debug.Assert(Kind != OperandKind.Memory);
|
||||||
|
|
||||||
return new ReadOnlySpan<Operation>(_data->Uses, _data->UsesCount);
|
return new ReadOnlySpan<Operation>(_data->Uses, (int)_data->UsesCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int UsesCount => _data->UsesCount;
|
public int UsesCount => (int)_data->UsesCount;
|
||||||
public int AssignmentsCount => _data->AssignmentsCount;
|
public int AssignmentsCount => _data->AssignmentsCount;
|
||||||
|
|
||||||
public bool Relocatable => Symbol.Type != SymbolType.None;
|
public bool Relocatable => Symbol.Type != SymbolType.None;
|
||||||
@ -265,6 +266,13 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
data = Allocators.References.Allocate<T>(initialCapacity);
|
data = Allocators.References.Allocate<T>(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void New<T>(ref T* data, ref uint count, ref uint capacity, uint initialCapacity) where T : unmanaged
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
capacity = initialCapacity;
|
||||||
|
data = Allocators.References.Allocate<T>(initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
private static void Add<T>(T item, ref T* data, ref ushort count, ref ushort capacity) where T : unmanaged
|
private static void Add<T>(T item, ref T* data, ref ushort count, ref ushort capacity) where T : unmanaged
|
||||||
{
|
{
|
||||||
if (count < capacity)
|
if (count < capacity)
|
||||||
@ -294,6 +302,40 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void Add<T>(T item, ref T* data, ref uint count, ref uint capacity) where T : unmanaged
|
||||||
|
{
|
||||||
|
if (count < capacity)
|
||||||
|
{
|
||||||
|
data[count++] = item;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could not add item in the fast path, fallback onto the slow path.
|
||||||
|
ExpandAdd(item, ref data, ref count, ref capacity);
|
||||||
|
|
||||||
|
static void ExpandAdd(T item, ref T* data, ref uint count, ref uint capacity)
|
||||||
|
{
|
||||||
|
uint newCount = checked(count + 1);
|
||||||
|
uint newCapacity = (uint)Math.Min(capacity * 2, int.MaxValue);
|
||||||
|
|
||||||
|
if (newCapacity <= capacity)
|
||||||
|
{
|
||||||
|
throw new OverflowException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldSpan = new Span<T>(data, (int)count);
|
||||||
|
|
||||||
|
capacity = newCapacity;
|
||||||
|
data = Allocators.References.Allocate<T>(capacity);
|
||||||
|
|
||||||
|
oldSpan.CopyTo(new Span<T>(data, (int)count));
|
||||||
|
|
||||||
|
data[count] = item;
|
||||||
|
count = newCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged
|
private static void Remove<T>(in T item, ref T* data, ref ushort count) where T : unmanaged
|
||||||
{
|
{
|
||||||
var span = new Span<T>(data, count);
|
var span = new Span<T>(data, count);
|
||||||
@ -314,6 +356,26 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void Remove<T>(in T item, ref T* data, ref uint count) where T : unmanaged
|
||||||
|
{
|
||||||
|
var span = new Span<T>(data, (int)count);
|
||||||
|
|
||||||
|
for (int i = 0; i < span.Length; i++)
|
||||||
|
{
|
||||||
|
if (EqualityComparer<T>.Default.Equals(span[i], item))
|
||||||
|
{
|
||||||
|
if (i + 1 < count)
|
||||||
|
{
|
||||||
|
span.Slice(i + 1).CopyTo(span.Slice(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
count--;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
if (Kind == OperandKind.LocalVariable)
|
if (Kind == OperandKind.LocalVariable)
|
||||||
|
@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
private bool _instancedDrawPending;
|
private bool _instancedDrawPending;
|
||||||
private bool _instancedIndexed;
|
private bool _instancedIndexed;
|
||||||
|
private bool _instancedIndexedInline;
|
||||||
|
|
||||||
private int _instancedFirstIndex;
|
private int _instancedFirstIndex;
|
||||||
private int _instancedFirstVertex;
|
private int _instancedFirstVertex;
|
||||||
@ -134,13 +135,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
{
|
{
|
||||||
_instancedDrawPending = true;
|
_instancedDrawPending = true;
|
||||||
|
|
||||||
|
int ibCount = _drawState.IbStreamer.InlineIndexCount;
|
||||||
|
|
||||||
_instancedIndexed = _drawState.DrawIndexed;
|
_instancedIndexed = _drawState.DrawIndexed;
|
||||||
|
_instancedIndexedInline = ibCount != 0;
|
||||||
|
|
||||||
_instancedFirstIndex = firstIndex;
|
_instancedFirstIndex = firstIndex;
|
||||||
_instancedFirstVertex = (int)_state.State.FirstVertex;
|
_instancedFirstVertex = (int)_state.State.FirstVertex;
|
||||||
_instancedFirstInstance = (int)_state.State.FirstInstance;
|
_instancedFirstInstance = (int)_state.State.FirstInstance;
|
||||||
|
|
||||||
_instancedIndexCount = indexCount;
|
_instancedIndexCount = ibCount != 0 ? ibCount : indexCount;
|
||||||
|
|
||||||
var drawState = _state.State.VertexBufferDrawState;
|
var drawState = _state.State.VertexBufferDrawState;
|
||||||
|
|
||||||
@ -451,8 +455,18 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
{
|
{
|
||||||
_instancedDrawPending = false;
|
_instancedDrawPending = false;
|
||||||
|
|
||||||
if (_instancedIndexed)
|
bool indexedInline = _instancedIndexedInline;
|
||||||
|
|
||||||
|
if (_instancedIndexed || indexedInline)
|
||||||
{
|
{
|
||||||
|
if (indexedInline)
|
||||||
|
{
|
||||||
|
int inlineIndexCount = _drawState.IbStreamer.GetAndResetInlineIndexCount();
|
||||||
|
BufferRange br = new BufferRange(_drawState.IbStreamer.GetInlineIndexBuffer(), 0, inlineIndexCount * 4);
|
||||||
|
|
||||||
|
_channel.BufferManager.SetIndexBuffer(br, IndexType.UInt);
|
||||||
|
}
|
||||||
|
|
||||||
_context.Renderer.Pipeline.DrawIndexed(
|
_context.Renderer.Pipeline.DrawIndexed(
|
||||||
_instancedIndexCount,
|
_instancedIndexCount,
|
||||||
_instanceIndex + 1,
|
_instanceIndex + 1,
|
||||||
|
@ -20,6 +20,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasInlineIndexData => _inlineIndexCount != 0;
|
public bool HasInlineIndexData => _inlineIndexCount != 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Total numbers of indices that have been pushed.
|
||||||
|
/// </summary>
|
||||||
|
public int InlineIndexCount => _inlineIndexCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the handle for the host buffer currently holding the inline index buffer data.
|
/// Gets the handle for the host buffer currently holding the inline index buffer data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -597,6 +597,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
GL.EndTransformFeedback();
|
GL.EndTransformFeedback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GL.ClipControl(ClipOrigin.UpperLeft, ClipDepthMode.NegativeOneToOne);
|
||||||
|
|
||||||
_drawTexture.Draw(
|
_drawTexture.Draw(
|
||||||
view,
|
view,
|
||||||
samp,
|
samp,
|
||||||
@ -627,6 +629,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
GL.BeginTransformFeedback(_tfTopology);
|
GL.BeginTransformFeedback(_tfTopology);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RestoreClipControl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -735,11 +735,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||||||
ulong argsPtr,
|
ulong argsPtr,
|
||||||
ulong stackTop,
|
ulong stackTop,
|
||||||
int priority,
|
int priority,
|
||||||
int cpuCore)
|
int cpuCore,
|
||||||
|
ThreadStart customThreadStart = null)
|
||||||
{
|
{
|
||||||
lock (_processLock)
|
lock (_processLock)
|
||||||
{
|
{
|
||||||
return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this, ThreadType.User, null);
|
return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this, ThreadType.User, customThreadStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2350,6 +2350,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||||||
[PointerSized] ulong stackTop,
|
[PointerSized] ulong stackTop,
|
||||||
int priority,
|
int priority,
|
||||||
int cpuCore)
|
int cpuCore)
|
||||||
|
{
|
||||||
|
return CreateThread(out handle, entrypoint, argsPtr, stackTop, priority, cpuCore, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult CreateThread(
|
||||||
|
out int handle,
|
||||||
|
ulong entrypoint,
|
||||||
|
ulong argsPtr,
|
||||||
|
ulong stackTop,
|
||||||
|
int priority,
|
||||||
|
int cpuCore,
|
||||||
|
ThreadStart customThreadStart)
|
||||||
{
|
{
|
||||||
handle = 0;
|
handle = 0;
|
||||||
|
|
||||||
@ -2386,7 +2398,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||||||
argsPtr,
|
argsPtr,
|
||||||
stackTop,
|
stackTop,
|
||||||
priority,
|
priority,
|
||||||
cpuCore);
|
cpuCore,
|
||||||
|
customThreadStart);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == KernelResult.Success)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
@ -38,15 +39,15 @@ namespace Ryujinx.HLE.HOS.Services
|
|||||||
private readonly Dictionary<int, Func<IpcService>> _ports = new Dictionary<int, Func<IpcService>>();
|
private readonly Dictionary<int, Func<IpcService>> _ports = new Dictionary<int, Func<IpcService>>();
|
||||||
|
|
||||||
public ManualResetEvent InitDone { get; }
|
public ManualResetEvent InitDone { get; }
|
||||||
public Func<IpcService> SmObjectFactory { get; }
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
public Func<IpcService> SmObjectFactory { get; }
|
||||||
|
|
||||||
public ServerBase(KernelContext context, string name, Func<IpcService> smObjectFactory = null)
|
public ServerBase(KernelContext context, string name, Func<IpcService> smObjectFactory = null)
|
||||||
{
|
{
|
||||||
InitDone = new ManualResetEvent(false);
|
InitDone = new ManualResetEvent(false);
|
||||||
|
_context = context;
|
||||||
Name = name;
|
Name = name;
|
||||||
SmObjectFactory = smObjectFactory;
|
SmObjectFactory = smObjectFactory;
|
||||||
_context = context;
|
|
||||||
|
|
||||||
const ProcessCreationFlags flags =
|
const ProcessCreationFlags flags =
|
||||||
ProcessCreationFlags.EnableAslr |
|
ProcessCreationFlags.EnableAslr |
|
||||||
@ -56,7 +57,7 @@ namespace Ryujinx.HLE.HOS.Services
|
|||||||
|
|
||||||
ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0);
|
ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0);
|
||||||
|
|
||||||
KernelStatic.StartInitialProcess(context, creationInfo, DefaultCapabilities, 44, ServerLoop);
|
KernelStatic.StartInitialProcess(context, creationInfo, DefaultCapabilities, 44, Main);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddPort(int serverPortHandle, Func<IpcService> objectFactory)
|
private void AddPort(int serverPortHandle, Func<IpcService> objectFactory)
|
||||||
@ -80,6 +81,11 @@ namespace Ryujinx.HLE.HOS.Services
|
|||||||
_sessions.Add(serverSessionHandle, obj);
|
_sessions.Add(serverSessionHandle, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Main()
|
||||||
|
{
|
||||||
|
ServerLoop();
|
||||||
|
}
|
||||||
|
|
||||||
private void ServerLoop()
|
private void ServerLoop()
|
||||||
{
|
{
|
||||||
_selfProcess = KernelStatic.GetCurrentProcess();
|
_selfProcess = KernelStatic.GetCurrentProcess();
|
||||||
|
@ -8,7 +8,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
{
|
{
|
||||||
private ulong _value;
|
private ulong _value;
|
||||||
private readonly EventFdFlags _flags;
|
private readonly EventFdFlags _flags;
|
||||||
private AutoResetEvent _event;
|
|
||||||
|
|
||||||
private object _lock = new object();
|
private object _lock = new object();
|
||||||
|
|
||||||
@ -19,9 +18,13 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
|
|
||||||
public EventFileDescriptor(ulong value, EventFdFlags flags)
|
public EventFileDescriptor(ulong value, EventFdFlags flags)
|
||||||
{
|
{
|
||||||
|
// FIXME: We should support blocking operations.
|
||||||
|
// Right now they can't be supported because it would cause the
|
||||||
|
// service to lock up as we only have one thread processing requests.
|
||||||
|
flags |= EventFdFlags.NonBlocking;
|
||||||
|
|
||||||
_value = value;
|
_value = value;
|
||||||
_flags = flags;
|
_flags = flags;
|
||||||
_event = new AutoResetEvent(false);
|
|
||||||
|
|
||||||
WriteEvent = new ManualResetEvent(true);
|
WriteEvent = new ManualResetEvent(true);
|
||||||
ReadEvent = new ManualResetEvent(true);
|
ReadEvent = new ManualResetEvent(true);
|
||||||
@ -31,7 +34,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_event.Dispose();
|
|
||||||
WriteEvent.Dispose();
|
WriteEvent.Dispose();
|
||||||
ReadEvent.Dispose();
|
ReadEvent.Dispose();
|
||||||
}
|
}
|
||||||
@ -57,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
{
|
{
|
||||||
while (_value == 0)
|
while (_value == 0)
|
||||||
{
|
{
|
||||||
_event.WaitOne();
|
Monitor.Wait(_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -106,7 +108,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
{
|
{
|
||||||
if (Blocking)
|
if (Blocking)
|
||||||
{
|
{
|
||||||
_event.WaitOne();
|
Monitor.Wait(_lock);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -119,7 +121,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
|||||||
writeSize = sizeof(ulong);
|
writeSize = sizeof(ulong);
|
||||||
|
|
||||||
_value += count;
|
_value += count;
|
||||||
_event.Set();
|
Monitor.Pulse(_lock);
|
||||||
|
|
||||||
WriteEvent.Set();
|
WriteEvent.Set();
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ namespace Ryujinx.Memory
|
|||||||
private ConcurrentDictionary<MemoryBlock, byte> _viewStorages;
|
private ConcurrentDictionary<MemoryBlock, byte> _viewStorages;
|
||||||
private int _viewCount;
|
private int _viewCount;
|
||||||
|
|
||||||
|
internal bool ForceWindows4KBView => _forceWindows4KBView;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pointer to the memory block data.
|
/// Pointer to the memory block data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -145,7 +147,7 @@ namespace Ryujinx.Memory
|
|||||||
srcBlock.IncrementViewCount();
|
srcBlock.IncrementViewCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryManagement.MapView(srcBlock._sharedMemory, srcOffset, GetPointerInternal(dstOffset, size), size, _forceWindows4KBView);
|
MemoryManagement.MapView(srcBlock._sharedMemory, srcOffset, GetPointerInternal(dstOffset, size), size, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -156,7 +158,7 @@ namespace Ryujinx.Memory
|
|||||||
/// <param name="size">Size of the range to be unmapped</param>
|
/// <param name="size">Size of the range to be unmapped</param>
|
||||||
public void UnmapView(MemoryBlock srcBlock, ulong offset, ulong size)
|
public void UnmapView(MemoryBlock srcBlock, ulong offset, ulong size)
|
||||||
{
|
{
|
||||||
MemoryManagement.UnmapView(srcBlock._sharedMemory, GetPointerInternal(offset, size), size, _forceWindows4KBView);
|
MemoryManagement.UnmapView(srcBlock._sharedMemory, GetPointerInternal(offset, size), size, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -68,17 +68,17 @@ namespace Ryujinx.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr address, ulong size, bool force4KBMap)
|
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr address, ulong size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
if (force4KBMap)
|
if (owner.ForceWindows4KBView)
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.MapView4KB(sharedMemory, srcOffset, address, (IntPtr)size);
|
MemoryManagementWindows.MapView4KB(sharedMemory, srcOffset, address, (IntPtr)size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.MapView(sharedMemory, srcOffset, address, (IntPtr)size);
|
MemoryManagementWindows.MapView(sharedMemory, srcOffset, address, (IntPtr)size, owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
@ -91,17 +91,17 @@ namespace Ryujinx.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnmapView(IntPtr sharedMemory, IntPtr address, ulong size, bool force4KBMap)
|
public static void UnmapView(IntPtr sharedMemory, IntPtr address, ulong size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
if (force4KBMap)
|
if (owner.ForceWindows4KBView)
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.UnmapView4KB(address, (IntPtr)size);
|
MemoryManagementWindows.UnmapView4KB(address, (IntPtr)size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryManagementWindows.UnmapView(sharedMemory, address, (IntPtr)size);
|
MemoryManagementWindows.UnmapView(sharedMemory, address, (IntPtr)size, owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
|
@ -68,9 +68,9 @@ namespace Ryujinx.Memory
|
|||||||
return WindowsApi.VirtualFree(location, size, AllocationType.Decommit);
|
return WindowsApi.VirtualFree(location, size, AllocationType.Decommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size)
|
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
_placeholders.MapView(sharedMemory, srcOffset, location, size);
|
_placeholders.MapView(sharedMemory, srcOffset, location, size, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MapView4KB(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size)
|
public static void MapView4KB(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size)
|
||||||
@ -106,9 +106,9 @@ namespace Ryujinx.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnmapView(IntPtr sharedMemory, IntPtr location, IntPtr size)
|
public static void UnmapView(IntPtr sharedMemory, IntPtr location, IntPtr size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
_placeholders.UnmapView(sharedMemory, location, size);
|
_placeholders.UnmapView(sharedMemory, location, size, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnmapView4KB(IntPtr location, IntPtr size)
|
public static void UnmapView4KB(IntPtr location, IntPtr size)
|
||||||
@ -154,7 +154,7 @@ namespace Ryujinx.Memory
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_placeholders.UnmapView(IntPtr.Zero, address, size);
|
_placeholders.UnreserveRange((ulong)address, (ulong)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return WindowsApi.VirtualFree(address, IntPtr.Zero, AllocationType.Release);
|
return WindowsApi.VirtualFree(address, IntPtr.Zero, AllocationType.Release);
|
||||||
|
@ -44,6 +44,50 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unreserves a range of memory that has been previously reserved with <see cref="ReserveRange"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Start address of the region to unreserve</param>
|
||||||
|
/// <param name="size">Size in bytes of the region to unreserve</param>
|
||||||
|
/// <exception cref="WindowsApiException">Thrown when the Windows API returns an error unreserving the memory</exception>
|
||||||
|
public void UnreserveRange(ulong address, ulong size)
|
||||||
|
{
|
||||||
|
ulong endAddress = address + size;
|
||||||
|
|
||||||
|
var overlaps = Array.Empty<IntervalTreeNode<ulong, ulong>>();
|
||||||
|
int count;
|
||||||
|
|
||||||
|
lock (_mappings)
|
||||||
|
{
|
||||||
|
count = _mappings.Get(address, endAddress, ref overlaps);
|
||||||
|
|
||||||
|
for (int index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
var overlap = overlaps[index];
|
||||||
|
|
||||||
|
if (IsMapped(overlap.Value))
|
||||||
|
{
|
||||||
|
if (!WindowsApi.UnmapViewOfFile2(WindowsApi.CurrentProcessHandle, (IntPtr)overlap.Start, 2))
|
||||||
|
{
|
||||||
|
throw new WindowsApiException("UnmapViewOfFile2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_mappings.Remove(overlap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 1)
|
||||||
|
{
|
||||||
|
CheckFreeResult(WindowsApi.VirtualFree(
|
||||||
|
(IntPtr)address,
|
||||||
|
(IntPtr)size,
|
||||||
|
AllocationType.Release | AllocationType.CoalescePlaceholders));
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveProtection(address, size);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps a shared memory view on a previously reserved memory region.
|
/// Maps a shared memory view on a previously reserved memory region.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -51,13 +95,14 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
/// <param name="srcOffset">Offset in the shared memory to map</param>
|
/// <param name="srcOffset">Offset in the shared memory to map</param>
|
||||||
/// <param name="location">Address to map the view into</param>
|
/// <param name="location">Address to map the view into</param>
|
||||||
/// <param name="size">Size of the view in bytes</param>
|
/// <param name="size">Size of the view in bytes</param>
|
||||||
public void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size)
|
/// <param name="owner">Memory block that owns the mapping</param>
|
||||||
|
public void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, IntPtr size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
_partialUnmapLock.AcquireReaderLock(Timeout.Infinite);
|
_partialUnmapLock.AcquireReaderLock(Timeout.Infinite);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UnmapViewInternal(sharedMemory, location, size);
|
UnmapViewInternal(sharedMemory, location, size, owner);
|
||||||
MapViewInternal(sharedMemory, srcOffset, location, size);
|
MapViewInternal(sharedMemory, srcOffset, location, size);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -173,13 +218,14 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
/// <param name="sharedMemory">Shared memory that the view being unmapped belongs to</param>
|
/// <param name="sharedMemory">Shared memory that the view being unmapped belongs to</param>
|
||||||
/// <param name="location">Address to unmap</param>
|
/// <param name="location">Address to unmap</param>
|
||||||
/// <param name="size">Size of the region to unmap in bytes</param>
|
/// <param name="size">Size of the region to unmap in bytes</param>
|
||||||
public void UnmapView(IntPtr sharedMemory, IntPtr location, IntPtr size)
|
/// <param name="owner">Memory block that owns the mapping</param>
|
||||||
|
public void UnmapView(IntPtr sharedMemory, IntPtr location, IntPtr size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
_partialUnmapLock.AcquireReaderLock(Timeout.Infinite);
|
_partialUnmapLock.AcquireReaderLock(Timeout.Infinite);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UnmapViewInternal(sharedMemory, location, size);
|
UnmapViewInternal(sharedMemory, location, size, owner);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -197,8 +243,9 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
/// <param name="sharedMemory">Shared memory that the view being unmapped belongs to</param>
|
/// <param name="sharedMemory">Shared memory that the view being unmapped belongs to</param>
|
||||||
/// <param name="location">Address to unmap</param>
|
/// <param name="location">Address to unmap</param>
|
||||||
/// <param name="size">Size of the region to unmap in bytes</param>
|
/// <param name="size">Size of the region to unmap in bytes</param>
|
||||||
|
/// <param name="owner">Memory block that owns the mapping</param>
|
||||||
/// <exception cref="WindowsApiException">Thrown when the Windows API returns an error unmapping or remapping the memory</exception>
|
/// <exception cref="WindowsApiException">Thrown when the Windows API returns an error unmapping or remapping the memory</exception>
|
||||||
private void UnmapViewInternal(IntPtr sharedMemory, IntPtr location, IntPtr size)
|
private void UnmapViewInternal(IntPtr sharedMemory, IntPtr location, IntPtr size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
ulong startAddress = (ulong)location;
|
ulong startAddress = (ulong)location;
|
||||||
ulong unmapSize = (ulong)size;
|
ulong unmapSize = (ulong)size;
|
||||||
@ -272,7 +319,7 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CoalesceForUnmap(startAddress, unmapSize);
|
CoalesceForUnmap(startAddress, unmapSize, owner);
|
||||||
RemoveProtection(startAddress, unmapSize);
|
RemoveProtection(startAddress, unmapSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,15 +328,21 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Address of the region that was unmapped</param>
|
/// <param name="address">Address of the region that was unmapped</param>
|
||||||
/// <param name="size">Size of the region that was unmapped in bytes</param>
|
/// <param name="size">Size of the region that was unmapped in bytes</param>
|
||||||
private void CoalesceForUnmap(ulong address, ulong size)
|
/// <param name="owner">Memory block that owns the mapping</param>
|
||||||
|
private void CoalesceForUnmap(ulong address, ulong size, MemoryBlock owner)
|
||||||
{
|
{
|
||||||
ulong endAddress = address + size;
|
ulong endAddress = address + size;
|
||||||
|
ulong blockAddress = (ulong)owner.Pointer;
|
||||||
|
ulong blockEnd = blockAddress + owner.Size;
|
||||||
var overlaps = Array.Empty<IntervalTreeNode<ulong, ulong>>();
|
var overlaps = Array.Empty<IntervalTreeNode<ulong, ulong>>();
|
||||||
int unmappedCount = 0;
|
int unmappedCount = 0;
|
||||||
|
|
||||||
lock (_mappings)
|
lock (_mappings)
|
||||||
{
|
{
|
||||||
int count = _mappings.Get(address - MinimumPageSize, endAddress + MinimumPageSize, ref overlaps);
|
int count = _mappings.Get(
|
||||||
|
Math.Max(address - MinimumPageSize, blockAddress),
|
||||||
|
Math.Min(endAddress + MinimumPageSize, blockEnd), ref overlaps);
|
||||||
|
|
||||||
if (count < 2)
|
if (count < 2)
|
||||||
{
|
{
|
||||||
// Nothing to coalesce if we only have 1 or no overlaps.
|
// Nothing to coalesce if we only have 1 or no overlaps.
|
||||||
|
Reference in New Issue
Block a user