Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c6f1908e0f | ||
|
851d81d24a | ||
|
459c4caeba | ||
|
539b22ef7b | ||
|
872f036d64 | ||
|
dca96122bf | ||
|
e752959109 | ||
|
cf01664698 | ||
|
b283a4adcd | ||
|
8428bb6541 | ||
|
9a0330f7f8 | ||
|
57fc996337 | ||
|
1f3b860f06 | ||
|
abe3c02ab4 | ||
|
45b417b2b4 | ||
|
d076339e3e | ||
|
837836431d | ||
|
9f555db5cd | ||
|
bf7fa60dfc | ||
|
752b93d3b7 | ||
|
f23b2878cc | ||
|
e211c3f00a | ||
|
d3709a753f |
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -11,6 +11,7 @@ on:
|
||||
- '*.yml'
|
||||
- 'README.md'
|
||||
|
||||
concurrency: release
|
||||
|
||||
jobs:
|
||||
release:
|
||||
|
@@ -1341,7 +1341,7 @@ namespace ARMeilleure.Decoders
|
||||
{
|
||||
string reversedEncoding = encoding.Substring(16) + encoding.Substring(0, 16);
|
||||
MakeOp reversedMakeOp =
|
||||
(InstDescriptor inst, ulong address, int opCode)
|
||||
(inst, address, opCode)
|
||||
=> makeOp(inst, address, (int)BitOperations.RotateRight((uint)opCode, 16));
|
||||
Set(reversedEncoding, AllInstT32, new InstDescriptor(name, emitter), reversedMakeOp);
|
||||
}
|
||||
|
@@ -125,7 +125,7 @@ namespace Ryujinx.Ava
|
||||
_inputManager = inputManager;
|
||||
_accountManager = accountManager;
|
||||
_userChannelPersistence = userChannelPersistence;
|
||||
_renderingThread = new Thread(RenderLoop) { Name = "GUI.RenderThread" };
|
||||
_renderingThread = new Thread(RenderLoop, 1 * 1024 * 1024) { Name = "GUI.RenderThread" };
|
||||
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
|
||||
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
||||
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
|
||||
|
@@ -315,7 +315,7 @@
|
||||
"DialogUpdaterConvertFailedMessage": "Failed to convert the current Ryujinx version.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Cancelling Update!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "You are already using the most updated version of Ryujinx!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from Github Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from GitHub Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Failed to convert the received Ryujinx version from Github Release.",
|
||||
"DialogUpdaterDownloadingMessage": "Downloading Update...",
|
||||
"DialogUpdaterExtractionMessage": "Extracting Update...",
|
||||
|
@@ -161,6 +161,7 @@
|
||||
<Style Selector="MenuItem">
|
||||
<Setter Property="Height" Value="{DynamicResource MenuItemHeight}" />
|
||||
<Setter Property="Padding" Value="{DynamicResource MenuItemPadding}" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
</Style>
|
||||
<Style Selector="MenuItem:selected /template/ Border#root">
|
||||
<Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||
|
127
Ryujinx.Ava/Helper/MetalHelper.cs
Normal file
127
Ryujinx.Ava/Helper/MetalHelper.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Runtime.InteropServices;
|
||||
using Avalonia;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Helper
|
||||
{
|
||||
public delegate void UpdateBoundsCallbackDelegate(Rect rect);
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
static class MetalHelper
|
||||
{
|
||||
private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
|
||||
|
||||
private struct Selector
|
||||
{
|
||||
public readonly IntPtr NativePtr;
|
||||
|
||||
public unsafe Selector(string value)
|
||||
{
|
||||
int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
|
||||
byte* data = stackalloc byte[size];
|
||||
|
||||
fixed (char* pValue = value)
|
||||
{
|
||||
System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
|
||||
}
|
||||
|
||||
NativePtr = sel_registerName(data);
|
||||
}
|
||||
|
||||
public static implicit operator Selector(string value) => new Selector(value);
|
||||
}
|
||||
|
||||
private static unsafe IntPtr GetClass(string value)
|
||||
{
|
||||
int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
|
||||
byte* data = stackalloc byte[size];
|
||||
|
||||
fixed (char* pValue = value)
|
||||
{
|
||||
System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
|
||||
}
|
||||
|
||||
return objc_getClass(data);
|
||||
}
|
||||
|
||||
private struct NSPoint
|
||||
{
|
||||
public double X;
|
||||
public double Y;
|
||||
|
||||
public NSPoint(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
}
|
||||
|
||||
private struct NSRect
|
||||
{
|
||||
public NSPoint Pos;
|
||||
public NSPoint Size;
|
||||
|
||||
public NSRect(double x, double y, double width, double height)
|
||||
{
|
||||
Pos = new NSPoint(x, y);
|
||||
Size = new NSPoint(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr GetMetalLayer(out IntPtr nsView, out UpdateBoundsCallbackDelegate updateBounds)
|
||||
{
|
||||
// Create a new CAMetalLayer.
|
||||
IntPtr layerClass = GetClass("CAMetalLayer");
|
||||
IntPtr metalLayer = IntPtr_objc_msgSend(layerClass, "alloc");
|
||||
objc_msgSend(metalLayer, "init");
|
||||
|
||||
// Create a child NSView to render into.
|
||||
IntPtr nsViewClass = GetClass("NSView");
|
||||
IntPtr child = IntPtr_objc_msgSend(nsViewClass, "alloc");
|
||||
objc_msgSend(child, "init", new NSRect(0, 0, 0, 0));
|
||||
|
||||
// Make its renderer our metal layer.
|
||||
objc_msgSend(child, "setWantsLayer:", (byte)1);
|
||||
objc_msgSend(child, "setLayer:", metalLayer);
|
||||
objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
|
||||
|
||||
// Ensure the scale factor is up to date.
|
||||
updateBounds = (Rect rect) => {
|
||||
objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
|
||||
};
|
||||
|
||||
nsView = child;
|
||||
return metalLayer;
|
||||
}
|
||||
|
||||
public static void DestroyMetalLayer(IntPtr nsView, IntPtr metalLayer)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static unsafe extern IntPtr sel_registerName(byte* data);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static unsafe extern IntPtr objc_getClass(byte* data);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, byte value);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, double value);
|
||||
|
||||
[DllImport(LibObjCImport, EntryPoint = "objc_msgSend")]
|
||||
private static extern IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
|
||||
}
|
||||
}
|
@@ -355,7 +355,7 @@ namespace Ryujinx.Modules
|
||||
list[index] = args.Result;
|
||||
Interlocked.Increment(ref completedRequests);
|
||||
|
||||
if (Interlocked.Equals(completedRequests, ConnectionCount))
|
||||
if (Equals(completedRequests, ConnectionCount))
|
||||
{
|
||||
byte[] mergedFileBytes = new byte[_buildSize];
|
||||
for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
|
||||
|
@@ -22,10 +22,11 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
public static double WindowScaleFactor { get; set; }
|
||||
public static string Version { get; private set; }
|
||||
public static string ConfigurationPath { get; private set; }
|
||||
public static bool PreviewerDetached { get; private set; }
|
||||
public static double WindowScaleFactor { get; set; }
|
||||
public static double DesktopScaleFactor { get; set; } = 1.0;
|
||||
public static string Version { get; private set; }
|
||||
public static string ConfigurationPath { get; private set; }
|
||||
public static bool PreviewerDetached { get; private set; }
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern int MessageBoxA(IntPtr hWnd, string text, string caption, uint type);
|
||||
@@ -81,8 +82,8 @@ namespace Ryujinx.Ava
|
||||
Console.Title = $"Ryujinx Console {Version}";
|
||||
|
||||
// Hook unhandled exception and process exit events.
|
||||
AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
||||
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
||||
AppDomain.CurrentDomain.ProcessExit += (sender, e) => Exit();
|
||||
|
||||
// Setup base data directory.
|
||||
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
|
||||
|
@@ -26,19 +26,23 @@
|
||||
<PackageReference Include="Avalonia.Svg" Version="0.10.18" />
|
||||
<PackageReference Include="Avalonia.Svg.Skia" Version="0.10.18" />
|
||||
<PackageReference Include="jp2masa.Avalonia.Flexbox" Version="0.2.0" />
|
||||
<PackageReference Include="DynamicData" Version="7.12.8" />
|
||||
<PackageReference Include="DynamicData" Version="7.12.11" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="1.4.5" />
|
||||
<PackageReference Include="XamlNameReferenceGenerator" Version="1.4.2" />
|
||||
<PackageReference Include="XamlNameReferenceGenerator" Version="1.5.1" />
|
||||
|
||||
<PackageReference Include="OpenTK.Core" Version="4.7.5" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build12" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win10-x64'" />
|
||||
<PackageReference Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
|
||||
<PackageReference Include="SPB" Version="0.0.4-build28" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||
|
||||
<!--NOTE: DO NOT REMOVE, THIS IS REQUIRED AS A RESULT OF A TRIMMING ISSUE IN AVALONIA -->
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -57,14 +61,18 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<Content Include="..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>alsoft.ini</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="..\distribution\legal\THIRDPARTY.md">
|
||||
</Content>
|
||||
<Content Include="..\distribution\legal\THIRDPARTY.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
</Content>
|
||||
<Content Include="..\LICENSE.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>LICENSE.txt</TargetPath>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -66,7 +66,7 @@ namespace Ryujinx.Ava.Ui.Applet
|
||||
});
|
||||
}
|
||||
|
||||
private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, Avalonia.Input.KeyEventArgs e)
|
||||
private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, KeyEventArgs e)
|
||||
{
|
||||
var key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.Key);
|
||||
|
||||
|
@@ -222,7 +222,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
|
||||
content.MinHeight = 80;
|
||||
|
||||
SymbolIcon icon = new SymbolIcon { Symbol = (Symbol)symbol, Margin = new Avalonia.Thickness(10) };
|
||||
SymbolIcon icon = new SymbolIcon { Symbol = (Symbol)symbol, Margin = new Thickness(10) };
|
||||
icon.FontSize = 40;
|
||||
icon.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center;
|
||||
Grid.SetColumn(icon, 0);
|
||||
@@ -232,15 +232,15 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
TextBlock primaryLabel = new TextBlock()
|
||||
{
|
||||
Text = primaryText,
|
||||
Margin = new Avalonia.Thickness(5),
|
||||
TextWrapping = Avalonia.Media.TextWrapping.Wrap,
|
||||
Margin = new Thickness(5),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = 450
|
||||
};
|
||||
TextBlock secondaryLabel = new TextBlock()
|
||||
{
|
||||
Text = secondaryText,
|
||||
Margin = new Avalonia.Thickness(5),
|
||||
TextWrapping = Avalonia.Media.TextWrapping.Wrap,
|
||||
Margin = new Thickness(5),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = 450
|
||||
};
|
||||
|
||||
|
@@ -2,11 +2,10 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Platform;
|
||||
using Ryujinx.Ava.Ui.Helper;
|
||||
using SPB.Graphics;
|
||||
using SPB.Platform;
|
||||
using SPB.Platform.GLX;
|
||||
using SPB.Platform.X11;
|
||||
using SPB.Windowing;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
@@ -23,6 +22,10 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
protected GLXWindow X11Window { get; set; }
|
||||
protected IntPtr WindowHandle { get; set; }
|
||||
protected IntPtr X11Display { get; set; }
|
||||
protected IntPtr NsView { get; set; }
|
||||
protected IntPtr MetalLayer { get; set; }
|
||||
|
||||
private UpdateBoundsCallbackDelegate _updateBoundsCallback;
|
||||
|
||||
public event EventHandler<IntPtr> WindowCreated;
|
||||
public event EventHandler<Size> SizeChanged;
|
||||
@@ -36,7 +39,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
|
||||
public EmbeddedWindow()
|
||||
{
|
||||
var stateObserverable = this.GetObservable(Control.BoundsProperty);
|
||||
var stateObserverable = this.GetObservable(BoundsProperty);
|
||||
|
||||
stateObserverable.Subscribe(StateChanged);
|
||||
|
||||
@@ -58,6 +61,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
private void StateChanged(Rect rect)
|
||||
{
|
||||
SizeChanged?.Invoke(this, rect.Size);
|
||||
_updateBoundsCallback?.Invoke(rect);
|
||||
}
|
||||
|
||||
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
|
||||
@@ -70,6 +74,11 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
{
|
||||
return CreateWin32(parent);
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
return CreateMacOs(parent);
|
||||
}
|
||||
|
||||
return base.CreateNativeControlCore(parent);
|
||||
}
|
||||
|
||||
@@ -85,6 +94,10 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
{
|
||||
DestroyWin32(control);
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
DestroyMacOS();
|
||||
}
|
||||
else
|
||||
{
|
||||
base.DestroyNativeControlCore(control);
|
||||
@@ -152,7 +165,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
isLeft = msg == WindowsMessages.LBUTTONDOWN;
|
||||
this.RaiseEvent(new PointerPressedEventArgs(
|
||||
this,
|
||||
new Avalonia.Input.Pointer(0, PointerType.Mouse, true),
|
||||
new Pointer(0, PointerType.Mouse, true),
|
||||
root,
|
||||
this.TranslatePoint(point, root).Value,
|
||||
(ulong)Environment.TickCount64,
|
||||
@@ -164,7 +177,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
isLeft = msg == WindowsMessages.LBUTTONUP;
|
||||
this.RaiseEvent(new PointerReleasedEventArgs(
|
||||
this,
|
||||
new Avalonia.Input.Pointer(0, PointerType.Mouse, true),
|
||||
new Pointer(0, PointerType.Mouse, true),
|
||||
root,
|
||||
this.TranslatePoint(point, root).Value,
|
||||
(ulong)Environment.TickCount64,
|
||||
@@ -176,7 +189,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
this.RaiseEvent(new PointerEventArgs(
|
||||
PointerMovedEvent,
|
||||
this,
|
||||
new Avalonia.Input.Pointer(0, PointerType.Mouse, true),
|
||||
new Pointer(0, PointerType.Mouse, true),
|
||||
root,
|
||||
this.TranslatePoint(point, root).Value,
|
||||
(ulong)Environment.TickCount64,
|
||||
@@ -187,6 +200,16 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
return DefWindowProc(hWnd, msg, (IntPtr)wParam, (IntPtr)lParam);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
IPlatformHandle CreateMacOs(IPlatformHandle parent)
|
||||
{
|
||||
MetalLayer = MetalHelper.GetMetalLayer(out IntPtr nsView, out _updateBoundsCallback);
|
||||
|
||||
NsView = nsView;
|
||||
|
||||
return new PlatformHandle(nsView, "NSView");
|
||||
}
|
||||
|
||||
void DestroyLinux()
|
||||
{
|
||||
X11Window?.Dispose();
|
||||
@@ -198,5 +221,11 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
DestroyWindow(handle.Handle);
|
||||
UnregisterClass(_className, GetModuleHandle(null));
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
void DestroyMacOS()
|
||||
{
|
||||
MetalHelper.DestroyMetalLayer(NsView, MetalLayer);
|
||||
}
|
||||
}
|
||||
}
|
@@ -138,6 +138,9 @@
|
||||
<Style Selector="ListBoxItem:selected /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource AppListBackgroundColor}" />
|
||||
</Style>
|
||||
<Style Selector="ListBoxItem:selected /template/ Border#SelectionIndicator">
|
||||
<Setter Property="MinHeight" Value="100" />
|
||||
</Style>
|
||||
<Style Selector="ListBoxItem:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource AppListHoverBackgroundColor}" />
|
||||
</Style>
|
||||
|
@@ -3,6 +3,7 @@ using Ryujinx.Ava.Ui.Controls;
|
||||
using Silk.NET.Vulkan;
|
||||
using SPB.Graphics.Vulkan;
|
||||
using SPB.Platform.GLX;
|
||||
using SPB.Platform.Metal;
|
||||
using SPB.Platform.Win32;
|
||||
using SPB.Platform.X11;
|
||||
using SPB.Windowing;
|
||||
@@ -37,6 +38,10 @@ namespace Ryujinx.Ava.Ui
|
||||
{
|
||||
_window = new SimpleX11Window(new NativeHandle(X11Display), new NativeHandle(WindowHandle));
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
_window = new SimpleMetalWindow(new NativeHandle(NsView), new NativeHandle(MetalLayer));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
|
@@ -545,7 +545,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
|
||||
config = new StandardKeyboardInputConfig
|
||||
{
|
||||
Version = Ryujinx.Common.Configuration.Hid.InputConfig.CurrentVersion,
|
||||
Version = InputConfig.CurrentVersion,
|
||||
Backend = InputBackendType.WindowKeyboard,
|
||||
Id = id,
|
||||
ControllerType = ControllerType.ProController,
|
||||
@@ -600,7 +600,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
|
||||
config = new StandardControllerInputConfig
|
||||
{
|
||||
Version = Ryujinx.Common.Configuration.Hid.InputConfig.CurrentVersion,
|
||||
Version = InputConfig.CurrentVersion,
|
||||
Backend = InputBackendType.GamepadSDL2,
|
||||
Id = id,
|
||||
ControllerType = ControllerType.ProController,
|
||||
|
@@ -108,6 +108,8 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
||||
|
||||
public bool DirectoryChanged
|
||||
{
|
||||
get => _directoryChanged;
|
||||
|
@@ -104,11 +104,11 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
|
||||
var device = ViewModel.Devices[ViewModel.Device];
|
||||
|
||||
if (device.Type == Models.DeviceType.Keyboard)
|
||||
if (device.Type == DeviceType.Keyboard)
|
||||
{
|
||||
assigner = new KeyboardKeyAssigner((IKeyboard)ViewModel.SelectedGamepad);
|
||||
}
|
||||
else if (device.Type == Models.DeviceType.Controller)
|
||||
else if (device.Type == DeviceType.Controller)
|
||||
{
|
||||
assigner = new GamepadButtonAssigner(ViewModel.SelectedGamepad, (ViewModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick);
|
||||
}
|
||||
|
@@ -12,9 +12,9 @@
|
||||
xmlns:window="clr-namespace:Ryujinx.Ava.Ui.Windows"
|
||||
Title="Ryujinx"
|
||||
Width="1280"
|
||||
Height="785"
|
||||
Height="777"
|
||||
MinWidth="1092"
|
||||
MinHeight="680"
|
||||
MinHeight="672"
|
||||
d:DesignHeight="720"
|
||||
d:DesignWidth="1280"
|
||||
x:CompileBindings="True"
|
||||
@@ -552,9 +552,8 @@
|
||||
<Grid
|
||||
Name="StatusBar"
|
||||
Grid.Row="2"
|
||||
MinHeight="30"
|
||||
Height="30"
|
||||
Margin="0,0"
|
||||
Margin="0"
|
||||
MinHeight="22"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="{DynamicResource ThemeContentBackgroundColor}"
|
||||
@@ -568,7 +567,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
Margin="10,0"
|
||||
Margin="5"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding EnableNonGameRunningControls}">
|
||||
<Grid Margin="0">
|
||||
@@ -610,14 +609,14 @@
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Margin="10,0"
|
||||
Margin="0,2"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsGameRunning}"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Name="VsyncStatus"
|
||||
Margin="0,0,5,0"
|
||||
Margin="5,0,5,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{Binding VsyncColor}"
|
||||
@@ -628,7 +627,7 @@
|
||||
<Border
|
||||
Width="2"
|
||||
Height="12"
|
||||
Margin="2,0"
|
||||
Margin="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding !ShowLoadProgress}" />
|
||||
@@ -644,7 +643,7 @@
|
||||
<Border
|
||||
Width="2"
|
||||
Height="12"
|
||||
Margin="2,0"
|
||||
Margin="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding !ShowLoadProgress}" />
|
||||
@@ -660,13 +659,13 @@
|
||||
<Border
|
||||
Width="2"
|
||||
Height="12"
|
||||
Margin="2,0"
|
||||
Margin="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding !ShowLoadProgress}" />
|
||||
<ui:ToggleSplitButton
|
||||
Name="VolumeStatus"
|
||||
Padding="5"
|
||||
Padding="5,0,5,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
@@ -679,6 +678,7 @@
|
||||
<Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
|
||||
<Grid Margin="0">
|
||||
<Slider
|
||||
MaxHeight="40"
|
||||
Width="150"
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
@@ -697,7 +697,7 @@
|
||||
<Border
|
||||
Width="2"
|
||||
Height="12"
|
||||
Margin="2,0"
|
||||
Margin="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding !ShowLoadProgress}" />
|
||||
@@ -711,7 +711,7 @@
|
||||
<Border
|
||||
Width="2"
|
||||
Height="12"
|
||||
Margin="2,0"
|
||||
Margin="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding !ShowLoadProgress}" />
|
||||
@@ -725,7 +725,7 @@
|
||||
<Border
|
||||
Width="2"
|
||||
Height="12"
|
||||
Margin="2,0"
|
||||
Margin="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding !ShowLoadProgress}" />
|
||||
@@ -739,7 +739,7 @@
|
||||
<Border
|
||||
Width="2"
|
||||
Height="12"
|
||||
Margin="2,0"
|
||||
Margin="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
IsVisible="{Binding !ShowLoadProgress}" />
|
||||
@@ -753,7 +753,7 @@
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="3"
|
||||
Margin="10,0"
|
||||
Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding ShowFirmwareStatus}"
|
||||
Orientation="Horizontal">
|
||||
|
@@ -154,6 +154,12 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HandleScalingChanged(double scale)
|
||||
{
|
||||
Program.DesktopScaleFactor = scale;
|
||||
base.HandleScalingChanged(scale);
|
||||
}
|
||||
|
||||
public void Application_Opened(object sender, ApplicationOpenedEventArgs args)
|
||||
{
|
||||
if (args.Application != null)
|
||||
|
@@ -540,7 +540,7 @@
|
||||
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
|
||||
<TextBlock Text="Vulkan" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<ComboBoxItem IsEnabled="{Binding IsOpenGLAvailable}">
|
||||
<TextBlock Text="OpenGL" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
@@ -45,7 +45,14 @@ namespace Ryujinx.Common.Configuration
|
||||
|
||||
public static void Initialize(string baseDirPath)
|
||||
{
|
||||
string userProfilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir);
|
||||
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
||||
if (appDataPath.Length == 0)
|
||||
{
|
||||
appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
}
|
||||
|
||||
string userProfilePath = Path.Combine(appDataPath, DefaultBaseDir);
|
||||
string portablePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DefaultPortableDir);
|
||||
|
||||
if (Directory.Exists(portablePath))
|
||||
|
@@ -8,7 +8,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
|
||||
/// <summary>
|
||||
/// A simple implementation of a ReaderWriterLock which can be used from native code.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public struct NativeReaderWriterLock
|
||||
{
|
||||
public int WriteLock;
|
||||
|
@@ -7,7 +7,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
|
||||
<PackageReference Include="System.Management" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -51,7 +50,7 @@ namespace Ryujinx.Common.System
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
userDpiScale = Graphics.FromHwnd(IntPtr.Zero).DpiX;
|
||||
userDpiScale = GdiPlusHelper.GetDpiX(IntPtr.Zero);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
|
76
Ryujinx.Common/System/GdiPlusHelper.cs
Normal file
76
Ryujinx.Common/System/GdiPlusHelper.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Ryujinx.Common.System
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
public static class GdiPlusHelper
|
||||
{
|
||||
private const string LibraryName = "gdiplus.dll";
|
||||
|
||||
private static readonly IntPtr _initToken;
|
||||
|
||||
static GdiPlusHelper()
|
||||
{
|
||||
CheckStatus(GdiplusStartup(out _initToken, StartupInputEx.Default, out _));
|
||||
}
|
||||
|
||||
private static void CheckStatus(int gdiStatus)
|
||||
{
|
||||
if (gdiStatus != 0)
|
||||
{
|
||||
throw new Exception($"GDI Status Error: {gdiStatus}");
|
||||
}
|
||||
}
|
||||
|
||||
private struct StartupInputEx
|
||||
{
|
||||
public int GdiplusVersion;
|
||||
|
||||
#pragma warning disable CS0649
|
||||
public IntPtr DebugEventCallback;
|
||||
public int SuppressBackgroundThread;
|
||||
public int SuppressExternalCodecs;
|
||||
public int StartupParameters;
|
||||
#pragma warning restore CS0649
|
||||
|
||||
public static StartupInputEx Default => new StartupInputEx
|
||||
{
|
||||
// We assume Windows 8 and upper
|
||||
GdiplusVersion = 2,
|
||||
DebugEventCallback = IntPtr.Zero,
|
||||
SuppressBackgroundThread = 0,
|
||||
SuppressExternalCodecs = 0,
|
||||
StartupParameters = 0,
|
||||
};
|
||||
}
|
||||
|
||||
private struct StartupOutput
|
||||
{
|
||||
public IntPtr NotificationHook;
|
||||
public IntPtr NotificationUnhook;
|
||||
}
|
||||
|
||||
[DllImport(LibraryName)]
|
||||
private static extern int GdiplusStartup(out IntPtr token, in StartupInputEx input, out StartupOutput output);
|
||||
|
||||
[DllImport(LibraryName)]
|
||||
private static extern int GdipCreateFromHWND(IntPtr hwnd, out IntPtr graphics);
|
||||
|
||||
[DllImport(LibraryName)]
|
||||
private static extern int GdipDeleteGraphics(IntPtr graphics);
|
||||
|
||||
[DllImport(LibraryName)]
|
||||
private static extern int GdipGetDpiX(IntPtr graphics, out float dpi);
|
||||
|
||||
public static float GetDpiX(IntPtr hwnd)
|
||||
{
|
||||
CheckStatus(GdipCreateFromHWND(hwnd, out IntPtr graphicsHandle));
|
||||
CheckStatus(GdipGetDpiX(graphicsHandle, out float result));
|
||||
CheckStatus(GdipDeleteGraphics(graphicsHandle));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@@ -50,186 +50,186 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
|
||||
private static void InitLookup()
|
||||
{
|
||||
_lookup[(int)CommandType.Action] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.Action] = (memory, threaded, renderer) =>
|
||||
ActionCommand.Run(ref GetCommand<ActionCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CreateBuffer] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CreateBuffer] = (memory, threaded, renderer) =>
|
||||
CreateBufferCommand.Run(ref GetCommand<CreateBufferCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CreateProgram] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CreateProgram] = (memory, threaded, renderer) =>
|
||||
CreateProgramCommand.Run(ref GetCommand<CreateProgramCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CreateSampler] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CreateSampler] = (memory, threaded, renderer) =>
|
||||
CreateSamplerCommand.Run(ref GetCommand<CreateSamplerCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CreateSync] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CreateSync] = (memory, threaded, renderer) =>
|
||||
CreateSyncCommand.Run(ref GetCommand<CreateSyncCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CreateTexture] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CreateTexture] = (memory, threaded, renderer) =>
|
||||
CreateTextureCommand.Run(ref GetCommand<CreateTextureCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.GetCapabilities] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.GetCapabilities] = (memory, threaded, renderer) =>
|
||||
GetCapabilitiesCommand.Run(ref GetCommand<GetCapabilitiesCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.PreFrame] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.PreFrame] = (memory, threaded, renderer) =>
|
||||
PreFrameCommand.Run(ref GetCommand<PreFrameCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.ReportCounter] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ReportCounter] = (memory, threaded, renderer) =>
|
||||
ReportCounterCommand.Run(ref GetCommand<ReportCounterCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.ResetCounter] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ResetCounter] = (memory, threaded, renderer) =>
|
||||
ResetCounterCommand.Run(ref GetCommand<ResetCounterCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.UpdateCounters] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.UpdateCounters] = (memory, threaded, renderer) =>
|
||||
UpdateCountersCommand.Run(ref GetCommand<UpdateCountersCommand>(memory), threaded, renderer);
|
||||
|
||||
_lookup[(int)CommandType.BufferDispose] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.BufferDispose] = (memory, threaded, renderer) =>
|
||||
BufferDisposeCommand.Run(ref GetCommand<BufferDisposeCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.BufferGetData] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.BufferGetData] = (memory, threaded, renderer) =>
|
||||
BufferGetDataCommand.Run(ref GetCommand<BufferGetDataCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.BufferSetData] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.BufferSetData] = (memory, threaded, renderer) =>
|
||||
BufferSetDataCommand.Run(ref GetCommand<BufferSetDataCommand>(memory), threaded, renderer);
|
||||
|
||||
_lookup[(int)CommandType.CounterEventDispose] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CounterEventDispose] = (memory, threaded, renderer) =>
|
||||
CounterEventDisposeCommand.Run(ref GetCommand<CounterEventDisposeCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CounterEventFlush] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CounterEventFlush] = (memory, threaded, renderer) =>
|
||||
CounterEventFlushCommand.Run(ref GetCommand<CounterEventFlushCommand>(memory), threaded, renderer);
|
||||
|
||||
_lookup[(int)CommandType.ProgramDispose] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ProgramDispose] = (memory, threaded, renderer) =>
|
||||
ProgramDisposeCommand.Run(ref GetCommand<ProgramDisposeCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.ProgramGetBinary] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ProgramGetBinary] = (memory, threaded, renderer) =>
|
||||
ProgramGetBinaryCommand.Run(ref GetCommand<ProgramGetBinaryCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.ProgramCheckLink] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ProgramCheckLink] = (memory, threaded, renderer) =>
|
||||
ProgramCheckLinkCommand.Run(ref GetCommand<ProgramCheckLinkCommand>(memory), threaded, renderer);
|
||||
|
||||
_lookup[(int)CommandType.SamplerDispose] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SamplerDispose] = (memory, threaded, renderer) =>
|
||||
SamplerDisposeCommand.Run(ref GetCommand<SamplerDisposeCommand>(memory), threaded, renderer);
|
||||
|
||||
_lookup[(int)CommandType.TextureCopyTo] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureCopyTo] = (memory, threaded, renderer) =>
|
||||
TextureCopyToCommand.Run(ref GetCommand<TextureCopyToCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureCopyToScaled] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureCopyToScaled] = (memory, threaded, renderer) =>
|
||||
TextureCopyToScaledCommand.Run(ref GetCommand<TextureCopyToScaledCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureCopyToSlice] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureCopyToSlice] = (memory, threaded, renderer) =>
|
||||
TextureCopyToSliceCommand.Run(ref GetCommand<TextureCopyToSliceCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureCreateView] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureCreateView] = (memory, threaded, renderer) =>
|
||||
TextureCreateViewCommand.Run(ref GetCommand<TextureCreateViewCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureGetData] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureGetData] = (memory, threaded, renderer) =>
|
||||
TextureGetDataCommand.Run(ref GetCommand<TextureGetDataCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureGetDataSlice] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureGetDataSlice] = (memory, threaded, renderer) =>
|
||||
TextureGetDataSliceCommand.Run(ref GetCommand<TextureGetDataSliceCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureRelease] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureRelease] = (memory, threaded, renderer) =>
|
||||
TextureReleaseCommand.Run(ref GetCommand<TextureReleaseCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureSetData] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureSetData] = (memory, threaded, renderer) =>
|
||||
TextureSetDataCommand.Run(ref GetCommand<TextureSetDataCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureSetDataSlice] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureSetDataSlice] = (memory, threaded, renderer) =>
|
||||
TextureSetDataSliceCommand.Run(ref GetCommand<TextureSetDataSliceCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureSetDataSliceRegion] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureSetDataSliceRegion] = (memory, threaded, renderer) =>
|
||||
TextureSetDataSliceRegionCommand.Run(ref GetCommand<TextureSetDataSliceRegionCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureSetStorage] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureSetStorage] = (memory, threaded, renderer) =>
|
||||
TextureSetStorageCommand.Run(ref GetCommand<TextureSetStorageCommand>(memory), threaded, renderer);
|
||||
|
||||
_lookup[(int)CommandType.WindowPresent] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.WindowPresent] = (memory, threaded, renderer) =>
|
||||
WindowPresentCommand.Run(ref GetCommand<WindowPresentCommand>(memory), threaded, renderer);
|
||||
|
||||
_lookup[(int)CommandType.Barrier] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.Barrier] = (memory, threaded, renderer) =>
|
||||
BarrierCommand.Run(ref GetCommand<BarrierCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.BeginTransformFeedback] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.BeginTransformFeedback] = (memory, threaded, renderer) =>
|
||||
BeginTransformFeedbackCommand.Run(ref GetCommand<BeginTransformFeedbackCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.ClearBuffer] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ClearBuffer] = (memory, threaded, renderer) =>
|
||||
ClearBufferCommand.Run(ref GetCommand<ClearBufferCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.ClearRenderTargetColor] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ClearRenderTargetColor] = (memory, threaded, renderer) =>
|
||||
ClearRenderTargetColorCommand.Run(ref GetCommand<ClearRenderTargetColorCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.ClearRenderTargetDepthStencil] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.ClearRenderTargetDepthStencil] = (memory, threaded, renderer) =>
|
||||
ClearRenderTargetDepthStencilCommand.Run(ref GetCommand<ClearRenderTargetDepthStencilCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CommandBufferBarrier] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CommandBufferBarrier] = (memory, threaded, renderer) =>
|
||||
CommandBufferBarrierCommand.Run(ref GetCommand<CommandBufferBarrierCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.CopyBuffer] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.CopyBuffer] = (memory, threaded, renderer) =>
|
||||
CopyBufferCommand.Run(ref GetCommand<CopyBufferCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.DispatchCompute] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.DispatchCompute] = (memory, threaded, renderer) =>
|
||||
DispatchComputeCommand.Run(ref GetCommand<DispatchComputeCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.Draw] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.Draw] = (memory, threaded, renderer) =>
|
||||
DrawCommand.Run(ref GetCommand<DrawCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.DrawIndexed] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.DrawIndexed] = (memory, threaded, renderer) =>
|
||||
DrawIndexedCommand.Run(ref GetCommand<DrawIndexedCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.DrawIndexedIndirect] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.DrawIndexedIndirect] = (memory, threaded, renderer) =>
|
||||
DrawIndexedIndirectCommand.Run(ref GetCommand<DrawIndexedIndirectCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.DrawIndexedIndirectCount] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.DrawIndexedIndirectCount] = (memory, threaded, renderer) =>
|
||||
DrawIndexedIndirectCountCommand.Run(ref GetCommand<DrawIndexedIndirectCountCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.DrawIndirect] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.DrawIndirect] = (memory, threaded, renderer) =>
|
||||
DrawIndirectCommand.Run(ref GetCommand<DrawIndirectCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.DrawIndirectCount] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.DrawIndirectCount] = (memory, threaded, renderer) =>
|
||||
DrawIndirectCountCommand.Run(ref GetCommand<DrawIndirectCountCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.DrawTexture] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.DrawTexture] = (memory, threaded, renderer) =>
|
||||
DrawTextureCommand.Run(ref GetCommand<DrawTextureCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.EndHostConditionalRendering] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.EndHostConditionalRendering] = (memory, threaded, renderer) =>
|
||||
EndHostConditionalRenderingCommand.Run(renderer);
|
||||
_lookup[(int)CommandType.EndTransformFeedback] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.EndTransformFeedback] = (memory, threaded, renderer) =>
|
||||
EndTransformFeedbackCommand.Run(ref GetCommand<EndTransformFeedbackCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetAlphaTest] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetAlphaTest] = (memory, threaded, renderer) =>
|
||||
SetAlphaTestCommand.Run(ref GetCommand<SetAlphaTestCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetBlendState] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetBlendState] = (memory, threaded, renderer) =>
|
||||
SetBlendStateCommand.Run(ref GetCommand<SetBlendStateCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetDepthBias] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetDepthBias] = (memory, threaded, renderer) =>
|
||||
SetDepthBiasCommand.Run(ref GetCommand<SetDepthBiasCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetDepthClamp] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetDepthClamp] = (memory, threaded, renderer) =>
|
||||
SetDepthClampCommand.Run(ref GetCommand<SetDepthClampCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetDepthMode] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetDepthMode] = (memory, threaded, renderer) =>
|
||||
SetDepthModeCommand.Run(ref GetCommand<SetDepthModeCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetDepthTest] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetDepthTest] = (memory, threaded, renderer) =>
|
||||
SetDepthTestCommand.Run(ref GetCommand<SetDepthTestCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetFaceCulling] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetFaceCulling] = (memory, threaded, renderer) =>
|
||||
SetFaceCullingCommand.Run(ref GetCommand<SetFaceCullingCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetFrontFace] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetFrontFace] = (memory, threaded, renderer) =>
|
||||
SetFrontFaceCommand.Run(ref GetCommand<SetFrontFaceCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetStorageBuffers] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetStorageBuffers] = (memory, threaded, renderer) =>
|
||||
SetStorageBuffersCommand.Run(ref GetCommand<SetStorageBuffersCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetTransformFeedbackBuffers] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetTransformFeedbackBuffers] = (memory, threaded, renderer) =>
|
||||
SetTransformFeedbackBuffersCommand.Run(ref GetCommand<SetTransformFeedbackBuffersCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetUniformBuffers] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetUniformBuffers] = (memory, threaded, renderer) =>
|
||||
SetUniformBuffersCommand.Run(ref GetCommand<SetUniformBuffersCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetImage] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetImage] = (memory, threaded, renderer) =>
|
||||
SetImageCommand.Run(ref GetCommand<SetImageCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetIndexBuffer] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetIndexBuffer] = (memory, threaded, renderer) =>
|
||||
SetIndexBufferCommand.Run(ref GetCommand<SetIndexBufferCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetLineParameters] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetLineParameters] = (memory, threaded, renderer) =>
|
||||
SetLineParametersCommand.Run(ref GetCommand<SetLineParametersCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetLogicOpState] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetLogicOpState] = (memory, threaded, renderer) =>
|
||||
SetLogicOpStateCommand.Run(ref GetCommand<SetLogicOpStateCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetMultisampleState] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetMultisampleState] = (memory, threaded, renderer) =>
|
||||
SetMultisampleStateCommand.Run(ref GetCommand<SetMultisampleStateCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetPatchParameters] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetPatchParameters] = (memory, threaded, renderer) =>
|
||||
SetPatchParametersCommand.Run(ref GetCommand<SetPatchParametersCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetPointParameters] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetPointParameters] = (memory, threaded, renderer) =>
|
||||
SetPointParametersCommand.Run(ref GetCommand<SetPointParametersCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetPolygonMode] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetPolygonMode] = (memory, threaded, renderer) =>
|
||||
SetPolygonModeCommand.Run(ref GetCommand<SetPolygonModeCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetPrimitiveRestart] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetPrimitiveRestart] = (memory, threaded, renderer) =>
|
||||
SetPrimitiveRestartCommand.Run(ref GetCommand<SetPrimitiveRestartCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetPrimitiveTopology] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetPrimitiveTopology] = (memory, threaded, renderer) =>
|
||||
SetPrimitiveTopologyCommand.Run(ref GetCommand<SetPrimitiveTopologyCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetProgram] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetProgram] = (memory, threaded, renderer) =>
|
||||
SetProgramCommand.Run(ref GetCommand<SetProgramCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetRasterizerDiscard] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetRasterizerDiscard] = (memory, threaded, renderer) =>
|
||||
SetRasterizerDiscardCommand.Run(ref GetCommand<SetRasterizerDiscardCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetRenderTargetColorMasks] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetRenderTargetColorMasks] = (memory, threaded, renderer) =>
|
||||
SetRenderTargetColorMasksCommand.Run(ref GetCommand<SetRenderTargetColorMasksCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetRenderTargetScale] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetRenderTargetScale] = (memory, threaded, renderer) =>
|
||||
SetRenderTargetScaleCommand.Run(ref GetCommand<SetRenderTargetScaleCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetRenderTargets] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetRenderTargets] = (memory, threaded, renderer) =>
|
||||
SetRenderTargetsCommand.Run(ref GetCommand<SetRenderTargetsCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetScissor] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetScissor] = (memory, threaded, renderer) =>
|
||||
SetScissorsCommand.Run(ref GetCommand<SetScissorsCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetStencilTest] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetStencilTest] = (memory, threaded, renderer) =>
|
||||
SetStencilTestCommand.Run(ref GetCommand<SetStencilTestCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetTextureAndSampler] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetTextureAndSampler] = (memory, threaded, renderer) =>
|
||||
SetTextureAndSamplerCommand.Run(ref GetCommand<SetTextureAndSamplerCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetUserClipDistance] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetUserClipDistance] = (memory, threaded, renderer) =>
|
||||
SetUserClipDistanceCommand.Run(ref GetCommand<SetUserClipDistanceCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetVertexAttribs] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetVertexAttribs] = (memory, threaded, renderer) =>
|
||||
SetVertexAttribsCommand.Run(ref GetCommand<SetVertexAttribsCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetVertexBuffers] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetVertexBuffers] = (memory, threaded, renderer) =>
|
||||
SetVertexBuffersCommand.Run(ref GetCommand<SetVertexBuffersCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.SetViewports] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.SetViewports] = (memory, threaded, renderer) =>
|
||||
SetViewportsCommand.Run(ref GetCommand<SetViewportsCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureBarrier] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureBarrier] = (memory, threaded, renderer) =>
|
||||
TextureBarrierCommand.Run(ref GetCommand<TextureBarrierCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TextureBarrierTiled] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TextureBarrierTiled] = (memory, threaded, renderer) =>
|
||||
TextureBarrierTiledCommand.Run(ref GetCommand<TextureBarrierTiledCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TryHostConditionalRendering] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TryHostConditionalRendering] = (memory, threaded, renderer) =>
|
||||
TryHostConditionalRenderingCommand.Run(ref GetCommand<TryHostConditionalRenderingCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.TryHostConditionalRenderingFlush] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.TryHostConditionalRenderingFlush] = (memory, threaded, renderer) =>
|
||||
TryHostConditionalRenderingFlushCommand.Run(ref GetCommand<TryHostConditionalRenderingFlushCommand>(memory), threaded, renderer);
|
||||
_lookup[(int)CommandType.UpdateRenderScale] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||
_lookup[(int)CommandType.UpdateRenderScale] = (memory, threaded, renderer) =>
|
||||
UpdateRenderScaleCommand.Run(ref GetCommand<UpdateRenderScaleCommand>(memory), threaded, renderer);
|
||||
}
|
||||
|
||||
|
@@ -72,7 +72,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
{
|
||||
_baseRenderer = renderer;
|
||||
|
||||
renderer.ScreenCaptured += (object sender, ScreenCaptureImageInfo info) => ScreenCaptured?.Invoke(this, info);
|
||||
renderer.ScreenCaptured += (sender, info) => ScreenCaptured?.Invoke(this, info);
|
||||
|
||||
Pipeline = new ThreadedPipeline(this, renderer.Pipeline);
|
||||
Window = new ThreadedWindow(this, renderer);
|
||||
|
@@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.GAL
|
||||
AddressMode.ClampToEdge,
|
||||
AddressMode.ClampToEdge,
|
||||
CompareMode.None,
|
||||
GAL.CompareOp.Always,
|
||||
CompareOp.Always,
|
||||
new ColorF(0f, 0f, 0f, 0f),
|
||||
0f,
|
||||
0f,
|
||||
|
@@ -253,14 +253,19 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
/// Indicates that any storage buffer use is unaligned.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
public void SetHasUnalignedStorageBuffer(bool value)
|
||||
/// <returns>True if the unaligned state changed, false otherwise</returns>
|
||||
public bool SetHasUnalignedStorageBuffer(bool value)
|
||||
{
|
||||
if (value != _graphics.HasUnalignedStorageBuffer)
|
||||
{
|
||||
_graphics.HasUnalignedStorageBuffer = value;
|
||||
|
||||
Signal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -304,14 +304,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
/// </summary>
|
||||
private void CommitBindings()
|
||||
{
|
||||
var buffers = _channel.BufferManager;
|
||||
var hasUnaligned = buffers.HasUnalignedStorageBuffers;
|
||||
|
||||
UpdateStorageBuffers();
|
||||
|
||||
if (!_channel.TextureManager.CommitGraphicsBindings(_shaderSpecState) || (buffers.HasUnalignedStorageBuffers != hasUnaligned))
|
||||
bool unalignedChanged = _currentSpecState.SetHasUnalignedStorageBuffer(_channel.BufferManager.HasUnalignedStorageBuffers);
|
||||
|
||||
if (!_channel.TextureManager.CommitGraphicsBindings(_shaderSpecState) || unalignedChanged)
|
||||
{
|
||||
_currentSpecState.SetHasUnalignedStorageBuffer(buffers.HasUnalignedStorageBuffers);
|
||||
// Shader must be reloaded. _vtgWritesRtLayer should not change.
|
||||
UpdateShaderState();
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
private const ushort FileFormatVersionMajor = 1;
|
||||
private const ushort FileFormatVersionMinor = 2;
|
||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||
private const uint CodeGenVersion = 4037;
|
||||
private const uint CodeGenVersion = 4069;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
private const string SharedDataFileName = "shared.data";
|
||||
|
@@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||
/// <summary>
|
||||
/// Texture target.
|
||||
/// </summary>
|
||||
public Image.TextureTarget TextureTarget;
|
||||
public TextureTarget TextureTarget;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the coordinates used to sample the texture are normalized or not (0.0..1.0 or 0..Width/Height).
|
||||
@@ -331,7 +331,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||
int cbufSlot,
|
||||
uint format,
|
||||
bool formatSrgb,
|
||||
Image.TextureTarget target,
|
||||
TextureTarget target,
|
||||
bool coordNormalized)
|
||||
{
|
||||
Box<TextureSpecializationState> state = GetOrCreateTextureSpecState(stageIndex, handle, cbufSlot);
|
||||
@@ -415,7 +415,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
/// <param name="cbufSlot">Slot of the texture buffer constant buffer</param>
|
||||
public Image.TextureTarget GetTextureTarget(int stageIndex, int handle, int cbufSlot)
|
||||
public TextureTarget GetTextureTarget(int stageIndex, int handle, int cbufSlot)
|
||||
{
|
||||
return GetTextureSpecState(stageIndex, handle, cbufSlot).Value.TextureTarget;
|
||||
}
|
||||
|
@@ -2,6 +2,6 @@ float Helper_SwizzleAdd(float x, float y, int mask)
|
||||
{
|
||||
vec4 xLut = vec4(1.0, -1.0, 1.0, 0.0);
|
||||
vec4 yLut = vec4(1.0, 1.0, -1.0, 1.0);
|
||||
int lutIdx = mask >> int($SUBGROUP_INVOCATION$ & 3u) * 2;
|
||||
int lutIdx = (mask >> (int($SUBGROUP_INVOCATION$ & 3u) * 2)) & 3;
|
||||
return x * xLut[lutIdx] + y * yLut[lutIdx];
|
||||
}
|
@@ -10,8 +10,6 @@ using static Spv.Specification;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
using SpvInstruction = Spv.Generator.Instruction;
|
||||
|
||||
static class Declarations
|
||||
{
|
||||
// At least 16 attributes are guaranteed by the spec.
|
||||
@@ -60,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
for (int funcIndex = 0; funcIndex < functions.Count; funcIndex++)
|
||||
{
|
||||
StructuredFunction function = functions[funcIndex];
|
||||
SpvInstruction[] locals = new SpvInstruction[function.InArguments.Length];
|
||||
Instruction[] locals = new Instruction[function.InArguments.Length];
|
||||
|
||||
for (int i = 0; i < function.InArguments.Length; i++)
|
||||
{
|
||||
@@ -122,7 +120,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
context.SharedMemory = DeclareMemory(context, StorageClass.Workgroup, size);
|
||||
}
|
||||
|
||||
private static SpvInstruction DeclareMemory(CodeGenContext context, StorageClass storage, int size)
|
||||
private static Instruction DeclareMemory(CodeGenContext context, StorageClass storage, int size)
|
||||
{
|
||||
var arrayType = context.TypeArray(context.TypeU32(), context.Constant(context.TypeU32(), size));
|
||||
var pointerType = context.TypePointer(storage, arrayType);
|
||||
|
@@ -1449,10 +1449,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
var xLut = context.ConstantComposite(v4float, one, minusOne, one, zero);
|
||||
var yLut = context.ConstantComposite(v4float, one, one, minusOne, one);
|
||||
|
||||
var three = context.Constant(context.TypeU32(), 3);
|
||||
|
||||
var threadId = context.GetAttribute(AggregateType.U32, AttributeConsts.LaneId, false);
|
||||
var shift = context.BitwiseAnd(context.TypeU32(), threadId, context.Constant(context.TypeU32(), 3));
|
||||
var shift = context.BitwiseAnd(context.TypeU32(), threadId, three);
|
||||
shift = context.ShiftLeftLogical(context.TypeU32(), shift, context.Constant(context.TypeU32(), 1));
|
||||
var lutIdx = context.ShiftRightLogical(context.TypeU32(), mask, shift);
|
||||
lutIdx = context.BitwiseAnd(context.TypeU32(), lutIdx, three);
|
||||
|
||||
var xLutValue = context.VectorExtractDynamic(context.TypeFP32(), xLut, lutIdx);
|
||||
var yLutValue = context.VectorExtractDynamic(context.TypeFP32(), yLut, lutIdx);
|
||||
|
@@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
public const int TessLevelOuter3 = 0x00c;
|
||||
public const int TessLevelInner0 = 0x010;
|
||||
public const int TessLevelInner1 = 0x014;
|
||||
public const int PrimitiveId = 0x060;
|
||||
public const int Layer = 0x064;
|
||||
public const int ViewportIndex = 0x068;
|
||||
public const int PointSize = 0x06c;
|
||||
@@ -85,8 +86,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
public const int LaneId = 0x2000020;
|
||||
|
||||
public const int InvocationId = 0x2000024;
|
||||
public const int PrimitiveId = 0x2000028;
|
||||
public const int PatchVerticesIn = 0x200002c;
|
||||
public const int PatchVerticesIn = 0x2000028;
|
||||
|
||||
public const int EqMask = 0x2000030;
|
||||
public const int GeMask = 0x2000034;
|
||||
|
@@ -48,5 +48,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
public static int GetConstantUbeOffset(int slot)
|
||||
{
|
||||
return UbeBaseOffset + slot * StorageDescSize;
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,11 +8,14 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
{
|
||||
static class GlobalToStorage
|
||||
{
|
||||
public static void RunPass(BasicBlock block, ShaderConfig config, ref int sbUseMask)
|
||||
public static void RunPass(BasicBlock block, ShaderConfig config, ref int sbUseMask, ref int ubeUseMask)
|
||||
{
|
||||
int sbStart = GetStorageBaseCbOffset(config.Stage);
|
||||
int sbEnd = sbStart + StorageDescsSize;
|
||||
|
||||
int ubeStart = UbeBaseOffset;
|
||||
int ubeEnd = UbeBaseOffset + UbeDescsSize;
|
||||
|
||||
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
|
||||
{
|
||||
for (int index = 0; index < node.Value.SourcesCount; index++)
|
||||
@@ -25,6 +28,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
{
|
||||
sbUseMask |= 1 << storageIndex;
|
||||
}
|
||||
|
||||
if (config.Stage == ShaderStage.Compute)
|
||||
{
|
||||
int constantIndex = GetStorageIndex(src, ubeStart, ubeEnd);
|
||||
|
||||
if (constantIndex >= 0)
|
||||
{
|
||||
ubeUseMask |= 1 << constantIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(node.Value is Operation operation))
|
||||
@@ -54,7 +67,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
// so NVN "emulates" more constant buffers using global memory access.
|
||||
// Here we try to replace the global access back to a constant buffer
|
||||
// load.
|
||||
storageIndex = SearchForStorageBase(block, source, UbeBaseOffset, UbeBaseOffset + UbeDescsSize);
|
||||
storageIndex = SearchForStorageBase(block, source, ubeStart, ubeStart + ubeEnd);
|
||||
|
||||
if (storageIndex >= 0)
|
||||
{
|
||||
@@ -64,7 +77,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
}
|
||||
}
|
||||
|
||||
config.SetAccessibleStorageBuffersMask(sbUseMask);
|
||||
config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask);
|
||||
}
|
||||
|
||||
private static LinkedListNode<INode> ReplaceGlobalWithStorage(BasicBlock block, LinkedListNode<INode> node, ShaderConfig config, int storageIndex)
|
||||
|
@@ -12,16 +12,17 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
RunOptimizationPasses(blocks);
|
||||
|
||||
int sbUseMask = 0;
|
||||
int ubeUseMask = 0;
|
||||
|
||||
// Those passes are looking for specific patterns and only needs to run once.
|
||||
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
|
||||
{
|
||||
GlobalToStorage.RunPass(blocks[blkIndex], config, ref sbUseMask);
|
||||
GlobalToStorage.RunPass(blocks[blkIndex], config, ref sbUseMask, ref ubeUseMask);
|
||||
BindlessToIndexed.RunPass(blocks[blkIndex], config);
|
||||
BindlessElimination.RunPass(blocks[blkIndex], config);
|
||||
}
|
||||
|
||||
config.SetAccessibleStorageBuffersMask(sbUseMask);
|
||||
config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask);
|
||||
|
||||
// Run optimizations one last time to remove any code that is now optimizable after above passes.
|
||||
RunOptimizationPasses(blocks);
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -89,12 +90,42 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
return local;
|
||||
}
|
||||
|
||||
Operand PrependExistingOperation(Operation operation)
|
||||
{
|
||||
Operand local = Local();
|
||||
|
||||
operation.Dest = local;
|
||||
node.List.AddBefore(node, operation);
|
||||
|
||||
return local;
|
||||
}
|
||||
|
||||
Operand addrLow = operation.GetSource(0);
|
||||
Operand addrHigh = operation.GetSource(1);
|
||||
|
||||
Operand sbBaseAddrLow = Const(0);
|
||||
Operand sbSlot = Const(0);
|
||||
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
|
||||
|
||||
Operand BindingRangeCheck(int cbOffset, out Operand baseAddrLow)
|
||||
{
|
||||
baseAddrLow = Cbuf(0, cbOffset);
|
||||
Operand baseAddrHigh = Cbuf(0, cbOffset + 1);
|
||||
Operand size = Cbuf(0, cbOffset + 2);
|
||||
|
||||
Operand offset = PrependOperation(Instruction.Subtract, addrLow, baseAddrLow);
|
||||
Operand borrow = PrependOperation(Instruction.CompareLessU32, addrLow, baseAddrLow);
|
||||
|
||||
Operand inRangeLow = PrependOperation(Instruction.CompareLessU32, offset, size);
|
||||
|
||||
Operand addrHighBorrowed = PrependOperation(Instruction.Add, addrHigh, borrow);
|
||||
|
||||
Operand inRangeHigh = PrependOperation(Instruction.CompareEqual, addrHighBorrowed, baseAddrHigh);
|
||||
|
||||
return PrependOperation(Instruction.BitwiseAnd, inRangeLow, inRangeHigh);
|
||||
}
|
||||
|
||||
int sbUseMask = config.AccessibleStorageBuffersMask;
|
||||
|
||||
while (sbUseMask != 0)
|
||||
@@ -107,20 +138,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
int cbOffset = GetStorageCbOffset(config.Stage, slot);
|
||||
|
||||
Operand baseAddrLow = Cbuf(0, cbOffset);
|
||||
Operand baseAddrHigh = Cbuf(0, cbOffset + 1);
|
||||
Operand size = Cbuf(0, cbOffset + 2);
|
||||
|
||||
Operand offset = PrependOperation(Instruction.Subtract, addrLow, baseAddrLow);
|
||||
Operand borrow = PrependOperation(Instruction.CompareLessU32, addrLow, baseAddrLow);
|
||||
|
||||
Operand inRangeLow = PrependOperation(Instruction.CompareLessU32, offset, size);
|
||||
|
||||
Operand addrHighBorrowed = PrependOperation(Instruction.Add, addrHigh, borrow);
|
||||
|
||||
Operand inRangeHigh = PrependOperation(Instruction.CompareEqual, addrHighBorrowed, baseAddrHigh);
|
||||
|
||||
Operand inRange = PrependOperation(Instruction.BitwiseAnd, inRangeLow, inRangeHigh);
|
||||
Operand inRange = BindingRangeCheck(cbOffset, out Operand baseAddrLow);
|
||||
|
||||
sbBaseAddrLow = PrependOperation(Instruction.ConditionalSelect, inRange, baseAddrLow, sbBaseAddrLow);
|
||||
sbSlot = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot);
|
||||
@@ -128,8 +146,6 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
if (config.AccessibleStorageBuffersMask != 0)
|
||||
{
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
|
||||
|
||||
Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
|
||||
Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
|
||||
|
||||
@@ -178,6 +194,46 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
storageOp = new Operation(Instruction.Copy, operation.Dest, Const(0));
|
||||
}
|
||||
|
||||
if (operation.Inst == Instruction.LoadGlobal)
|
||||
{
|
||||
int cbeUseMask = config.AccessibleConstantBuffersMask;
|
||||
|
||||
while (cbeUseMask != 0)
|
||||
{
|
||||
int slot = BitOperations.TrailingZeroCount(cbeUseMask);
|
||||
int cbSlot = UbeFirstCbuf + slot;
|
||||
|
||||
cbeUseMask &= ~(1 << slot);
|
||||
|
||||
config.SetUsedConstantBuffer(cbSlot);
|
||||
|
||||
Operand previousResult = PrependExistingOperation(storageOp);
|
||||
|
||||
int cbOffset = GetConstantUbeOffset(slot);
|
||||
|
||||
Operand inRange = BindingRangeCheck(cbOffset, out Operand baseAddrLow);
|
||||
|
||||
Operand baseAddrTruncConst = PrependOperation(Instruction.BitwiseAnd, baseAddrLow, alignMask);
|
||||
Operand byteOffsetConst = PrependOperation(Instruction.Subtract, addrLow, baseAddrTruncConst);
|
||||
|
||||
Operand cbIndex = PrependOperation(Instruction.ShiftRightU32, byteOffsetConst, Const(2));
|
||||
|
||||
Operand[] sourcesCb = new Operand[operation.SourcesCount];
|
||||
|
||||
sourcesCb[0] = Const(cbSlot);
|
||||
sourcesCb[1] = cbIndex;
|
||||
|
||||
for (int index = 2; index < operation.SourcesCount; index++)
|
||||
{
|
||||
sourcesCb[index] = operation.GetSource(index);
|
||||
}
|
||||
|
||||
Operand ldcResult = PrependOperation(Instruction.LoadConstant, sourcesCb);
|
||||
|
||||
storageOp = new Operation(Instruction.ConditionalSelect, operation.Dest, inRange, ldcResult, previousResult);
|
||||
}
|
||||
}
|
||||
|
||||
for (int index = 0; index < operation.SourcesCount; index++)
|
||||
{
|
||||
operation.SetSource(index, null);
|
||||
|
@@ -66,6 +66,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
public UInt128 ThisInputAttributesComponents { get; private set; }
|
||||
|
||||
public int AccessibleStorageBuffersMask { get; private set; }
|
||||
public int AccessibleConstantBuffersMask { get; private set; }
|
||||
|
||||
private int _usedConstantBuffers;
|
||||
private int _usedStorageBuffers;
|
||||
@@ -100,7 +101,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
GpuAccessor = gpuAccessor;
|
||||
Options = options;
|
||||
|
||||
AccessibleStorageBuffersMask = (1 << GlobalMemory.StorageMaxCount) - 1;
|
||||
AccessibleStorageBuffersMask = (1 << GlobalMemory.StorageMaxCount) - 1;
|
||||
AccessibleConstantBuffersMask = (1 << GlobalMemory.UbeMaxCount) - 1;
|
||||
|
||||
UsedInputAttributesPerPatch = new HashSet<int>();
|
||||
UsedOutputAttributesPerPatch = new HashSet<int>();
|
||||
@@ -121,6 +123,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
OutputTopology = outputTopology;
|
||||
MaxOutputVertices = maxOutputVertices;
|
||||
TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
|
||||
|
||||
if (Stage != ShaderStage.Compute)
|
||||
{
|
||||
AccessibleConstantBuffersMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationOptions options) : this(gpuAccessor, options)
|
||||
@@ -404,9 +411,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
UsedFeatures |= flags;
|
||||
}
|
||||
|
||||
public void SetAccessibleStorageBuffersMask(int mask)
|
||||
public void SetAccessibleBufferMasks(int sbMask, int ubeMask)
|
||||
{
|
||||
AccessibleStorageBuffersMask = mask;
|
||||
AccessibleStorageBuffersMask = sbMask;
|
||||
AccessibleConstantBuffersMask = ubeMask;
|
||||
}
|
||||
|
||||
public void SetUsedConstantBuffer(int slot)
|
||||
|
@@ -272,7 +272,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_gd,
|
||||
cbs.CommandBuffer,
|
||||
dstBuffer,
|
||||
BufferHolder.DefaultAccessFlags,
|
||||
DefaultAccessFlags,
|
||||
AccessFlags.TransferWriteBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
cbs.CommandBuffer,
|
||||
dstBuffer,
|
||||
AccessFlags.TransferWriteBit,
|
||||
BufferHolder.DefaultAccessFlags,
|
||||
DefaultAccessFlags,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
dstOffset,
|
||||
@@ -319,7 +319,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
gd,
|
||||
cbs.CommandBuffer,
|
||||
dstBuffer,
|
||||
BufferHolder.DefaultAccessFlags,
|
||||
DefaultAccessFlags,
|
||||
AccessFlags.TransferWriteBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
@@ -335,7 +335,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
cbs.CommandBuffer,
|
||||
dstBuffer,
|
||||
AccessFlags.TransferWriteBit,
|
||||
BufferHolder.DefaultAccessFlags,
|
||||
DefaultAccessFlags,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
dstOffset,
|
||||
|
@@ -97,7 +97,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_dummyBuffer = gd.BufferManager.Create(gd, 0x10000, forConditionalRendering: false, deviceLocal: true);
|
||||
}
|
||||
|
||||
_dummyTexture = gd.CreateTextureView(new GAL.TextureCreateInfo(
|
||||
_dummyTexture = gd.CreateTextureView(new TextureCreateInfo(
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
|
@@ -3,7 +3,7 @@ using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
readonly struct DisposableBufferView : System.IDisposable
|
||||
readonly struct DisposableBufferView : IDisposable
|
||||
{
|
||||
private readonly Vk _api;
|
||||
private readonly Device _device;
|
||||
|
@@ -86,7 +86,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
iter++;
|
||||
}
|
||||
|
||||
DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineFull.DescriptorSetLayouts];
|
||||
DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineBase.DescriptorSetLayouts];
|
||||
|
||||
var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
|
||||
{
|
||||
@@ -117,10 +117,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
BindingCount = (uint)iCount
|
||||
};
|
||||
|
||||
gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.UniformSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.StorageSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.TextureSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.ImageSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.UniformSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.StorageSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.TextureSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.ImageSetIndex]).ThrowOnError();
|
||||
|
||||
fixed (DescriptorSetLayout* pLayouts = layouts)
|
||||
{
|
||||
@@ -128,7 +128,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
SType = StructureType.PipelineLayoutCreateInfo,
|
||||
PSetLayouts = pLayouts,
|
||||
SetLayoutCount = PipelineFull.DescriptorSetLayouts
|
||||
SetLayoutCount = PipelineBase.DescriptorSetLayouts
|
||||
};
|
||||
|
||||
gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
|
||||
@@ -191,7 +191,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Set(iLayoutBindings, DescriptorType.StorageImage, ref iIndex, shader.Bindings.ImageBindings);
|
||||
}
|
||||
|
||||
DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineFull.DescriptorSetLayouts];
|
||||
DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineBase.DescriptorSetLayouts];
|
||||
|
||||
var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
|
||||
{
|
||||
@@ -221,10 +221,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
BindingCount = (uint)iCount
|
||||
};
|
||||
|
||||
gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.UniformSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.StorageSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.TextureSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.ImageSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.UniformSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.StorageSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.TextureSetIndex]).ThrowOnError();
|
||||
gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.ImageSetIndex]).ThrowOnError();
|
||||
|
||||
fixed (DescriptorSetLayout* pLayouts = layouts)
|
||||
{
|
||||
@@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
SType = StructureType.PipelineLayoutCreateInfo,
|
||||
PSetLayouts = pLayouts,
|
||||
SetLayoutCount = PipelineFull.DescriptorSetLayouts
|
||||
SetLayoutCount = PipelineBase.DescriptorSetLayouts
|
||||
};
|
||||
|
||||
gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
@@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
ExtConditionalRendering.ExtensionName,
|
||||
ExtExtendedDynamicState.ExtensionName,
|
||||
ExtTransformFeedback.ExtensionName,
|
||||
KhrDrawIndirectCount.ExtensionName,
|
||||
KhrPushDescriptor.ExtensionName,
|
||||
"VK_EXT_custom_border_color",
|
||||
@@ -36,8 +37,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public static string[] RequiredExtensions { get; } = new string[]
|
||||
{
|
||||
KhrSwapchain.ExtensionName,
|
||||
ExtTransformFeedback.ExtensionName
|
||||
KhrSwapchain.ExtensionName
|
||||
};
|
||||
|
||||
private static string[] _excludedMessages = new string[]
|
||||
@@ -382,12 +382,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
DepthClamp = true,
|
||||
DualSrcBlend = true,
|
||||
FragmentStoresAndAtomics = true,
|
||||
GeometryShader = true,
|
||||
GeometryShader = supportedFeatures.GeometryShader,
|
||||
ImageCubeArray = true,
|
||||
IndependentBlend = true,
|
||||
LogicOp = true,
|
||||
LogicOp = supportedFeatures.LogicOp,
|
||||
MultiViewport = true,
|
||||
PipelineStatisticsQuery = true,
|
||||
PipelineStatisticsQuery = supportedFeatures.PipelineStatisticsQuery,
|
||||
SamplerAnisotropy = true,
|
||||
ShaderClipDistance = true,
|
||||
ShaderFloat64 = supportedFeatures.ShaderFloat64,
|
||||
|
@@ -39,13 +39,11 @@ namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
public readonly string ContainerPath;
|
||||
public readonly string NcaPath;
|
||||
public bool Enabled;
|
||||
|
||||
public AocItem(string containerPath, string ncaPath, bool enabled)
|
||||
public AocItem(string containerPath, string ncaPath)
|
||||
{
|
||||
ContainerPath = containerPath;
|
||||
NcaPath = ncaPath;
|
||||
Enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +51,7 @@ namespace Ryujinx.HLE.FileSystem
|
||||
|
||||
private VirtualFileSystem _virtualFileSystem;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
private readonly object _lock = new();
|
||||
|
||||
public ContentManager(VirtualFileSystem virtualFileSystem)
|
||||
{
|
||||
@@ -226,27 +224,21 @@ namespace Ryujinx.HLE.FileSystem
|
||||
pfs0.OpenFile(ref cnmtFile.Ref(), pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read);
|
||||
|
||||
var cnmt = new Cnmt(cnmtFile.Get.AsStream());
|
||||
|
||||
if (cnmt.Type != ContentMetaType.AddOnContent || (cnmt.TitleId & 0xFFFFFFFFFFFFE000) != aocBaseId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string ncaId = BitConverter.ToString(cnmt.ContentEntries[0].NcaId).Replace("-", "").ToLower();
|
||||
if (!_aocData.TryAdd(cnmt.TitleId, new AocItem(containerPath, $"{ncaId}.nca", true)))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Duplicate AddOnContent detected. TitleId {cnmt.TitleId:X16}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, $"Found AddOnContent with TitleId {cnmt.TitleId:X16}");
|
||||
}
|
||||
|
||||
AddAocItem(cnmt.TitleId, containerPath, $"{ncaId}.nca", true);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAocItem(ulong titleId, string containerPath, string ncaPath, bool enabled)
|
||||
public void AddAocItem(ulong titleId, string containerPath, string ncaPath, bool mergedToContainer = false)
|
||||
{
|
||||
if (!_aocData.TryAdd(titleId, new AocItem(containerPath, ncaPath, enabled)))
|
||||
// TODO: Check Aoc version.
|
||||
if (!_aocData.TryAdd(titleId, new AocItem(containerPath, ncaPath)))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Duplicate AddOnContent detected. TitleId {titleId:X16}");
|
||||
}
|
||||
@@ -254,25 +246,27 @@ namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Application, $"Found AddOnContent with TitleId {titleId:X16}");
|
||||
|
||||
using (FileStream fileStream = File.OpenRead(containerPath))
|
||||
using (PartitionFileSystem pfs = new PartitionFileSystem(fileStream.AsStorage()))
|
||||
if (!mergedToContainer)
|
||||
{
|
||||
_virtualFileSystem.ImportTickets(pfs);
|
||||
using FileStream fileStream = File.OpenRead(containerPath);
|
||||
using PartitionFileSystem partitionFileSystem = new(fileStream.AsStorage());
|
||||
|
||||
_virtualFileSystem.ImportTickets(partitionFileSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearAocData() => _aocData.Clear();
|
||||
|
||||
public int GetAocCount() => _aocData.Where(e => e.Value.Enabled).Count();
|
||||
public int GetAocCount() => _aocData.Count;
|
||||
|
||||
public IList<ulong> GetAocTitleIds() => _aocData.Where(e => e.Value.Enabled).Select(e => e.Key).ToList();
|
||||
public IList<ulong> GetAocTitleIds() => _aocData.Select(e => e.Key).ToList();
|
||||
|
||||
public bool GetAocDataStorage(ulong aocTitleId, out IStorage aocStorage, IntegrityCheckLevel integrityCheckLevel)
|
||||
{
|
||||
aocStorage = null;
|
||||
|
||||
if (_aocData.TryGetValue(aocTitleId, out AocItem aoc) && aoc.Enabled)
|
||||
if (_aocData.TryGetValue(aocTitleId, out AocItem aoc))
|
||||
{
|
||||
var file = new FileStream(aoc.ContainerPath, FileMode.Open, FileAccess.Read);
|
||||
using var ncaFile = new UniqueRef<IFile>();
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
@@ -11,7 +11,6 @@ using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using Ryujinx.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
||||
{
|
||||
@@ -68,8 +67,8 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
||||
{
|
||||
int ryujinxLogoSize = 32;
|
||||
|
||||
Stream logoStream = EmbeddedResources.GetStream("Ryujinx.Ui.Common/Resources/Logo_Ryujinx.png");
|
||||
_ryujinxLogo = LoadResource(logoStream, ryujinxLogoSize, ryujinxLogoSize);
|
||||
string ryujinxIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Logo_Ryujinx.png";
|
||||
_ryujinxLogo = LoadResource(Assembly.GetExecutingAssembly(), ryujinxIconPath, ryujinxLogoSize, ryujinxLogoSize);
|
||||
|
||||
string padAcceptIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_BtnA.png";
|
||||
string padCancelIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_BtnB.png";
|
||||
@@ -117,7 +116,8 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
||||
uiThemeFontFamily,
|
||||
"Liberation Sans",
|
||||
"FreeSans",
|
||||
"DejaVu Sans"
|
||||
"DejaVu Sans",
|
||||
"Lucida Grande"
|
||||
};
|
||||
|
||||
foreach (string fontFamily in availableFonts)
|
||||
|
@@ -426,9 +426,9 @@ namespace Ryujinx.HLE.HOS
|
||||
{
|
||||
foreach (DownloadableContentNca downloadableContentNca in downloadableContentContainer.DownloadableContentNcaList)
|
||||
{
|
||||
if (File.Exists(downloadableContentContainer.ContainerPath))
|
||||
if (File.Exists(downloadableContentContainer.ContainerPath) && downloadableContentNca.Enabled)
|
||||
{
|
||||
_device.Configuration.ContentManager.AddAocItem(downloadableContentNca.TitleId, downloadableContentContainer.ContainerPath, downloadableContentNca.FullPath, downloadableContentNca.Enabled);
|
||||
_device.Configuration.ContentManager.AddAocItem(downloadableContentNca.TitleId, downloadableContentContainer.ContainerPath, downloadableContentNca.FullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -1,8 +1,12 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc.AccountService;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
{
|
||||
@@ -142,6 +146,28 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode CheckNetworkServiceAvailabilityAsync(ServiceCtx context, out IAsyncContext asyncContext)
|
||||
{
|
||||
KEvent asyncEvent = new(context.Device.System.KernelContext);
|
||||
AsyncExecution asyncExecution = new(asyncEvent);
|
||||
|
||||
asyncExecution.Initialize(1000, CheckNetworkServiceAvailabilityAsyncImpl);
|
||||
|
||||
asyncContext = new IAsyncContext(asyncExecution);
|
||||
|
||||
// return ResultCode.NullObject if the IAsyncContext pointer is null. Doesn't occur in our case.
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
private async Task CheckNetworkServiceAvailabilityAsyncImpl(CancellationToken token)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceAcc);
|
||||
|
||||
// TODO: Use a real function instead, with the CancellationToken.
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public ResultCode StoreSaveDataThumbnail(ServiceCtx context)
|
||||
{
|
||||
ResultCode resultCode = CheckUserId(context, out UserId _);
|
||||
|
@@ -124,6 +124,20 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(103)] // 4.0.0+
|
||||
// CheckNetworkServiceAvailabilityAsync() -> object<nn::account::detail::IAsyncContext>
|
||||
public ResultCode CheckNetworkServiceAvailabilityAsync(ServiceCtx context)
|
||||
{
|
||||
ResultCode resultCode = _applicationServiceServer.CheckNetworkServiceAvailabilityAsync(context, out IAsyncContext asyncContext);
|
||||
|
||||
if (resultCode == ResultCode.Success)
|
||||
{
|
||||
MakeObject(context, asyncContext);
|
||||
}
|
||||
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
[CommandHipc(110)]
|
||||
// StoreSaveDataThumbnail(nn::account::Uid, buffer<bytes, 5>)
|
||||
public ResultCode StoreSaveDataThumbnail(ServiceCtx context)
|
||||
|
@@ -157,7 +157,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||
int supportedLanguages = (int)context.Device.Application.ControlData.Value.SupportedLanguageFlag;
|
||||
int firstSupported = BitOperations.TrailingZeroCount(supportedLanguages);
|
||||
|
||||
if (firstSupported > (int)SystemState.TitleLanguage.BrazilianPortuguese)
|
||||
if (firstSupported > (int)TitleLanguage.BrazilianPortuguese)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.ServiceAm, "Application has zero supported languages");
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||
// TODO: In the future, a GUI could enable user-specified search priority
|
||||
if (((1 << (int)context.Device.System.State.DesiredTitleLanguage) & supportedLanguages) == 0)
|
||||
{
|
||||
SystemLanguage newLanguage = Enum.Parse<SystemLanguage>(Enum.GetName(typeof(SystemState.TitleLanguage), firstSupported));
|
||||
SystemLanguage newLanguage = Enum.Parse<SystemLanguage>(Enum.GetName(typeof(TitleLanguage), firstSupported));
|
||||
desiredLanguageCode = SystemStateMgr.GetLanguageCode((int)newLanguage);
|
||||
|
||||
Logger.Info?.Print(LogClass.ServiceAm, $"Application doesn't support configured language. Using {newLanguage}");
|
||||
|
@@ -901,7 +901,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
|
||||
[CommandHipc(606)]
|
||||
public ResultCode GetRightsId(ServiceCtx context)
|
||||
{
|
||||
LibHac.Ncm.StorageId storageId = (LibHac.Ncm.StorageId)context.RequestData.ReadInt64();
|
||||
StorageId storageId = (StorageId)context.RequestData.ReadInt64();
|
||||
ProgramId programId = context.RequestData.ReadStruct<ProgramId>();
|
||||
|
||||
Result result = _baseFileSystemProxy.Get.GetRightsId(out RightsId rightsId, programId, storageId);
|
||||
|
@@ -130,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||
}
|
||||
|
||||
List<(int Offset, string Location, string Abbr)> outList = new List<(int Offset, string Location, string Abbr)>();
|
||||
var now = System.DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
var now = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
using (IStorage ncaStorage = new LocalStorage(_virtualFileSystem.SwitchPathToSystemPath(tzBinaryContentPath), FileAccess.Read, FileMode.Open))
|
||||
using (IFileSystem romfs = new Nca(_virtualFileSystem.KeySet, ncaStorage).OpenFileSystem(NcaSectionType.Data, _fsIntegrityCheckLevel))
|
||||
{
|
||||
|
@@ -36,6 +36,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Homebrew.npdm" />
|
||||
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" />
|
||||
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" />
|
||||
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnB.png" />
|
||||
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Icon_KeyF6.png" />
|
||||
@@ -44,6 +45,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Homebrew.npdm" />
|
||||
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" />
|
||||
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" />
|
||||
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnB.png" />
|
||||
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_KeyF6.png" />
|
||||
|
@@ -77,6 +77,26 @@ namespace Ryujinx.Headless.SDL2
|
||||
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient);
|
||||
_userChannelPersistence = new UserChannelPersistence();
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
AutoResetEvent invoked = new AutoResetEvent(false);
|
||||
|
||||
// MacOS must perform SDL polls from the main thread.
|
||||
Ryujinx.SDL2.Common.SDL2Driver.MainThreadDispatcher = (Action action) =>
|
||||
{
|
||||
invoked.Reset();
|
||||
|
||||
WindowBase.QueueMainThreadAction(() =>
|
||||
{
|
||||
action();
|
||||
|
||||
invoked.Set();
|
||||
});
|
||||
|
||||
invoked.WaitOne();
|
||||
};
|
||||
}
|
||||
|
||||
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
||||
|
||||
GraphicsConfig.EnableShaderCache = true;
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.Core" Version="4.7.5" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build12" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -28,14 +28,18 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.8.0" />
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="..\distribution\legal\THIRDPARTY.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<Content Include="..\distribution\legal\THIRDPARTY.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||
</Content>
|
||||
<Content Include="..\LICENSE.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>LICENSE.txt</TargetPath>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Due to .net core 3.1 embedded resource loading -->
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Input.HLE;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static SDL2.SDL;
|
||||
@@ -26,15 +27,34 @@ namespace Ryujinx.Headless.SDL2.Vulkan
|
||||
MouseDriver.SetClientSize(DefaultWidth, DefaultHeight);
|
||||
}
|
||||
|
||||
private void BasicInvoke(Action action)
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
public unsafe IntPtr CreateWindowSurface(IntPtr instance)
|
||||
{
|
||||
if (SDL_Vulkan_CreateSurface(WindowHandle, instance, out ulong surfaceHandle) == SDL_bool.SDL_FALSE)
|
||||
ulong surfaceHandle = 0;
|
||||
|
||||
Action createSurface = () =>
|
||||
{
|
||||
string errorMessage = $"SDL_Vulkan_CreateSurface failed with error \"{SDL_GetError()}\"";
|
||||
if (SDL_Vulkan_CreateSurface(WindowHandle, instance, out surfaceHandle) == SDL_bool.SDL_FALSE)
|
||||
{
|
||||
string errorMessage = $"SDL_Vulkan_CreateSurface failed with error \"{SDL_GetError()}\"";
|
||||
|
||||
Logger.Error?.Print(LogClass.Application, errorMessage);
|
||||
Logger.Error?.Print(LogClass.Application, errorMessage);
|
||||
|
||||
throw new Exception(errorMessage);
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
if (SDL2Driver.MainThreadDispatcher != null)
|
||||
{
|
||||
SDL2Driver.MainThreadDispatcher(createSurface);
|
||||
}
|
||||
else
|
||||
{
|
||||
createSurface();
|
||||
}
|
||||
|
||||
return (IntPtr)surfaceHandle;
|
||||
|
@@ -11,6 +11,7 @@ using Ryujinx.Input;
|
||||
using Ryujinx.Input.HLE;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
@@ -26,6 +27,13 @@ namespace Ryujinx.Headless.SDL2
|
||||
private const SDL_WindowFlags DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI | SDL_WindowFlags.SDL_WINDOW_RESIZABLE | SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS | SDL_WindowFlags.SDL_WINDOW_SHOWN;
|
||||
private const int TargetFps = 60;
|
||||
|
||||
private static ConcurrentQueue<Action> MainThreadActions = new ConcurrentQueue<Action>();
|
||||
|
||||
public static void QueueMainThreadAction(Action action)
|
||||
{
|
||||
MainThreadActions.Enqueue(action);
|
||||
}
|
||||
|
||||
public NpadManager NpadManager { get; }
|
||||
public TouchScreenManager TouchScreenManager { get; }
|
||||
public Switch Device { get; private set; }
|
||||
@@ -168,6 +176,14 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
public void Render()
|
||||
{
|
||||
InitializeWindowRenderer();
|
||||
|
||||
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
||||
|
||||
InitializeRenderer();
|
||||
|
||||
_gpuVendorName = GetGpuVendorName();
|
||||
|
||||
Device.Gpu.Renderer.RunLoop(() =>
|
||||
{
|
||||
Device.Gpu.SetGpuThread();
|
||||
@@ -241,6 +257,14 @@ namespace Ryujinx.Headless.SDL2
|
||||
_exitEvent.Dispose();
|
||||
}
|
||||
|
||||
public void ProcessMainThreadQueue()
|
||||
{
|
||||
while (MainThreadActions.TryDequeue(out Action action))
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
public void MainLoop()
|
||||
{
|
||||
while (_isActive)
|
||||
@@ -249,6 +273,8 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
SDL_PumpEvents();
|
||||
|
||||
ProcessMainThreadQueue();
|
||||
|
||||
// Polling becomes expensive if it's not slept
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
@@ -315,14 +341,6 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
InitializeWindow();
|
||||
|
||||
InitializeWindowRenderer();
|
||||
|
||||
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
||||
|
||||
InitializeRenderer();
|
||||
|
||||
_gpuVendorName = GetGpuVendorName();
|
||||
|
||||
Thread renderLoopThread = new Thread(Render)
|
||||
{
|
||||
Name = "GUI.RenderLoop"
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@@ -153,7 +153,8 @@ namespace Ryujinx.Memory
|
||||
|
||||
if (OperatingSystem.IsMacOSVersionAtLeast(10, 14))
|
||||
{
|
||||
result |= MAP_JIT_DARWIN;
|
||||
// Only to be used with the Hardened Runtime.
|
||||
// result |= MAP_JIT_DARWIN;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@@ -11,7 +11,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.8.0" />
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -122,14 +122,14 @@ namespace Ryujinx.Tests.Unicorn
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
Interface.Checked(Native.Interface.uc_close(uc));
|
||||
Interface.Checked(Interface.uc_close(uc));
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void RunForCount(ulong count)
|
||||
{
|
||||
Interface.Checked(Native.Interface.uc_emu_start(uc, this.PC, 0xFFFFFFFFFFFFFFFFu, 0, count));
|
||||
Interface.Checked(Interface.uc_emu_start(uc, this.PC, 0xFFFFFFFFFFFFFFFFu, 0, count));
|
||||
}
|
||||
|
||||
public void Step()
|
||||
@@ -222,7 +222,7 @@ namespace Ryujinx.Tests.Unicorn
|
||||
{
|
||||
byte[] data = new byte[4];
|
||||
|
||||
Interface.Checked(Native.Interface.uc_reg_read(uc, (int)register, data));
|
||||
Interface.Checked(Interface.uc_reg_read(uc, (int)register, data));
|
||||
|
||||
return (uint)BitConverter.ToInt32(data, 0);
|
||||
}
|
||||
|
@@ -111,14 +111,14 @@ namespace Ryujinx.Tests.Unicorn
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
Interface.Checked(Native.Interface.uc_close(uc));
|
||||
Interface.Checked(Interface.uc_close(uc));
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void RunForCount(ulong count)
|
||||
{
|
||||
Interface.Checked(Native.Interface.uc_emu_start(uc, this.PC, 0xFFFFFFFFFFFFFFFFu, 0, count));
|
||||
Interface.Checked(Interface.uc_emu_start(uc, this.PC, 0xFFFFFFFFFFFFFFFFu, 0, count));
|
||||
}
|
||||
|
||||
public void Step()
|
||||
@@ -241,7 +241,7 @@ namespace Ryujinx.Tests.Unicorn
|
||||
{
|
||||
byte[] data = new byte[8];
|
||||
|
||||
Interface.Checked(Native.Interface.uc_reg_read(uc, (int)register, data));
|
||||
Interface.Checked(Interface.uc_reg_read(uc, (int)register, data));
|
||||
|
||||
return (ulong)BitConverter.ToInt64(data, 0);
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@@ -25,14 +25,14 @@ namespace Ryujinx.Modules
|
||||
|
||||
public UpdateDialog(MainWindow mainWindow, Version newVersion, string buildUrl) : this(new Builder("Ryujinx.Modules.Updater.UpdateDialog.glade"), mainWindow, newVersion, buildUrl) { }
|
||||
|
||||
private UpdateDialog(Builder builder, MainWindow mainWindow, Version newVersion, string buildUrl) : base(builder.GetObject("UpdateDialog").Handle)
|
||||
private UpdateDialog(Builder builder, MainWindow mainWindow, Version newVersion, string buildUrl) : base(builder.GetRawOwnedObject("UpdateDialog"))
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
|
||||
_mainWindow = mainWindow;
|
||||
_buildUrl = buildUrl;
|
||||
|
||||
Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
|
||||
Icon = new Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
|
||||
MainText.Text = "Do you want to update Ryujinx to the latest version?";
|
||||
SecondaryText.Text = $"{Program.Version} -> {newVersion}";
|
||||
|
||||
|
@@ -293,7 +293,7 @@ namespace Ryujinx.Modules
|
||||
list[index] = args.Result;
|
||||
Interlocked.Increment(ref completedRequests);
|
||||
|
||||
if (Interlocked.Equals(completedRequests, ConnectionCount))
|
||||
if (Equals(completedRequests, ConnectionCount))
|
||||
{
|
||||
byte[] mergedFileBytes = new byte[_buildSize];
|
||||
for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
|
||||
|
@@ -16,6 +16,7 @@ using Ryujinx.Ui.Widgets;
|
||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
@@ -40,6 +41,12 @@ namespace Ryujinx
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern int MessageBoxA(IntPtr hWnd, string text, string caption, uint type);
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
static extern int setenv(string name, string value, int overwrite);
|
||||
|
||||
[DllImport("libc")]
|
||||
static extern IntPtr getenv(string name);
|
||||
|
||||
private const uint MB_ICONWARNING = 0x30;
|
||||
|
||||
static Program()
|
||||
@@ -97,6 +104,35 @@ namespace Ryujinx
|
||||
XInitThreads();
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
string baseDirectory = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
|
||||
string resourcesDataDir;
|
||||
|
||||
if (Path.GetFileName(baseDirectory) == "MacOS")
|
||||
{
|
||||
resourcesDataDir = Path.Combine(Directory.GetParent(baseDirectory).FullName, "Resources");
|
||||
}
|
||||
else
|
||||
{
|
||||
resourcesDataDir = baseDirectory;
|
||||
}
|
||||
|
||||
void SetEnvironmentVariableNoCaching(string key, string value)
|
||||
{
|
||||
int res = setenv(key, value, 1);
|
||||
Debug.Assert(res != -1);
|
||||
}
|
||||
|
||||
// On macOS, GTK3 needs XDG_DATA_DIRS to be set, otherwise it will try searching for "gschemas.compiled" in system directories.
|
||||
SetEnvironmentVariableNoCaching("XDG_DATA_DIRS", Path.Combine(resourcesDataDir, "share"));
|
||||
|
||||
// On macOS, GTK3 needs GDK_PIXBUF_MODULE_FILE to be set, otherwise it will try searching for "loaders.cache" in system directories.
|
||||
SetEnvironmentVariableNoCaching("GDK_PIXBUF_MODULE_FILE", Path.Combine(resourcesDataDir, "lib", "gdk-pixbuf-2.0", "2.10.0", "loaders.cache"));
|
||||
|
||||
SetEnvironmentVariableNoCaching("GTK_IM_MODULE_FILE", Path.Combine(resourcesDataDir, "lib", "gtk-3.0", "3.0.0", "immodules.cache"));
|
||||
}
|
||||
|
||||
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
|
||||
Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}");
|
||||
|
||||
@@ -115,7 +151,7 @@ namespace Ryujinx
|
||||
// Initialize SDL2 driver
|
||||
SDL2Driver.MainThreadDispatcher = action =>
|
||||
{
|
||||
Gtk.Application.Invoke(delegate
|
||||
Application.Invoke(delegate
|
||||
{
|
||||
action();
|
||||
});
|
||||
@@ -246,7 +282,7 @@ namespace Ryujinx
|
||||
? GraphicsBackend.Vulkan
|
||||
: GraphicsBackend.OpenGl;
|
||||
|
||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(ConfigurationPath);
|
||||
}
|
||||
|
||||
Application.Run();
|
||||
|
@@ -19,10 +19,12 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GtkSharp" Version="3.22.25.128" />
|
||||
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||
<PackageReference Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||
<PackageReference Include="GtkSharp.Dependencies.osx" Version="0.0.5" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build12" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win10-x64'" />
|
||||
<PackageReference Include="OpenTK.Core" Version="4.7.5" />
|
||||
<PackageReference Include="OpenTK.Graphics" Version="4.7.5" />
|
||||
<PackageReference Include="SPB" Version="0.0.4-build28" />
|
||||
@@ -46,14 +48,18 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<Content Include="..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>alsoft.ini</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="..\distribution\legal\THIRDPARTY.md">
|
||||
</Content>
|
||||
<Content Include="..\distribution\legal\THIRDPARTY.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
</Content>
|
||||
<Content Include="..\LICENSE.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>LICENSE.txt</TargetPath>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Due to .net core 3.1 embedded resource loading -->
|
||||
@@ -62,10 +68,6 @@
|
||||
<ApplicationIcon>Ryujinx.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64'">
|
||||
<DefineConstants>$(DefineConstants);MACOS_BUILD</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Ui\MainWindow.glade" />
|
||||
<None Remove="Ui\Widgets\ProfileDialog.glade" />
|
||||
|
134
Ryujinx/Ui/Helper/MetalHelper.cs
Normal file
134
Ryujinx/Ui/Helper/MetalHelper.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using Gdk;
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Ui.Helper
|
||||
{
|
||||
public delegate void UpdateBoundsCallbackDelegate(Window window);
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
static class MetalHelper
|
||||
{
|
||||
private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
|
||||
|
||||
private struct Selector
|
||||
{
|
||||
public readonly IntPtr NativePtr;
|
||||
|
||||
public unsafe Selector(string value)
|
||||
{
|
||||
int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
|
||||
byte* data = stackalloc byte[size];
|
||||
|
||||
fixed (char* pValue = value)
|
||||
{
|
||||
System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
|
||||
}
|
||||
|
||||
NativePtr = sel_registerName(data);
|
||||
}
|
||||
|
||||
public static implicit operator Selector(string value) => new Selector(value);
|
||||
}
|
||||
|
||||
private static unsafe IntPtr GetClass(string value)
|
||||
{
|
||||
int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
|
||||
byte* data = stackalloc byte[size];
|
||||
|
||||
fixed (char* pValue = value)
|
||||
{
|
||||
System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
|
||||
}
|
||||
|
||||
return objc_getClass(data);
|
||||
}
|
||||
|
||||
private struct NSPoint
|
||||
{
|
||||
public double X;
|
||||
public double Y;
|
||||
|
||||
public NSPoint(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
}
|
||||
|
||||
private struct NSRect
|
||||
{
|
||||
public NSPoint Pos;
|
||||
public NSPoint Size;
|
||||
|
||||
public NSRect(double x, double y, double width, double height)
|
||||
{
|
||||
Pos = new NSPoint(x, y);
|
||||
Size = new NSPoint(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr GetMetalLayer(Display display, Window window, out IntPtr nsView, out UpdateBoundsCallbackDelegate updateBounds)
|
||||
{
|
||||
nsView = gdk_quartz_window_get_nsview(window.Handle);
|
||||
|
||||
// Create a new CAMetalLayer.
|
||||
IntPtr layerClass = GetClass("CAMetalLayer");
|
||||
IntPtr metalLayer = IntPtr_objc_msgSend(layerClass, "alloc");
|
||||
objc_msgSend(metalLayer, "init");
|
||||
|
||||
// Create a child NSView to render into.
|
||||
IntPtr nsViewClass = GetClass("NSView");
|
||||
IntPtr child = IntPtr_objc_msgSend(nsViewClass, "alloc");
|
||||
objc_msgSend(child, "init", new NSRect());
|
||||
|
||||
// Add it as a child.
|
||||
objc_msgSend(nsView, "addSubview:", child);
|
||||
|
||||
// Make its renderer our metal layer.
|
||||
objc_msgSend(child, "setWantsLayer:", (byte)1);
|
||||
objc_msgSend(child, "setLayer:", metalLayer);
|
||||
objc_msgSend(metalLayer, "setContentsScale:", (double)display.GetMonitorAtWindow(window).ScaleFactor);
|
||||
|
||||
// Set the frame position/location.
|
||||
updateBounds = (Window window) => {
|
||||
window.GetPosition(out int x, out int y);
|
||||
int width = window.Width;
|
||||
int height = window.Height;
|
||||
objc_msgSend(child, "setFrame:", new NSRect(x, y, width, height));
|
||||
};
|
||||
|
||||
updateBounds(window);
|
||||
|
||||
return metalLayer;
|
||||
}
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static unsafe extern IntPtr sel_registerName(byte* data);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static unsafe extern IntPtr objc_getClass(byte* data);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, byte value);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
|
||||
|
||||
[DllImport(LibObjCImport)]
|
||||
private static extern void objc_msgSend(IntPtr receiver, Selector selector, double value);
|
||||
|
||||
[DllImport(LibObjCImport, EntryPoint = "objc_msgSend")]
|
||||
private static extern IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
|
||||
|
||||
[DllImport("libgdk-3.0.dylib")]
|
||||
private static extern IntPtr gdk_quartz_window_get_nsview(IntPtr gdkWindow);
|
||||
}
|
||||
}
|
@@ -142,7 +142,7 @@ namespace Ryujinx.Ui
|
||||
|
||||
public MainWindow() : this(new Builder("Ryujinx.Ui.MainWindow.glade")) { }
|
||||
|
||||
private MainWindow(Builder builder) : base(builder.GetObject("_mainWin").Handle)
|
||||
private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("_mainWin"))
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
|
||||
@@ -846,9 +846,7 @@ namespace Ryujinx.Ui
|
||||
_deviceExitStatus.Reset();
|
||||
|
||||
Translator.IsReadyForTranslation.Reset();
|
||||
#if MACOS_BUILD
|
||||
CreateGameWindow();
|
||||
#else
|
||||
|
||||
Thread windowThread = new Thread(() =>
|
||||
{
|
||||
CreateGameWindow();
|
||||
@@ -858,7 +856,6 @@ namespace Ryujinx.Ui
|
||||
};
|
||||
|
||||
windowThread.Start();
|
||||
#endif
|
||||
|
||||
_gameLoaded = true;
|
||||
_actionMenu.Sensitive = true;
|
||||
|
@@ -132,7 +132,7 @@ namespace Ryujinx.Ui
|
||||
|
||||
private void HideCursorStateChanged(object sender, ReactiveEventArgs<bool> state)
|
||||
{
|
||||
Gtk.Application.Invoke(delegate
|
||||
Application.Invoke(delegate
|
||||
{
|
||||
_hideCursorOnIdle = state.NewValue;
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace Ryujinx.Ui
|
||||
&& keyboard.IsPressed(Key.Enter))
|
||||
|| keyboard.IsPressed(Key.Escape);
|
||||
|
||||
bool fullScreenToggled = ParentWindow.State.HasFlag(Gdk.WindowState.Fullscreen);
|
||||
bool fullScreenToggled = ParentWindow.State.HasFlag(WindowState.Fullscreen);
|
||||
|
||||
if (toggleFullscreen != _toggleFullscreen)
|
||||
{
|
||||
@@ -340,7 +340,7 @@ namespace Ryujinx.Ui
|
||||
string directory = AppDataManager.Mode switch
|
||||
{
|
||||
AppDataManager.LaunchMode.Portable => System.IO.Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
|
||||
_ => System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures), "Ryujinx")
|
||||
_ => System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx")
|
||||
};
|
||||
|
||||
string path = System.IO.Path.Combine(directory, filename);
|
||||
@@ -434,7 +434,7 @@ namespace Ryujinx.Ui
|
||||
if (_ticks >= _ticksPerFrame)
|
||||
{
|
||||
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? "Docked" : "Handheld";
|
||||
float scale = Graphics.Gpu.GraphicsConfig.ResScale;
|
||||
float scale = GraphicsConfig.ResScale;
|
||||
if (scale != 1)
|
||||
{
|
||||
dockedMode += $" ({scale}x)";
|
||||
|
@@ -1,9 +1,11 @@
|
||||
using Gdk;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Input.HLE;
|
||||
using Ryujinx.Ui.Helper;
|
||||
using SPB.Graphics.Vulkan;
|
||||
using SPB.Platform.Win32;
|
||||
using SPB.Platform.X11;
|
||||
using SPB.Platform.Metal;
|
||||
using SPB.Windowing;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -13,6 +15,7 @@ namespace Ryujinx.Ui
|
||||
public class VKRenderer : RendererWidgetBase
|
||||
{
|
||||
public NativeWindowBase NativeWindow { get; private set; }
|
||||
private UpdateBoundsCallbackDelegate _updateBoundsCallback;
|
||||
|
||||
public VKRenderer(InputManager inputManager, GraphicsDebugLevel glLogLevel) : base(inputManager, glLogLevel) { }
|
||||
|
||||
@@ -31,6 +34,12 @@ namespace Ryujinx.Ui
|
||||
|
||||
return new SimpleX11Window(new NativeHandle(displayHandle), new NativeHandle(windowHandle));
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
IntPtr metalLayer = MetalHelper.GetMetalLayer(Display, Window, out IntPtr nsView, out _updateBoundsCallback);
|
||||
|
||||
return new SimpleMetalWindow(new NativeHandle(nsView), new NativeHandle(metalLayer));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -53,7 +62,11 @@ namespace Ryujinx.Ui
|
||||
WaitEvent.Set();
|
||||
}
|
||||
|
||||
return base.OnConfigureEvent(evnt);
|
||||
bool result = base.OnConfigureEvent(evnt);
|
||||
|
||||
_updateBoundsCallback?.Invoke(Window);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public unsafe IntPtr CreateWindowSurface(IntPtr instance)
|
||||
|
@@ -18,7 +18,7 @@ namespace Ryujinx.Ui.Widgets
|
||||
|
||||
public ProfileDialog() : this(new Builder("Ryujinx.Ui.Widgets.ProfileDialog.glade")) { }
|
||||
|
||||
private ProfileDialog(Builder builder) : base(builder.GetObject("_profileDialog").Handle)
|
||||
private ProfileDialog(Builder builder) : base(builder.GetRawOwnedObject("_profileDialog"))
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
|
||||
|
@@ -46,7 +46,7 @@ namespace Ryujinx.Ui.Windows
|
||||
SetDefaultSize(740, 400);
|
||||
SetPosition(WindowPosition.Center);
|
||||
|
||||
VBox vbox = new VBox(false, 0);
|
||||
Box vbox = new(Orientation.Vertical, 0);
|
||||
Add(vbox);
|
||||
|
||||
ScrolledWindow scrolledWindow = new ScrolledWindow
|
||||
@@ -55,7 +55,7 @@ namespace Ryujinx.Ui.Windows
|
||||
};
|
||||
scrolledWindow.SetPolicy(PolicyType.Automatic, PolicyType.Automatic);
|
||||
|
||||
HBox hbox = new HBox(false, 0);
|
||||
Box hbox = new(Orientation.Horizontal, 0);
|
||||
|
||||
Button chooseButton = new Button()
|
||||
{
|
||||
|
@@ -23,7 +23,7 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
public CheatWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.CheatWindow.glade"), virtualFileSystem, titleId, titleName) { }
|
||||
|
||||
private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) : base(builder.GetObject("_cheatWindow").Handle)
|
||||
private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName) : base(builder.GetRawOwnedObject("_cheatWindow"))
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
_baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]";
|
||||
|
@@ -119,7 +119,7 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
public ControllerWindow(MainWindow mainWindow, PlayerIndex controllerId) : this(mainWindow, new Builder("Ryujinx.Ui.Windows.ControllerWindow.glade"), controllerId) { }
|
||||
|
||||
private ControllerWindow(MainWindow mainWindow, Builder builder, PlayerIndex controllerId) : base(builder.GetObject("_controllerWin").Handle)
|
||||
private ControllerWindow(MainWindow mainWindow, Builder builder, PlayerIndex controllerId) : base(builder.GetRawOwnedObject("_controllerWin"))
|
||||
{
|
||||
_mainWindow = mainWindow;
|
||||
_selectedGamepad = null;
|
||||
@@ -379,13 +379,16 @@ namespace Ryujinx.Ui.Windows
|
||||
break;
|
||||
}
|
||||
|
||||
_controllerImage.Pixbuf = _controllerType.ActiveId switch
|
||||
if (!OperatingSystem.IsMacOS())
|
||||
{
|
||||
"ProController" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_ProCon.svg", 400, 400),
|
||||
"JoyconLeft" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConLeft.svg", 400, 500),
|
||||
"JoyconRight" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConRight.svg", 400, 500),
|
||||
_ => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConPair.svg", 400, 500),
|
||||
};
|
||||
_controllerImage.Pixbuf = _controllerType.ActiveId switch
|
||||
{
|
||||
"ProController" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_ProCon.svg", 400, 400),
|
||||
"JoyconLeft" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConLeft.svg", 400, 500),
|
||||
"JoyconRight" => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConRight.svg", 400, 500),
|
||||
_ => new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Controller_JoyConPair.svg", 400, 500),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearValues()
|
||||
|
@@ -34,7 +34,7 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
public DlcWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.DlcWindow.glade"), virtualFileSystem, titleId, titleName) { }
|
||||
|
||||
private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetObject("_dlcWindow").Handle)
|
||||
private DlcWindow(Builder builder, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_dlcWindow"))
|
||||
{
|
||||
builder.Autoconnect(this);
|
||||
|
||||
|
@@ -113,7 +113,7 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
public SettingsWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this(parent, new Builder("Ryujinx.Ui.Windows.SettingsWindow.glade"), virtualFileSystem, contentManager) { }
|
||||
|
||||
private SettingsWindow(MainWindow parent, Builder builder, VirtualFileSystem virtualFileSystem, ContentManager contentManager) : base(builder.GetObject("_settingsWin").Handle)
|
||||
private SettingsWindow(MainWindow parent, Builder builder, VirtualFileSystem virtualFileSystem, ContentManager contentManager) : base(builder.GetRawOwnedObject("_settingsWin"))
|
||||
{
|
||||
Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png");
|
||||
|
||||
@@ -422,7 +422,7 @@ namespace Ryujinx.Ui.Windows
|
||||
Task.Run(() =>
|
||||
{
|
||||
openAlIsSupported = OpenALHardwareDeviceDriver.IsSupported;
|
||||
soundIoIsSupported = SoundIoHardwareDeviceDriver.IsSupported;
|
||||
soundIoIsSupported = !OperatingSystem.IsMacOS() && SoundIoHardwareDeviceDriver.IsSupported;
|
||||
sdl2IsSupported = SDL2HardwareDeviceDriver.IsSupported;
|
||||
});
|
||||
|
||||
@@ -438,6 +438,15 @@ namespace Ryujinx.Ui.Windows
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
});
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
var store = (_graphicsBackend.Model as ListStore);
|
||||
store.GetIter(out TreeIter openglIter, new TreePath(new int[] {1}));
|
||||
store.Remove(ref openglIter);
|
||||
|
||||
_graphicsBackend.Model = store;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePreferredGpuComboBox()
|
||||
|
@@ -40,7 +40,7 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
public TitleUpdateWindow(MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : this(new Builder("Ryujinx.Ui.Windows.TitleUpdateWindow.glade"), parent, virtualFileSystem, titleId, titleName) { }
|
||||
|
||||
private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetObject("_titleUpdateWindow").Handle)
|
||||
private TitleUpdateWindow(Builder builder, MainWindow parent, VirtualFileSystem virtualFileSystem, string titleId, string titleName) : base(builder.GetRawOwnedObject("_titleUpdateWindow"))
|
||||
{
|
||||
_parent = parent;
|
||||
|
||||
|
@@ -52,7 +52,8 @@ namespace Ryujinx.Ui.Windows
|
||||
_selectedLabel = new Label("Selected User Profile:")
|
||||
{
|
||||
Margin = 15,
|
||||
Attributes = new AttrList()
|
||||
Attributes = new AttrList(),
|
||||
Halign = Align.Start
|
||||
};
|
||||
_selectedLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
|
||||
|
||||
@@ -136,7 +137,8 @@ namespace Ryujinx.Ui.Windows
|
||||
_availableUsersLabel = new Label("Available User Profiles:")
|
||||
{
|
||||
Margin = 15,
|
||||
Attributes = new AttrList()
|
||||
Attributes = new AttrList(),
|
||||
Halign = Align.Start
|
||||
};
|
||||
_availableUsersLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
|
||||
|
||||
@@ -226,10 +228,9 @@ namespace Ryujinx.Ui.Windows
|
||||
_usersTreeViewWindow.Add(_usersTreeView);
|
||||
|
||||
_usersTreeViewBox.Add(_usersTreeViewWindow);
|
||||
|
||||
_bottomBox.PackStart(new Gtk.Alignment(-1, 0, 0, 0) { _addButton }, false, false, 0);
|
||||
_bottomBox.PackStart(new Gtk.Alignment(-1, 0, 0, 0) { _deleteButton }, false, false, 0);
|
||||
_bottomBox.PackEnd(new Gtk.Alignment(1, 0, 0, 0) { _closeButton }, false, false, 0);
|
||||
_bottomBox.PackStart(_addButton, false, false, 0);
|
||||
_bottomBox.PackStart(_deleteButton, false, false, 0);
|
||||
_bottomBox.PackEnd(_closeButton, false, false, 0);
|
||||
|
||||
_selectedUserInfoBox.Add(_selectedUserNameEntry);
|
||||
_selectedUserInfoBox.Add(_selectedUserIdLabel);
|
||||
@@ -238,12 +239,12 @@ namespace Ryujinx.Ui.Windows
|
||||
_selectedUserButtonsBox.Add(_changeProfileImageButton);
|
||||
|
||||
_selectedUserBox.Add(_selectedUserImage);
|
||||
_selectedUserBox.PackStart(new Gtk.Alignment(-1, 0, 0, 0) { _selectedUserInfoBox }, true, true, 0);
|
||||
_selectedUserBox.Add(_selectedUserButtonsBox);
|
||||
_selectedUserBox.PackStart(_selectedUserInfoBox, false, false, 0);
|
||||
_selectedUserBox.PackEnd(_selectedUserButtonsBox, false, false, 0);
|
||||
|
||||
_mainBox.PackStart(new Gtk.Alignment(-1, 0, 0, 0) { _selectedLabel }, false, false, 0);
|
||||
_mainBox.PackStart(_selectedLabel, false, false, 0);
|
||||
_mainBox.PackStart(_selectedUserBox, false, true, 0);
|
||||
_mainBox.PackStart(new Gtk.Alignment(-1, 0, 0, 0) { _availableUsersLabel }, false, false, 0);
|
||||
_mainBox.PackStart(_availableUsersLabel, false, false, 0);
|
||||
_mainBox.Add(_usersTreeViewBox);
|
||||
_mainBox.Add(_bottomBox);
|
||||
|
||||
|
Reference in New Issue
Block a user