Compare commits

...

3 Commits

Author SHA1 Message Date
snek 5913b02a05
Merge c93aaebd4e into 73f985d27c 2024-09-19 13:21:58 +09:00
jhorv 73f985d27c
Replace passing by IMemoryOwner<byte> with passing by concrete MemoryOwner<byte> (#7171)
* refactor(perf): pass MemoryOwner<byte> around as itself rather than IMemoryOwner<byte>

* fix(perf): get span via MemoryOwner<byte>.Span property instead of through Memory property

* fix: incorrect comment change
2024-09-18 23:00:54 -03:00
snek c93aaebd4e
Attempt to stop games gracefully before terminating emulation 2024-09-06 12:07:49 -07:00
22 changed files with 126 additions and 88 deletions

View File

@ -1,4 +1,4 @@
using System.Buffers; using Ryujinx.Common.Memory;
namespace Ryujinx.Graphics.GAL namespace Ryujinx.Graphics.GAL
{ {
@ -18,30 +18,30 @@ namespace Ryujinx.Graphics.GAL
PinnedSpan<byte> GetData(int layer, int level); PinnedSpan<byte> GetData(int layer, int level);
/// <summary> /// <summary>
/// Sets the texture data. The data passed as a <see cref="IMemoryOwner{Byte}" /> will be disposed when /// Sets the texture data. The data passed as a <see cref="MemoryOwner{Byte}" /> will be disposed when
/// the operation completes. /// the operation completes.
/// </summary> /// </summary>
/// <param name="data">Texture data bytes</param> /// <param name="data">Texture data bytes</param>
void SetData(IMemoryOwner<byte> data); void SetData(MemoryOwner<byte> data);
/// <summary> /// <summary>
/// Sets the texture data. The data passed as a <see cref="IMemoryOwner{Byte}" /> will be disposed when /// Sets the texture data. The data passed as a <see cref="MemoryOwner{Byte}" /> will be disposed when
/// the operation completes. /// the operation completes.
/// </summary> /// </summary>
/// <param name="data">Texture data bytes</param> /// <param name="data">Texture data bytes</param>
/// <param name="layer">Target layer</param> /// <param name="layer">Target layer</param>
/// <param name="level">Target level</param> /// <param name="level">Target level</param>
void SetData(IMemoryOwner<byte> data, int layer, int level); void SetData(MemoryOwner<byte> data, int layer, int level);
/// <summary> /// <summary>
/// Sets the texture data. The data passed as a <see cref="IMemoryOwner{Byte}" /> will be disposed when /// Sets the texture data. The data passed as a <see cref="MemoryOwner{Byte}" /> will be disposed when
/// the operation completes. /// the operation completes.
/// </summary> /// </summary>
/// <param name="data">Texture data bytes</param> /// <param name="data">Texture data bytes</param>
/// <param name="layer">Target layer</param> /// <param name="layer">Target layer</param>
/// <param name="level">Target level</param> /// <param name="level">Target level</param>
/// <param name="region">Target sub-region of the texture to update</param> /// <param name="region">Target sub-region of the texture to update</param>
void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region); void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region);
void SetStorage(BufferRange buffer); void SetStorage(BufferRange buffer);

View File

@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources; using Ryujinx.Graphics.GAL.Multithreading.Resources;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{ {
@ -8,9 +8,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{ {
public readonly CommandType CommandType => CommandType.TextureSetData; public readonly CommandType CommandType => CommandType.TextureSetData;
private TableRef<ThreadedTexture> _texture; private TableRef<ThreadedTexture> _texture;
private TableRef<IMemoryOwner<byte>> _data; private TableRef<MemoryOwner<byte>> _data;
public void Set(TableRef<ThreadedTexture> texture, TableRef<IMemoryOwner<byte>> data) public void Set(TableRef<ThreadedTexture> texture, TableRef<MemoryOwner<byte>> data)
{ {
_texture = texture; _texture = texture;
_data = data; _data = data;

View File

@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources; using Ryujinx.Graphics.GAL.Multithreading.Resources;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{ {
@ -8,11 +8,11 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{ {
public readonly CommandType CommandType => CommandType.TextureSetDataSlice; public readonly CommandType CommandType => CommandType.TextureSetDataSlice;
private TableRef<ThreadedTexture> _texture; private TableRef<ThreadedTexture> _texture;
private TableRef<IMemoryOwner<byte>> _data; private TableRef<MemoryOwner<byte>> _data;
private int _layer; private int _layer;
private int _level; private int _level;
public void Set(TableRef<ThreadedTexture> texture, TableRef<IMemoryOwner<byte>> data, int layer, int level) public void Set(TableRef<ThreadedTexture> texture, TableRef<MemoryOwner<byte>> data, int layer, int level)
{ {
_texture = texture; _texture = texture;
_data = data; _data = data;

View File

@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources; using Ryujinx.Graphics.GAL.Multithreading.Resources;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{ {
@ -8,12 +8,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{ {
public readonly CommandType CommandType => CommandType.TextureSetDataSliceRegion; public readonly CommandType CommandType => CommandType.TextureSetDataSliceRegion;
private TableRef<ThreadedTexture> _texture; private TableRef<ThreadedTexture> _texture;
private TableRef<IMemoryOwner<byte>> _data; private TableRef<MemoryOwner<byte>> _data;
private int _layer; private int _layer;
private int _level; private int _level;
private Rectangle<int> _region; private Rectangle<int> _region;
public void Set(TableRef<ThreadedTexture> texture, TableRef<IMemoryOwner<byte>> data, int layer, int level, Rectangle<int> region) public void Set(TableRef<ThreadedTexture> texture, TableRef<MemoryOwner<byte>> data, int layer, int level, Rectangle<int> region)
{ {
_texture = texture; _texture = texture;
_data = data; _data = data;

View File

@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture; using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Model;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Resources namespace Ryujinx.Graphics.GAL.Multithreading.Resources
{ {
@ -111,21 +111,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data) public void SetData(MemoryOwner<byte> data)
{ {
_renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data)); _renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data));
_renderer.QueueCommand(); _renderer.QueueCommand();
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level) public void SetData(MemoryOwner<byte> data, int layer, int level)
{ {
_renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data), layer, level); _renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data), layer, level);
_renderer.QueueCommand(); _renderer.QueueCommand();
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region) public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{ {
_renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data), layer, level, region); _renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data), layer, level, region);
_renderer.QueueCommand(); _renderer.QueueCommand();

View File

@ -1,10 +1,10 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.Gpu.Engine.Threed; using Ryujinx.Graphics.Gpu.Engine.Threed;
using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -353,7 +353,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
if (target != null) if (target != null)
{ {
IMemoryOwner<byte> data; MemoryOwner<byte> data;
if (srcLinear) if (srcLinear)
{ {
data = LayoutConverter.ConvertLinearStridedToLinear( data = LayoutConverter.ConvertLinearStridedToLinear(

View File

@ -7,7 +7,6 @@ using Ryujinx.Graphics.Texture.Astc;
using Ryujinx.Memory; using Ryujinx.Memory;
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
@ -662,7 +661,7 @@ namespace Ryujinx.Graphics.Gpu.Image
} }
} }
IMemoryOwner<byte> result = ConvertToHostCompatibleFormat(data); MemoryOwner<byte> result = ConvertToHostCompatibleFormat(data);
if (ScaleFactor != 1f && AllowScaledSetData()) if (ScaleFactor != 1f && AllowScaledSetData())
{ {
@ -685,7 +684,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Uploads new texture data to the host GPU. /// Uploads new texture data to the host GPU.
/// </summary> /// </summary>
/// <param name="data">New data</param> /// <param name="data">New data</param>
public void SetData(IMemoryOwner<byte> data) public void SetData(MemoryOwner<byte> data)
{ {
BlacklistScale(); BlacklistScale();
@ -704,7 +703,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="data">New data</param> /// <param name="data">New data</param>
/// <param name="layer">Target layer</param> /// <param name="layer">Target layer</param>
/// <param name="level">Target level</param> /// <param name="level">Target level</param>
public void SetData(IMemoryOwner<byte> data, int layer, int level) public void SetData(MemoryOwner<byte> data, int layer, int level)
{ {
BlacklistScale(); BlacklistScale();
@ -722,7 +721,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="layer">Target layer</param> /// <param name="layer">Target layer</param>
/// <param name="level">Target level</param> /// <param name="level">Target level</param>
/// <param name="region">Target sub-region of the texture to update</param> /// <param name="region">Target sub-region of the texture to update</param>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region) public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{ {
BlacklistScale(); BlacklistScale();
@ -740,7 +739,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="level">Mip level to convert</param> /// <param name="level">Mip level to convert</param>
/// <param name="single">True to convert a single slice</param> /// <param name="single">True to convert a single slice</param>
/// <returns>Converted data</returns> /// <returns>Converted data</returns>
public IMemoryOwner<byte> ConvertToHostCompatibleFormat(ReadOnlySpan<byte> data, int level = 0, bool single = false) public MemoryOwner<byte> ConvertToHostCompatibleFormat(ReadOnlySpan<byte> data, int level = 0, bool single = false)
{ {
int width = Info.Width; int width = Info.Width;
int height = Info.Height; int height = Info.Height;
@ -755,7 +754,7 @@ namespace Ryujinx.Graphics.Gpu.Image
int sliceDepth = single ? 1 : depth; int sliceDepth = single ? 1 : depth;
IMemoryOwner<byte> linear; MemoryOwner<byte> linear;
if (Info.IsLinear) if (Info.IsLinear)
{ {
@ -788,7 +787,7 @@ namespace Ryujinx.Graphics.Gpu.Image
data); data);
} }
IMemoryOwner<byte> result = linear; MemoryOwner<byte> result = linear;
// Handle compressed cases not supported by the host: // Handle compressed cases not supported by the host:
// - ASTC is usually not supported on desktop cards. // - ASTC is usually not supported on desktop cards.
@ -832,19 +831,19 @@ namespace Ryujinx.Graphics.Gpu.Image
case Format.Etc2RgbaUnorm: case Format.Etc2RgbaUnorm:
using (result) using (result)
{ {
return ETC2Decoder.DecodeRgba(result.Memory.Span, width, height, sliceDepth, levels, layers); return ETC2Decoder.DecodeRgba(result.Span, width, height, sliceDepth, levels, layers);
} }
case Format.Etc2RgbPtaSrgb: case Format.Etc2RgbPtaSrgb:
case Format.Etc2RgbPtaUnorm: case Format.Etc2RgbPtaUnorm:
using (result) using (result)
{ {
return ETC2Decoder.DecodePta(result.Memory.Span, width, height, sliceDepth, levels, layers); return ETC2Decoder.DecodePta(result.Span, width, height, sliceDepth, levels, layers);
} }
case Format.Etc2RgbSrgb: case Format.Etc2RgbSrgb:
case Format.Etc2RgbUnorm: case Format.Etc2RgbUnorm:
using (result) using (result)
{ {
return ETC2Decoder.DecodeRgb(result.Memory.Span, width, height, sliceDepth, levels, layers); return ETC2Decoder.DecodeRgb(result.Span, width, height, sliceDepth, levels, layers);
} }
} }
} }
@ -856,43 +855,43 @@ namespace Ryujinx.Graphics.Gpu.Image
case Format.Bc1RgbaUnorm: case Format.Bc1RgbaUnorm:
using (result) using (result)
{ {
return BCnDecoder.DecodeBC1(result.Memory.Span, width, height, sliceDepth, levels, layers); return BCnDecoder.DecodeBC1(result.Span, width, height, sliceDepth, levels, layers);
} }
case Format.Bc2Srgb: case Format.Bc2Srgb:
case Format.Bc2Unorm: case Format.Bc2Unorm:
using (result) using (result)
{ {
return BCnDecoder.DecodeBC2(result.Memory.Span, width, height, sliceDepth, levels, layers); return BCnDecoder.DecodeBC2(result.Span, width, height, sliceDepth, levels, layers);
} }
case Format.Bc3Srgb: case Format.Bc3Srgb:
case Format.Bc3Unorm: case Format.Bc3Unorm:
using (result) using (result)
{ {
return BCnDecoder.DecodeBC3(result.Memory.Span, width, height, sliceDepth, levels, layers); return BCnDecoder.DecodeBC3(result.Span, width, height, sliceDepth, levels, layers);
} }
case Format.Bc4Snorm: case Format.Bc4Snorm:
case Format.Bc4Unorm: case Format.Bc4Unorm:
using (result) using (result)
{ {
return BCnDecoder.DecodeBC4(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc4Snorm); return BCnDecoder.DecodeBC4(result.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc4Snorm);
} }
case Format.Bc5Snorm: case Format.Bc5Snorm:
case Format.Bc5Unorm: case Format.Bc5Unorm:
using (result) using (result)
{ {
return BCnDecoder.DecodeBC5(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc5Snorm); return BCnDecoder.DecodeBC5(result.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc5Snorm);
} }
case Format.Bc6HSfloat: case Format.Bc6HSfloat:
case Format.Bc6HUfloat: case Format.Bc6HUfloat:
using (result) using (result)
{ {
return BCnDecoder.DecodeBC6(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc6HSfloat); return BCnDecoder.DecodeBC6(result.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc6HSfloat);
} }
case Format.Bc7Srgb: case Format.Bc7Srgb:
case Format.Bc7Unorm: case Format.Bc7Unorm:
using (result) using (result)
{ {
return BCnDecoder.DecodeBC7(result.Memory.Span, width, height, sliceDepth, levels, layers); return BCnDecoder.DecodeBC7(result.Span, width, height, sliceDepth, levels, layers);
} }
} }
} }
@ -900,7 +899,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
using (result) using (result)
{ {
var converted = PixelConverter.ConvertR4G4ToR4G4B4A4(result.Memory.Span, width); var converted = PixelConverter.ConvertR4G4ToR4G4B4A4(result.Span, width);
if (_context.Capabilities.SupportsR4G4B4A4Format) if (_context.Capabilities.SupportsR4G4B4A4Format)
{ {
@ -910,7 +909,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
using (converted) using (converted)
{ {
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(converted.Memory.Span, width); return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(converted.Span, width);
} }
} }
} }
@ -921,7 +920,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
using (result) using (result)
{ {
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Memory.Span, width); return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Span, width);
} }
} }
} }
@ -933,24 +932,24 @@ namespace Ryujinx.Graphics.Gpu.Image
case Format.R5G6B5Unorm: case Format.R5G6B5Unorm:
using (result) using (result)
{ {
return PixelConverter.ConvertR5G6B5ToR8G8B8A8(result.Memory.Span, width); return PixelConverter.ConvertR5G6B5ToR8G8B8A8(result.Span, width);
} }
case Format.B5G5R5A1Unorm: case Format.B5G5R5A1Unorm:
case Format.R5G5B5X1Unorm: case Format.R5G5B5X1Unorm:
case Format.R5G5B5A1Unorm: case Format.R5G5B5A1Unorm:
using (result) using (result)
{ {
return PixelConverter.ConvertR5G5B5ToR8G8B8A8(result.Memory.Span, width, Format == Format.R5G5B5X1Unorm); return PixelConverter.ConvertR5G5B5ToR8G8B8A8(result.Span, width, Format == Format.R5G5B5X1Unorm);
} }
case Format.A1B5G5R5Unorm: case Format.A1B5G5R5Unorm:
using (result) using (result)
{ {
return PixelConverter.ConvertA1B5G5R5ToR8G8B8A8(result.Memory.Span, width); return PixelConverter.ConvertA1B5G5R5ToR8G8B8A8(result.Span, width);
} }
case Format.R4G4B4A4Unorm: case Format.R4G4B4A4Unorm:
using (result) using (result)
{ {
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Memory.Span, width); return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Span, width);
} }
} }
} }

