Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
0a75b73fa4 | |||
46b7c905f5 | |||
40f2bd37e3 |
@ -9,12 +9,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
public static bool InBackground;
|
public static bool InBackground;
|
||||||
private Thread _thread;
|
private readonly Thread _thread;
|
||||||
private bool _running;
|
private bool _running;
|
||||||
|
|
||||||
private AutoResetEvent _signal;
|
private readonly AutoResetEvent _signal;
|
||||||
private Queue<Action> _work;
|
private readonly Queue<Action> _work;
|
||||||
private ObjectPool<ManualResetEventSlim> _invokePool;
|
private readonly ObjectPool<ManualResetEventSlim> _invokePool;
|
||||||
private readonly IOpenGLContext _backgroundContext;
|
private readonly IOpenGLContext _backgroundContext;
|
||||||
|
|
||||||
public BackgroundContextWorker(IOpenGLContext backgroundContext)
|
public BackgroundContextWorker(IOpenGLContext backgroundContext)
|
||||||
@ -88,4 +88,4 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_signal.Dispose();
|
_signal.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,18 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case DebugType.DebugTypeError : Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR"); break;
|
case DebugType.DebugTypeError:
|
||||||
case DebugType.DebugTypePerformance: Logger.Warning?.Print(LogClass.Gpu, $"{severity}: {msg}", "GLPERF"); break;
|
Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR");
|
||||||
case DebugType.DebugTypePushGroup : Logger.Info?.Print(LogClass.Gpu, $"{{ ({id}) {severity}: {msg}", "GLINFO"); break;
|
break;
|
||||||
case DebugType.DebugTypePopGroup : Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO"); break;
|
case DebugType.DebugTypePerformance:
|
||||||
|
Logger.Warning?.Print(LogClass.Gpu, $"{severity}: {msg}", "GLPERF");
|
||||||
|
break;
|
||||||
|
case DebugType.DebugTypePushGroup:
|
||||||
|
Logger.Info?.Print(LogClass.Gpu, $"{{ ({id}) {severity}: {msg}", "GLINFO");
|
||||||
|
break;
|
||||||
|
case DebugType.DebugTypePopGroup:
|
||||||
|
Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (source == DebugSource.DebugSourceApplication)
|
if (source == DebugSource.DebugSourceApplication)
|
||||||
{
|
{
|
||||||
|
@ -65,16 +65,12 @@ void main()
|
|||||||
|
|
||||||
if (x0 > x1)
|
if (x0 > x1)
|
||||||
{
|
{
|
||||||
float temp = s0;
|
(s1, s0) = (s0, s1);
|
||||||
s0 = s1;
|
|
||||||
s1 = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y0 > y1)
|
if (y0 > y1)
|
||||||
{
|
{
|
||||||
float temp = t0;
|
(t1, t0) = (t0, t1);
|
||||||
t0 = t1;
|
|
||||||
t1 = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.Uniform1(_uniformSrcX0Location, s0);
|
GL.Uniform1(_uniformSrcX0Location, s0);
|
||||||
|
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FsrScalingFilter(OpenGLRenderer renderer, IPostProcessingEffect filter)
|
public FsrScalingFilter(OpenGLRenderer renderer)
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
@ -174,4 +174,4 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||||||
GL.ActiveTexture((TextureUnit)previousUnit);
|
GL.ActiveTexture((TextureUnit)previousUnit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,4 +78,4 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||||||
return textureView;
|
return textureView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL.Effects
|
namespace Ryujinx.Graphics.OpenGL.Effects
|
||||||
{
|
{
|
||||||
internal interface IPostProcessingEffect : IDisposable
|
internal interface IPostProcessingEffect : IDisposable
|
||||||
{
|
{
|
||||||
const int LocalGroupSize = 64;
|
const int LocalGroupSize = 64;
|
||||||
TextureView Run(TextureView view, int width, int height);
|
TextureView Run(TextureView view, int width, int height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,4 +15,4 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||||||
Extents2D source,
|
Extents2D source,
|
||||||
Extents2D destination);
|
Extents2D destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL.Effects
|
namespace Ryujinx.Graphics.OpenGL.Effects
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
|
|||||||
private int[] _neighbourShaderPrograms;
|
private int[] _neighbourShaderPrograms;
|
||||||
private TextureStorage _edgeOutputTexture;
|
private TextureStorage _edgeOutputTexture;
|
||||||
private TextureStorage _blendOutputTexture;
|
private TextureStorage _blendOutputTexture;
|
||||||
private string[] _qualities;
|
private readonly string[] _qualities;
|
||||||
private int _inputUniform;
|
private int _inputUniform;
|
||||||
private int _outputUniform;
|
private int _outputUniform;
|
||||||
private int _samplerAreaUniform;
|
private int _samplerAreaUniform;
|
||||||
|
@ -4,42 +4,42 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
readonly struct FormatInfo
|
readonly struct FormatInfo
|
||||||
{
|
{
|
||||||
public int Components { get; }
|
public int Components { get; }
|
||||||
public bool Normalized { get; }
|
public bool Normalized { get; }
|
||||||
public bool Scaled { get; }
|
public bool Scaled { get; }
|
||||||
|
|
||||||
public PixelInternalFormat PixelInternalFormat { get; }
|
public PixelInternalFormat PixelInternalFormat { get; }
|
||||||
public PixelFormat PixelFormat { get; }
|
public PixelFormat PixelFormat { get; }
|
||||||
public PixelType PixelType { get; }
|
public PixelType PixelType { get; }
|
||||||
|
|
||||||
public bool IsCompressed { get; }
|
public bool IsCompressed { get; }
|
||||||
|
|
||||||
public FormatInfo(
|
public FormatInfo(
|
||||||
int components,
|
int components,
|
||||||
bool normalized,
|
bool normalized,
|
||||||
bool scaled,
|
bool scaled,
|
||||||
All pixelInternalFormat,
|
All pixelInternalFormat,
|
||||||
PixelFormat pixelFormat,
|
PixelFormat pixelFormat,
|
||||||
PixelType pixelType)
|
PixelType pixelType)
|
||||||
{
|
{
|
||||||
Components = components;
|
Components = components;
|
||||||
Normalized = normalized;
|
Normalized = normalized;
|
||||||
Scaled = scaled;
|
Scaled = scaled;
|
||||||
PixelInternalFormat = (PixelInternalFormat)pixelInternalFormat;
|
PixelInternalFormat = (PixelInternalFormat)pixelInternalFormat;
|
||||||
PixelFormat = pixelFormat;
|
PixelFormat = pixelFormat;
|
||||||
PixelType = pixelType;
|
PixelType = pixelType;
|
||||||
IsCompressed = false;
|
IsCompressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormatInfo(int components, bool normalized, bool scaled, All pixelFormat)
|
public FormatInfo(int components, bool normalized, bool scaled, All pixelFormat)
|
||||||
{
|
{
|
||||||
Components = components;
|
Components = components;
|
||||||
Normalized = normalized;
|
Normalized = normalized;
|
||||||
Scaled = scaled;
|
Scaled = scaled;
|
||||||
PixelInternalFormat = 0;
|
PixelInternalFormat = 0;
|
||||||
PixelFormat = (PixelFormat)pixelFormat;
|
PixelFormat = (PixelFormat)pixelFormat;
|
||||||
PixelType = 0;
|
PixelType = 0;
|
||||||
IsCompressed = true;
|
IsCompressed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
struct FormatTable
|
readonly struct FormatTable
|
||||||
{
|
{
|
||||||
private static FormatInfo[] _table;
|
private static readonly FormatInfo[] _table;
|
||||||
private static SizedInternalFormat[] _tableImage;
|
private static readonly SizedInternalFormat[] _tableImage;
|
||||||
|
|
||||||
static FormatTable()
|
static FormatTable()
|
||||||
{
|
{
|
||||||
@ -16,6 +16,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_table = new FormatInfo[tableSize];
|
_table = new FormatInfo[tableSize];
|
||||||
_tableImage = new SizedInternalFormat[tableSize];
|
_tableImage = new SizedInternalFormat[tableSize];
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
Add(Format.R8Unorm, new FormatInfo(1, true, false, All.R8, PixelFormat.Red, PixelType.UnsignedByte));
|
Add(Format.R8Unorm, new FormatInfo(1, true, false, All.R8, PixelFormat.Red, PixelType.UnsignedByte));
|
||||||
Add(Format.R8Snorm, new FormatInfo(1, true, false, All.R8Snorm, PixelFormat.Red, PixelType.Byte));
|
Add(Format.R8Snorm, new FormatInfo(1, true, false, All.R8Snorm, PixelFormat.Red, PixelType.Byte));
|
||||||
Add(Format.R8Uint, new FormatInfo(1, false, false, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
|
Add(Format.R8Uint, new FormatInfo(1, false, false, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
|
||||||
@ -200,6 +201,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Add(Format.R10G10B10A2Unorm, (SizedInternalFormat)All.Rgb10A2);
|
Add(Format.R10G10B10A2Unorm, (SizedInternalFormat)All.Rgb10A2);
|
||||||
Add(Format.R10G10B10A2Uint, (SizedInternalFormat)All.Rgb10A2ui);
|
Add(Format.R10G10B10A2Uint, (SizedInternalFormat)All.Rgb10A2ui);
|
||||||
Add(Format.R11G11B10Float, (SizedInternalFormat)All.R11fG11fB10f);
|
Add(Format.R11G11B10Float, (SizedInternalFormat)All.R11fG11fB10f);
|
||||||
|
#pragma warning restore IDE0055
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(Format format, FormatInfo info)
|
private static void Add(Format format, FormatInfo info)
|
||||||
|
@ -105,7 +105,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_colorsCount = colorsCount;
|
_colorsCount = colorsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDrawBuffersImpl(int colorsCount)
|
private static void SetDrawBuffersImpl(int colorsCount)
|
||||||
{
|
{
|
||||||
DrawBuffersEnum[] drawBuffers = new DrawBuffersEnum[colorsCount];
|
DrawBuffersEnum[] drawBuffers = new DrawBuffersEnum[colorsCount];
|
||||||
|
|
||||||
|
@ -5,30 +5,30 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
static class HwCapabilities
|
static class HwCapabilities
|
||||||
{
|
{
|
||||||
private static readonly Lazy<bool> _supportsAlphaToCoverageDitherControl = new Lazy<bool>(() => HasExtension("GL_NV_alpha_to_coverage_dither_control"));
|
private static readonly Lazy<bool> _supportsAlphaToCoverageDitherControl = new(() => HasExtension("GL_NV_alpha_to_coverage_dither_control"));
|
||||||
private static readonly Lazy<bool> _supportsAstcCompression = new Lazy<bool>(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
|
private static readonly Lazy<bool> _supportsAstcCompression = new(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
|
||||||
private static readonly Lazy<bool> _supportsBlendEquationAdvanced = new Lazy<bool>(() => HasExtension("GL_NV_blend_equation_advanced"));
|
private static readonly Lazy<bool> _supportsBlendEquationAdvanced = new(() => HasExtension("GL_NV_blend_equation_advanced"));
|
||||||
private static readonly Lazy<bool> _supportsDrawTexture = new Lazy<bool>(() => HasExtension("GL_NV_draw_texture"));
|
private static readonly Lazy<bool> _supportsDrawTexture = new(() => HasExtension("GL_NV_draw_texture"));
|
||||||
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new Lazy<bool>(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
||||||
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new Lazy<bool>(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
||||||
private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new Lazy<bool>(() => HasExtension("GL_NV_geometry_shader_passthrough"));
|
private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new(() => HasExtension("GL_NV_geometry_shader_passthrough"));
|
||||||
private static readonly Lazy<bool> _supportsImageLoadFormatted = new Lazy<bool>(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
private static readonly Lazy<bool> _supportsImageLoadFormatted = new(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
||||||
private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters"));
|
private static readonly Lazy<bool> _supportsIndirectParameters = new(() => HasExtension("GL_ARB_indirect_parameters"));
|
||||||
private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
private static readonly Lazy<bool> _supportsParallelShaderCompile = new(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
||||||
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new Lazy<bool>(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
||||||
private static readonly Lazy<bool> _supportsQuads = new Lazy<bool>(SupportsQuadsCheck);
|
private static readonly Lazy<bool> _supportsQuads = new(SupportsQuadsCheck);
|
||||||
private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new Lazy<bool>(() => HasExtension("GL_ARB_seamless_cubemap_per_texture"));
|
private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new(() => HasExtension("GL_ARB_seamless_cubemap_per_texture"));
|
||||||
private static readonly Lazy<bool> _supportsShaderBallot = new Lazy<bool>(() => HasExtension("GL_ARB_shader_ballot"));
|
private static readonly Lazy<bool> _supportsShaderBallot = new(() => HasExtension("GL_ARB_shader_ballot"));
|
||||||
private static readonly Lazy<bool> _supportsShaderViewportLayerArray = new Lazy<bool>(() => HasExtension("GL_ARB_shader_viewport_layer_array"));
|
private static readonly Lazy<bool> _supportsShaderViewportLayerArray = new(() => HasExtension("GL_ARB_shader_viewport_layer_array"));
|
||||||
private static readonly Lazy<bool> _supportsViewportArray2 = new Lazy<bool>(() => HasExtension("GL_NV_viewport_array2"));
|
private static readonly Lazy<bool> _supportsViewportArray2 = new(() => HasExtension("GL_NV_viewport_array2"));
|
||||||
private static readonly Lazy<bool> _supportsTextureCompressionBptc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_bptc"));
|
private static readonly Lazy<bool> _supportsTextureCompressionBptc = new(() => HasExtension("GL_EXT_texture_compression_bptc"));
|
||||||
private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_rgtc"));
|
private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new(() => HasExtension("GL_EXT_texture_compression_rgtc"));
|
||||||
private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_s3tc"));
|
private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new(() => HasExtension("GL_EXT_texture_compression_s3tc"));
|
||||||
private static readonly Lazy<bool> _supportsTextureShadowLod = new Lazy<bool>(() => HasExtension("GL_EXT_texture_shadow_lod"));
|
private static readonly Lazy<bool> _supportsTextureShadowLod = new(() => HasExtension("GL_EXT_texture_shadow_lod"));
|
||||||
private static readonly Lazy<bool> _supportsViewportSwizzle = new Lazy<bool>(() => HasExtension("GL_NV_viewport_swizzle"));
|
private static readonly Lazy<bool> _supportsViewportSwizzle = new(() => HasExtension("GL_NV_viewport_swizzle"));
|
||||||
|
|
||||||
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new Lazy<int>(() => GetLimit(All.MaxComputeSharedMemorySize));
|
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new(() => GetLimit(All.MaxComputeSharedMemorySize));
|
||||||
private static readonly Lazy<int> _storageBufferOffsetAlignment = new Lazy<int>(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
private static readonly Lazy<int> _storageBufferOffsetAlignment = new(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
||||||
|
|
||||||
public enum GpuVendor
|
public enum GpuVendor
|
||||||
{
|
{
|
||||||
@ -40,45 +40,44 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Nvidia
|
Nvidia
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Lazy<GpuVendor> _gpuVendor = new Lazy<GpuVendor>(GetGpuVendor);
|
private static readonly Lazy<GpuVendor> _gpuVendor = new(GetGpuVendor);
|
||||||
|
|
||||||
private static bool _isAMD => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.AmdUnix;
|
private static bool IsIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix;
|
||||||
private static bool _isIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix;
|
|
||||||
|
|
||||||
public static GpuVendor Vendor => _gpuVendor.Value;
|
public static GpuVendor Vendor => _gpuVendor.Value;
|
||||||
|
|
||||||
private static Lazy<float> _maxSupportedAnisotropy = new Lazy<float>(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy));
|
private static readonly Lazy<float> _maxSupportedAnisotropy = new(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy));
|
||||||
|
|
||||||
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
|
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
|
||||||
|
|
||||||
public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value;
|
public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value;
|
||||||
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
|
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
|
||||||
public static bool SupportsBlendEquationAdvanced => _supportsBlendEquationAdvanced.Value;
|
public static bool SupportsBlendEquationAdvanced => _supportsBlendEquationAdvanced.Value;
|
||||||
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
|
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
|
||||||
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
||||||
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
||||||
public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value;
|
public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value;
|
||||||
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
||||||
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
||||||
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
||||||
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
||||||
public static bool SupportsQuads => _supportsQuads.Value;
|
public static bool SupportsQuads => _supportsQuads.Value;
|
||||||
public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value;
|
public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value;
|
||||||
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
||||||
public static bool SupportsShaderViewportLayerArray => _supportsShaderViewportLayerArray.Value;
|
public static bool SupportsShaderViewportLayerArray => _supportsShaderViewportLayerArray.Value;
|
||||||
public static bool SupportsViewportArray2 => _supportsViewportArray2.Value;
|
public static bool SupportsViewportArray2 => _supportsViewportArray2.Value;
|
||||||
public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value;
|
public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value;
|
||||||
public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value;
|
public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value;
|
||||||
public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value;
|
public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value;
|
||||||
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
||||||
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
|
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
|
||||||
|
|
||||||
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
|
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
|
||||||
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
||||||
public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _isIntel;
|
public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || IsIntel;
|
||||||
|
|
||||||
public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value;
|
public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value;
|
||||||
public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value;
|
public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value;
|
||||||
|
|
||||||
public static float MaximumSupportedAnisotropy => _maxSupportedAnisotropy.Value;
|
public static float MaximumSupportedAnisotropy => _maxSupportedAnisotropy.Value;
|
||||||
|
|
||||||
@ -139,4 +138,4 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return GL.GetError() == ErrorCode.NoError;
|
return GL.GetError() == ErrorCode.NoError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,4 +100,4 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
_entries.Clear();
|
_entries.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureBorderColor, borderColor);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureBorderColor, borderColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureMinLod, info.MinLod);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureMinLod, info.MinLod);
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxLod, info.MaxLod);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxLod, info.MaxLod);
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureLodBias, info.MipLodBias);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureLodBias, info.MipLodBias);
|
||||||
|
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxAnisotropyExt, info.MaxAnisotropy);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxAnisotropyExt, info.MaxAnisotropy);
|
||||||
|
@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
{
|
{
|
||||||
class TextureBuffer : TextureBase, ITexture
|
class TextureBuffer : TextureBase, ITexture
|
||||||
{
|
{
|
||||||
private OpenGLRenderer _renderer;
|
private readonly OpenGLRenderer _renderer;
|
||||||
private int _bufferOffset;
|
private int _bufferOffset;
|
||||||
private int _bufferSize;
|
private int _bufferSize;
|
||||||
private int _bufferCount;
|
private int _bufferCount;
|
||||||
@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
{
|
{
|
||||||
var dataSpan = data.AsSpan();
|
var dataSpan = data.AsSpan();
|
||||||
|
|
||||||
Buffer.SetData(_buffer, _bufferOffset, dataSpan.Slice(0, Math.Min(dataSpan.Length, _bufferSize)));
|
Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||||
|
@ -26,13 +26,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
public void Copy(
|
public void Copy(
|
||||||
TextureView src,
|
TextureView src,
|
||||||
TextureView dst,
|
TextureView dst,
|
||||||
Extents2D srcRegion,
|
Extents2D srcRegion,
|
||||||
Extents2D dstRegion,
|
Extents2D dstRegion,
|
||||||
bool linearFilter,
|
bool linearFilter,
|
||||||
int srcLayer = 0,
|
int srcLayer = 0,
|
||||||
int dstLayer = 0,
|
int dstLayer = 0,
|
||||||
int srcLevel = 0,
|
int srcLevel = 0,
|
||||||
int dstLevel = 0)
|
int dstLevel = 0)
|
||||||
{
|
{
|
||||||
int levels = Math.Min(src.Info.Levels - srcLevel, dst.Info.Levels - dstLevel);
|
int levels = Math.Min(src.Info.Levels - srcLevel, dst.Info.Levels - dstLevel);
|
||||||
int layers = Math.Min(src.Info.GetLayers() - srcLayer, dst.Info.GetLayers() - dstLayer);
|
int layers = Math.Min(src.Info.GetLayers() - srcLayer, dst.Info.GetLayers() - dstLayer);
|
||||||
@ -43,15 +43,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
public void Copy(
|
public void Copy(
|
||||||
TextureView src,
|
TextureView src,
|
||||||
TextureView dst,
|
TextureView dst,
|
||||||
Extents2D srcRegion,
|
Extents2D srcRegion,
|
||||||
Extents2D dstRegion,
|
Extents2D dstRegion,
|
||||||
bool linearFilter,
|
bool linearFilter,
|
||||||
int srcLayer,
|
int srcLayer,
|
||||||
int dstLayer,
|
int dstLayer,
|
||||||
int srcLevel,
|
int srcLevel,
|
||||||
int dstLevel,
|
int dstLevel,
|
||||||
int layers,
|
int layers,
|
||||||
int levels)
|
int levels)
|
||||||
{
|
{
|
||||||
TextureView srcConverted = src.Format.IsBgr() != dst.Format.IsBgr() ? BgraSwap(src) : src;
|
TextureView srcConverted = src.Format.IsBgr() != dst.Format.IsBgr() ? BgraSwap(src) : src;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -81,9 +80,6 @@ void main()
|
|||||||
|
|
||||||
public void CopyIncompatibleFormats(ITextureInfo src, ITextureInfo dst, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int depth, int levels)
|
public void CopyIncompatibleFormats(ITextureInfo src, ITextureInfo dst, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int depth, int levels)
|
||||||
{
|
{
|
||||||
TextureCreateInfo srcInfo = src.Info;
|
|
||||||
TextureCreateInfo dstInfo = dst.Info;
|
|
||||||
|
|
||||||
int srcBpp = src.Info.BytesPerPixel;
|
int srcBpp = src.Info.BytesPerPixel;
|
||||||
int dstBpp = dst.Info.BytesPerPixel;
|
int dstBpp = dst.Info.BytesPerPixel;
|
||||||
|
|
||||||
@ -176,7 +172,7 @@ void main()
|
|||||||
return GetShader(ComputeShaderWidening, _wideningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
|
return GetShader(ComputeShaderWidening, _wideningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetShader(
|
private static int GetShader(
|
||||||
string code,
|
string code,
|
||||||
Dictionary<int, int> programHandles,
|
Dictionary<int, int> programHandles,
|
||||||
int componentSize,
|
int componentSize,
|
||||||
|
@ -94,8 +94,8 @@ void main()
|
|||||||
}";
|
}";
|
||||||
|
|
||||||
private readonly OpenGLRenderer _renderer;
|
private readonly OpenGLRenderer _renderer;
|
||||||
private int[] _msToNonMSProgramHandles;
|
private readonly int[] _msToNonMSProgramHandles;
|
||||||
private int[] _nonMSToMSProgramHandles;
|
private readonly int[] _nonMSToMSProgramHandles;
|
||||||
|
|
||||||
public TextureCopyMS(OpenGLRenderer renderer)
|
public TextureCopyMS(OpenGLRenderer renderer)
|
||||||
{
|
{
|
||||||
@ -219,7 +219,7 @@ void main()
|
|||||||
return GetShader(ComputeShaderNonMSToMS, _nonMSToMSProgramHandles, bytesPerPixel);
|
return GetShader(ComputeShaderNonMSToMS, _nonMSToMSProgramHandles, bytesPerPixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetShader(string code, int[] programHandles, int bytesPerPixel)
|
private static int GetShader(string code, int[] programHandles, int bytesPerPixel)
|
||||||
{
|
{
|
||||||
int index = BitOperations.Log2((uint)bytesPerPixel);
|
int index = BitOperations.Log2((uint)bytesPerPixel);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info, float scaleFactor)
|
public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info, float scaleFactor)
|
||||||
{
|
{
|
||||||
_renderer = renderer;
|
_renderer = renderer;
|
||||||
Info = info;
|
Info = info;
|
||||||
|
|
||||||
Handle = GL.GenTexture();
|
Handle = GL.GenTexture();
|
||||||
ScaleFactor = scaleFactor;
|
ScaleFactor = scaleFactor;
|
||||||
|
@ -88,9 +88,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
{
|
{
|
||||||
// Swap B <-> R for BGRA formats, as OpenGL has no support for them
|
// Swap B <-> R for BGRA formats, as OpenGL has no support for them
|
||||||
// and we need to manually swap the components on read/write on the GPU.
|
// and we need to manually swap the components on read/write on the GPU.
|
||||||
int temp = swizzleRgba[0];
|
(swizzleRgba[2], swizzleRgba[0]) = (swizzleRgba[0], swizzleRgba[2]);
|
||||||
swizzleRgba[0] = swizzleRgba[2];
|
|
||||||
swizzleRgba[2] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
||||||
@ -186,8 +184,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
// This approach uses blit, which causes a resolution loss since some samples will be lost
|
// This approach uses blit, which causes a resolution loss since some samples will be lost
|
||||||
// in the process.
|
// in the process.
|
||||||
|
|
||||||
Extents2D srcRegion = new Extents2D(0, 0, Width, Height);
|
Extents2D srcRegion = new(0, 0, Width, Height);
|
||||||
Extents2D dstRegion = new Extents2D(0, 0, destinationView.Width, destinationView.Height);
|
Extents2D dstRegion = new(0, 0, destinationView.Width, destinationView.Height);
|
||||||
|
|
||||||
if (destinationView.Target.IsMultisample())
|
if (destinationView.Target.IsMultisample())
|
||||||
{
|
{
|
||||||
|
@ -21,13 +21,13 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
public IWindow Window => _window;
|
public IWindow Window => _window;
|
||||||
|
|
||||||
private TextureCopy _textureCopy;
|
private readonly TextureCopy _textureCopy;
|
||||||
private TextureCopy _backgroundTextureCopy;
|
private readonly TextureCopy _backgroundTextureCopy;
|
||||||
internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy;
|
internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy;
|
||||||
internal TextureCopyIncompatible TextureCopyIncompatible { get; }
|
internal TextureCopyIncompatible TextureCopyIncompatible { get; }
|
||||||
internal TextureCopyMS TextureCopyMS { get; }
|
internal TextureCopyMS TextureCopyMS { get; }
|
||||||
|
|
||||||
private Sync _sync;
|
private readonly Sync _sync;
|
||||||
|
|
||||||
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
|
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
|
||||||
|
|
||||||
@ -222,9 +222,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
private void PrintGpuInformation()
|
private void PrintGpuInformation()
|
||||||
{
|
{
|
||||||
GpuVendor = GL.GetString(StringName.Vendor);
|
GpuVendor = GL.GetString(StringName.Vendor);
|
||||||
GpuRenderer = GL.GetString(StringName.Renderer);
|
GpuRenderer = GL.GetString(StringName.Renderer);
|
||||||
GpuVersion = GL.GetString(StringName.Version);
|
GpuVersion = GL.GetString(StringName.Version);
|
||||||
|
|
||||||
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
|
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
class PersistentBuffers : IDisposable
|
class PersistentBuffers : IDisposable
|
||||||
{
|
{
|
||||||
private PersistentBuffer _main = new PersistentBuffer();
|
private readonly PersistentBuffer _main = new();
|
||||||
private PersistentBuffer _background = new PersistentBuffer();
|
private readonly PersistentBuffer _background = new();
|
||||||
|
|
||||||
private Dictionary<BufferHandle, IntPtr> _maps = new Dictionary<BufferHandle, IntPtr>();
|
private readonly Dictionary<BufferHandle, IntPtr> _maps = new();
|
||||||
|
|
||||||
public PersistentBuffer Default => BackgroundContextWorker.InBackground ? _background : _main;
|
public PersistentBuffer Default => BackgroundContextWorker.InBackground ? _background : _main;
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return _dataMap;
|
return _dataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Sync()
|
private static void Sync()
|
||||||
{
|
{
|
||||||
GL.MemoryBarrier(MemoryBarrierFlags.ClientMappedBufferBarrierBit);
|
GL.MemoryBarrier(MemoryBarrierFlags.ClientMappedBufferBarrierBit);
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
Sync();
|
Sync();
|
||||||
|
|
||||||
return new ReadOnlySpan<byte>(_bufferMap.ToPointer(), size).Slice(offset);
|
return new ReadOnlySpan<byte>(_bufferMap.ToPointer(), size)[offset..];
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
|
public unsafe ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
|
||||||
|
@ -44,11 +44,11 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
private CounterQueueEvent _activeConditionalRender;
|
private CounterQueueEvent _activeConditionalRender;
|
||||||
|
|
||||||
private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
|
private readonly Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
|
||||||
private Vector4<float>[] _renderScale = new Vector4<float>[73];
|
private readonly Vector4<float>[] _renderScale = new Vector4<float>[73];
|
||||||
private int _fragmentScaleCount;
|
private int _fragmentScaleCount;
|
||||||
|
|
||||||
private (TextureBase, Format)[] _images;
|
private readonly (TextureBase, Format)[] _images;
|
||||||
private TextureBase _unit0Texture;
|
private TextureBase _unit0Texture;
|
||||||
private Sampler _unit0Sampler;
|
private Sampler _unit0Sampler;
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
PostDraw();
|
PostDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawQuadsImpl(
|
private static void DrawQuadsImpl(
|
||||||
int vertexCount,
|
int vertexCount,
|
||||||
int instanceCount,
|
int instanceCount,
|
||||||
int firstVertex,
|
int firstVertex,
|
||||||
@ -285,7 +285,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
quadsCount);
|
quadsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawQuadStripImpl(
|
private static void DrawQuadStripImpl(
|
||||||
int vertexCount,
|
int vertexCount,
|
||||||
int instanceCount,
|
int instanceCount,
|
||||||
int firstVertex,
|
int firstVertex,
|
||||||
@ -366,8 +366,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
switch (_elementsType)
|
switch (_elementsType)
|
||||||
{
|
{
|
||||||
case DrawElementsType.UnsignedShort: indexElemSize = 2; break;
|
case DrawElementsType.UnsignedShort:
|
||||||
case DrawElementsType.UnsignedInt: indexElemSize = 4; break;
|
indexElemSize = 2;
|
||||||
|
break;
|
||||||
|
case DrawElementsType.UnsignedInt:
|
||||||
|
indexElemSize = 4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr indexBaseOffset = _indexBaseOffset + firstIndex * indexElemSize;
|
IntPtr indexBaseOffset = _indexBaseOffset + firstIndex * indexElemSize;
|
||||||
@ -1471,7 +1475,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
|
GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetBuffers(ReadOnlySpan<BufferAssignment> buffers, bool isStorage)
|
private static void SetBuffers(ReadOnlySpan<BufferAssignment> buffers, bool isStorage)
|
||||||
{
|
{
|
||||||
BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer;
|
BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer;
|
||||||
|
|
||||||
@ -1701,11 +1705,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||||
{
|
{
|
||||||
if (value is CounterQueueEvent)
|
// Compare an event and a constant value.
|
||||||
|
if (value is CounterQueueEvent evt)
|
||||||
{
|
{
|
||||||
// Compare an event and a constant value.
|
|
||||||
CounterQueueEvent evt = (CounterQueueEvent)value;
|
|
||||||
|
|
||||||
// Easy host conditional rendering when the check matches what GL can do:
|
// Easy host conditional rendering when the check matches what GL can do:
|
||||||
// - Event is of type samples passed.
|
// - Event is of type samples passed.
|
||||||
// - Result is not a combination of multiple queries.
|
// - Result is not a combination of multiple queries.
|
||||||
|
@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
if (log.Length > MaxShaderLogLength)
|
if (log.Length > MaxShaderLogLength)
|
||||||
{
|
{
|
||||||
log = log.Substring(0, MaxShaderLogLength) + "...";
|
log = log[..MaxShaderLogLength] + "...";
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Warning?.Print(LogClass.Gpu, $"Shader linking failed: \n{log}");
|
Logger.Warning?.Print(LogClass.Gpu, $"Shader linking failed: \n{log}");
|
||||||
|
@ -14,9 +14,9 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
public int Query { get; }
|
public int Query { get; }
|
||||||
|
|
||||||
private int _buffer;
|
private readonly int _buffer;
|
||||||
private IntPtr _bufferMap;
|
private readonly IntPtr _bufferMap;
|
||||||
private QueryTarget _type;
|
private readonly QueryTarget _type;
|
||||||
|
|
||||||
public BufferedQuery(QueryTarget type)
|
public BufferedQuery(QueryTarget type)
|
||||||
{
|
{
|
||||||
@ -64,7 +64,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool WaitingForValue(long data)
|
private static bool WaitingForValue(long data)
|
||||||
{
|
{
|
||||||
return data == DefaultValue ||
|
return data == DefaultValue ||
|
||||||
((ulong)data & HighMask) == (unchecked((ulong)DefaultValue) & HighMask);
|
((ulong)data & HighMask) == (unchecked((ulong)DefaultValue) & HighMask);
|
||||||
|
@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
private readonly Pipeline _pipeline;
|
private readonly Pipeline _pipeline;
|
||||||
|
|
||||||
private Queue<CounterQueueEvent> _events = new Queue<CounterQueueEvent>();
|
private readonly Queue<CounterQueueEvent> _events = new();
|
||||||
private CounterQueueEvent _current;
|
private CounterQueueEvent _current;
|
||||||
|
|
||||||
private ulong _accumulatedCounter;
|
private ulong _accumulatedCounter;
|
||||||
@ -23,12 +23,12 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
private Queue<BufferedQuery> _queryPool;
|
private readonly Queue<BufferedQuery> _queryPool;
|
||||||
private AutoResetEvent _queuedEvent = new AutoResetEvent(false);
|
private readonly AutoResetEvent _queuedEvent = new(false);
|
||||||
private AutoResetEvent _wakeSignal = new AutoResetEvent(false);
|
private readonly AutoResetEvent _wakeSignal = new(false);
|
||||||
private AutoResetEvent _eventConsumed = new AutoResetEvent(false);
|
private readonly AutoResetEvent _eventConsumed = new(false);
|
||||||
|
|
||||||
private Thread _consumerThread;
|
private readonly Thread _consumerThread;
|
||||||
|
|
||||||
internal CounterQueue(Pipeline pipeline, CounterType type)
|
internal CounterQueue(Pipeline pipeline, CounterType type)
|
||||||
{
|
{
|
||||||
@ -148,14 +148,13 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
private static QueryTarget GetTarget(CounterType type)
|
private static QueryTarget GetTarget(CounterType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
return type switch
|
||||||
{
|
{
|
||||||
case CounterType.SamplesPassed: return QueryTarget.SamplesPassed;
|
CounterType.SamplesPassed => QueryTarget.SamplesPassed,
|
||||||
case CounterType.PrimitivesGenerated: return QueryTarget.PrimitivesGenerated;
|
CounterType.PrimitivesGenerated => QueryTarget.PrimitivesGenerated,
|
||||||
case CounterType.TransformFeedbackPrimitivesWritten: return QueryTarget.TransformFeedbackPrimitivesWritten;
|
CounterType.TransformFeedbackPrimitivesWritten => QueryTarget.TransformFeedbackPrimitivesWritten,
|
||||||
}
|
_ => QueryTarget.SamplesPassed,
|
||||||
|
};
|
||||||
return QueryTarget.SamplesPassed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Flush(bool blocking)
|
public void Flush(bool blocking)
|
||||||
|
@ -18,8 +18,8 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
public ulong DrawIndex { get; }
|
public ulong DrawIndex { get; }
|
||||||
|
|
||||||
private CounterQueue _queue;
|
private readonly CounterQueue _queue;
|
||||||
private BufferedQuery _counter;
|
private readonly BufferedQuery _counter;
|
||||||
|
|
||||||
private bool _hostAccessReserved = false;
|
private bool _hostAccessReserved = false;
|
||||||
private int _refCount = 1; // Starts with a reference from the counter queue.
|
private int _refCount = 1; // Starts with a reference from the counter queue.
|
||||||
|
@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
{
|
{
|
||||||
class Counters : IDisposable
|
class Counters : IDisposable
|
||||||
{
|
{
|
||||||
private CounterQueue[] _counterQueues;
|
private readonly CounterQueue[] _counterQueues;
|
||||||
|
|
||||||
public Counters()
|
public Counters()
|
||||||
{
|
{
|
||||||
@ -54,4 +54,4 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
private const int DisposedLiveFrames = 2;
|
private const int DisposedLiveFrames = 2;
|
||||||
|
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
private readonly Dictionary<TextureCreateInfo, List<DisposedTexture>> _textures = new Dictionary<TextureCreateInfo, List<DisposedTexture>>();
|
private readonly Dictionary<TextureCreateInfo, List<DisposedTexture>> _textures = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a texture that is not being used anymore to the resource pool to be used later.
|
/// Add a texture that is not being used anymore to the resource pool to be used later.
|
||||||
@ -32,8 +32,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
List<DisposedTexture> list;
|
if (!_textures.TryGetValue(view.Info, out List<DisposedTexture> list))
|
||||||
if (!_textures.TryGetValue(view.Info, out list))
|
|
||||||
{
|
{
|
||||||
list = new List<DisposedTexture>();
|
list = new List<DisposedTexture>();
|
||||||
_textures.Add(view.Info, list);
|
_textures.Add(view.Info, list);
|
||||||
@ -59,8 +58,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
List<DisposedTexture> list;
|
if (!_textures.TryGetValue(info, out List<DisposedTexture> list))
|
||||||
if (!_textures.TryGetValue(info, out list))
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ulong _firstHandle = 0;
|
private ulong _firstHandle = 0;
|
||||||
private ClientWaitSyncFlags _syncFlags => HwCapabilities.RequiresSyncFlush ? ClientWaitSyncFlags.None : ClientWaitSyncFlags.SyncFlushCommandsBit;
|
private static ClientWaitSyncFlags SyncFlags => HwCapabilities.RequiresSyncFlush ? ClientWaitSyncFlags.None : ClientWaitSyncFlags.SyncFlushCommandsBit;
|
||||||
|
|
||||||
private List<SyncHandle> _handles = new List<SyncHandle>();
|
private readonly List<SyncHandle> _handles = new();
|
||||||
|
|
||||||
public void Create(ulong id)
|
public void Create(ulong id)
|
||||||
{
|
{
|
||||||
SyncHandle handle = new SyncHandle
|
SyncHandle handle = new()
|
||||||
{
|
{
|
||||||
ID = id,
|
ID = id,
|
||||||
Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None)
|
Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None)
|
||||||
@ -57,7 +57,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
if (handle.ID > lastHandle)
|
if (handle.ID > lastHandle)
|
||||||
{
|
{
|
||||||
WaitSyncStatus syncResult = GL.ClientWaitSync(handle.Handle, _syncFlags, 0);
|
WaitSyncStatus syncResult = GL.ClientWaitSync(handle.Handle, SyncFlags, 0);
|
||||||
|
|
||||||
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
||||||
{
|
{
|
||||||
@ -101,8 +101,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitSyncStatus syncResult = GL.ClientWaitSync(result.Handle, _syncFlags, 1000000000);
|
WaitSyncStatus syncResult = GL.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
|
||||||
|
|
||||||
if (syncResult == WaitSyncStatus.TimeoutExpired)
|
if (syncResult == WaitSyncStatus.TimeoutExpired)
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.Gpu, $"GL Sync Object {result.ID} failed to signal within 1000ms. Continuing...");
|
Logger.Error?.PrintMsg(LogClass.Gpu, $"GL Sync Object {result.ID} failed to signal within 1000ms. Continuing...");
|
||||||
@ -123,9 +123,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
first = _handles.FirstOrDefault();
|
first = _handles.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first == null) break;
|
if (first == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
WaitSyncStatus syncResult = GL.ClientWaitSync(first.Handle, _syncFlags, 0);
|
WaitSyncStatus syncResult = GL.ClientWaitSync(first.Handle, SyncFlags, 0);
|
||||||
|
|
||||||
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
||||||
{
|
{
|
||||||
@ -140,7 +143,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
first.Handle = IntPtr.Zero;
|
first.Handle = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// This sync handle and any following have not been reached yet.
|
// This sync handle and any following have not been reached yet.
|
||||||
break;
|
break;
|
||||||
|
@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
private uint _vertexBuffersLimited;
|
private uint _vertexBuffersLimited;
|
||||||
|
|
||||||
private BufferRange _indexBuffer;
|
private BufferRange _indexBuffer;
|
||||||
private BufferHandle _tempIndexBuffer;
|
private readonly BufferHandle _tempIndexBuffer;
|
||||||
private BufferHandle _tempVertexBuffer;
|
private BufferHandle _tempVertexBuffer;
|
||||||
private int _tempVertexBufferSize;
|
private int _tempVertexBufferSize;
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
}
|
}
|
||||||
|
|
||||||
int offset = attrib.Offset;
|
int offset = attrib.Offset;
|
||||||
int size = fmtInfo.Components;
|
int size = fmtInfo.Components;
|
||||||
|
|
||||||
bool isFloat = fmtInfo.PixelType == PixelType.Float ||
|
bool isFloat = fmtInfo.PixelType == PixelType.Float ||
|
||||||
fmtInfo.PixelType == PixelType.HalfFloat;
|
fmtInfo.PixelType == PixelType.HalfFloat;
|
||||||
|
@ -375,7 +375,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
if (_scalingFilter is not FsrScalingFilter)
|
if (_scalingFilter is not FsrScalingFilter)
|
||||||
{
|
{
|
||||||
_scalingFilter?.Dispose();
|
_scalingFilter?.Dispose();
|
||||||
_scalingFilter = new FsrScalingFilter(_renderer, _antiAliasing);
|
_scalingFilter = new FsrScalingFilter(_renderer);
|
||||||
}
|
}
|
||||||
_isLinear = false;
|
_isLinear = false;
|
||||||
_scalingFilter.Level = _scalingFilterLevel;
|
_scalingFilter.Level = _scalingFilterLevel;
|
||||||
@ -417,4 +417,4 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_updateScalingFilter = true;
|
_updateScalingFilter = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,15 @@ namespace Ryujinx.Input.Assigner
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GamepadButtonAssigner : IButtonAssigner
|
public class GamepadButtonAssigner : IButtonAssigner
|
||||||
{
|
{
|
||||||
private IGamepad _gamepad;
|
private readonly IGamepad _gamepad;
|
||||||
|
|
||||||
private GamepadStateSnapshot _currState;
|
private GamepadStateSnapshot _currState;
|
||||||
|
|
||||||
private GamepadStateSnapshot _prevState;
|
private GamepadStateSnapshot _prevState;
|
||||||
|
|
||||||
private JoystickButtonDetector _detector;
|
private readonly JoystickButtonDetector _detector;
|
||||||
|
|
||||||
private bool _forStick;
|
private readonly bool _forStick;
|
||||||
|
|
||||||
public GamepadButtonAssigner(IGamepad gamepad, float triggerThreshold, bool forStick)
|
public GamepadButtonAssigner(IGamepad gamepad, float triggerThreshold, bool forStick)
|
||||||
{
|
{
|
||||||
@ -35,7 +35,7 @@ namespace Ryujinx.Input.Assigner
|
|||||||
{
|
{
|
||||||
_currState = _gamepad.GetStateSnapshot();
|
_currState = _gamepad.GetStateSnapshot();
|
||||||
_prevState = _currState;
|
_prevState = _currState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReadInput()
|
public void ReadInput()
|
||||||
@ -116,7 +116,7 @@ namespace Ryujinx.Input.Assigner
|
|||||||
|
|
||||||
private class JoystickButtonDetector
|
private class JoystickButtonDetector
|
||||||
{
|
{
|
||||||
private Dictionary<GamepadButtonInputId, InputSummary> _stats;
|
private readonly Dictionary<GamepadButtonInputId, InputSummary> _stats;
|
||||||
|
|
||||||
public JoystickButtonDetector()
|
public JoystickButtonDetector()
|
||||||
{
|
{
|
||||||
@ -135,9 +135,8 @@ namespace Ryujinx.Input.Assigner
|
|||||||
|
|
||||||
public void AddInput(GamepadButtonInputId button, float value)
|
public void AddInput(GamepadButtonInputId button, float value)
|
||||||
{
|
{
|
||||||
InputSummary inputSummary;
|
|
||||||
|
|
||||||
if (!_stats.TryGetValue(button, out inputSummary))
|
if (!_stats.TryGetValue(button, out InputSummary inputSummary))
|
||||||
{
|
{
|
||||||
inputSummary = new InputSummary();
|
inputSummary = new InputSummary();
|
||||||
_stats.Add(button, inputSummary);
|
_stats.Add(button, inputSummary);
|
||||||
@ -148,7 +147,7 @@ namespace Ryujinx.Input.Assigner
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new();
|
||||||
|
|
||||||
foreach (var kvp in _stats)
|
foreach (var kvp in _stats)
|
||||||
{
|
{
|
||||||
|
@ -33,4 +33,4 @@ namespace Ryujinx.Input.Assigner
|
|||||||
/// <returns>The pressed button that was read</returns>
|
/// <returns>The pressed button that was read</returns>
|
||||||
string GetPressedButton();
|
string GetPressedButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ namespace Ryujinx.Input.Assigner
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class KeyboardKeyAssigner : IButtonAssigner
|
public class KeyboardKeyAssigner : IButtonAssigner
|
||||||
{
|
{
|
||||||
private IKeyboard _keyboard;
|
private readonly IKeyboard _keyboard;
|
||||||
|
|
||||||
private KeyboardStateSnapshot _keyboardState;
|
private KeyboardStateSnapshot _keyboardState;
|
||||||
|
|
||||||
@ -47,4 +47,4 @@ namespace Ryujinx.Input.Assigner
|
|||||||
return !ShouldCancel() ? keyPressed : "";
|
return !ShouldCancel() ? keyPressed : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,6 @@
|
|||||||
SingleLeftTrigger1,
|
SingleLeftTrigger1,
|
||||||
SingleRightTrigger1,
|
SingleRightTrigger1,
|
||||||
|
|
||||||
Count
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@ namespace Ryujinx.Input
|
|||||||
/// Motion
|
/// Motion
|
||||||
/// <remarks>Also named sixaxis</remarks>
|
/// <remarks>Also named sixaxis</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Motion
|
Motion,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver);
|
return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TouchScreenManager CreateTouchScreenManager()
|
public TouchScreenManager CreateTouchScreenManager()
|
||||||
{
|
{
|
||||||
if (MouseDriver == null)
|
if (MouseDriver == null)
|
||||||
@ -48,6 +48,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
|
using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
|
||||||
using ConfigControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
|
using ConfigControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
|
||||||
|
|
||||||
@ -28,29 +27,28 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HLEButtonMappingEntry[] _hleButtonMapping = new HLEButtonMappingEntry[]
|
private static readonly HLEButtonMappingEntry[] _hleButtonMapping = {
|
||||||
{
|
new(GamepadButtonInputId.A, ControllerKeys.A),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.A, ControllerKeys.A),
|
new(GamepadButtonInputId.B, ControllerKeys.B),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.B, ControllerKeys.B),
|
new(GamepadButtonInputId.X, ControllerKeys.X),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.X, ControllerKeys.X),
|
new(GamepadButtonInputId.Y, ControllerKeys.Y),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.Y, ControllerKeys.Y),
|
new(GamepadButtonInputId.LeftStick, ControllerKeys.LStick),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.LeftStick, ControllerKeys.LStick),
|
new(GamepadButtonInputId.RightStick, ControllerKeys.RStick),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.RightStick, ControllerKeys.RStick),
|
new(GamepadButtonInputId.LeftShoulder, ControllerKeys.L),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.LeftShoulder, ControllerKeys.L),
|
new(GamepadButtonInputId.RightShoulder, ControllerKeys.R),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.RightShoulder, ControllerKeys.R),
|
new(GamepadButtonInputId.LeftTrigger, ControllerKeys.Zl),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.LeftTrigger, ControllerKeys.Zl),
|
new(GamepadButtonInputId.RightTrigger, ControllerKeys.Zr),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.RightTrigger, ControllerKeys.Zr),
|
new(GamepadButtonInputId.DpadUp, ControllerKeys.DpadUp),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.DpadUp, ControllerKeys.DpadUp),
|
new(GamepadButtonInputId.DpadDown, ControllerKeys.DpadDown),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.DpadDown, ControllerKeys.DpadDown),
|
new(GamepadButtonInputId.DpadLeft, ControllerKeys.DpadLeft),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.DpadLeft, ControllerKeys.DpadLeft),
|
new(GamepadButtonInputId.DpadRight, ControllerKeys.DpadRight),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.DpadRight, ControllerKeys.DpadRight),
|
new(GamepadButtonInputId.Minus, ControllerKeys.Minus),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.Minus, ControllerKeys.Minus),
|
new(GamepadButtonInputId.Plus, ControllerKeys.Plus),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.Plus, ControllerKeys.Plus),
|
|
||||||
|
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, ControllerKeys.SlLeft),
|
new(GamepadButtonInputId.SingleLeftTrigger0, ControllerKeys.SlLeft),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, ControllerKeys.SrLeft),
|
new(GamepadButtonInputId.SingleRightTrigger0, ControllerKeys.SrLeft),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, ControllerKeys.SlRight),
|
new(GamepadButtonInputId.SingleLeftTrigger1, ControllerKeys.SlRight),
|
||||||
new HLEButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, ControllerKeys.SrRight),
|
new(GamepadButtonInputId.SingleRightTrigger1, ControllerKeys.SrRight),
|
||||||
};
|
};
|
||||||
|
|
||||||
private class HLEKeyboardMappingEntry
|
private class HLEKeyboardMappingEntry
|
||||||
@ -65,150 +63,147 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HLEKeyboardMappingEntry[] KeyMapping = new HLEKeyboardMappingEntry[]
|
private static readonly HLEKeyboardMappingEntry[] _keyMapping = {
|
||||||
{
|
new(Key.A, 0x4),
|
||||||
new HLEKeyboardMappingEntry(Key.A, 0x4),
|
new(Key.B, 0x5),
|
||||||
new HLEKeyboardMappingEntry(Key.B, 0x5),
|
new(Key.C, 0x6),
|
||||||
new HLEKeyboardMappingEntry(Key.C, 0x6),
|
new(Key.D, 0x7),
|
||||||
new HLEKeyboardMappingEntry(Key.D, 0x7),
|
new(Key.E, 0x8),
|
||||||
new HLEKeyboardMappingEntry(Key.E, 0x8),
|
new(Key.F, 0x9),
|
||||||
new HLEKeyboardMappingEntry(Key.F, 0x9),
|
new(Key.G, 0xA),
|
||||||
new HLEKeyboardMappingEntry(Key.G, 0xA),
|
new(Key.H, 0xB),
|
||||||
new HLEKeyboardMappingEntry(Key.H, 0xB),
|
new(Key.I, 0xC),
|
||||||
new HLEKeyboardMappingEntry(Key.I, 0xC),
|
new(Key.J, 0xD),
|
||||||
new HLEKeyboardMappingEntry(Key.J, 0xD),
|
new(Key.K, 0xE),
|
||||||
new HLEKeyboardMappingEntry(Key.K, 0xE),
|
new(Key.L, 0xF),
|
||||||
new HLEKeyboardMappingEntry(Key.L, 0xF),
|
new(Key.M, 0x10),
|
||||||
new HLEKeyboardMappingEntry(Key.M, 0x10),
|
new(Key.N, 0x11),
|
||||||
new HLEKeyboardMappingEntry(Key.N, 0x11),
|
new(Key.O, 0x12),
|
||||||
new HLEKeyboardMappingEntry(Key.O, 0x12),
|
new(Key.P, 0x13),
|
||||||
new HLEKeyboardMappingEntry(Key.P, 0x13),
|
new(Key.Q, 0x14),
|
||||||
new HLEKeyboardMappingEntry(Key.Q, 0x14),
|
new(Key.R, 0x15),
|
||||||
new HLEKeyboardMappingEntry(Key.R, 0x15),
|
new(Key.S, 0x16),
|
||||||
new HLEKeyboardMappingEntry(Key.S, 0x16),
|
new(Key.T, 0x17),
|
||||||
new HLEKeyboardMappingEntry(Key.T, 0x17),
|
new(Key.U, 0x18),
|
||||||
new HLEKeyboardMappingEntry(Key.U, 0x18),
|
new(Key.V, 0x19),
|
||||||
new HLEKeyboardMappingEntry(Key.V, 0x19),
|
new(Key.W, 0x1A),
|
||||||
new HLEKeyboardMappingEntry(Key.W, 0x1A),
|
new(Key.X, 0x1B),
|
||||||
new HLEKeyboardMappingEntry(Key.X, 0x1B),
|
new(Key.Y, 0x1C),
|
||||||
new HLEKeyboardMappingEntry(Key.Y, 0x1C),
|
new(Key.Z, 0x1D),
|
||||||
new HLEKeyboardMappingEntry(Key.Z, 0x1D),
|
|
||||||
|
|
||||||
new HLEKeyboardMappingEntry(Key.Number1, 0x1E),
|
new(Key.Number1, 0x1E),
|
||||||
new HLEKeyboardMappingEntry(Key.Number2, 0x1F),
|
new(Key.Number2, 0x1F),
|
||||||
new HLEKeyboardMappingEntry(Key.Number3, 0x20),
|
new(Key.Number3, 0x20),
|
||||||
new HLEKeyboardMappingEntry(Key.Number4, 0x21),
|
new(Key.Number4, 0x21),
|
||||||
new HLEKeyboardMappingEntry(Key.Number5, 0x22),
|
new(Key.Number5, 0x22),
|
||||||
new HLEKeyboardMappingEntry(Key.Number6, 0x23),
|
new(Key.Number6, 0x23),
|
||||||
new HLEKeyboardMappingEntry(Key.Number7, 0x24),
|
new(Key.Number7, 0x24),
|
||||||
new HLEKeyboardMappingEntry(Key.Number8, 0x25),
|
new(Key.Number8, 0x25),
|
||||||
new HLEKeyboardMappingEntry(Key.Number9, 0x26),
|
new(Key.Number9, 0x26),
|
||||||
new HLEKeyboardMappingEntry(Key.Number0, 0x27),
|
new(Key.Number0, 0x27),
|
||||||
|
|
||||||
new HLEKeyboardMappingEntry(Key.Enter, 0x28),
|
new(Key.Enter, 0x28),
|
||||||
new HLEKeyboardMappingEntry(Key.Escape, 0x29),
|
new(Key.Escape, 0x29),
|
||||||
new HLEKeyboardMappingEntry(Key.BackSpace, 0x2A),
|
new(Key.BackSpace, 0x2A),
|
||||||
new HLEKeyboardMappingEntry(Key.Tab, 0x2B),
|
new(Key.Tab, 0x2B),
|
||||||
new HLEKeyboardMappingEntry(Key.Space, 0x2C),
|
new(Key.Space, 0x2C),
|
||||||
new HLEKeyboardMappingEntry(Key.Minus, 0x2D),
|
new(Key.Minus, 0x2D),
|
||||||
new HLEKeyboardMappingEntry(Key.Plus, 0x2E),
|
new(Key.Plus, 0x2E),
|
||||||
new HLEKeyboardMappingEntry(Key.BracketLeft, 0x2F),
|
new(Key.BracketLeft, 0x2F),
|
||||||
new HLEKeyboardMappingEntry(Key.BracketRight, 0x30),
|
new(Key.BracketRight, 0x30),
|
||||||
new HLEKeyboardMappingEntry(Key.BackSlash, 0x31),
|
new(Key.BackSlash, 0x31),
|
||||||
new HLEKeyboardMappingEntry(Key.Tilde, 0x32),
|
new(Key.Tilde, 0x32),
|
||||||
new HLEKeyboardMappingEntry(Key.Semicolon, 0x33),
|
new(Key.Semicolon, 0x33),
|
||||||
new HLEKeyboardMappingEntry(Key.Quote, 0x34),
|
new(Key.Quote, 0x34),
|
||||||
new HLEKeyboardMappingEntry(Key.Grave, 0x35),
|
new(Key.Grave, 0x35),
|
||||||
new HLEKeyboardMappingEntry(Key.Comma, 0x36),
|
new(Key.Comma, 0x36),
|
||||||
new HLEKeyboardMappingEntry(Key.Period, 0x37),
|
new(Key.Period, 0x37),
|
||||||
new HLEKeyboardMappingEntry(Key.Slash, 0x38),
|
new(Key.Slash, 0x38),
|
||||||
new HLEKeyboardMappingEntry(Key.CapsLock, 0x39),
|
new(Key.CapsLock, 0x39),
|
||||||
|
|
||||||
new HLEKeyboardMappingEntry(Key.F1, 0x3a),
|
new(Key.F1, 0x3a),
|
||||||
new HLEKeyboardMappingEntry(Key.F2, 0x3b),
|
new(Key.F2, 0x3b),
|
||||||
new HLEKeyboardMappingEntry(Key.F3, 0x3c),
|
new(Key.F3, 0x3c),
|
||||||
new HLEKeyboardMappingEntry(Key.F4, 0x3d),
|
new(Key.F4, 0x3d),
|
||||||
new HLEKeyboardMappingEntry(Key.F5, 0x3e),
|
new(Key.F5, 0x3e),
|
||||||
new HLEKeyboardMappingEntry(Key.F6, 0x3f),
|
new(Key.F6, 0x3f),
|
||||||
new HLEKeyboardMappingEntry(Key.F7, 0x40),
|
new(Key.F7, 0x40),
|
||||||
new HLEKeyboardMappingEntry(Key.F8, 0x41),
|
new(Key.F8, 0x41),
|
||||||
new HLEKeyboardMappingEntry(Key.F9, 0x42),
|
new(Key.F9, 0x42),
|
||||||
new HLEKeyboardMappingEntry(Key.F10, 0x43),
|
new(Key.F10, 0x43),
|
||||||
new HLEKeyboardMappingEntry(Key.F11, 0x44),
|
new(Key.F11, 0x44),
|
||||||
new HLEKeyboardMappingEntry(Key.F12, 0x45),
|
new(Key.F12, 0x45),
|
||||||
|
|
||||||
new HLEKeyboardMappingEntry(Key.PrintScreen, 0x46),
|
new(Key.PrintScreen, 0x46),
|
||||||
new HLEKeyboardMappingEntry(Key.ScrollLock, 0x47),
|
new(Key.ScrollLock, 0x47),
|
||||||
new HLEKeyboardMappingEntry(Key.Pause, 0x48),
|
new(Key.Pause, 0x48),
|
||||||
new HLEKeyboardMappingEntry(Key.Insert, 0x49),
|
new(Key.Insert, 0x49),
|
||||||
new HLEKeyboardMappingEntry(Key.Home, 0x4A),
|
new(Key.Home, 0x4A),
|
||||||
new HLEKeyboardMappingEntry(Key.PageUp, 0x4B),
|
new(Key.PageUp, 0x4B),
|
||||||
new HLEKeyboardMappingEntry(Key.Delete, 0x4C),
|
new(Key.Delete, 0x4C),
|
||||||
new HLEKeyboardMappingEntry(Key.End, 0x4D),
|
new(Key.End, 0x4D),
|
||||||
new HLEKeyboardMappingEntry(Key.PageDown, 0x4E),
|
new(Key.PageDown, 0x4E),
|
||||||
new HLEKeyboardMappingEntry(Key.Right, 0x4F),
|
new(Key.Right, 0x4F),
|
||||||
new HLEKeyboardMappingEntry(Key.Left, 0x50),
|
new(Key.Left, 0x50),
|
||||||
new HLEKeyboardMappingEntry(Key.Down, 0x51),
|
new(Key.Down, 0x51),
|
||||||
new HLEKeyboardMappingEntry(Key.Up, 0x52),
|
new(Key.Up, 0x52),
|
||||||
|
|
||||||
new HLEKeyboardMappingEntry(Key.NumLock, 0x53),
|
new(Key.NumLock, 0x53),
|
||||||
new HLEKeyboardMappingEntry(Key.KeypadDivide, 0x54),
|
new(Key.KeypadDivide, 0x54),
|
||||||
new HLEKeyboardMappingEntry(Key.KeypadMultiply, 0x55),
|
new(Key.KeypadMultiply, 0x55),
|
||||||
new HLEKeyboardMappingEntry(Key.KeypadSubtract, 0x56),
|
new(Key.KeypadSubtract, 0x56),
|
||||||
new HLEKeyboardMappingEntry(Key.KeypadAdd, 0x57),
|
new(Key.KeypadAdd, 0x57),
|
||||||
new HLEKeyboardMappingEntry(Key.KeypadEnter, 0x58),
|
new(Key.KeypadEnter, 0x58),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad1, 0x59),
|
new(Key.Keypad1, 0x59),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad2, 0x5A),
|
new(Key.Keypad2, 0x5A),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad3, 0x5B),
|
new(Key.Keypad3, 0x5B),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad4, 0x5C),
|
new(Key.Keypad4, 0x5C),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad5, 0x5D),
|
new(Key.Keypad5, 0x5D),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad6, 0x5E),
|
new(Key.Keypad6, 0x5E),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad7, 0x5F),
|
new(Key.Keypad7, 0x5F),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad8, 0x60),
|
new(Key.Keypad8, 0x60),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad9, 0x61),
|
new(Key.Keypad9, 0x61),
|
||||||
new HLEKeyboardMappingEntry(Key.Keypad0, 0x62),
|
new(Key.Keypad0, 0x62),
|
||||||
new HLEKeyboardMappingEntry(Key.KeypadDecimal, 0x63),
|
new(Key.KeypadDecimal, 0x63),
|
||||||
|
|
||||||
new HLEKeyboardMappingEntry(Key.F13, 0x68),
|
new(Key.F13, 0x68),
|
||||||
new HLEKeyboardMappingEntry(Key.F14, 0x69),
|
new(Key.F14, 0x69),
|
||||||
new HLEKeyboardMappingEntry(Key.F15, 0x6A),
|
new(Key.F15, 0x6A),
|
||||||
new HLEKeyboardMappingEntry(Key.F16, 0x6B),
|
new(Key.F16, 0x6B),
|
||||||
new HLEKeyboardMappingEntry(Key.F17, 0x6C),
|
new(Key.F17, 0x6C),
|
||||||
new HLEKeyboardMappingEntry(Key.F18, 0x6D),
|
new(Key.F18, 0x6D),
|
||||||
new HLEKeyboardMappingEntry(Key.F19, 0x6E),
|
new(Key.F19, 0x6E),
|
||||||
new HLEKeyboardMappingEntry(Key.F20, 0x6F),
|
new(Key.F20, 0x6F),
|
||||||
new HLEKeyboardMappingEntry(Key.F21, 0x70),
|
new(Key.F21, 0x70),
|
||||||
new HLEKeyboardMappingEntry(Key.F22, 0x71),
|
new(Key.F22, 0x71),
|
||||||
new HLEKeyboardMappingEntry(Key.F23, 0x72),
|
new(Key.F23, 0x72),
|
||||||
new HLEKeyboardMappingEntry(Key.F24, 0x73),
|
new(Key.F24, 0x73),
|
||||||
|
|
||||||
new HLEKeyboardMappingEntry(Key.ControlLeft, 0xE0),
|
new(Key.ControlLeft, 0xE0),
|
||||||
new HLEKeyboardMappingEntry(Key.ShiftLeft, 0xE1),
|
new(Key.ShiftLeft, 0xE1),
|
||||||
new HLEKeyboardMappingEntry(Key.AltLeft, 0xE2),
|
new(Key.AltLeft, 0xE2),
|
||||||
new HLEKeyboardMappingEntry(Key.WinLeft, 0xE3),
|
new(Key.WinLeft, 0xE3),
|
||||||
new HLEKeyboardMappingEntry(Key.ControlRight, 0xE4),
|
new(Key.ControlRight, 0xE4),
|
||||||
new HLEKeyboardMappingEntry(Key.ShiftRight, 0xE5),
|
new(Key.ShiftRight, 0xE5),
|
||||||
new HLEKeyboardMappingEntry(Key.AltRight, 0xE6),
|
new(Key.AltRight, 0xE6),
|
||||||
new HLEKeyboardMappingEntry(Key.WinRight, 0xE7),
|
new(Key.WinRight, 0xE7),
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly HLEKeyboardMappingEntry[] KeyModifierMapping = new HLEKeyboardMappingEntry[]
|
private static readonly HLEKeyboardMappingEntry[] _keyModifierMapping = {
|
||||||
{
|
new(Key.ControlLeft, 0),
|
||||||
new HLEKeyboardMappingEntry(Key.ControlLeft, 0),
|
new(Key.ShiftLeft, 1),
|
||||||
new HLEKeyboardMappingEntry(Key.ShiftLeft, 1),
|
new(Key.AltLeft, 2),
|
||||||
new HLEKeyboardMappingEntry(Key.AltLeft, 2),
|
new(Key.WinLeft, 3),
|
||||||
new HLEKeyboardMappingEntry(Key.WinLeft, 3),
|
new(Key.ControlRight, 4),
|
||||||
new HLEKeyboardMappingEntry(Key.ControlRight, 4),
|
new(Key.ShiftRight, 5),
|
||||||
new HLEKeyboardMappingEntry(Key.ShiftRight, 5),
|
new(Key.AltRight, 6),
|
||||||
new HLEKeyboardMappingEntry(Key.AltRight, 6),
|
new(Key.WinRight, 7),
|
||||||
new HLEKeyboardMappingEntry(Key.WinRight, 7),
|
new(Key.CapsLock, 8),
|
||||||
new HLEKeyboardMappingEntry(Key.CapsLock, 8),
|
new(Key.ScrollLock, 9),
|
||||||
new HLEKeyboardMappingEntry(Key.ScrollLock, 9),
|
new(Key.NumLock, 10),
|
||||||
new HLEKeyboardMappingEntry(Key.NumLock, 10),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private bool _isValid;
|
private bool _isValid;
|
||||||
private string _id;
|
|
||||||
|
|
||||||
private MotionInput _leftMotionInput;
|
private MotionInput _leftMotionInput;
|
||||||
private MotionInput _rightMotionInput;
|
private MotionInput _rightMotionInput;
|
||||||
@ -219,14 +214,14 @@ namespace Ryujinx.Input.HLE
|
|||||||
public IGamepadDriver GamepadDriver { get; private set; }
|
public IGamepadDriver GamepadDriver { get; private set; }
|
||||||
public GamepadStateSnapshot State { get; private set; }
|
public GamepadStateSnapshot State { get; private set; }
|
||||||
|
|
||||||
public string Id => _id;
|
public string Id { get; private set; }
|
||||||
|
|
||||||
private CemuHookClient _cemuHookClient;
|
private readonly CemuHookClient _cemuHookClient;
|
||||||
|
|
||||||
public NpadController(CemuHookClient cemuHookClient)
|
public NpadController(CemuHookClient cemuHookClient)
|
||||||
{
|
{
|
||||||
State = default;
|
State = default;
|
||||||
_id = null;
|
Id = null;
|
||||||
_isValid = false;
|
_isValid = false;
|
||||||
_cemuHookClient = cemuHookClient;
|
_cemuHookClient = cemuHookClient;
|
||||||
}
|
}
|
||||||
@ -237,8 +232,8 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
_gamepad?.Dispose();
|
_gamepad?.Dispose();
|
||||||
|
|
||||||
_id = config.Id;
|
Id = config.Id;
|
||||||
_gamepad = GamepadDriver.GetGamepad(_id);
|
_gamepad = GamepadDriver.GetGamepad(Id);
|
||||||
_isValid = _gamepad != null;
|
_isValid = _gamepad != null;
|
||||||
|
|
||||||
UpdateUserConfiguration(config);
|
UpdateUserConfiguration(config);
|
||||||
@ -278,7 +273,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
if (motionConfig.MotionBackend != MotionInputBackendType.CemuHook)
|
if (motionConfig.MotionBackend != MotionInputBackendType.CemuHook)
|
||||||
{
|
{
|
||||||
_leftMotionInput = new MotionInput();
|
_leftMotionInput = new MotionInput();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_leftMotionInput = null;
|
_leftMotionInput = null;
|
||||||
@ -347,7 +342,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
public GamepadInput GetHLEInputState()
|
public GamepadInput GetHLEInputState()
|
||||||
{
|
{
|
||||||
GamepadInput state = new GamepadInput();
|
GamepadInput state = new();
|
||||||
|
|
||||||
// First update all buttons
|
// First update all buttons
|
||||||
foreach (HLEButtonMappingEntry entry in _hleButtonMapping)
|
foreach (HLEButtonMappingEntry entry in _hleButtonMapping)
|
||||||
@ -366,13 +361,13 @@ namespace Ryujinx.Input.HLE
|
|||||||
state.LStick = new JoystickPosition
|
state.LStick = new JoystickPosition
|
||||||
{
|
{
|
||||||
Dx = ClampAxis(leftAxisX),
|
Dx = ClampAxis(leftAxisX),
|
||||||
Dy = ClampAxis(leftAxisY)
|
Dy = ClampAxis(leftAxisY),
|
||||||
};
|
};
|
||||||
|
|
||||||
state.RStick = new JoystickPosition
|
state.RStick = new JoystickPosition
|
||||||
{
|
{
|
||||||
Dx = ClampAxis(rightAxisX),
|
Dx = ClampAxis(rightAxisX),
|
||||||
Dy = ClampAxis(rightAxisY)
|
Dy = ClampAxis(rightAxisY),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (_config is StandardControllerInputConfig controllerConfig)
|
else if (_config is StandardControllerInputConfig controllerConfig)
|
||||||
@ -391,16 +386,16 @@ namespace Ryujinx.Input.HLE
|
|||||||
private static JoystickPosition ApplyDeadzone(float x, float y, float deadzone)
|
private static JoystickPosition ApplyDeadzone(float x, float y, float deadzone)
|
||||||
{
|
{
|
||||||
float magnitudeClamped = Math.Min(MathF.Sqrt(x * x + y * y), 1f);
|
float magnitudeClamped = Math.Min(MathF.Sqrt(x * x + y * y), 1f);
|
||||||
|
|
||||||
if (magnitudeClamped <= deadzone)
|
if (magnitudeClamped <= deadzone)
|
||||||
{
|
{
|
||||||
return new JoystickPosition() {Dx = 0, Dy = 0};
|
return new JoystickPosition { Dx = 0, Dy = 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JoystickPosition()
|
return new JoystickPosition
|
||||||
{
|
{
|
||||||
Dx = ClampAxis((x / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))),
|
Dx = ClampAxis((x / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))),
|
||||||
Dy = ClampAxis((y / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone)))
|
Dy = ClampAxis((y / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +423,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
return new JoystickPosition
|
return new JoystickPosition
|
||||||
{
|
{
|
||||||
Dx = (int)point.X,
|
Dx = (int)point.X,
|
||||||
Dy = (int)point.Y
|
Dy = (int)point.Y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,12 +471,12 @@ namespace Ryujinx.Input.HLE
|
|||||||
rotation = new Vector3();
|
rotation = new Vector3();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SixAxisInput()
|
return new SixAxisInput
|
||||||
{
|
{
|
||||||
Accelerometer = accelerometer,
|
Accelerometer = accelerometer,
|
||||||
Gyroscope = gyroscope,
|
Gyroscope = gyroscope,
|
||||||
Rotation = rotation,
|
Rotation = rotation,
|
||||||
Orientation = orientationForHLE
|
Orientation = orientationForHLE,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,20 +497,20 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
KeyboardStateSnapshot keyboardState = keyboard.GetKeyboardStateSnapshot();
|
KeyboardStateSnapshot keyboardState = keyboard.GetKeyboardStateSnapshot();
|
||||||
|
|
||||||
KeyboardInput hidKeyboard = new KeyboardInput
|
KeyboardInput hidKeyboard = new()
|
||||||
{
|
{
|
||||||
Modifier = 0,
|
Modifier = 0,
|
||||||
Keys = new ulong[0x4]
|
Keys = new ulong[0x4],
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (HLEKeyboardMappingEntry entry in KeyMapping)
|
foreach (HLEKeyboardMappingEntry entry in _keyMapping)
|
||||||
{
|
{
|
||||||
ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL;
|
ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL;
|
||||||
|
|
||||||
hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40));
|
hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (HLEKeyboardMappingEntry entry in KeyModifierMapping)
|
foreach (HLEKeyboardMappingEntry entry in _keyModifierMapping)
|
||||||
{
|
{
|
||||||
int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0;
|
int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0;
|
||||||
|
|
||||||
@ -539,6 +534,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,13 +7,15 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
|
using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
|
||||||
|
using ControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
|
||||||
|
using PlayerIndex = Ryujinx.HLE.HOS.Services.Hid.PlayerIndex;
|
||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
|
|
||||||
namespace Ryujinx.Input.HLE
|
namespace Ryujinx.Input.HLE
|
||||||
{
|
{
|
||||||
public class NpadManager : IDisposable
|
public class NpadManager : IDisposable
|
||||||
{
|
{
|
||||||
private CemuHookClient _cemuHookClient;
|
private readonly CemuHookClient _cemuHookClient;
|
||||||
|
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
@ -21,7 +23,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
private const int MaxControllers = 9;
|
private const int MaxControllers = 9;
|
||||||
|
|
||||||
private NpadController[] _controllers;
|
private readonly NpadController[] _controllers;
|
||||||
|
|
||||||
private readonly IGamepadDriver _keyboardDriver;
|
private readonly IGamepadDriver _keyboardDriver;
|
||||||
private readonly IGamepadDriver _gamepadDriver;
|
private readonly IGamepadDriver _gamepadDriver;
|
||||||
@ -51,7 +53,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
List<InputConfig> validInputs = new List<InputConfig>();
|
List<InputConfig> validInputs = new();
|
||||||
foreach (var inputConfigEntry in _inputConfig)
|
foreach (var inputConfigEntry in _inputConfig)
|
||||||
{
|
{
|
||||||
if (_controllers[(int)inputConfigEntry.PlayerIndex] != null)
|
if (_controllers[(int)inputConfigEntry.PlayerIndex] != null)
|
||||||
@ -96,10 +98,8 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
return controller.UpdateDriverConfiguration(targetDriver, config);
|
return controller.UpdateDriverConfiguration(targetDriver, config);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return controller.GamepadDriver != null;
|
||||||
return controller.GamepadDriver != null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReloadConfiguration(List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
|
public void ReloadConfiguration(List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
|
||||||
@ -112,11 +112,11 @@ namespace Ryujinx.Input.HLE
|
|||||||
_controllers[i] = null;
|
_controllers[i] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<InputConfig> validInputs = new List<InputConfig>();
|
List<InputConfig> validInputs = new();
|
||||||
|
|
||||||
foreach (InputConfig inputConfigEntry in inputConfig)
|
foreach (InputConfig inputConfigEntry in inputConfig)
|
||||||
{
|
{
|
||||||
NpadController controller = new NpadController(_cemuHookClient);
|
NpadController controller = new(_cemuHookClient);
|
||||||
|
|
||||||
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
|
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
|
||||||
|
|
||||||
@ -131,9 +131,9 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_inputConfig = inputConfig;
|
_inputConfig = inputConfig;
|
||||||
_enableKeyboard = enableKeyboard;
|
_enableKeyboard = enableKeyboard;
|
||||||
_enableMouse = enableMouse;
|
_enableMouse = enableMouse;
|
||||||
|
|
||||||
_device.Hid.RefreshInputConfig(validInputs);
|
_device.Hid.RefreshInputConfig(validInputs);
|
||||||
}
|
}
|
||||||
@ -167,8 +167,8 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
List<GamepadInput> hleInputStates = new List<GamepadInput>();
|
List<GamepadInput> hleInputStates = new();
|
||||||
List<SixAxisInput> hleMotionStates = new List<SixAxisInput>(NpadDevices.MaxControllers);
|
List<SixAxisInput> hleMotionStates = new(NpadDevices.MaxControllers);
|
||||||
|
|
||||||
KeyboardInput? hleKeyboardInput = null;
|
KeyboardInput? hleKeyboardInput = null;
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
(SixAxisInput, SixAxisInput) motionState = default;
|
(SixAxisInput, SixAxisInput) motionState = default;
|
||||||
|
|
||||||
NpadController controller = _controllers[(int)inputConfig.PlayerIndex];
|
NpadController controller = _controllers[(int)inputConfig.PlayerIndex];
|
||||||
Ryujinx.HLE.HOS.Services.Hid.PlayerIndex playerIndex = (Ryujinx.HLE.HOS.Services.Hid.PlayerIndex)inputConfig.PlayerIndex;
|
PlayerIndex playerIndex = (PlayerIndex)inputConfig.PlayerIndex;
|
||||||
|
|
||||||
bool isJoyconPair = false;
|
bool isJoyconPair = false;
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
inputState.Buttons |= _device.Hid.UpdateStickButtons(inputState.LStick, inputState.RStick);
|
inputState.Buttons |= _device.Hid.UpdateStickButtons(inputState.LStick, inputState.RStick);
|
||||||
|
|
||||||
isJoyconPair = inputConfig.ControllerType == Common.Configuration.Hid.ControllerType.JoyconPair;
|
isJoyconPair = inputConfig.ControllerType == ControllerType.JoyconPair;
|
||||||
|
|
||||||
var altMotionState = isJoyconPair ? controller.GetHLEMotionState(true) : default;
|
var altMotionState = isJoyconPair ? controller.GetHLEMotionState(true) : default;
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
return _inputConfig.Find(x => x.PlayerIndex == (Ryujinx.Common.Configuration.Hid.PlayerIndex)index);
|
return _inputConfig.Find(x => x.PlayerIndex == (Common.Configuration.Hid.PlayerIndex)index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +314,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
MouseStateSnapshot snapshot = IMouse.GetMouseStateSnapshot(_mouse);
|
MouseStateSnapshot snapshot = IMouse.GetMouseStateSnapshot(_mouse);
|
||||||
var touchPosition = IMouse.GetScreenPosition(snapshot.Position, _mouse.ClientSize, aspectRatio);
|
var touchPosition = IMouse.GetScreenPosition(snapshot.Position, _mouse.ClientSize, aspectRatio);
|
||||||
|
|
||||||
TouchPoint currentPoint = new TouchPoint
|
TouchPoint currentPoint = new()
|
||||||
{
|
{
|
||||||
Attribute = TouchAttribute.End,
|
Attribute = TouchAttribute.End,
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
// Placeholder values till more data is acquired
|
// Placeholder values till more data is acquired
|
||||||
DiameterX = 10,
|
DiameterX = 10,
|
||||||
DiameterY = 10,
|
DiameterY = 10,
|
||||||
Angle = 90
|
Angle = 90,
|
||||||
};
|
};
|
||||||
|
|
||||||
_device.Hid.Touchscreen.Update(currentPoint);
|
_device.Hid.Touchscreen.Update(currentPoint);
|
||||||
@ -71,7 +71,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
attribute = TouchAttribute.End;
|
attribute = TouchAttribute.End;
|
||||||
}
|
}
|
||||||
|
|
||||||
TouchPoint currentPoint = new TouchPoint
|
TouchPoint currentPoint = new()
|
||||||
{
|
{
|
||||||
Attribute = attribute,
|
Attribute = attribute,
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ namespace Ryujinx.Input.HLE
|
|||||||
// Placeholder values till more data is acquired
|
// Placeholder values till more data is acquired
|
||||||
DiameterX = 10,
|
DiameterX = 10,
|
||||||
DiameterY = 10,
|
DiameterY = 10,
|
||||||
Angle = 90
|
Angle = 90,
|
||||||
};
|
};
|
||||||
|
|
||||||
_device.Hid.Touchscreen.Update(currentPoint);
|
_device.Hid.Touchscreen.Update(currentPoint);
|
||||||
@ -94,6 +94,9 @@ namespace Ryujinx.Input.HLE
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,9 @@ namespace Ryujinx.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMouse : IGamepad
|
public interface IMouse : IGamepad
|
||||||
{
|
{
|
||||||
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
private const int SwitchPanelWidth = 1280;
|
private const int SwitchPanelWidth = 1280;
|
||||||
|
#pragma warning restore IDE0051
|
||||||
private const int SwitchPanelHeight = 720;
|
private const int SwitchPanelHeight = 720;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -101,4 +103,4 @@ namespace Ryujinx.Input
|
|||||||
return new Vector2();
|
return new Vector2();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,6 @@
|
|||||||
BackSlash,
|
BackSlash,
|
||||||
Unbound,
|
Unbound,
|
||||||
|
|
||||||
Count
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ namespace Ryujinx.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class KeyboardStateSnapshot
|
public class KeyboardStateSnapshot
|
||||||
{
|
{
|
||||||
private bool[] _keysState;
|
private readonly bool[] _keysState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="KeyboardStateSnapshot"/>.
|
/// Create a new <see cref="KeyboardStateSnapshot"/>.
|
||||||
|
@ -19,7 +19,7 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
{
|
{
|
||||||
public class Client : IDisposable
|
public class Client : IDisposable
|
||||||
{
|
{
|
||||||
public const uint Magic = 0x43555344; // DSUC
|
public const uint Magic = 0x43555344; // DSUC
|
||||||
public const ushort Version = 1001;
|
public const ushort Version = 1001;
|
||||||
|
|
||||||
private bool _active;
|
private bool _active;
|
||||||
@ -29,15 +29,15 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
private readonly Dictionary<int, UdpClient> _clients;
|
private readonly Dictionary<int, UdpClient> _clients;
|
||||||
|
|
||||||
private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues<PlayerIndex>().Length];
|
private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues<PlayerIndex>().Length];
|
||||||
private readonly long[] _clientRetryTimer = new long[Enum.GetValues<PlayerIndex>().Length];
|
private readonly long[] _clientRetryTimer = new long[Enum.GetValues<PlayerIndex>().Length];
|
||||||
private NpadManager _npadManager;
|
private readonly NpadManager _npadManager;
|
||||||
|
|
||||||
public Client(NpadManager npadManager)
|
public Client(NpadManager npadManager)
|
||||||
{
|
{
|
||||||
_npadManager = npadManager;
|
_npadManager = npadManager;
|
||||||
_hosts = new Dictionary<int, IPEndPoint>();
|
_hosts = new Dictionary<int, IPEndPoint>();
|
||||||
_motionData = new Dictionary<int, Dictionary<int, MotionInput>>();
|
_motionData = new Dictionary<int, Dictionary<int, MotionInput>>();
|
||||||
_clients = new Dictionary<int, UdpClient>();
|
_clients = new Dictionary<int, UdpClient>();
|
||||||
|
|
||||||
CloseClients();
|
CloseClients();
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(host), port);
|
IPEndPoint endPoint = new(IPAddress.Parse(host), port);
|
||||||
|
|
||||||
client = new UdpClient(host, port);
|
client = new UdpClient(host, port);
|
||||||
|
|
||||||
@ -141,9 +141,9 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
{
|
{
|
||||||
lock (_motionData)
|
lock (_motionData)
|
||||||
{
|
{
|
||||||
if (_motionData.ContainsKey(player))
|
if (_motionData.TryGetValue(player, out Dictionary<int, MotionInput> value))
|
||||||
{
|
{
|
||||||
if (_motionData[player].TryGetValue(slot, out input))
|
if (value.TryGetValue(slot, out input))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -164,26 +164,26 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
private void Send(byte[] data, int clientId)
|
private void Send(byte[] data, int clientId)
|
||||||
{
|
{
|
||||||
if (_clients.TryGetValue(clientId, out UdpClient _client))
|
if (_clients.TryGetValue(clientId, out UdpClient client))
|
||||||
{
|
{
|
||||||
if (_client != null && _client.Client != null && _client.Client.Connected)
|
if (client != null && client.Client != null && client.Client.Connected)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_client?.Send(data, data.Length);
|
client?.Send(data, data.Length);
|
||||||
}
|
}
|
||||||
catch (SocketException socketException)
|
catch (SocketException socketException)
|
||||||
{
|
{
|
||||||
if (!_clientErrorStatus[clientId])
|
if (!_clientErrorStatus[clientId])
|
||||||
{
|
{
|
||||||
Logger.Warning?.PrintMsg(LogClass.Hid, $"Unable to send data request to motion source at {_client.Client.RemoteEndPoint}. Error: {socketException.ErrorCode}");
|
Logger.Warning?.PrintMsg(LogClass.Hid, $"Unable to send data request to motion source at {client.Client.RemoteEndPoint}. Error: {socketException.ErrorCode}");
|
||||||
}
|
}
|
||||||
|
|
||||||
_clientErrorStatus[clientId] = true;
|
_clientErrorStatus[clientId] = true;
|
||||||
|
|
||||||
RemoveClient(clientId);
|
RemoveClient(clientId);
|
||||||
|
|
||||||
_client?.Dispose();
|
client?.Dispose();
|
||||||
|
|
||||||
SetRetryTimer(clientId);
|
SetRetryTimer(clientId);
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
RemoveClient(clientId);
|
RemoveClient(clientId);
|
||||||
|
|
||||||
_client?.Dispose();
|
client?.Dispose();
|
||||||
|
|
||||||
SetRetryTimer(clientId);
|
SetRetryTimer(clientId);
|
||||||
}
|
}
|
||||||
@ -203,13 +203,13 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
private byte[] Receive(int clientId, int timeout = 0)
|
private byte[] Receive(int clientId, int timeout = 0)
|
||||||
{
|
{
|
||||||
if (_hosts.TryGetValue(clientId, out IPEndPoint endPoint) && _clients.TryGetValue(clientId, out UdpClient _client))
|
if (_hosts.TryGetValue(clientId, out IPEndPoint endPoint) && _clients.TryGetValue(clientId, out UdpClient client))
|
||||||
{
|
{
|
||||||
if (_client != null && _client.Client != null && _client.Client.Connected)
|
if (client != null && client.Client != null && client.Client.Connected)
|
||||||
{
|
{
|
||||||
_client.Client.ReceiveTimeout = timeout;
|
client.Client.ReceiveTimeout = timeout;
|
||||||
|
|
||||||
var result = _client?.Receive(ref endPoint);
|
var result = client?.Receive(ref endPoint);
|
||||||
|
|
||||||
if (result.Length > 0)
|
if (result.Length > 0)
|
||||||
{
|
{
|
||||||
@ -242,9 +242,9 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
public void ReceiveLoop(int clientId)
|
public void ReceiveLoop(int clientId)
|
||||||
{
|
{
|
||||||
if (_hosts.TryGetValue(clientId, out IPEndPoint endPoint) && _clients.TryGetValue(clientId, out UdpClient _client))
|
if (_hosts.TryGetValue(clientId, out IPEndPoint endPoint) && _clients.TryGetValue(clientId, out UdpClient client))
|
||||||
{
|
{
|
||||||
if (_client != null && _client.Client != null && _client.Client.Connected)
|
if (client != null && client.Client != null && client.Client.Connected)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -271,7 +271,7 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
RemoveClient(clientId);
|
RemoveClient(clientId);
|
||||||
|
|
||||||
_client?.Dispose();
|
client?.Dispose();
|
||||||
|
|
||||||
SetRetryTimer(clientId);
|
SetRetryTimer(clientId);
|
||||||
}
|
}
|
||||||
@ -281,7 +281,7 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
RemoveClient(clientId);
|
RemoveClient(clientId);
|
||||||
|
|
||||||
_client?.Dispose();
|
client?.Dispose();
|
||||||
|
|
||||||
SetRetryTimer(clientId);
|
SetRetryTimer(clientId);
|
||||||
}
|
}
|
||||||
@ -297,8 +297,8 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
data = data.AsSpan()[16..].ToArray();
|
data = data.AsSpan()[16..].ToArray();
|
||||||
|
|
||||||
using MemoryStream stream = new MemoryStream(data);
|
using MemoryStream stream = new(data);
|
||||||
using BinaryReader reader = new BinaryReader(stream);
|
using BinaryReader reader = new(stream);
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@ -310,18 +310,18 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
case MessageType.Data:
|
case MessageType.Data:
|
||||||
ControllerDataResponse inputData = reader.ReadStruct<ControllerDataResponse>();
|
ControllerDataResponse inputData = reader.ReadStruct<ControllerDataResponse>();
|
||||||
|
|
||||||
Vector3 accelerometer = new Vector3()
|
Vector3 accelerometer = new()
|
||||||
{
|
{
|
||||||
X = -inputData.AccelerometerX,
|
X = -inputData.AccelerometerX,
|
||||||
Y = inputData.AccelerometerZ,
|
Y = inputData.AccelerometerZ,
|
||||||
Z = -inputData.AccelerometerY
|
Z = -inputData.AccelerometerY,
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector3 gyroscrope = new Vector3()
|
Vector3 gyroscrope = new()
|
||||||
{
|
{
|
||||||
X = inputData.GyroscopePitch,
|
X = inputData.GyroscopePitch,
|
||||||
Y = inputData.GyroscopeRoll,
|
Y = inputData.GyroscopeRoll,
|
||||||
Z = -inputData.GyroscopeYaw
|
Z = -inputData.GyroscopeYaw,
|
||||||
};
|
};
|
||||||
|
|
||||||
ulong timestamp = inputData.MotionTimestamp;
|
ulong timestamp = inputData.MotionTimestamp;
|
||||||
@ -346,7 +346,7 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MotionInput input = new MotionInput();
|
MotionInput input = new();
|
||||||
|
|
||||||
input.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone);
|
input.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone);
|
||||||
|
|
||||||
@ -355,11 +355,11 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MotionInput input = new MotionInput();
|
MotionInput input = new();
|
||||||
|
|
||||||
input.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone);
|
input.Update(accelerometer, gyroscrope, timestamp, cemuHookConfig.Sensitivity, (float)cemuHookConfig.GyroDeadzone);
|
||||||
|
|
||||||
_motionData.Add(clientId, new Dictionary<int, MotionInput>() { { slot, input } });
|
_motionData.Add(clientId, new Dictionary<int, MotionInput> { { slot, input } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -380,38 +380,37 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
Header header = GenerateHeader(clientId);
|
Header header = GenerateHeader(clientId);
|
||||||
|
|
||||||
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream())
|
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
using BinaryWriter writer = new(stream);
|
||||||
|
|
||||||
|
writer.WriteStruct(header);
|
||||||
|
|
||||||
|
ControllerInfoRequest request = new()
|
||||||
{
|
{
|
||||||
writer.WriteStruct(header);
|
Type = MessageType.Info,
|
||||||
|
PortsCount = 4,
|
||||||
|
};
|
||||||
|
|
||||||
ControllerInfoRequest request = new ControllerInfoRequest()
|
request.PortIndices[0] = (byte)slot;
|
||||||
{
|
|
||||||
Type = MessageType.Info,
|
|
||||||
PortsCount = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
request.PortIndices[0] = (byte)slot;
|
writer.WriteStruct(request);
|
||||||
|
|
||||||
writer.WriteStruct(request);
|
header.Length = (ushort)(stream.Length - 16);
|
||||||
|
|
||||||
header.Length = (ushort)(stream.Length - 16);
|
writer.Seek(6, SeekOrigin.Begin);
|
||||||
|
writer.Write(header.Length);
|
||||||
|
|
||||||
writer.Seek(6, SeekOrigin.Begin);
|
Crc32.Hash(stream.ToArray(), header.Crc32.AsSpan());
|
||||||
writer.Write(header.Length);
|
|
||||||
|
|
||||||
Crc32.Hash(stream.ToArray(), header.Crc32.AsSpan());
|
writer.Seek(8, SeekOrigin.Begin);
|
||||||
|
writer.Write(header.Crc32.AsSpan());
|
||||||
|
|
||||||
writer.Seek(8, SeekOrigin.Begin);
|
byte[] data = stream.ToArray();
|
||||||
writer.Write(header.Crc32.AsSpan());
|
|
||||||
|
|
||||||
byte[] data = stream.ToArray();
|
Send(data, clientId);
|
||||||
|
|
||||||
Send(data, clientId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void RequestData(int clientId, int slot)
|
public void RequestData(int clientId, int slot)
|
||||||
{
|
{
|
||||||
if (!_active)
|
if (!_active)
|
||||||
{
|
{
|
||||||
@ -420,44 +419,43 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
Header header = GenerateHeader(clientId);
|
Header header = GenerateHeader(clientId);
|
||||||
|
|
||||||
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream())
|
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
using BinaryWriter writer = new(stream);
|
||||||
|
|
||||||
|
writer.WriteStruct(header);
|
||||||
|
|
||||||
|
ControllerDataRequest request = new()
|
||||||
{
|
{
|
||||||
writer.WriteStruct(header);
|
Type = MessageType.Data,
|
||||||
|
Slot = (byte)slot,
|
||||||
|
SubscriberType = SubscriberType.Slot,
|
||||||
|
};
|
||||||
|
|
||||||
ControllerDataRequest request = new ControllerDataRequest()
|
writer.WriteStruct(request);
|
||||||
{
|
|
||||||
Type = MessageType.Data,
|
|
||||||
Slot = (byte)slot,
|
|
||||||
SubscriberType = SubscriberType.Slot
|
|
||||||
};
|
|
||||||
|
|
||||||
writer.WriteStruct(request);
|
header.Length = (ushort)(stream.Length - 16);
|
||||||
|
|
||||||
header.Length = (ushort)(stream.Length - 16);
|
writer.Seek(6, SeekOrigin.Begin);
|
||||||
|
writer.Write(header.Length);
|
||||||
|
|
||||||
writer.Seek(6, SeekOrigin.Begin);
|
Crc32.Hash(stream.ToArray(), header.Crc32.AsSpan());
|
||||||
writer.Write(header.Length);
|
|
||||||
|
|
||||||
Crc32.Hash(stream.ToArray(), header.Crc32.AsSpan());
|
writer.Seek(8, SeekOrigin.Begin);
|
||||||
|
writer.Write(header.Crc32.AsSpan());
|
||||||
|
|
||||||
writer.Seek(8, SeekOrigin.Begin);
|
byte[] data = stream.ToArray();
|
||||||
writer.Write(header.Crc32.AsSpan());
|
|
||||||
|
|
||||||
byte[] data = stream.ToArray();
|
Send(data, clientId);
|
||||||
|
|
||||||
Send(data, clientId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Header GenerateHeader(int clientId)
|
private static Header GenerateHeader(int clientId)
|
||||||
{
|
{
|
||||||
Header header = new Header()
|
Header header = new()
|
||||||
{
|
{
|
||||||
Id = (uint)clientId,
|
Id = (uint)clientId,
|
||||||
MagicString = Magic,
|
MagicString = Magic,
|
||||||
Version = Version,
|
Version = Version,
|
||||||
Length = 0
|
Length = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return header;
|
return header;
|
||||||
@ -465,9 +463,10 @@ namespace Ryujinx.Input.Motion.CemuHook
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
_active = false;
|
_active = false;
|
||||||
|
|
||||||
CloseClients();
|
CloseClients();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,15 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
public struct ControllerDataResponse
|
public struct ControllerDataResponse
|
||||||
{
|
{
|
||||||
public SharedResponse Shared;
|
public SharedResponse Shared;
|
||||||
public byte Connected;
|
public byte Connected;
|
||||||
public uint PacketId;
|
public uint PacketId;
|
||||||
public byte ExtraButtons;
|
public byte ExtraButtons;
|
||||||
public byte MainButtons;
|
public byte MainButtons;
|
||||||
public ushort PSExtraInput;
|
public ushort PSExtraInput;
|
||||||
public ushort LeftStickXY;
|
public ushort LeftStickXY;
|
||||||
public ushort RightStickXY;
|
public ushort RightStickXY;
|
||||||
public uint DPadAnalog;
|
public uint DPadAnalog;
|
||||||
public ulong MainButtonsAnalog;
|
public ulong MainButtonsAnalog;
|
||||||
|
|
||||||
public Array6<byte> Touch1;
|
public Array6<byte> Touch1;
|
||||||
public Array6<byte> Touch2;
|
public Array6<byte> Touch2;
|
||||||
@ -42,6 +42,6 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
{
|
{
|
||||||
All,
|
All,
|
||||||
Slot,
|
Slot,
|
||||||
Mac
|
Mac,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
public struct ControllerInfoResponse
|
public struct ControllerInfoResponse
|
||||||
{
|
{
|
||||||
public SharedResponse Shared;
|
public SharedResponse Shared;
|
||||||
private byte _zero;
|
private readonly byte _zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
@ -17,4 +17,4 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
public int PortsCount;
|
public int PortsCount;
|
||||||
public Array4<byte> PortIndices;
|
public Array4<byte> PortIndices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,4 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
public Array4<byte> Crc32;
|
public Array4<byte> Crc32;
|
||||||
public uint Id;
|
public uint Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
{
|
{
|
||||||
Protocol = 0x100000,
|
Protocol = 0x100000,
|
||||||
Info,
|
Info,
|
||||||
Data
|
Data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
public struct SharedResponse
|
public struct SharedResponse
|
||||||
{
|
{
|
||||||
public MessageType Type;
|
public MessageType Type;
|
||||||
public byte Slot;
|
public byte Slot;
|
||||||
public SlotState State;
|
public SlotState State;
|
||||||
public DeviceModelType ModelType;
|
public DeviceModelType ModelType;
|
||||||
public ConnectionType ConnectionType;
|
public ConnectionType ConnectionType;
|
||||||
|
|
||||||
public Array6<byte> MacAddress;
|
public Array6<byte> MacAddress;
|
||||||
public BatteryStatus BatteryStatus;
|
public BatteryStatus BatteryStatus;
|
||||||
@ -20,21 +20,21 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
{
|
{
|
||||||
Disconnected,
|
Disconnected,
|
||||||
Reserved,
|
Reserved,
|
||||||
Connected
|
Connected,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeviceModelType : byte
|
public enum DeviceModelType : byte
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
PartialGyro,
|
PartialGyro,
|
||||||
FullGyro
|
FullGyro,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ConnectionType : byte
|
public enum ConnectionType : byte
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
USB,
|
USB,
|
||||||
Bluetooth
|
Bluetooth,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum BatteryStatus : byte
|
public enum BatteryStatus : byte
|
||||||
@ -46,6 +46,6 @@ namespace Ryujinx.Input.Motion.CemuHook.Protocol
|
|||||||
High,
|
High,
|
||||||
Full,
|
Full,
|
||||||
Charging,
|
Charging,
|
||||||
Charged
|
Charged,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,19 @@ namespace Ryujinx.Input
|
|||||||
{
|
{
|
||||||
public class MotionInput
|
public class MotionInput
|
||||||
{
|
{
|
||||||
public ulong TimeStamp { get; set; }
|
public ulong TimeStamp { get; set; }
|
||||||
public Vector3 Accelerometer { get; set; }
|
public Vector3 Accelerometer { get; set; }
|
||||||
public Vector3 Gyroscrope { get; set; }
|
public Vector3 Gyroscrope { get; set; }
|
||||||
public Vector3 Rotation { get; set; }
|
public Vector3 Rotation { get; set; }
|
||||||
|
|
||||||
private readonly MotionSensorFilter _filter;
|
private readonly MotionSensorFilter _filter;
|
||||||
|
|
||||||
public MotionInput()
|
public MotionInput()
|
||||||
{
|
{
|
||||||
TimeStamp = 0;
|
TimeStamp = 0;
|
||||||
Accelerometer = new Vector3();
|
Accelerometer = new Vector3();
|
||||||
Gyroscrope = new Vector3();
|
Gyroscrope = new Vector3();
|
||||||
Rotation = new Vector3();
|
Rotation = new Vector3();
|
||||||
|
|
||||||
// TODO: RE the correct filter.
|
// TODO: RE the correct filter.
|
||||||
_filter = new MotionSensorFilter(0f);
|
_filter = new MotionSensorFilter(0f);
|
||||||
@ -62,4 +62,4 @@ namespace Ryujinx.Input
|
|||||||
return degree * (MathF.PI / 180);
|
return degree * (MathF.PI / 180);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,19 +106,19 @@ namespace Ryujinx.Input.Motion
|
|||||||
float q1 = Quaternion.W;
|
float q1 = Quaternion.W;
|
||||||
|
|
||||||
// Estimated direction of gravity.
|
// Estimated direction of gravity.
|
||||||
Vector3 gravity = new Vector3()
|
Vector3 gravity = new()
|
||||||
{
|
{
|
||||||
X = 2f * (q2 * q4 - q1 * q3),
|
X = 2f * (q2 * q4 - q1 * q3),
|
||||||
Y = 2f * (q1 * q2 + q3 * q4),
|
Y = 2f * (q1 * q2 + q3 * q4),
|
||||||
Z = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4
|
Z = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Error is cross product between estimated direction and measured direction of gravity.
|
// Error is cross product between estimated direction and measured direction of gravity.
|
||||||
Vector3 error = new Vector3()
|
Vector3 error = new()
|
||||||
{
|
{
|
||||||
X = accel.Y * gravity.Z - accel.Z * gravity.Y,
|
X = accel.Y * gravity.Z - accel.Z * gravity.Y,
|
||||||
Y = accel.Z * gravity.X - accel.X * gravity.Z,
|
Y = accel.Z * gravity.X - accel.X * gravity.Z,
|
||||||
Z = accel.X * gravity.Y - accel.Y * gravity.X
|
Z = accel.X * gravity.Y - accel.Y * gravity.X,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Ki > 0f)
|
if (Ki > 0f)
|
||||||
@ -134,7 +134,7 @@ namespace Ryujinx.Input.Motion
|
|||||||
gyro += (Kp * error) + (Ki * _intergralError);
|
gyro += (Kp * error) + (Ki * _intergralError);
|
||||||
|
|
||||||
// Integrate rate of change of quaternion.
|
// Integrate rate of change of quaternion.
|
||||||
Vector3 delta = new Vector3(q2, q3, q4);
|
Vector3 delta = new(q2, q3, q4);
|
||||||
|
|
||||||
q1 += (-q2 * gyro.X - q3 * gyro.Y - q4 * gyro.Z) * (SampleRateCoefficient * SamplePeriod);
|
q1 += (-q2 * gyro.X - q3 * gyro.Y - q4 * gyro.Z) * (SampleRateCoefficient * SamplePeriod);
|
||||||
q2 += (q1 * gyro.X + delta.Y * gyro.Z - delta.Z * gyro.Y) * (SampleRateCoefficient * SamplePeriod);
|
q2 += (q1 * gyro.X + delta.Y * gyro.Z - delta.Z * gyro.Y) * (SampleRateCoefficient * SamplePeriod);
|
||||||
@ -142,7 +142,7 @@ namespace Ryujinx.Input.Motion
|
|||||||
q4 += (q1 * gyro.Z + delta.X * gyro.Y - delta.Y * gyro.X) * (SampleRateCoefficient * SamplePeriod);
|
q4 += (q1 * gyro.Z + delta.X * gyro.Y - delta.Y * gyro.X) * (SampleRateCoefficient * SamplePeriod);
|
||||||
|
|
||||||
// Normalise quaternion.
|
// Normalise quaternion.
|
||||||
Quaternion quaternion = new Quaternion(q2, q3, q4, q1);
|
Quaternion quaternion = new(q2, q3, q4, q1);
|
||||||
|
|
||||||
norm = 1f / quaternion.Length();
|
norm = 1f / quaternion.Length();
|
||||||
|
|
||||||
@ -159,4 +159,4 @@ namespace Ryujinx.Input.Motion
|
|||||||
Quaternion = Quaternion.Identity;
|
Quaternion = Quaternion.Identity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,6 @@
|
|||||||
/// Gyroscope.
|
/// Gyroscope.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>Values are in degrees</remarks>
|
/// <remarks>Values are in degrees</remarks>
|
||||||
Gyroscope
|
Gyroscope,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,6 @@ namespace Ryujinx.Input
|
|||||||
Button7,
|
Button7,
|
||||||
Button8,
|
Button8,
|
||||||
Button9,
|
Button9,
|
||||||
Count
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ namespace Ryujinx.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MouseStateSnapshot
|
public class MouseStateSnapshot
|
||||||
{
|
{
|
||||||
private bool[] _buttonState;
|
private readonly bool[] _buttonState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The position of the mouse cursor
|
/// The position of the mouse cursor
|
||||||
@ -31,7 +31,7 @@ namespace Ryujinx.Input
|
|||||||
_buttonState = buttonState;
|
_buttonState = buttonState;
|
||||||
|
|
||||||
Position = position;
|
Position = position;
|
||||||
Scroll = scroll;
|
Scroll = scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -42,4 +42,4 @@ namespace Ryujinx.Input
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool IsPressed(MouseButton button) => _buttonState[(int)button];
|
public bool IsPressed(MouseButton button) => _buttonState[(int)button];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@
|
|||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
|
||||||
Count
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ namespace Ryujinx.Memory
|
|||||||
{
|
{
|
||||||
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
||||||
|
|
||||||
data.Slice(0, size).CopyTo(GetHostSpanContiguous(va, size));
|
data[..size].CopyTo(GetHostSpanContiguous(va, size));
|
||||||
|
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
@ -215,7 +215,7 @@ namespace Ryujinx.Memory
|
|||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int GetPagesCount(ulong va, uint size, out ulong startVa)
|
private static int GetPagesCount(ulong va, uint size, out ulong startVa)
|
||||||
{
|
{
|
||||||
// WARNING: Always check if ulong does not overflow during the operations.
|
// WARNING: Always check if ulong does not overflow during the operations.
|
||||||
startVa = va & ~(ulong)PageMask;
|
startVa = va & ~(ulong)PageMask;
|
||||||
@ -224,7 +224,7 @@ namespace Ryujinx.Memory
|
|||||||
return (int)(vaSpan / PageSize);
|
return (int)(vaSpan / PageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrowMemoryNotContiguous() => throw new MemoryNotContiguousException();
|
private static void ThrowMemoryNotContiguous() => throw new MemoryNotContiguousException();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private bool IsContiguousAndMapped(ulong va, int size) => IsContiguous(va, size) && IsMapped(va);
|
private bool IsContiguousAndMapped(ulong va, int size) => IsContiguous(va, size) && IsMapped(va);
|
||||||
@ -361,7 +361,7 @@ namespace Ryujinx.Memory
|
|||||||
{
|
{
|
||||||
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
|
||||||
|
|
||||||
GetHostSpanContiguous(va, size).CopyTo(data.Slice(0, size));
|
GetHostSpanContiguous(va, size).CopyTo(data[..size]);
|
||||||
|
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,6 @@ namespace Ryujinx.Memory
|
|||||||
/// Indicates that the memory will be used to store JIT generated code.
|
/// Indicates that the memory will be used to store JIT generated code.
|
||||||
/// On some platforms, this requires special flags to be passed that will allow the memory to be executable.
|
/// On some platforms, this requires special flags to be passed that will allow the memory to be executable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Jit = 1 << 5
|
Jit = 1 << 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,9 +364,9 @@ namespace Ryujinx.Memory
|
|||||||
/// <param name="pointer">Native pointer</param>
|
/// <param name="pointer">Native pointer</param>
|
||||||
/// <param name="offset">Offset to add</param>
|
/// <param name="offset">Offset to add</param>
|
||||||
/// <returns>Native pointer with the added offset</returns>
|
/// <returns>Native pointer with the added offset</returns>
|
||||||
private IntPtr PtrAddr(IntPtr pointer, ulong offset)
|
private static IntPtr PtrAddr(IntPtr pointer, ulong offset)
|
||||||
{
|
{
|
||||||
return (IntPtr)(pointer.ToInt64() + (long)offset);
|
return new IntPtr(pointer.ToInt64() + (long)offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -439,4 +439,4 @@ namespace Ryujinx.Memory
|
|||||||
|
|
||||||
private static void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException();
|
private static void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,4 +203,4 @@ namespace Ryujinx.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ namespace Ryujinx.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr ptr = mmap(IntPtr.Zero, size, prot, flags, -1, 0);
|
IntPtr ptr = Mmap(IntPtr.Zero, size, prot, flags, -1, 0);
|
||||||
|
|
||||||
if (ptr == MAP_FAILED)
|
if (ptr == MAP_FAILED)
|
||||||
{
|
{
|
||||||
@ -115,7 +115,7 @@ namespace Ryujinx.Memory
|
|||||||
MemoryPermission.ReadAndExecute => MmapProts.PROT_READ | MmapProts.PROT_EXEC,
|
MemoryPermission.ReadAndExecute => MmapProts.PROT_READ | MmapProts.PROT_EXEC,
|
||||||
MemoryPermission.ReadWriteExecute => MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC,
|
MemoryPermission.ReadWriteExecute => MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC,
|
||||||
MemoryPermission.Execute => MmapProts.PROT_EXEC,
|
MemoryPermission.Execute => MmapProts.PROT_EXEC,
|
||||||
_ => throw new MemoryProtectionException(permission)
|
_ => throw new MemoryProtectionException(permission),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,12 +185,12 @@ namespace Ryujinx.Memory
|
|||||||
|
|
||||||
public static void DestroySharedMemory(IntPtr handle)
|
public static void DestroySharedMemory(IntPtr handle)
|
||||||
{
|
{
|
||||||
close((int)handle);
|
close(handle.ToInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IntPtr MapSharedMemory(IntPtr handle, ulong size)
|
public static IntPtr MapSharedMemory(IntPtr handle, ulong size)
|
||||||
{
|
{
|
||||||
return mmap(IntPtr.Zero, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, (int)handle, 0);
|
return Mmap(IntPtr.Zero, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, handle.ToInt32(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnmapSharedMemory(IntPtr address, ulong size)
|
public static void UnmapSharedMemory(IntPtr address, ulong size)
|
||||||
@ -200,12 +200,12 @@ namespace Ryujinx.Memory
|
|||||||
|
|
||||||
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, ulong size)
|
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, ulong size)
|
||||||
{
|
{
|
||||||
mmap(location, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_FIXED | MmapFlags.MAP_SHARED, (int)sharedMemory, (long)srcOffset);
|
Mmap(location, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_FIXED | MmapFlags.MAP_SHARED, sharedMemory.ToInt32(), (long)srcOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnmapView(IntPtr location, ulong size)
|
public static void UnmapView(IntPtr location, ulong size)
|
||||||
{
|
{
|
||||||
mmap(location, size, MmapProts.PROT_NONE, MmapFlags.MAP_FIXED | MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_NORESERVE, -1, 0);
|
Mmap(location, size, MmapProts.PROT_NONE, MmapFlags.MAP_FIXED | MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_NORESERVE, -1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,4 +148,4 @@ namespace Ryujinx.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace Ryujinx.Memory
|
|||||||
PROT_NONE = 0,
|
PROT_NONE = 0,
|
||||||
PROT_READ = 1,
|
PROT_READ = 1,
|
||||||
PROT_WRITE = 2,
|
PROT_WRITE = 2,
|
||||||
PROT_EXEC = 4
|
PROT_EXEC = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@ -26,7 +26,7 @@ namespace Ryujinx.Memory
|
|||||||
MAP_NORESERVE = 8,
|
MAP_NORESERVE = 8,
|
||||||
MAP_FIXED = 16,
|
MAP_FIXED = 16,
|
||||||
MAP_UNLOCKED = 32,
|
MAP_UNLOCKED = 32,
|
||||||
MAP_JIT_DARWIN = 0x800
|
MAP_JIT_DARWIN = 0x800,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@ -164,9 +164,9 @@ namespace Ryujinx.Memory
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IntPtr mmap(IntPtr address, ulong length, MmapProts prot, MmapFlags flags, int fd, long offset)
|
public static IntPtr Mmap(IntPtr address, ulong length, MmapProts prot, MmapFlags flags, int fd, long offset)
|
||||||
{
|
{
|
||||||
return Internal_mmap(address, length, prot, MmapFlagsToSystemFlags(flags), fd, offset);
|
return Internal_mmap(address, length, prot, MmapFlagsToSystemFlags(flags), fd, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,6 @@ namespace Ryujinx.Memory
|
|||||||
/// and allocate its own private storage for the mapping.
|
/// and allocate its own private storage for the mapping.
|
||||||
/// This allows some mappings that would otherwise fail due to host platform restrictions to succeed.
|
/// This allows some mappings that would otherwise fail due to host platform restrictions to succeed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Private = 1 << 0
|
Private = 1 << 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,4 +16,4 @@ namespace Ryujinx.Memory
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,6 @@ namespace Ryujinx.Memory
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates an invalid protection.
|
/// Indicates an invalid protection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Invalid = 255
|
Invalid = 255,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@ namespace Ryujinx.Memory.Range
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Range of memory composed of an address and size.
|
/// Range of memory composed of an address and size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct HostMemoryRange : IEquatable<HostMemoryRange>
|
public readonly struct HostMemoryRange : IEquatable<HostMemoryRange>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty memory range, with a null address and zero size.
|
/// An empty memory range, with a null address and zero size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static HostMemoryRange Empty => new HostMemoryRange(0, 0);
|
public static HostMemoryRange Empty => new(0, 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start address of the range.
|
/// Start address of the range.
|
||||||
@ -67,5 +67,15 @@ namespace Ryujinx.Memory.Range
|
|||||||
{
|
{
|
||||||
return HashCode.Combine(Address, Size);
|
return HashCode.Combine(Address, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(HostMemoryRange left, HostMemoryRange right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(HostMemoryRange left, HostMemoryRange right)
|
||||||
|
{
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,4 +28,4 @@ namespace Ryujinx.Memory.Range
|
|||||||
/// <returns>True if overlapping, false otherwise</returns>
|
/// <returns>True if overlapping, false otherwise</returns>
|
||||||
bool OverlapsWith(ulong address, ulong size);
|
bool OverlapsWith(ulong address, ulong size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty memory range, with a null address and zero size.
|
/// An empty memory range, with a null address and zero size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static MemoryRange Empty => new MemoryRange(0UL, 0);
|
public static MemoryRange Empty => new(0UL, 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start address of the range.
|
/// Start address of the range.
|
||||||
|
@ -310,7 +310,7 @@ namespace Ryujinx.Memory.Range
|
|||||||
return _singleRange.GetHashCode();
|
return _singleRange.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
HashCode hash = new HashCode();
|
HashCode hash = new();
|
||||||
|
|
||||||
foreach (MemoryRange range in _ranges)
|
foreach (MemoryRange range in _ranges)
|
||||||
{
|
{
|
||||||
@ -328,5 +328,15 @@ namespace Ryujinx.Memory.Range
|
|||||||
{
|
{
|
||||||
return HasSingleRange ? _singleRange.ToString() : string.Join(", ", _ranges);
|
return HasSingleRange ? _singleRange.ToString() : string.Join(", ", _ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(MultiRange left, MultiRange right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(MultiRange left, MultiRange right)
|
||||||
|
{
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ namespace Ryujinx.Memory.Range
|
|||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
return default(T);
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _items[index].Value;
|
return _items[index].Value;
|
||||||
@ -398,7 +398,7 @@ namespace Ryujinx.Memory.Range
|
|||||||
/// <returns>List index of the item, or complement index of nearest item with lower value on the list</returns>
|
/// <returns>List index of the item, or complement index of nearest item with lower value on the list</returns>
|
||||||
private int BinarySearch(ulong address)
|
private int BinarySearch(ulong address)
|
||||||
{
|
{
|
||||||
int left = 0;
|
int left = 0;
|
||||||
int right = Count - 1;
|
int right = Count - 1;
|
||||||
|
|
||||||
while (left <= right)
|
while (left <= right)
|
||||||
@ -435,7 +435,7 @@ namespace Ryujinx.Memory.Range
|
|||||||
/// <returns>List index of the item, or complement index of nearest item with lower value on the list</returns>
|
/// <returns>List index of the item, or complement index of nearest item with lower value on the list</returns>
|
||||||
private int BinarySearch(ulong address, ulong endAddress)
|
private int BinarySearch(ulong address, ulong endAddress)
|
||||||
{
|
{
|
||||||
int left = 0;
|
int left = 0;
|
||||||
int right = Count - 1;
|
int right = Count - 1;
|
||||||
|
|
||||||
while (left <= right)
|
while (left <= right)
|
||||||
@ -480,4 +480,4 @@ namespace Ryujinx.Memory.Range
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
/// This lock must be obtained when traversing or updating the region-handle hierarchy.
|
/// This lock must be obtained when traversing or updating the region-handle hierarchy.
|
||||||
/// It is not required when reading dirty flags.
|
/// It is not required when reading dirty flags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal object TrackingLock = new object();
|
internal object TrackingLock = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new tracking structure for the given "physical" memory block,
|
/// Create a new tracking structure for the given "physical" memory block,
|
||||||
@ -114,7 +114,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
/// <returns>A list of virtual regions within the given range</returns>
|
/// <returns>A list of virtual regions within the given range</returns>
|
||||||
internal List<VirtualRegion> GetVirtualRegionsForHandle(ulong va, ulong size)
|
internal List<VirtualRegion> GetVirtualRegionsForHandle(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
List<VirtualRegion> result = new List<VirtualRegion>();
|
List<VirtualRegion> result = new();
|
||||||
_virtualRegions.GetOrAddRegions(result, va, size, (va, size) => new VirtualRegion(this, va, size));
|
_virtualRegions.GetOrAddRegions(result, va, size, (va, size) => new VirtualRegion(this, va, size));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -172,7 +172,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
lock (TrackingLock)
|
lock (TrackingLock)
|
||||||
{
|
{
|
||||||
bool mapped = _memoryManager.IsRangeMapped(address, size);
|
bool mapped = _memoryManager.IsRangeMapped(address, size);
|
||||||
RegionHandle handle = new RegionHandle(this, paAddress, paSize, address, size, id, mapped);
|
RegionHandle handle = new(this, paAddress, paSize, address, size, id, mapped);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
lock (TrackingLock)
|
lock (TrackingLock)
|
||||||
{
|
{
|
||||||
bool mapped = _memoryManager.IsRangeMapped(address, size);
|
bool mapped = _memoryManager.IsRangeMapped(address, size);
|
||||||
RegionHandle handle = new RegionHandle(this, paAddress, paSize, address, size, bitmap, bit, id, mapped);
|
RegionHandle handle = new(this, paAddress, paSize, address, size, bitmap, bit, id, mapped);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -21,11 +22,11 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
private readonly ulong Granularity;
|
private readonly ulong Granularity;
|
||||||
private readonly ulong Size;
|
private readonly ulong Size;
|
||||||
|
|
||||||
private ConcurrentBitmap _dirtyBitmap;
|
private readonly ConcurrentBitmap _dirtyBitmap;
|
||||||
|
|
||||||
private int _sequenceNumber;
|
private int _sequenceNumber;
|
||||||
private BitMap _sequenceNumberBitmap;
|
private readonly BitMap _sequenceNumberBitmap;
|
||||||
private BitMap _dirtyCheckedBitmap;
|
private readonly BitMap _dirtyCheckedBitmap;
|
||||||
private int _uncheckedHandles;
|
private int _uncheckedHandles;
|
||||||
|
|
||||||
public bool Dirty { get; private set; } = true;
|
public bool Dirty { get; private set; } = true;
|
||||||
@ -54,7 +55,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
// It is assumed that the provided handles do not overlap, in order, are on page boundaries,
|
// It is assumed that the provided handles do not overlap, in order, are on page boundaries,
|
||||||
// and don't extend past the requested range.
|
// and don't extend past the requested range.
|
||||||
|
|
||||||
foreach (RegionHandle handle in handles)
|
foreach (RegionHandle handle in handles.Cast<RegionHandle>())
|
||||||
{
|
{
|
||||||
int startIndex = (int)((handle.RealAddress - address) / granularity);
|
int startIndex = (int)((handle.RealAddress - address) / granularity);
|
||||||
|
|
||||||
@ -406,6 +407,8 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
foreach (var handle in _handles)
|
foreach (var handle in _handles)
|
||||||
{
|
{
|
||||||
handle.Dispose();
|
handle.Dispose();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection.Metadata;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Memory.Tracking
|
namespace Ryujinx.Memory.Tracking
|
||||||
@ -50,7 +49,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
|
|
||||||
internal IMultiRegionHandle Parent { get; set; }
|
internal IMultiRegionHandle Parent { get; set; }
|
||||||
|
|
||||||
private event Action _onDirty;
|
private event Action OnDirty;
|
||||||
|
|
||||||
private readonly object _preActionLock = new();
|
private readonly object _preActionLock = new();
|
||||||
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
|
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
|
||||||
@ -269,7 +268,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
Dirty = true;
|
Dirty = true;
|
||||||
if (!oldDirty)
|
if (!oldDirty)
|
||||||
{
|
{
|
||||||
_onDirty?.Invoke();
|
OnDirty?.Invoke();
|
||||||
}
|
}
|
||||||
Parent?.SignalWrite();
|
Parent?.SignalWrite();
|
||||||
}
|
}
|
||||||
@ -311,7 +310,10 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
/// <param name="consecutiveCheck">True if this reprotect is the result of consecutive dirty checks</param>
|
/// <param name="consecutiveCheck">True if this reprotect is the result of consecutive dirty checks</param>
|
||||||
public void Reprotect(bool asDirty, bool consecutiveCheck = false)
|
public void Reprotect(bool asDirty, bool consecutiveCheck = false)
|
||||||
{
|
{
|
||||||
if (_volatile) return;
|
if (_volatile)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Dirty = asDirty;
|
Dirty = asDirty;
|
||||||
|
|
||||||
@ -403,7 +405,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
/// <param name="action">Action to call on dirty</param>
|
/// <param name="action">Action to call on dirty</param>
|
||||||
public void RegisterDirtyEvent(Action action)
|
public void RegisterDirtyEvent(Action action)
|
||||||
{
|
{
|
||||||
_onDirty += action;
|
OnDirty += action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -461,6 +463,8 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
lock (_tracking.TrackingLock)
|
lock (_tracking.TrackingLock)
|
||||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
private readonly ulong _address;
|
private readonly ulong _address;
|
||||||
private readonly ulong _granularity;
|
private readonly ulong _granularity;
|
||||||
private readonly ulong _size;
|
private readonly ulong _size;
|
||||||
private MemoryTracking _tracking;
|
private readonly MemoryTracking _tracking;
|
||||||
private readonly int _id;
|
private readonly int _id;
|
||||||
|
|
||||||
public bool Dirty { get; private set; } = true;
|
public bool Dirty { get; private set; } = true;
|
||||||
@ -271,6 +271,8 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
foreach (var handle in _handles)
|
foreach (var handle in _handles)
|
||||||
{
|
{
|
||||||
handle?.Dispose();
|
handle?.Dispose();
|
||||||
|
@ -8,7 +8,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class VirtualRegion : AbstractRegion
|
class VirtualRegion : AbstractRegion
|
||||||
{
|
{
|
||||||
public List<RegionHandle> Handles = new List<RegionHandle>();
|
public List<RegionHandle> Handles = new();
|
||||||
|
|
||||||
private readonly MemoryTracking _tracking;
|
private readonly MemoryTracking _tracking;
|
||||||
private MemoryPermission _lastPermission;
|
private MemoryPermission _lastPermission;
|
||||||
@ -86,7 +86,10 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
foreach (var handle in Handles)
|
foreach (var handle in Handles)
|
||||||
{
|
{
|
||||||
result &= handle.RequiredPermission;
|
result &= handle.RequiredPermission;
|
||||||
if (result == 0) return result;
|
if (result == 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -128,7 +131,7 @@ namespace Ryujinx.Memory.Tracking
|
|||||||
|
|
||||||
public override INonOverlappingRange Split(ulong splitAddress)
|
public override INonOverlappingRange Split(ulong splitAddress)
|
||||||
{
|
{
|
||||||
VirtualRegion newRegion = new VirtualRegion(_tracking, splitAddress, EndAddress - splitAddress, _lastPermission);
|
VirtualRegion newRegion = new(_tracking, splitAddress, EndAddress - splitAddress, _lastPermission);
|
||||||
Size = splitAddress - Address;
|
Size = splitAddress - Address;
|
||||||
|
|
||||||
// The new region inherits all of our parents.
|
// The new region inherits all of our parents.
|
||||||
|
@ -84,4 +84,4 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,11 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
|
|
||||||
_partialUnmapStatePtr = PartialUnmapState.GlobalState;
|
_partialUnmapStatePtr = PartialUnmapState.GlobalState;
|
||||||
|
|
||||||
_partialUnmapTrimThread = new Thread(TrimThreadLocalMapLoop);
|
_partialUnmapTrimThread = new Thread(TrimThreadLocalMapLoop)
|
||||||
_partialUnmapTrimThread.Name = "CPU.PartialUnmapTrimThread";
|
{
|
||||||
_partialUnmapTrimThread.IsBackground = true;
|
Name = "CPU.PartialUnmapTrimThread",
|
||||||
|
IsBackground = true,
|
||||||
|
};
|
||||||
_partialUnmapTrimThread.Start();
|
_partialUnmapTrimThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,8 +706,6 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
count = _protections.GetNodes(address, endAddress, ref overlaps);
|
count = _protections.GetNodes(address, endAddress, ref overlaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong startAddress = address;
|
|
||||||
|
|
||||||
for (int index = 0; index < count; index++)
|
for (int index = 0; index < count; index++)
|
||||||
{
|
{
|
||||||
var protection = overlaps[index];
|
var protection = overlaps[index];
|
||||||
@ -733,4 +733,4 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
static partial class WindowsApi
|
static partial class WindowsApi
|
||||||
{
|
{
|
||||||
public static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
|
public static readonly IntPtr InvalidHandleValue = new(-1);
|
||||||
public static readonly IntPtr CurrentProcessHandle = new IntPtr(-1);
|
public static readonly IntPtr CurrentProcessHandle = new(-1);
|
||||||
|
|
||||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||||
public static partial IntPtr VirtualAlloc(
|
public static partial IntPtr VirtualAlloc(
|
||||||
@ -96,8 +96,8 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
MemoryPermission.ReadAndExecute => MemoryProtection.ExecuteRead,
|
MemoryPermission.ReadAndExecute => MemoryProtection.ExecuteRead,
|
||||||
MemoryPermission.ReadWriteExecute => MemoryProtection.ExecuteReadWrite,
|
MemoryPermission.ReadWriteExecute => MemoryProtection.ExecuteReadWrite,
|
||||||
MemoryPermission.Execute => MemoryProtection.Execute,
|
MemoryPermission.Execute => MemoryProtection.Execute,
|
||||||
_ => throw new MemoryProtectionException(permission)
|
_ => throw new MemoryProtectionException(permission),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,4 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
return $"{functionName} returned error code 0x{WindowsApi.GetLastError():X}.";
|
return $"{functionName} returned error code 0x{WindowsApi.GetLastError():X}.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,14 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
Commit = 0x1000,
|
Commit = 0x1000,
|
||||||
Reserve = 0x2000,
|
Reserve = 0x2000,
|
||||||
Decommit = 0x4000,
|
Decommit = 0x4000,
|
||||||
ReplacePlaceholder = 0x4000,
|
ReplacePlaceholder = Decommit,
|
||||||
Release = 0x8000,
|
Release = 0x8000,
|
||||||
ReservePlaceholder = 0x40000,
|
ReservePlaceholder = 0x40000,
|
||||||
Reset = 0x80000,
|
Reset = 0x80000,
|
||||||
Physical = 0x400000,
|
Physical = 0x400000,
|
||||||
TopDown = 0x100000,
|
TopDown = 0x100000,
|
||||||
WriteWatch = 0x200000,
|
WriteWatch = 0x200000,
|
||||||
LargePages = 0x20000000
|
LargePages = 0x20000000,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@ -33,7 +33,7 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
ExecuteWriteCopy = 0x80,
|
ExecuteWriteCopy = 0x80,
|
||||||
GuardModifierflag = 0x100,
|
GuardModifierflag = 0x100,
|
||||||
NoCacheModifierflag = 0x200,
|
NoCacheModifierflag = 0x200,
|
||||||
WriteCombineModifierflag = 0x400
|
WriteCombineModifierflag = 0x400,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@ -47,6 +47,6 @@ namespace Ryujinx.Memory.WindowsShared
|
|||||||
SectionCommit = 0x8000000,
|
SectionCommit = 0x8000000,
|
||||||
SectionImage = 0x1000000,
|
SectionImage = 0x1000000,
|
||||||
SectionNoCache = 0x10000000,
|
SectionNoCache = 0x10000000,
|
||||||
SectionReserve = 0x4000000
|
SectionReserve = 0x4000000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user