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