View File

@ -1,3 +1,4 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
@ -5,7 +6,6 @@ using Ryujinx.Memory;
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using Ryujinx.Memory.Tracking; using Ryujinx.Memory.Tracking;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -445,7 +445,7 @@ namespace Ryujinx.Graphics.Gpu.Image
ReadOnlySpan<byte> data = dataSpan[(offset - spanBase)..]; ReadOnlySpan<byte> data = dataSpan[(offset - spanBase)..];
IMemoryOwner<byte> result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true); MemoryOwner<byte> result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true);
Storage.SetData(result, info.BaseLayer + layer, info.BaseLevel + level); Storage.SetData(result, info.BaseLayer + layer, info.BaseLevel + level);
} }

View File

@ -1,7 +1,7 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
using System.Buffers;
namespace Ryujinx.Graphics.OpenGL.Image namespace Ryujinx.Graphics.OpenGL.Image
{ {
@ -55,9 +55,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data) public void SetData(MemoryOwner<byte> data)
{ {
var dataSpan = data.Memory.Span; var dataSpan = data.Span;
Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]); Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
@ -65,13 +65,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level) public void SetData(MemoryOwner<byte> data, int layer, int level)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region) public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
} }

View File

@ -1,8 +1,8 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
using System.Buffers;
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.Graphics.OpenGL.Image namespace Ryujinx.Graphics.OpenGL.Image
@ -448,13 +448,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
} }
} }
public void SetData(IMemoryOwner<byte> data) public void SetData(MemoryOwner<byte> data)
{ {
using (data = EnsureDataFormat(data)) using (data = EnsureDataFormat(data))
{ {
unsafe unsafe
{ {
var dataSpan = data.Memory.Span; var dataSpan = data.Span;
fixed (byte* ptr = dataSpan) fixed (byte* ptr = dataSpan)
{ {
ReadFrom((IntPtr)ptr, dataSpan.Length); ReadFrom((IntPtr)ptr, dataSpan.Length);
@ -463,13 +463,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
} }
} }
public void SetData(IMemoryOwner<byte> data, int layer, int level) public void SetData(MemoryOwner<byte> data, int layer, int level)
{ {
using (data = EnsureDataFormat(data)) using (data = EnsureDataFormat(data))
{ {
unsafe unsafe
{ {
fixed (byte* ptr = data.Memory.Span) fixed (byte* ptr = data.Span)
{ {
int width = Math.Max(Info.Width >> level, 1); int width = Math.Max(Info.Width >> level, 1);
int height = Math.Max(Info.Height >> level, 1); int height = Math.Max(Info.Height >> level, 1);
@ -480,7 +480,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
} }
} }
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region) public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{ {
using (data = EnsureDataFormat(data)) using (data = EnsureDataFormat(data))
{ {
@ -489,7 +489,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
unsafe unsafe
{ {
fixed (byte* ptr = data.Memory.Span) fixed (byte* ptr = data.Span)
{ {
ReadFrom2D( ReadFrom2D(
(IntPtr)ptr, (IntPtr)ptr,
@ -522,13 +522,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
ReadFrom2D(data, layer, level, x, y, width, height, mipSize); ReadFrom2D(data, layer, level, x, y, width, height, mipSize);
} }
private IMemoryOwner<byte> EnsureDataFormat(IMemoryOwner<byte> data) private MemoryOwner<byte> EnsureDataFormat(MemoryOwner<byte> data)
{ {
if (Format == Format.S8UintD24Unorm) if (Format == Format.S8UintD24Unorm)
{ {
using (data) using (data)
{ {
return FormatConverter.ConvertS8D24ToD24S8(data.Memory.Span); return FormatConverter.ConvertS8D24ToD24S8(data.Span);
} }
} }

View File

@ -1,7 +1,7 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using Format = Ryujinx.Graphics.GAL.Format; using Format = Ryujinx.Graphics.GAL.Format;
using VkFormat = Silk.NET.Vulkan.Format; using VkFormat = Silk.NET.Vulkan.Format;
@ -84,20 +84,20 @@ namespace Ryujinx.Graphics.Vulkan
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data) public void SetData(MemoryOwner<byte> data)
{ {
_gd.SetBufferData(_bufferHandle, _offset, data.Memory.Span); _gd.SetBufferData(_bufferHandle, _offset, data.Span);
data.Dispose(); data.Dispose();
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level) public void SetData(MemoryOwner<byte> data, int layer, int level)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region) public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
} }

View File

@ -1,7 +1,7 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@ -746,23 +746,23 @@ namespace Ryujinx.Graphics.Vulkan
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data) public void SetData(MemoryOwner<byte> data)
{ {
SetData(data.Memory.Span, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false); SetData(data.Span, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false);
data.Dispose(); data.Dispose();
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level) public void SetData(MemoryOwner<byte> data, int layer, int level)
{ {
SetData(data.Memory.Span, layer, level, 1, 1, singleSlice: true); SetData(data.Span, layer, level, 1, 1, singleSlice: true);
data.Dispose(); data.Dispose();
} }
/// <inheritdoc/> /// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region) public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{ {
SetData(data.Memory.Span, layer, level, 1, 1, singleSlice: true, region); SetData(data.Span, layer, level, 1, 1, singleSlice: true, region);
data.Dispose(); data.Dispose();
} }

View File

@ -21,6 +21,7 @@ using Ryujinx.Graphics.GAL.Multithreading;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Input.GTK3; using Ryujinx.Input.GTK3;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
@ -677,7 +678,8 @@ namespace Ryujinx.UI
ConfigurationState.Instance.System.AudioVolume, ConfigurationState.Instance.System.AudioVolume,
ConfigurationState.Instance.System.UseHypervisor, ConfigurationState.Instance.System.UseHypervisor,
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value, ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
ConfigurationState.Instance.Multiplayer.Mode); ConfigurationState.Instance.Multiplayer.Mode,
() => StopEmulation());
_emulationContext = new HLE.Switch(configuration); _emulationContext = new HLE.Switch(configuration);
} }
@ -1484,7 +1486,7 @@ namespace Ryujinx.UI
SaveConfig(); SaveConfig();
} }
private void StopEmulation_Pressed(object sender, EventArgs args) private void StopEmulation()
{ {
if (_emulationContext != null) if (_emulationContext != null)
{ {
@ -1497,6 +1499,16 @@ namespace Ryujinx.UI
RendererWidget?.Exit(); RendererWidget?.Exit();
} }
private void StopEmulation_Pressed(object sender, EventArgs args)
{
_emulationContext.System.RequestExit();
Task.Run(async () =>
{
await Task.Delay(5000);
StopEmulation();
});
}
private void PauseEmulation_Pressed(object sender, EventArgs args) private void PauseEmulation_Pressed(object sender, EventArgs args)
{ {
_pauseEmulation.Sensitive = false; _pauseEmulation.Sensitive = false;

View File

@ -169,6 +169,11 @@ namespace Ryujinx.HLE
/// </summary> /// </summary>
public Action RefreshInputConfig { internal get; set; } public Action RefreshInputConfig { internal get; set; }
/// <summary>
/// An action to stop emulation.
/// </summary>
public Action Stop { internal get; set; }
public HLEConfiguration(VirtualFileSystem virtualFileSystem, public HLEConfiguration(VirtualFileSystem virtualFileSystem,
LibHacHorizonManager libHacHorizonManager, LibHacHorizonManager libHacHorizonManager,
ContentManager contentManager, ContentManager contentManager,
@ -194,7 +199,8 @@ namespace Ryujinx.HLE
float audioVolume, float audioVolume,
bool useHypervisor, bool useHypervisor,
string multiplayerLanInterfaceId, string multiplayerLanInterfaceId,
MultiplayerMode multiplayerMode) MultiplayerMode multiplayerMode,
Action stop)
{ {
VirtualFileSystem = virtualFileSystem; VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager; LibHacHorizonManager = libHacHorizonManager;
@ -222,6 +228,7 @@ namespace Ryujinx.HLE
UseHypervisor = useHypervisor; UseHypervisor = useHypervisor;
MultiplayerLanInterfaceId = multiplayerLanInterfaceId; MultiplayerLanInterfaceId = multiplayerLanInterfaceId;
MultiplayerMode = multiplayerMode; MultiplayerMode = multiplayerMode;
Stop = stop;
} }
} }
} }

View File

@ -329,6 +329,12 @@ namespace Ryujinx.HLE.HOS
AppletState.SetFocus(true); AppletState.SetFocus(true);
} }
public void RequestExit()
{
AppletState.Messages.Enqueue(AppletMessage.Exit);
AppletState.MessageEvent.ReadableEvent.Signal();
}
public void SimulateWakeUpMessage() public void SimulateWakeUpMessage()
{ {
AppletState.Messages.Enqueue(AppletMessage.Resume); AppletState.Messages.Enqueue(AppletMessage.Resume);

View File

@ -51,7 +51,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
// Exit() // Exit()
public ResultCode Exit(ServiceCtx context) public ResultCode Exit(ServiceCtx context)
{ {
Logger.Stub?.PrintStub(LogClass.ServiceAm); Logger.Warning?.Print(LogClass.ServiceAm, "Self Applet Exit");
context.Device.Configuration.Stop();
return ResultCode.Success; return ResultCode.Success;
} }

View File

@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {
private readonly MemoryOwner<byte> _rawDataOwner; private readonly MemoryOwner<byte> _rawDataOwner;
private Span<byte> Raw => _rawDataOwner.Memory.Span; private Span<byte> Raw => _rawDataOwner.Span;
private ref ParcelHeader Header => ref MemoryMarshal.Cast<byte, ParcelHeader>(Raw)[0]; private ref ParcelHeader Header => ref MemoryMarshal.Cast<byte, ParcelHeader>(Raw)[0];

View File

@ -580,7 +580,8 @@ namespace Ryujinx.Headless.SDL2
options.AudioVolume, options.AudioVolume,
options.UseHypervisor ?? true, options.UseHypervisor ?? true,
options.MultiplayerLanInterfaceId, options.MultiplayerLanInterfaceId,
Common.Configuration.Multiplayer.MultiplayerMode.Disabled); Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
() => _window.Exit());
return new Switch(configuration); return new Switch(configuration);
} }

View File

@ -221,7 +221,12 @@ namespace Ryujinx.Headless.SDL2
break; break;
case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE: case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE:
Exit(); Device.System.RequestExit();
/*
SDL2Driver.Instance.AddTimer(5000, () => {
Exit();
});
*/
break; break;
} }
} }

