mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-12 13:49:12 +00:00
Merge branch 'master' into 4304-missing-updates
This commit is contained in:
commit
b6b1973e8b
8 changed files with 148 additions and 43 deletions
|
@ -101,6 +101,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AlwaysFlushOnOverlap { get; private set; }
|
public bool AlwaysFlushOnOverlap { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the texture was fully unmapped since the modified flag was set, and flushes should be ignored until it is modified again.
|
||||||
|
/// </summary>
|
||||||
|
public bool FlushStale { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Increments when the host texture is swapped, or when the texture is removed from all pools.
|
/// Increments when the host texture is swapped, or when the texture is removed from all pools.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -149,6 +154,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HadPoolOwner { get; private set; }
|
public bool HadPoolOwner { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// Physical memory ranges where the texture data is located.
|
/// Physical memory ranges where the texture data is located.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MultiRange Range { get; private set; }
|
public MultiRange Range { get; private set; }
|
||||||
|
@ -1411,6 +1417,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SignalModified()
|
public void SignalModified()
|
||||||
{
|
{
|
||||||
|
FlushStale = false;
|
||||||
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
|
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
|
||||||
|
|
||||||
if (_modifiedStale || Group.HasCopyDependencies)
|
if (_modifiedStale || Group.HasCopyDependencies)
|
||||||
|
@ -1431,6 +1438,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
if (bound)
|
if (bound)
|
||||||
{
|
{
|
||||||
|
FlushStale = false;
|
||||||
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
|
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1695,12 +1703,17 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// <param name="unmapRange">The range of memory being unmapped</param>
|
/// <param name="unmapRange">The range of memory being unmapped</param>
|
||||||
public void Unmapped(MultiRange unmapRange)
|
public void Unmapped(MultiRange unmapRange)
|
||||||
{
|
{
|
||||||
|
if (unmapRange.Contains(Range))
|
||||||
|
{
|
||||||
|
// If this is a full unmap, prevent flushes until the texture is mapped again.
|
||||||
|
FlushStale = true;
|
||||||
|
}
|
||||||
|
|
||||||
ChangedMapping = true;
|
ChangedMapping = true;
|
||||||
|
|
||||||
if (Group.Storage == this)
|
if (Group.Storage == this)
|
||||||
{
|
{
|
||||||
Group.Unmapped();
|
Group.Unmapped();
|
||||||
|
|
||||||
Group.ClearModified(unmapRange);
|
Group.ClearModified(unmapRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
// Any texture that has been unmapped at any point or is partially unmapped
|
// Any texture that has been unmapped at any point or is partially unmapped
|
||||||
// should update their pool references after the remap completes.
|
// should update their pool references after the remap completes.
|
||||||
|
|
||||||
MultiRange unmapped = ((MemoryManager)sender).GetPhysicalRegions(e.Address, e.Size);
|
|
||||||
|
|
||||||
foreach (var texture in _partiallyMappedTextures)
|
foreach (var texture in _partiallyMappedTextures)
|
||||||
{
|
{
|
||||||
texture.UpdatePoolMappings();
|
texture.UpdatePoolMappings();
|
||||||
|
@ -735,9 +733,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
if (overlap.IsView)
|
if (overlap.IsView)
|
||||||
{
|
{
|
||||||
overlapCompatibility = overlapCompatibility == TextureViewCompatibility.FormatAlias ?
|
overlapCompatibility = TextureViewCompatibility.CopyOnly;
|
||||||
TextureViewCompatibility.Incompatible :
|
|
||||||
TextureViewCompatibility.CopyOnly;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -815,7 +811,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
Texture overlap = _textureOverlaps[index];
|
Texture overlap = _textureOverlaps[index];
|
||||||
OverlapInfo oInfo = _overlapInfo[index];
|
OverlapInfo oInfo = _overlapInfo[index];
|
||||||
|
|
||||||
if (oInfo.Compatibility <= TextureViewCompatibility.LayoutIncompatible || oInfo.Compatibility == TextureViewCompatibility.FormatAlias)
|
if (oInfo.Compatibility <= TextureViewCompatibility.LayoutIncompatible)
|
||||||
{
|
{
|
||||||
if (!overlap.IsView && texture.DataOverlaps(overlap, oInfo.Compatibility))
|
if (!overlap.IsView && texture.DataOverlaps(overlap, oInfo.Compatibility))
|
||||||
{
|
{
|
||||||
|
|
|
@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
// D32F and R32F texture have the same representation internally,
|
// D32F and R32F texture have the same representation internally,
|
||||||
// however the R32F format is used to sample from depth textures.
|
// however the R32F format is used to sample from depth textures.
|
||||||
if (lhs.FormatInfo.Format == Format.D32Float && rhs.FormatInfo.Format == Format.R32Float && (forSampler || depthAlias))
|
if (IsValidDepthAsColorAlias(lhs.FormatInfo.Format, rhs.FormatInfo.Format) && (forSampler || depthAlias))
|
||||||
{
|
{
|
||||||
return TextureMatchQuality.FormatAlias;
|
return TextureMatchQuality.FormatAlias;
|
||||||
}
|
}
|
||||||
|
@ -239,14 +239,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
return TextureMatchQuality.FormatAlias;
|
return TextureMatchQuality.FormatAlias;
|
||||||
}
|
}
|
||||||
|
else if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
|
||||||
if (lhs.FormatInfo.Format == Format.D16Unorm && rhs.FormatInfo.Format == Format.R16Unorm)
|
lhs.FormatInfo.Format == Format.S8UintD24Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
|
||||||
{
|
|
||||||
return TextureMatchQuality.FormatAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
|
|
||||||
lhs.FormatInfo.Format == Format.S8UintD24Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
|
|
||||||
{
|
{
|
||||||
return TextureMatchQuality.FormatAlias;
|
return TextureMatchQuality.FormatAlias;
|
||||||
}
|
}
|
||||||
|
@ -632,12 +626,27 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
if (lhsFormat.Format.IsDepthOrStencil() || rhsFormat.Format.IsDepthOrStencil())
|
if (lhsFormat.Format.IsDepthOrStencil() || rhsFormat.Format.IsDepthOrStencil())
|
||||||
{
|
{
|
||||||
return FormatMatches(lhs, rhs, flags.HasFlag(TextureSearchFlags.ForSampler), flags.HasFlag(TextureSearchFlags.DepthAlias)) switch
|
bool forSampler = flags.HasFlag(TextureSearchFlags.ForSampler);
|
||||||
|
bool depthAlias = flags.HasFlag(TextureSearchFlags.DepthAlias);
|
||||||
|
|
||||||
|
TextureMatchQuality matchQuality = FormatMatches(lhs, rhs, forSampler, depthAlias);
|
||||||
|
|
||||||
|
if (matchQuality == TextureMatchQuality.Perfect)
|
||||||
{
|
{
|
||||||
TextureMatchQuality.Perfect => TextureViewCompatibility.Full,
|
return TextureViewCompatibility.Full;
|
||||||
TextureMatchQuality.FormatAlias => TextureViewCompatibility.FormatAlias,
|
}
|
||||||
_ => TextureViewCompatibility.Incompatible,
|
else if (matchQuality == TextureMatchQuality.FormatAlias)
|
||||||
};
|
{
|
||||||
|
return TextureViewCompatibility.FormatAlias;
|
||||||
|
}
|
||||||
|
else if (IsValidColorAsDepthAlias(lhsFormat.Format, rhsFormat.Format) || IsValidDepthAsColorAlias(lhsFormat.Format, rhsFormat.Format))
|
||||||
|
{
|
||||||
|
return TextureViewCompatibility.CopyOnly;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return TextureViewCompatibility.Incompatible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFormatHostIncompatible(lhs, caps) || IsFormatHostIncompatible(rhs, caps))
|
if (IsFormatHostIncompatible(lhs, caps) || IsFormatHostIncompatible(rhs, caps))
|
||||||
|
@ -666,6 +675,30 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
return TextureViewCompatibility.Incompatible;
|
return TextureViewCompatibility.Incompatible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if it's valid to alias a color format as a depth format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhsFormat">Source format to be checked</param>
|
||||||
|
/// <param name="rhsFormat">Target format to be checked</param>
|
||||||
|
/// <returns>True if it's valid to alias the formats</returns>
|
||||||
|
private static bool IsValidColorAsDepthAlias(Format lhsFormat, Format rhsFormat)
|
||||||
|
{
|
||||||
|
return (lhsFormat == Format.R32Float && rhsFormat == Format.D32Float) ||
|
||||||
|
(lhsFormat == Format.R16Unorm && rhsFormat == Format.D16Unorm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if it's valid to alias a depth format as a color format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhsFormat">Source format to be checked</param>
|
||||||
|
/// <param name="rhsFormat">Target format to be checked</param>
|
||||||
|
/// <returns>True if it's valid to alias the formats</returns>
|
||||||
|
private static bool IsValidDepthAsColorAlias(Format lhsFormat, Format rhsFormat)
|
||||||
|
{
|
||||||
|
return (lhsFormat == Format.D32Float && rhsFormat == Format.R32Float) ||
|
||||||
|
(lhsFormat == Format.D16Unorm && rhsFormat == Format.R16Unorm);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if aliasing of two formats that would normally be considered incompatible be allowed,
|
/// Checks if aliasing of two formats that would normally be considered incompatible be allowed,
|
||||||
/// using copy dependencies.
|
/// using copy dependencies.
|
||||||
|
|
|
@ -1659,6 +1659,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If size is zero, we have nothing to flush.
|
||||||
|
// If the flush is stale, we should ignore it because the texture was unmapped since the modified
|
||||||
|
// flag was set, and flushing it is not safe anymore as the GPU might no longer own the memory.
|
||||||
|
if (size == 0 || Storage.FlushStale)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// There is a small gap here where the action is removed but _actionRegistered is still 1.
|
// There is a small gap here where the action is removed but _actionRegistered is still 1.
|
||||||
// In this case it will skip registering the action, but here we are already handling it,
|
// In this case it will skip registering the action, but here we are already handling it,
|
||||||
// so there shouldn't be any issue as it's the same handler for all actions.
|
// so there shouldn't be any issue as it's the same handler for all actions.
|
||||||
|
|
|
@ -367,7 +367,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextureView PboCopy(TextureView from, TextureView to, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int width, int height)
|
public void PboCopy(TextureView from, TextureView to, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int width, int height)
|
||||||
{
|
{
|
||||||
int dstWidth = width;
|
int dstWidth = width;
|
||||||
int dstHeight = height;
|
int dstHeight = height;
|
||||||
|
@ -445,8 +445,6 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
||||||
|
|
||||||
return to;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsurePbo(TextureView view)
|
private void EnsurePbo(TextureView view)
|
||||||
|
|
|
@ -140,6 +140,28 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
|
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
|
||||||
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
|
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
|
||||||
}
|
}
|
||||||
|
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
|
||||||
|
{
|
||||||
|
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||||
|
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
|
||||||
|
|
||||||
|
for (int level = 0; level < levels; level++)
|
||||||
|
{
|
||||||
|
int srcWidth = Math.Max(1, Width >> level);
|
||||||
|
int srcHeight = Math.Max(1, Height >> level);
|
||||||
|
|
||||||
|
int dstWidth = Math.Max(1, destinationView.Width >> (firstLevel + level));
|
||||||
|
int dstHeight = Math.Max(1, destinationView.Height >> (firstLevel + level));
|
||||||
|
|
||||||
|
int minWidth = Math.Min(srcWidth, dstWidth);
|
||||||
|
int minHeight = Math.Min(srcHeight, dstHeight);
|
||||||
|
|
||||||
|
for (int layer = 0; layer < layers; layer++)
|
||||||
|
{
|
||||||
|
_renderer.TextureCopy.PboCopy(this, destinationView, 0, firstLayer + layer, 0, firstLevel + level, minWidth, minHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_renderer.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
|
_renderer.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
|
||||||
|
@ -169,6 +191,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||||
}
|
}
|
||||||
|
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
|
||||||
|
{
|
||||||
|
int minWidth = Math.Min(Width, destinationView.Width);
|
||||||
|
int minHeight = Math.Min(Height, destinationView.Height);
|
||||||
|
|
||||||
|
_renderer.TextureCopy.PboCopy(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, minWidth, minHeight);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_renderer.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
_renderer.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||||
|
|
|
@ -211,6 +211,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
int levels = Math.Min(Info.Levels, dst.Info.Levels - firstLevel);
|
int levels = Math.Min(Info.Levels, dst.Info.Levels - firstLevel);
|
||||||
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, 0, firstLayer, 0, firstLevel, layers, levels);
|
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, 0, firstLayer, 0, firstLevel, layers, levels);
|
||||||
}
|
}
|
||||||
|
else if (src.Info.Format.IsDepthOrStencil() != dst.Info.Format.IsDepthOrStencil())
|
||||||
|
{
|
||||||
|
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
|
||||||
|
int levels = Math.Min(Info.Levels, dst.Info.Levels - firstLevel);
|
||||||
|
|
||||||
|
_gd.HelperShader.CopyColor(_gd, cbs, src, dst, 0, firstLayer, 0, FirstLevel, layers, levels);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TextureCopy.Copy(
|
TextureCopy.Copy(
|
||||||
|
@ -260,6 +267,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||||
}
|
}
|
||||||
|
else if (src.Info.Format.IsDepthOrStencil() != dst.Info.Format.IsDepthOrStencil())
|
||||||
|
{
|
||||||
|
_gd.HelperShader.CopyColor(_gd, cbs, src, dst, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TextureCopy.Copy(
|
TextureCopy.Copy(
|
||||||
|
|
|
@ -39,6 +39,8 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
private readonly KernelContext _context;
|
private readonly KernelContext _context;
|
||||||
private KProcess _selfProcess;
|
private KProcess _selfProcess;
|
||||||
private KThread _selfThread;
|
private KThread _selfThread;
|
||||||
|
private KEvent _wakeEvent;
|
||||||
|
private int _wakeHandle = 0;
|
||||||
|
|
||||||
private readonly ReaderWriterLockSlim _handleLock = new();
|
private readonly ReaderWriterLockSlim _handleLock = new();
|
||||||
private readonly Dictionary<int, IpcService> _sessions = new();
|
private readonly Dictionary<int, IpcService> _sessions = new();
|
||||||
|
@ -125,6 +127,8 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
_handleLock.ExitWriteLock();
|
_handleLock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_wakeEvent.WritableEvent.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IpcService GetSessionObj(int serverSessionHandle)
|
private IpcService GetSessionObj(int serverSessionHandle)
|
||||||
|
@ -187,6 +191,9 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
AddPort(serverPortHandle, SmObjectFactory);
|
AddPort(serverPortHandle, SmObjectFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_wakeEvent = new KEvent(_context);
|
||||||
|
Result result = _selfProcess.HandleTable.GenerateHandle(_wakeEvent.ReadableEvent, out _wakeHandle);
|
||||||
|
|
||||||
InitDone.Set();
|
InitDone.Set();
|
||||||
|
|
||||||
ulong messagePtr = _selfThread.TlsAddress;
|
ulong messagePtr = _selfThread.TlsAddress;
|
||||||
|
@ -195,7 +202,6 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
_selfProcess.CpuMemory.Write(messagePtr + 0x0, 0);
|
_selfProcess.CpuMemory.Write(messagePtr + 0x0, 0);
|
||||||
_selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10);
|
_selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10);
|
||||||
_selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48));
|
_selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48));
|
||||||
|
|
||||||
int replyTargetHandle = 0;
|
int replyTargetHandle = 0;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -211,13 +217,15 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
portHandleCount = _ports.Count;
|
portHandleCount = _ports.Count;
|
||||||
|
|
||||||
handleCount = portHandleCount + _sessions.Count;
|
handleCount = portHandleCount + _sessions.Count + 1;
|
||||||
|
|
||||||
handles = ArrayPool<int>.Shared.Rent(handleCount);
|
handles = ArrayPool<int>.Shared.Rent(handleCount);
|
||||||
|
|
||||||
_ports.Keys.CopyTo(handles, 0);
|
handles[0] = _wakeHandle;
|
||||||
|
|
||||||
_sessions.Keys.CopyTo(handles, portHandleCount);
|
_ports.Keys.CopyTo(handles, 1);
|
||||||
|
|
||||||
|
_sessions.Keys.CopyTo(handles, portHandleCount + 1);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -227,8 +235,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We still need a timeout here to allow the service to pick up and listen new sessions...
|
var rc = _context.Syscall.ReplyAndReceive(out int signaledIndex, handles.AsSpan(0, handleCount), replyTargetHandle, -1);
|
||||||
var rc = _context.Syscall.ReplyAndReceive(out int signaledIndex, handles.AsSpan(0, handleCount), replyTargetHandle, 1000000L);
|
|
||||||
|
|
||||||
_selfThread.HandlePostSyscall();
|
_selfThread.HandlePostSyscall();
|
||||||
|
|
||||||
|
@ -239,7 +246,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
replyTargetHandle = 0;
|
replyTargetHandle = 0;
|
||||||
|
|
||||||
if (rc == Result.Success && signaledIndex >= portHandleCount)
|
if (rc == Result.Success && signaledIndex >= portHandleCount + 1)
|
||||||
{
|
{
|
||||||
// We got a IPC request, process it, pass to the appropriate service if needed.
|
// We got a IPC request, process it, pass to the appropriate service if needed.
|
||||||
int signaledHandle = handles[signaledIndex];
|
int signaledHandle = handles[signaledIndex];
|
||||||
|
@ -253,24 +260,32 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
if (rc == Result.Success)
|
if (rc == Result.Success)
|
||||||
{
|
{
|
||||||
// We got a new connection, accept the session to allow servicing future requests.
|
if (signaledIndex > 0)
|
||||||
if (_context.Syscall.AcceptSession(out int serverSessionHandle, handles[signaledIndex]) == Result.Success)
|
|
||||||
{
|
{
|
||||||
bool handleWriteLockTaken = false;
|
// We got a new connection, accept the session to allow servicing future requests.
|
||||||
try
|
if (_context.Syscall.AcceptSession(out int serverSessionHandle, handles[signaledIndex]) == Result.Success)
|
||||||
{
|
{
|
||||||
handleWriteLockTaken = _handleLock.TryEnterWriteLock(Timeout.Infinite);
|
bool handleWriteLockTaken = false;
|
||||||
IpcService obj = _ports[handles[signaledIndex]].Invoke();
|
try
|
||||||
_sessions.Add(serverSessionHandle, obj);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (handleWriteLockTaken)
|
|
||||||
{
|
{
|
||||||
_handleLock.ExitWriteLock();
|
handleWriteLockTaken = _handleLock.TryEnterWriteLock(Timeout.Infinite);
|
||||||
|
IpcService obj = _ports[handles[signaledIndex]].Invoke();
|
||||||
|
_sessions.Add(serverSessionHandle, obj);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (handleWriteLockTaken)
|
||||||
|
{
|
||||||
|
_handleLock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The _wakeEvent signalled, which means we have a new session.
|
||||||
|
_wakeEvent.WritableEvent.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_selfProcess.CpuMemory.Write(messagePtr + 0x0, 0);
|
_selfProcess.CpuMemory.Write(messagePtr + 0x0, 0);
|
||||||
|
@ -499,6 +514,8 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
if (Interlocked.Exchange(ref _isDisposed, 1) == 0)
|
if (Interlocked.Exchange(ref _isDisposed, 1) == 0)
|
||||||
{
|
{
|
||||||
|
_selfProcess.HandleTable.CloseHandle(_wakeHandle);
|
||||||
|
|
||||||
foreach (IpcService service in _sessions.Values)
|
foreach (IpcService service in _sessions.Values)
|
||||||
{
|
{
|
||||||
(service as IDisposable)?.Dispose();
|
(service as IDisposable)?.Dispose();
|
||||||
|
|
Loading…
Reference in a new issue