View File

@ -1,5 +1,5 @@
using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers;
namespace Ryujinx.Memory namespace Ryujinx.Memory
{ {
@ -7,7 +7,7 @@ namespace Ryujinx.Memory
{ {
private readonly IWritableBlock _block; private readonly IWritableBlock _block;
private readonly ulong _va; private readonly ulong _va;
private readonly IMemoryOwner<byte> _memoryOwner; private readonly MemoryOwner<byte> _memoryOwner;
private readonly bool _tracked; private readonly bool _tracked;
private bool NeedsWriteback => _block != null; private bool NeedsWriteback => _block != null;
@ -22,7 +22,7 @@ namespace Ryujinx.Memory
Memory = memory; Memory = memory;
} }
public WritableRegion(IWritableBlock block, ulong va, IMemoryOwner<byte> memoryOwner, bool tracked = false) public WritableRegion(IWritableBlock block, ulong va, MemoryOwner<byte> memoryOwner, bool tracked = false)
: this(block, va, memoryOwner.Memory, tracked) : this(block, va, memoryOwner.Memory, tracked)
{ {
_memoryOwner = memoryOwner; _memoryOwner = memoryOwner;

View File

@ -25,7 +25,7 @@ namespace Ryujinx.SDL2.Common
public static Action<Action> MainThreadDispatcher { get; set; } public static Action<Action> MainThreadDispatcher { get; set; }
private const uint SdlInitFlags = SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_VIDEO; private const uint SdlInitFlags = SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER;
private bool _isRunning; private bool _isRunning;
private uint _refereceCount; private uint _refereceCount;

View File

@ -872,7 +872,8 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.System.AudioVolume, ConfigurationState.Instance.System.AudioVolume,
ConfigurationState.Instance.System.UseHypervisor, ConfigurationState.Instance.System.UseHypervisor,
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value, ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
ConfigurationState.Instance.Multiplayer.Mode); ConfigurationState.Instance.Multiplayer.Mode,
() => Stop());
Device = new Switch(configuration); Device = new Switch(configuration);
} }
@ -1092,7 +1093,12 @@ namespace Ryujinx.Ava
if (shouldExit) if (shouldExit)
{ {
Stop(); Device.System.RequestExit();
Task.Run(async () =>
{
await Task.Delay(5000);
Stop();
});
} }
} }