Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
b2aed882d6 nuget: bump Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK
Bumps Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK from 1.2.0 to 1.2.3.

---
updated-dependencies:
- dependency-name: Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-31 07:09:40 +00:00
127 changed files with 1915 additions and 2627 deletions

View File

@@ -1,19 +0,0 @@
name: Missing Shader Instruction
description: Shader Instruction is missing in Ryujinx.
title: "[GPU]"
labels: [gpu, not-implemented]
body:
- type: textarea
id: instruction
attributes:
label: Shader instruction
description: What shader instruction is missing?
validations:
required: true
- type: textarea
id: required
attributes:
label: Required by
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this instruction.
validations:
required: true

View File

@@ -18,10 +18,6 @@ on:
- '*.yml'
- 'README.md'
concurrency:
group: pr-checks-${{ github.event.number }}
cancel-in-progress: true
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
DOTNET_CLI_TELEMETRY_OPTOUT: 1

View File

@@ -13,7 +13,7 @@
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="1.1.7" />
<PackageVersion Include="DiscordRichPresence" Version="1.1.3.18" />
<PackageVersion Include="DynamicData" Version="7.14.2" />
<PackageVersion Include="DynamicData" Version="7.13.8" />
<PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" />
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
@@ -21,7 +21,7 @@
<PackageVersion Include="LibHac" Version="0.18.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NUnit" Version="3.13.3" />
@@ -32,7 +32,7 @@
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.7" />
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.3" />
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.26.3-build25" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
@@ -44,7 +44,7 @@
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageVersion Include="SPB" Version="0.0.4-build28" />
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.30.1" />
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
<PackageVersion Include="System.Management" Version="7.0.1" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />

View File

@@ -6,11 +6,10 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace ARMeilleure.Translation.Cache
{
static partial class JitCache
static class JitCache
{
private const int PageSize = 4 * 1024;
private const int PageMask = PageSize - 1;
@@ -28,10 +27,6 @@ namespace ARMeilleure.Translation.Cache
private static readonly object _lock = new object();
private static bool _initialized;
[SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)]
public static partial IntPtr FlushInstructionCache(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize);
public static void Initialize(IJitMemoryAllocator allocator)
{
if (_initialized) return;
@@ -41,11 +36,7 @@ namespace ARMeilleure.Translation.Cache
if (_initialized) return;
_jitRegion = new ReservedRegion(allocator, CacheSize);
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
{
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
}
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
@@ -86,14 +77,7 @@ namespace ARMeilleure.Translation.Cache
Marshal.Copy(code, 0, funcPtr, code.Length);
ReprotectAsExecutable(funcOffset, code.Length);
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (UIntPtr)code.Length);
}
else
{
_jitCacheInvalidator?.Invalidate(funcPtr, (ulong)code.Length);
}
_jitCacheInvalidator.Invalidate(funcPtr, (ulong)code.Length);
}
Add(funcOffset, code.Length, func.UnwindInfo);

View File

@@ -47,8 +47,8 @@ namespace ARMeilleure.Translation.Cache
public JitCacheInvalidation(IJitMemoryAllocator allocator)
{
// On macOS and Windows, a different path is used to write to the JIT cache, which does the invalidation.
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
// On macOS, a different path is used to write to the JIT cache, which does the invalidation.
if (!OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
ulong size = (ulong)_invalidationCode.Length * sizeof(int);
ulong mask = (ulong)ReservedRegion.DefaultGranularity - 1;

View File

@@ -92,8 +92,6 @@ namespace Ryujinx.Ava
private bool _isActive;
private bool _renderingStarted;
private ManualResetEvent _gpuDoneEvent;
private IRenderer _renderer;
private readonly Thread _renderingThread;
private readonly CancellationTokenSource _gpuCancellationTokenSource;
@@ -185,7 +183,6 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
_gpuCancellationTokenSource = new CancellationTokenSource();
_gpuDoneEvent = new ManualResetEvent(false);
}
private void TopLevel_PointerEnterOrMoved(object sender, PointerEventArgs e)
@@ -426,10 +423,10 @@ namespace Ryujinx.Ava
_isActive = false;
// NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose.
// We only need to wait for all commands submitted during the main gpu loop to be processed.
_gpuDoneEvent.WaitOne();
_gpuDoneEvent.Dispose();
if (_renderingThread.IsAlive)
{
_renderingThread.Join();
}
DisplaySleep.Restore();
@@ -920,14 +917,6 @@ namespace Ryujinx.Ava
UpdateStatus();
}
}
// Make sure all commands in the run loop are fully executed before leaving the loop.
if (Device.Gpu.Renderer is ThreadedRenderer threaded)
{
threaded.FlushThreadedCommands();
}
_gpuDoneEvent.Set();
});
(_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(null);

View File

@@ -544,9 +544,6 @@
"SwkbdMinCharacters": "Must be at least {0} characters long",
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
"SoftwareKeyboard": "Software Keyboard",
"SoftwareKeyboardModeNumbersOnly": "Must be numbers only",
"SoftwareKeyboardModeAlphabet": "Must be non CJK-characters only",
"SoftwareKeyboardModeASCII": "Must be ASCII text only",
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",

View File

@@ -527,9 +527,6 @@
"SwkbdMinCharacters": "至少应为 {0} 个字长",
"SwkbdMinRangeCharacters": "必须为 {0}-{1} 个字长",
"SoftwareKeyboard": "软件键盘",
"SoftwareKeyboardModeNumbersOnly": "只接受数字",
"SoftwareKeyboardModeAlphabet": "只接受英文字母",
"SoftwareKeyboardModeASCII": "只接受 ASCII 符号",
"DialogControllerAppletMessagePlayerRange": "游戏需要 {0} 个玩家并满足以下要求:\n\n手柄类型{1}\n\n玩家类型{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
"DialogControllerAppletMessage": "游戏需要刚好 {0} 个玩家并满足以下要求:\n\n手柄类型{1}\n\n玩家类型{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
"DialogControllerAppletDockModeSet": "目前处于主机模式,无法使用掌机操作方式",

View File

@@ -527,9 +527,6 @@
"SwkbdMinCharacters": "至少應為 {0} 個字長",
"SwkbdMinRangeCharacters": "必須為 {0}-{1} 個字長",
"SoftwareKeyboard": "軟體鍵盤",
"SoftwareKeyboardModeNumbersOnly": "只接受數字",
"SoftwareKeyboardModeAlphabet": "只接受英文字母",
"SoftwareKeyboardModeASCII": "只接受 ASCII 符號",
"DialogControllerAppletMessagePlayerRange": "本遊戲需要 {0} 個玩家持有:\n\n類型{1}\n\n玩家{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
"DialogControllerAppletMessage": "本遊戲需要剛好 {0} 個玩家持有:\n\n類型{1}\n\n玩家{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
"DialogControllerAppletDockModeSet": "現在處於主機模式,無法使用掌機操作方式\n\n",

View File

@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using FluentAvalonia.Core;
using Ryujinx.Input;
using System;
using System.Numerics;
@@ -29,14 +30,14 @@ namespace Ryujinx.Ava.Input
_window = window;
_widget.PointerMoved += Parent_PointerMovedEvent;
_widget.PointerPressed += Parent_PointerPressedEvent;
_widget.PointerReleased += Parent_PointerReleasedEvent;
_widget.PointerWheelChanged += Parent_PointerWheelChanged;
_widget.PointerPressed += Parent_PointerPressEvent;
_widget.PointerReleased += Parent_PointerReleaseEvent;
_widget.PointerWheelChanged += Parent_ScrollEvent;
_window.PointerMoved += Parent_PointerMovedEvent;
_window.PointerPressed += Parent_PointerPressedEvent;
_window.PointerReleased += Parent_PointerReleasedEvent;
_window.PointerWheelChanged += Parent_PointerWheelChanged;
_window.PointerPressed += Parent_PointerPressEvent;
_window.PointerReleased += Parent_PointerReleaseEvent;
_window.PointerWheelChanged += Parent_ScrollEvent;
PressedButtons = new bool[(int)MouseButton.Count];
@@ -62,25 +63,29 @@ namespace Ryujinx.Ava.Input
_size = new Size((int)rect.Width, (int)rect.Height);
}
private void Parent_PointerWheelChanged(object o, PointerWheelEventArgs args)
private void Parent_ScrollEvent(object o, PointerWheelEventArgs args)
{
Scroll = new Vector2((float)args.Delta.X, (float)args.Delta.Y);
}
private void Parent_PointerReleasedEvent(object o, PointerReleasedEventArgs args)
private void Parent_PointerReleaseEvent(object o, PointerReleasedEventArgs args)
{
uint button = (uint)args.InitialPressMouseButton - 1;
if ((uint)PressedButtons.Length > button)
if (args.InitialPressMouseButton != Avalonia.Input.MouseButton.None)
{
PressedButtons[button] = false;
int button = (int)args.InitialPressMouseButton;
if (PressedButtons.Count() >= button)
{
PressedButtons[button] = false;
}
}
}
private void Parent_PointerPressedEvent(object o, PointerPressedEventArgs args)
{
uint button = (uint)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind;
if ((uint)PressedButtons.Length > button)
private void Parent_PointerPressEvent(object o, PointerPressedEventArgs args)
{
int button = (int)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind;
if (PressedButtons.Count() >= button)
{
PressedButtons[button] = true;
}
@@ -95,17 +100,17 @@ namespace Ryujinx.Ava.Input
public void SetMousePressed(MouseButton button)
{
if ((uint)PressedButtons.Length > (uint)button)
if (PressedButtons.Count() >= (int)button)
{
PressedButtons[(uint)button] = true;
PressedButtons[(int)button] = true;
}
}
public void SetMouseReleased(MouseButton button)
{
if ((uint)PressedButtons.Length > (uint)button)
if (PressedButtons.Count() >= (int)button)
{
PressedButtons[(uint)button] = false;
PressedButtons[(int)button] = false;
}
}
@@ -116,9 +121,9 @@ namespace Ryujinx.Ava.Input
public bool IsButtonPressed(MouseButton button)
{
if ((uint)PressedButtons.Length > (uint)button)
if (PressedButtons.Count() >= (int)button)
{
return PressedButtons[(uint)button];
return PressedButtons[(int)button];
}
return false;
@@ -144,14 +149,14 @@ namespace Ryujinx.Ava.Input
_isDisposed = true;
_widget.PointerMoved -= Parent_PointerMovedEvent;
_widget.PointerPressed -= Parent_PointerPressedEvent;
_widget.PointerReleased -= Parent_PointerReleasedEvent;
_widget.PointerWheelChanged -= Parent_PointerWheelChanged;
_widget.PointerPressed -= Parent_PointerPressEvent;
_widget.PointerReleased -= Parent_PointerReleaseEvent;
_widget.PointerWheelChanged -= Parent_ScrollEvent;
_window.PointerMoved -= Parent_PointerMovedEvent;
_window.PointerPressed -= Parent_PointerPressedEvent;
_window.PointerReleased -= Parent_PointerReleasedEvent;
_window.PointerWheelChanged -= Parent_PointerWheelChanged;
_window.PointerPressed -= Parent_PointerPressEvent;
_window.PointerReleased -= Parent_PointerReleaseEvent;
_window.PointerWheelChanged -= Parent_ScrollEvent;
_widget = null;
}

View File

@@ -740,18 +740,6 @@ namespace Ryujinx.Modules
{
var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir.
// Determine and exclude user files only when the updater is running, not when cleaning old files
if (_running)
{
// Compare the loose files in base directory against the loose files from the incoming update, and store foreign ones in a user list.
var oldFiles = Directory.EnumerateFiles(HomeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
var newFiles = Directory.EnumerateFiles(UpdatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(HomeDir, filename));
// Remove user files from the paths in files.
files = files.Except(userFiles);
}
if (OperatingSystem.IsWindows())
{
foreach (string dir in WindowsDependencyDirs)

View File

@@ -9,17 +9,14 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Controls
{
internal partial class SwkbdAppletDialog : UserControl
{
private Predicate<int> _checkLength = _ => true;
private Predicate<string> _checkInput = _ => true;
private Predicate<int> _checkLength;
private int _inputMax;
private int _inputMin;
private string _placeholder;
@@ -38,6 +35,8 @@ namespace Ryujinx.Ava.UI.Controls
Input.Watermark = _placeholder;
Input.AddHandler(TextInputEvent, Message_TextInput, RoutingStrategies.Tunnel, true);
SetInputLengthValidation(0, int.MaxValue); // Disable by default.
}
public SwkbdAppletDialog()
@@ -68,7 +67,6 @@ namespace Ryujinx.Ava.UI.Controls
string input = string.Empty;
content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
content.SetInputValidation(args.KeyboardMode);
content._host = contentDialog;
contentDialog.Title = title;
@@ -93,12 +91,6 @@ namespace Ryujinx.Ava.UI.Controls
return (result, input);
}
private void ApplyValidationInfo(string text)
{
Error.IsVisible = !string.IsNullOrEmpty(text);
Error.Text = text;
}
public void SetInputLengthValidation(int min, int max)
{
_inputMin = Math.Min(min, max);
@@ -107,8 +99,6 @@ namespace Ryujinx.Ava.UI.Controls
Error.IsVisible = false;
Error.FontStyle = FontStyle.Italic;
string validationInfoText = "";
if (_inputMin <= 0 && _inputMax == int.MaxValue) // Disable.
{
Error.IsVisible = false;
@@ -117,48 +107,21 @@ namespace Ryujinx.Ava.UI.Controls
}
else if (_inputMin > 0 && _inputMax == int.MaxValue)
{
validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin);
Error.IsVisible = true;
Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin);
_checkLength = length => _inputMin <= length;
}
else
{
validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax);
Error.IsVisible = true;
Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax);
_checkLength = length => _inputMin <= length && length <= _inputMax;
}
ApplyValidationInfo(validationInfoText);
Message_TextInput(this, new TextInputEventArgs());
}
private void SetInputValidation(KeyboardMode mode)
{
string validationInfoText = Error.Text;
string localeText;
switch (mode)
{
case KeyboardMode.NumbersOnly:
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeNumbersOnly);
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
_checkInput = text => text.All(char.IsDigit);
break;
case KeyboardMode.Alphabet:
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeAlphabet);
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
_checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
break;
case KeyboardMode.ASCII:
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeASCII);
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
_checkInput = text => text.All(char.IsAscii);
break;
default:
_checkInput = _ => true;
break;
}
ApplyValidationInfo(validationInfoText);
Message_TextInput(this, new TextInputEventArgs());
}
@@ -166,7 +129,7 @@ namespace Ryujinx.Ava.UI.Controls
{
if (_host != null)
{
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length);
}
}
@@ -178,7 +141,7 @@ namespace Ryujinx.Ava.UI.Controls
}
else
{
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length);
}
}
}

View File

@@ -32,10 +32,10 @@
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<flex:FlexPanel
HorizontalAlignment="Center"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AlignContent="FlexStart"
JustifyContent="FlexStart" />
JustifyContent="Center" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>

View File

@@ -21,7 +21,6 @@ namespace Ryujinx.Ava.UI.Helpers
if (value is byte[] buffer && targetType == typeof(IImage))
{
MemoryStream mem = new(buffer);
return new Bitmap(mem);
}

View File

@@ -318,7 +318,7 @@ namespace Ryujinx.Ava.UI.Helpers
Window parent = GetMainWindow();
if (parent != null && parent.IsActive && (parent as MainWindow).ViewModel.IsGameRunning)
if (parent is { IsActive: true } and MainWindow window && window.ViewModel.IsGameRunning)
{
contentDialogOverlayWindow = new()
{

View File

@@ -257,7 +257,6 @@ namespace Ryujinx.Ava.UI.ViewModels
OnPropertyChanged();
OnPropertyChanged(nameof(EnableNonGameRunningControls));
OnPropertyChanged(nameof(IsAppletMenuActive));
OnPropertyChanged(nameof(StatusBarVisible));
OnPropertyChanged(nameof(ShowFirmwareStatus));
}

View File

@@ -9,7 +9,9 @@ using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS;
using Ryujinx.Modules;
using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;

View File

@@ -16,7 +16,6 @@
</Design.DataContext>
<DockPanel
Margin="0,0,0,5"
Height="35"
HorizontalAlignment="Stretch">
<Button
Width="40"

View File

@@ -58,20 +58,11 @@
JustifyContent="SpaceAround"
RowSpacing="2">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="28"
FontWeight="Bold"
Text="Ryujinx"
TextAlignment="Center"
Width="100" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="11"
Text="(REE-YOU-JINX)"
TextAlignment="Center"
Width="100" />
TextAlignment="Left" />
<TextBlock Text="(REE-YOU-JINX)" TextAlignment="Left" />
</flex:FlexPanel>
</Grid>
<TextBlock

View File

@@ -519,14 +519,14 @@ namespace Ryujinx.Ava.UI.Windows
private void ConfirmExit()
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
ViewModel.IsClosing = await ContentDialogHelper.CreateExitDialog();
{
ViewModel.IsClosing = await ContentDialogHelper.CreateExitDialog();
if (ViewModel.IsClosing)
{
Close();
}
});
if (ViewModel.IsClosing)
{
Close();
}
});
}
public async void LoadApplications()

View File

@@ -1,7 +1,6 @@
using System.Diagnostics;
using System.Text;
using System.Text;
namespace Ryujinx.Common.Logging.Formatters
namespace Ryujinx.Common.Logging
{
internal class DefaultLogFormatter : ILogFormatter
{
@@ -28,14 +27,6 @@ namespace Ryujinx.Common.Logging.Formatters
if (args.Data is not null)
{
if (args.Data is StackTrace trace)
{
sb.Append('\n');
sb.Append(trace);
return sb.ToString();
}
sb.Append(' ');
DynamicObjectFormatter.Format(sb, args.Data);
}
@@ -48,4 +39,4 @@ namespace Ryujinx.Common.Logging.Formatters
}
}
}
}
}

View File

@@ -3,9 +3,9 @@ using System;
using System.Reflection;
using System.Text;
namespace Ryujinx.Common.Logging.Formatters
namespace Ryujinx.Common.Logging
{
internal static class DynamicObjectFormatter
internal class DynamicObjectFormatter
{
private static readonly ObjectPool<StringBuilder> StringBuilderPool = SharedPools.Default<StringBuilder>();
@@ -17,7 +17,7 @@ namespace Ryujinx.Common.Logging.Formatters
}
StringBuilder sb = StringBuilderPool.Allocate();
try
{
Format(sb, dynamicObject);

View File

@@ -1,7 +1,7 @@
namespace Ryujinx.Common.Logging.Formatters
namespace Ryujinx.Common.Logging
{
interface ILogFormatter
{
string Format(LogEventArgs args);
}
}
}

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Logging.Formatters;
using System;
using System;
using System.Text.Json.Serialization;
namespace Ryujinx.Common.Logging

View File

@@ -1,4 +1,3 @@
using Ryujinx.Common.Logging.Targets;
using Ryujinx.Common.SystemInterop;
using System;
using System.Collections.Generic;
@@ -56,16 +55,6 @@ namespace Ryujinx.Common.Logging
}
}
[StackTraceHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintStack(LogClass logClass, string message, [CallerMemberName] string caller = "")
{
if (m_EnabledClasses[(int)logClass])
{
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), new StackTrace(true)));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintStub(LogClass logClass, string message = "", [CallerMemberName] string caller = "")
{
@@ -133,7 +122,7 @@ namespace Ryujinx.Common.Logging
AsyncLogTargetOverflowAction.Discard));
Notice = new Log(LogLevel.Notice);
// Enable important log levels before configuration is loaded
Error = new Log(LogLevel.Error);
Warning = new Log(LogLevel.Warning);
@@ -232,4 +221,4 @@ namespace Ryujinx.Common.Logging
m_EnabledClasses[(int)logClass] = enabled;
}
}
}
}

View File

@@ -2,7 +2,7 @@
using System.Collections.Concurrent;
using System.Threading;
namespace Ryujinx.Common.Logging.Targets
namespace Ryujinx.Common.Logging
{
public enum AsyncLogTargetOverflowAction
{

View File

@@ -1,7 +1,6 @@
using Ryujinx.Common.Logging.Formatters;
using System;
using System;
namespace Ryujinx.Common.Logging.Targets
namespace Ryujinx.Common.Logging
{
public class ConsoleLogTarget : ILogTarget
{
@@ -39,4 +38,4 @@ namespace Ryujinx.Common.Logging.Targets
Console.ResetColor();
}
}
}
}

View File

@@ -1,9 +1,8 @@
using Ryujinx.Common.Logging.Formatters;
using System;
using System;
using System.IO;
using System.Linq;
namespace Ryujinx.Common.Logging.Targets
namespace Ryujinx.Common.Logging
{
public class FileLogTarget : ILogTarget
{

View File

@@ -1,6 +1,6 @@
using System;
namespace Ryujinx.Common.Logging.Targets
namespace Ryujinx.Common.Logging
{
public interface ILogTarget : IDisposable
{

View File

@@ -1,7 +1,7 @@
using Ryujinx.Common.Utilities;
using System.IO;
namespace Ryujinx.Common.Logging.Targets
namespace Ryujinx.Common.Logging
{
public class JsonLogTarget : ILogTarget
{

View File

@@ -1,5 +1,4 @@
#nullable enable
using Ryujinx.Common.Logging;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -19,14 +18,12 @@ namespace Ryujinx.Common.Utilities
public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var enumValue = reader.GetString();
if (Enum.TryParse(enumValue, out TEnum value))
if (string.IsNullOrEmpty(enumValue))
{
return value;
return default;
}
Logger.Warning?.Print(LogClass.Configuration, $"Failed to parse enum value \"{enumValue}\" for {typeof(TEnum)}, using default \"{default(TEnum)}\"");
return default;
return Enum.Parse<TEnum>(enumValue);
}
public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
@@ -34,4 +31,4 @@ namespace Ryujinx.Common.Utilities
writer.WriteStringValue(value.ToString());
}
}
}
}

View File

@@ -34,8 +34,6 @@ namespace Ryujinx.Graphics.GAL
public readonly bool SupportsCubemapView;
public readonly bool SupportsNonConstantTextureOffset;
public readonly bool SupportsShaderBallot;
public readonly bool SupportsShaderBarrierDivergence;
public readonly bool SupportsShaderFloat64;
public readonly bool SupportsTextureShadowLod;
public readonly bool SupportsViewportIndexVertexTessellation;
public readonly bool SupportsViewportMask;
@@ -83,8 +81,6 @@ namespace Ryujinx.Graphics.GAL
bool supportsCubemapView,
bool supportsNonConstantTextureOffset,
bool supportsShaderBallot,
bool supportsShaderBarrierDivergence,
bool supportsShaderFloat64,
bool supportsTextureShadowLod,
bool supportsViewportIndexVertexTessellation,
bool supportsViewportMask,
@@ -128,8 +124,6 @@ namespace Ryujinx.Graphics.GAL
SupportsCubemapView = supportsCubemapView;
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
SupportsShaderBallot = supportsShaderBallot;
SupportsShaderBarrierDivergence = supportsShaderBarrierDivergence;
SupportsShaderFloat64 = supportsShaderFloat64;
SupportsTextureShadowLod = supportsTextureShadowLod;
SupportsViewportIndexVertexTessellation = supportsViewportIndexVertexTessellation;
SupportsViewportMask = supportsViewportMask;

View File

@@ -383,7 +383,6 @@ namespace Ryujinx.Graphics.GAL
case Format.R10G10B10A2Unorm:
case Format.R10G10B10A2Uint:
case Format.R11G11B10Float:
case Format.B8G8R8A8Unorm:
return true;
}

View File

@@ -1,6 +1,5 @@
using Ryujinx.Common.Configuration;
using System;
using System.Threading;
namespace Ryujinx.Graphics.GAL
{
@@ -53,7 +52,7 @@ namespace Ryujinx.Graphics.GAL
void ResetCounter(CounterType type);
void RunLoop(ThreadStart gpuLoop)
void RunLoop(Action gpuLoop)
{
gpuLoop();
}

View File

@@ -30,6 +30,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
private IRenderer _baseRenderer;
private Thread _gpuThread;
private Thread _backendThread;
private bool _disposed;
private bool _running;
private AutoResetEvent _frameComplete = new AutoResetEvent(true);
@@ -97,17 +98,19 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_refQueue = new object[MaxRefsPerCommand * QueueCount];
}
public void RunLoop(ThreadStart gpuLoop)
public void RunLoop(Action gpuLoop)
{
_running = true;
_backendThread = Thread.CurrentThread;
_gpuThread = new Thread(gpuLoop)
{
Name = "GPU.MainThread"
};
_gpuThread = new Thread(() => {
gpuLoop();
_running = false;
_galWorkAvailable.Set();
});
_gpuThread.Name = "GPU.MainThread";
_gpuThread.Start();
RenderLoop();
@@ -117,7 +120,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
{
// Power through the render queue until the Gpu thread work is done.
while (_running)
while (_running && !_disposed)
{
_galWorkAvailable.Wait();
_galWorkAvailable.Reset();
@@ -485,23 +488,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading
return _baseRenderer.PrepareHostMapping(address, size);
}
public void FlushThreadedCommands()
{
SpinWait wait = new();
while (Volatile.Read(ref _commandCount) > 0)
{
wait.SpinOnce();
}
}
public void Dispose()
{
// Dispose must happen from the render thread, after all commands have completed.
// Stop the GPU thread.
_running = false;
_galWorkAvailable.Set();
_disposed = true;
if (_gpuThread != null && _gpuThread.IsAlive)
{

View File

@@ -63,8 +63,6 @@ namespace Ryujinx.Graphics.GAL
public bool PrimitiveRestartEnable;
public uint PatchControlPoints;
public DepthMode DepthMode;
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
{
VertexAttribCount = vertexAttribs.Length;

View File

@@ -80,6 +80,11 @@ namespace Ryujinx.Graphics.Gpu
/// </summary>
public const int GobAlignment = 64;
/// <summary>
/// Expected byte alignment for storage buffers
/// </summary>
public const int StorageAlignment = 16;
/// <summary>
/// Number of the uniform buffer reserved by the driver to store the storage buffer base addresses.
/// </summary>

View File

@@ -151,6 +151,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
ShaderProgramInfo info = cs.Shaders[0].Info;
bool hasUnaligned = _channel.BufferManager.HasUnalignedStorageBuffers;
for (int index = 0; index < info.SBuffers.Count; index++)
{
BufferDescriptor sb = info.SBuffers[index];
@@ -175,17 +177,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
_channel.BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), size, sb.Flags);
}
if (_channel.BufferManager.HasUnalignedStorageBuffers != computeState.HasUnalignedStorageBuffer)
if ((_channel.BufferManager.HasUnalignedStorageBuffers) != hasUnaligned)
{
// Refetch the shader, as assumptions about storage buffer alignment have changed.
computeState = new GpuChannelComputeState(
qmd.CtaThreadDimension0,
qmd.CtaThreadDimension1,
qmd.CtaThreadDimension2,
localMemorySize,
sharedMemorySize,
_channel.BufferManager.HasUnalignedStorageBuffers);
cs = memoryManager.Physical.ShaderCache.GetComputeShader(_channel, poolState, computeState, shaderGpuVa);
_context.Renderer.Pipeline.SetProgram(cs.HostProgram);
@@ -193,6 +187,30 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
info = cs.Shaders[0].Info;
}
for (int index = 0; index < info.CBuffers.Count; index++)
{
BufferDescriptor cb = info.CBuffers[index];
// NVN uses the "hardware" constant buffer for anything that is less than 8,
// and those are already bound above.
// Anything greater than or equal to 8 uses the emulated constant buffers.
// They are emulated using global memory loads.
if (cb.Slot < 8)
{
continue;
}
ulong cbDescAddress = _channel.BufferManager.GetComputeUniformBufferAddress(0);
int cbDescOffset = 0x260 + (cb.Slot - 8) * 0x10;
cbDescAddress += (ulong)cbDescOffset;
SbDescriptor cbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(cbDescAddress);
_channel.BufferManager.SetComputeUniformBuffer(cb.Slot, cbDescriptor.PackAddress(), (uint)cbDescriptor.Size);
}
_channel.BufferManager.SetComputeBufferBindings(cs.Bindings);
_channel.TextureManager.SetComputeBindings(cs.Bindings);

View File

@@ -100,22 +100,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
{
#pragma warning disable CS0649
public uint SetObject;
public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63];
public uint NoOperation;
public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF);
public uint SetNotifyB;
public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify);
public uint WaitForIdle;
public fixed uint Reserved114[7];
public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF);
public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7);
public uint SendGoIdle;
public uint PmTrigger;
public uint PmTriggerWfi;
@@ -126,11 +126,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint LineLengthIn;
public uint LineCount;
public uint OffsetOutUpper;
public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF);
public uint OffsetOut;
public uint PitchOut;
public uint SetDstBlockSize;
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF);
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public uint SetDstWidth;
@@ -138,11 +138,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetDstDepth;
public uint SetDstLayer;
public uint SetDstOriginBytesX;
public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF);
public uint SetDstOriginSamplesY;
public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF);
public uint LaunchDma;
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1);
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);
@@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint LoadInlineData;
public fixed uint Reserved1B8[9];
public uint SetI2mSemaphoreA;
public int SetI2mSemaphoreAOffsetUpper => (int)(SetI2mSemaphoreA & 0xFF);
public int SetI2mSemaphoreAOffsetUpper => (int)((SetI2mSemaphoreA >> 0) & 0xFF);
public uint SetI2mSemaphoreB;
public uint SetI2mSemaphoreC;
public fixed uint Reserved1E8[2];
@@ -162,7 +162,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetI2mSpareNoop02;
public uint SetI2mSpareNoop03;
public uint SetValidSpanOverflowAreaA;
public int SetValidSpanOverflowAreaAAddressUpper => (int)(SetValidSpanOverflowAreaA & 0xFF);
public int SetValidSpanOverflowAreaAAddressUpper => (int)((SetValidSpanOverflowAreaA >> 0) & 0xFF);
public uint SetValidSpanOverflowAreaB;
public uint SetValidSpanOverflowAreaC;
public uint SetCoalesceWaitingPeriodUnit;
@@ -185,12 +185,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetReservedSwMethod06;
public uint SetReservedSwMethod07;
public uint SetCwdControl;
public SetCwdControlSmSelection SetCwdControlSmSelection => (SetCwdControlSmSelection)(SetCwdControl & 0x1);
public SetCwdControlSmSelection SetCwdControlSmSelection => (SetCwdControlSmSelection)((SetCwdControl >> 0) & 0x1);
public uint InvalidateTextureHeaderCacheNoWfi;
public InvalidateCacheLines InvalidateTextureHeaderCacheNoWfiLines => (InvalidateCacheLines)(InvalidateTextureHeaderCacheNoWfi & 0x1);
public InvalidateCacheLines InvalidateTextureHeaderCacheNoWfiLines => (InvalidateCacheLines)((InvalidateTextureHeaderCacheNoWfi >> 0) & 0x1);
public int InvalidateTextureHeaderCacheNoWfiTag => (int)((InvalidateTextureHeaderCacheNoWfi >> 4) & 0x3FFFFF);
public uint SetCwdRefCounter;
public int SetCwdRefCounterSelect => (int)(SetCwdRefCounter & 0x3F);
public int SetCwdRefCounterSelect => (int)((SetCwdRefCounter >> 0) & 0x3F);
public int SetCwdRefCounterValue => (int)((SetCwdRefCounter >> 8) & 0xFFFF);
public uint SetReservedSwMethod08;
public uint SetReservedSwMethod09;
@@ -201,28 +201,28 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetReservedSwMethod14;
public uint SetReservedSwMethod15;
public uint SetGwcScgType;
public SetGwcScgTypeScgType SetGwcScgTypeScgType => (SetGwcScgTypeScgType)(SetGwcScgType & 0x1);
public SetGwcScgTypeScgType SetGwcScgTypeScgType => (SetGwcScgTypeScgType)((SetGwcScgType >> 0) & 0x1);
public uint SetScgControl;
public int SetScgControlCompute1MaxSmCount => (int)(SetScgControl & 0x1FF);
public int SetScgControlCompute1MaxSmCount => (int)((SetScgControl >> 0) & 0x1FF);
public uint InvalidateConstantBufferCacheA;
public int InvalidateConstantBufferCacheAAddressUpper => (int)(InvalidateConstantBufferCacheA & 0xFF);
public int InvalidateConstantBufferCacheAAddressUpper => (int)((InvalidateConstantBufferCacheA >> 0) & 0xFF);
public uint InvalidateConstantBufferCacheB;
public uint InvalidateConstantBufferCacheC;
public int InvalidateConstantBufferCacheCByteCount => (int)(InvalidateConstantBufferCacheC & 0x1FFFF);
public int InvalidateConstantBufferCacheCByteCount => (int)((InvalidateConstantBufferCacheC >> 0) & 0x1FFFF);
public bool InvalidateConstantBufferCacheCThruL2 => (InvalidateConstantBufferCacheC & 0x80000000) != 0;
public uint SetComputeClassVersion;
public int SetComputeClassVersionCurrent => (int)(SetComputeClassVersion & 0xFFFF);
public int SetComputeClassVersionCurrent => (int)((SetComputeClassVersion >> 0) & 0xFFFF);
public int SetComputeClassVersionOldestSupported => (int)((SetComputeClassVersion >> 16) & 0xFFFF);
public uint CheckComputeClassVersion;
public int CheckComputeClassVersionCurrent => (int)(CheckComputeClassVersion & 0xFFFF);
public int CheckComputeClassVersionCurrent => (int)((CheckComputeClassVersion >> 0) & 0xFFFF);
public int CheckComputeClassVersionOldestSupported => (int)((CheckComputeClassVersion >> 16) & 0xFFFF);
public uint SetQmdVersion;
public int SetQmdVersionCurrent => (int)(SetQmdVersion & 0xFFFF);
public int SetQmdVersionCurrent => (int)((SetQmdVersion >> 0) & 0xFFFF);
public int SetQmdVersionOldestSupported => (int)((SetQmdVersion >> 16) & 0xFFFF);
public uint SetWfiConfig;
public bool SetWfiConfigEnableScgTypeWfi => (SetWfiConfig & 0x1) != 0;
public uint CheckQmdVersion;
public int CheckQmdVersionCurrent => (int)(CheckQmdVersion & 0xFFFF);
public int CheckQmdVersionCurrent => (int)((CheckQmdVersion >> 0) & 0xFFFF);
public int CheckQmdVersionOldestSupported => (int)((CheckQmdVersion >> 16) & 0xFFFF);
public uint WaitForIdleScgType;
public uint InvalidateSkedCaches;
@@ -231,28 +231,28 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool SetScgRenderEnableControlCompute1UsesRenderEnable => (SetScgRenderEnableControl & 0x1) != 0;
public fixed uint Reserved2A0[4];
public uint SetCwdSlotCount;
public int SetCwdSlotCountV => (int)(SetCwdSlotCount & 0xFF);
public int SetCwdSlotCountV => (int)((SetCwdSlotCount >> 0) & 0xFF);
public uint SendPcasA;
public uint SendPcasB;
public int SendPcasBFrom => (int)(SendPcasB & 0xFFFFFF);
public int SendPcasBFrom => (int)((SendPcasB >> 0) & 0xFFFFFF);
public int SendPcasBDelta => (int)((SendPcasB >> 24) & 0xFF);
public uint SendSignalingPcasB;
public bool SendSignalingPcasBInvalidate => (SendSignalingPcasB & 0x1) != 0;
public bool SendSignalingPcasBSchedule => (SendSignalingPcasB & 0x2) != 0;
public fixed uint Reserved2C0[9];
public uint SetShaderLocalMemoryNonThrottledA;
public int SetShaderLocalMemoryNonThrottledASizeUpper => (int)(SetShaderLocalMemoryNonThrottledA & 0xFF);
public int SetShaderLocalMemoryNonThrottledASizeUpper => (int)((SetShaderLocalMemoryNonThrottledA >> 0) & 0xFF);
public uint SetShaderLocalMemoryNonThrottledB;
public uint SetShaderLocalMemoryNonThrottledC;
public int SetShaderLocalMemoryNonThrottledCMaxSmCount => (int)(SetShaderLocalMemoryNonThrottledC & 0x1FF);
public int SetShaderLocalMemoryNonThrottledCMaxSmCount => (int)((SetShaderLocalMemoryNonThrottledC >> 0) & 0x1FF);
public uint SetShaderLocalMemoryThrottledA;
public int SetShaderLocalMemoryThrottledASizeUpper => (int)(SetShaderLocalMemoryThrottledA & 0xFF);
public int SetShaderLocalMemoryThrottledASizeUpper => (int)((SetShaderLocalMemoryThrottledA >> 0) & 0xFF);
public uint SetShaderLocalMemoryThrottledB;
public uint SetShaderLocalMemoryThrottledC;
public int SetShaderLocalMemoryThrottledCMaxSmCount => (int)(SetShaderLocalMemoryThrottledC & 0x1FF);
public int SetShaderLocalMemoryThrottledCMaxSmCount => (int)((SetShaderLocalMemoryThrottledC >> 0) & 0x1FF);
public fixed uint Reserved2FC[5];
public uint SetSpaVersion;
public int SetSpaVersionMinor => (int)(SetSpaVersion & 0xFF);
public int SetSpaVersionMinor => (int)((SetSpaVersion >> 0) & 0xFF);
public int SetSpaVersionMajor => (int)((SetSpaVersion >> 8) & 0xFF);
public fixed uint Reserved314[123];
public uint SetFalcon00;
@@ -291,14 +291,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetShaderLocalMemoryWindow;
public fixed uint Reserved780[4];
public uint SetShaderLocalMemoryA;
public int SetShaderLocalMemoryAAddressUpper => (int)(SetShaderLocalMemoryA & 0xFF);
public int SetShaderLocalMemoryAAddressUpper => (int)((SetShaderLocalMemoryA >> 0) & 0xFF);
public uint SetShaderLocalMemoryB;
public fixed uint Reserved798[383];
public uint SetShaderCacheControl;
public bool SetShaderCacheControlIcachePrefetchEnable => (SetShaderCacheControl & 0x1) != 0;
public fixed uint ReservedD98[19];
public uint SetSmTimeoutInterval;
public int SetSmTimeoutIntervalCounterBit => (int)(SetSmTimeoutInterval & 0x3F);
public int SetSmTimeoutIntervalCounterBit => (int)((SetSmTimeoutInterval >> 0) & 0x3F);
public fixed uint ReservedDE8[87];
public uint SetSpareNoop12;
public uint SetSpareNoop13;
@@ -324,48 +324,48 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool InvalidateTextureHeaderCacheAllV => (InvalidateTextureHeaderCacheAll & 0x1) != 0;
public fixed uint Reserved1214[29];
public uint InvalidateTextureDataCacheNoWfi;
public InvalidateCacheLines InvalidateTextureDataCacheNoWfiLines => (InvalidateCacheLines)(InvalidateTextureDataCacheNoWfi & 0x1);
public InvalidateCacheLines InvalidateTextureDataCacheNoWfiLines => (InvalidateCacheLines)((InvalidateTextureDataCacheNoWfi >> 0) & 0x1);
public int InvalidateTextureDataCacheNoWfiTag => (int)((InvalidateTextureDataCacheNoWfi >> 4) & 0x3FFFFF);
public fixed uint Reserved128C[7];
public uint ActivatePerfSettingsForComputeContext;
public bool ActivatePerfSettingsForComputeContextAll => (ActivatePerfSettingsForComputeContext & 0x1) != 0;
public fixed uint Reserved12AC[33];
public uint InvalidateSamplerCache;
public InvalidateCacheLines InvalidateSamplerCacheLines => (InvalidateCacheLines)(InvalidateSamplerCache & 0x1);
public InvalidateCacheLines InvalidateSamplerCacheLines => (InvalidateCacheLines)((InvalidateSamplerCache >> 0) & 0x1);
public int InvalidateSamplerCacheTag => (int)((InvalidateSamplerCache >> 4) & 0x3FFFFF);
public uint InvalidateTextureHeaderCache;
public InvalidateCacheLines InvalidateTextureHeaderCacheLines => (InvalidateCacheLines)(InvalidateTextureHeaderCache & 0x1);
public InvalidateCacheLines InvalidateTextureHeaderCacheLines => (InvalidateCacheLines)((InvalidateTextureHeaderCache >> 0) & 0x1);
public int InvalidateTextureHeaderCacheTag => (int)((InvalidateTextureHeaderCache >> 4) & 0x3FFFFF);
public uint InvalidateTextureDataCache;
public InvalidateCacheLines InvalidateTextureDataCacheLines => (InvalidateCacheLines)(InvalidateTextureDataCache & 0x1);
public InvalidateCacheLines InvalidateTextureDataCacheLines => (InvalidateCacheLines)((InvalidateTextureDataCache >> 0) & 0x1);
public int InvalidateTextureDataCacheTag => (int)((InvalidateTextureDataCache >> 4) & 0x3FFFFF);
public fixed uint Reserved133C[58];
public uint InvalidateSamplerCacheNoWfi;
public InvalidateCacheLines InvalidateSamplerCacheNoWfiLines => (InvalidateCacheLines)(InvalidateSamplerCacheNoWfi & 0x1);
public InvalidateCacheLines InvalidateSamplerCacheNoWfiLines => (InvalidateCacheLines)((InvalidateSamplerCacheNoWfi >> 0) & 0x1);
public int InvalidateSamplerCacheNoWfiTag => (int)((InvalidateSamplerCacheNoWfi >> 4) & 0x3FFFFF);
public fixed uint Reserved1428[64];
public uint SetShaderExceptions;
public bool SetShaderExceptionsEnable => (SetShaderExceptions & 0x1) != 0;
public fixed uint Reserved152C[9];
public uint SetRenderEnableA;
public int SetRenderEnableAOffsetUpper => (int)(SetRenderEnableA & 0xFF);
public int SetRenderEnableAOffsetUpper => (int)((SetRenderEnableA >> 0) & 0xFF);
public uint SetRenderEnableB;
public uint SetRenderEnableC;
public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7);
public uint SetTexSamplerPoolA;
public int SetTexSamplerPoolAOffsetUpper => (int)(SetTexSamplerPoolA & 0xFF);
public int SetTexSamplerPoolAOffsetUpper => (int)((SetTexSamplerPoolA >> 0) & 0xFF);
public uint SetTexSamplerPoolB;
public uint SetTexSamplerPoolC;
public int SetTexSamplerPoolCMaximumIndex => (int)(SetTexSamplerPoolC & 0xFFFFF);
public int SetTexSamplerPoolCMaximumIndex => (int)((SetTexSamplerPoolC >> 0) & 0xFFFFF);
public fixed uint Reserved1568[3];
public uint SetTexHeaderPoolA;
public int SetTexHeaderPoolAOffsetUpper => (int)(SetTexHeaderPoolA & 0xFF);
public int SetTexHeaderPoolAOffsetUpper => (int)((SetTexHeaderPoolA >> 0) & 0xFF);
public uint SetTexHeaderPoolB;
public uint SetTexHeaderPoolC;
public int SetTexHeaderPoolCMaximumIndex => (int)(SetTexHeaderPoolC & 0x3FFFFF);
public int SetTexHeaderPoolCMaximumIndex => (int)((SetTexHeaderPoolC >> 0) & 0x3FFFFF);
public fixed uint Reserved1580[34];
public uint SetProgramRegionA;
public int SetProgramRegionAAddressUpper => (int)(SetProgramRegionA & 0xFF);
public int SetProgramRegionAAddressUpper => (int)((SetProgramRegionA >> 0) & 0xFF);
public uint SetProgramRegionB;
public fixed uint Reserved1610[34];
public uint InvalidateShaderCachesNoWfi;
@@ -374,7 +374,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool InvalidateShaderCachesNoWfiConstant => (InvalidateShaderCachesNoWfi & 0x1000) != 0;
public fixed uint Reserved169C[170];
public uint SetRenderEnableOverride;
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)(SetRenderEnableOverride & 0x3);
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)((SetRenderEnableOverride >> 0) & 0x3);
public fixed uint Reserved1948[57];
public uint PipeNop;
public uint SetSpare00;
@@ -383,11 +383,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public uint SetSpare03;
public fixed uint Reserved1A40[48];
public uint SetReportSemaphoreA;
public int SetReportSemaphoreAOffsetUpper => (int)(SetReportSemaphoreA & 0xFF);
public int SetReportSemaphoreAOffsetUpper => (int)((SetReportSemaphoreA >> 0) & 0xFF);
public uint SetReportSemaphoreB;
public uint SetReportSemaphoreC;
public uint SetReportSemaphoreD;
public SetReportSemaphoreDOperation SetReportSemaphoreDOperation => (SetReportSemaphoreDOperation)(SetReportSemaphoreD & 0x3);
public SetReportSemaphoreDOperation SetReportSemaphoreDOperation => (SetReportSemaphoreDOperation)((SetReportSemaphoreD >> 0) & 0x3);
public bool SetReportSemaphoreDAwakenEnable => (SetReportSemaphoreD & 0x100000) != 0;
public SetReportSemaphoreDStructureSize SetReportSemaphoreDStructureSize => (SetReportSemaphoreDStructureSize)((SetReportSemaphoreD >> 28) & 0x1);
public bool SetReportSemaphoreDFlushDisable => (SetReportSemaphoreD & 0x4) != 0;
@@ -396,7 +396,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public SetReportSemaphoreDReductionFormat SetReportSemaphoreDReductionFormat => (SetReportSemaphoreDReductionFormat)((SetReportSemaphoreD >> 17) & 0x3);
public fixed uint Reserved1B10[702];
public uint SetBindlessTexture;
public int SetBindlessTextureConstantBufferSlotSelect => (int)(SetBindlessTexture & 0x7);
public int SetBindlessTextureConstantBufferSlotSelect => (int)((SetBindlessTexture >> 0) & 0x7);
public uint SetTrapHandler;
public fixed uint Reserved2610[843];
public Array8<uint> SetShaderPerformanceCounterValueUpper;
@@ -423,11 +423,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
public bool SetShaderPerformanceCounterControlBWindowed(int i) => (SetShaderPerformanceCounterControlB[i] & 0x8) != 0;
public int SetShaderPerformanceCounterControlBFunc(int i) => (int)((SetShaderPerformanceCounterControlB[i] >> 4) & 0xFFFF);
public uint SetShaderPerformanceCounterTrapControl;
public int SetShaderPerformanceCounterTrapControlMask => (int)(SetShaderPerformanceCounterTrapControl & 0xFF);
public int SetShaderPerformanceCounterTrapControlMask => (int)((SetShaderPerformanceCounterTrapControl >> 0) & 0xFF);
public uint StartShaderPerformanceCounter;
public int StartShaderPerformanceCounterCounterMask => (int)(StartShaderPerformanceCounter & 0xFF);
public int StartShaderPerformanceCounterCounterMask => (int)((StartShaderPerformanceCounter >> 0) & 0xFF);
public uint StopShaderPerformanceCounter;
public int StopShaderPerformanceCounterCounterMask => (int)(StopShaderPerformanceCounter & 0xFF);
public int StopShaderPerformanceCounterCounterMask => (int)((StopShaderPerformanceCounter >> 0) & 0xFF);
public fixed uint Reserved33E8[6];
public MmeShadowScratch SetMmeShadowScratch;
#pragma warning restore CS0649

View File

@@ -186,22 +186,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint PmTrigger;
public fixed uint Reserved144[63];
public uint SetSemaphoreA;
public int SetSemaphoreAUpper => (int)(SetSemaphoreA & 0xFF);
public int SetSemaphoreAUpper => (int)((SetSemaphoreA >> 0) & 0xFF);
public uint SetSemaphoreB;
public uint SetSemaphorePayload;
public fixed uint Reserved24C[2];
public uint SetRenderEnableA;
public int SetRenderEnableAUpper => (int)(SetRenderEnableA & 0xFF);
public int SetRenderEnableAUpper => (int)((SetRenderEnableA >> 0) & 0xFF);
public uint SetRenderEnableB;
public uint SetRenderEnableC;
public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7);
public uint SetSrcPhysMode;
public SetPhysModeTarget SetSrcPhysModeTarget => (SetPhysModeTarget)(SetSrcPhysMode & 0x3);
public SetPhysModeTarget SetSrcPhysModeTarget => (SetPhysModeTarget)((SetSrcPhysMode >> 0) & 0x3);
public uint SetDstPhysMode;
public SetPhysModeTarget SetDstPhysModeTarget => (SetPhysModeTarget)(SetDstPhysMode & 0x3);
public SetPhysModeTarget SetDstPhysModeTarget => (SetPhysModeTarget)((SetDstPhysMode >> 0) & 0x3);
public fixed uint Reserved268[38];
public uint LaunchDma;
public LaunchDmaDataTransferType LaunchDmaDataTransferType => (LaunchDmaDataTransferType)(LaunchDma & 0x3);
public LaunchDmaDataTransferType LaunchDmaDataTransferType => (LaunchDmaDataTransferType)((LaunchDma >> 0) & 0x3);
public bool LaunchDmaFlushEnable => (LaunchDma & 0x4) != 0;
public LaunchDmaSemaphoreType LaunchDmaSemaphoreType => (LaunchDmaSemaphoreType)((LaunchDma >> 3) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 5) & 0x3);
@@ -218,10 +218,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public LaunchDmaBypassL2 LaunchDmaBypassL2 => (LaunchDmaBypassL2)((LaunchDma >> 20) & 0x1);
public fixed uint Reserved304[63];
public uint OffsetInUpper;
public int OffsetInUpperUpper => (int)(OffsetInUpper & 0xFF);
public int OffsetInUpperUpper => (int)((OffsetInUpper >> 0) & 0xFF);
public uint OffsetInLower;
public uint OffsetOutUpper;
public int OffsetOutUpperUpper => (int)(OffsetOutUpper & 0xFF);
public int OffsetOutUpperUpper => (int)((OffsetOutUpper >> 0) & 0xFF);
public uint OffsetOutLower;
public uint PitchIn;
public uint PitchOut;
@@ -231,7 +231,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint SetRemapConstA;
public uint SetRemapConstB;
public uint SetRemapComponents;
public SetRemapComponentsDst SetRemapComponentsDstX => (SetRemapComponentsDst)(SetRemapComponents & 0x7);
public SetRemapComponentsDst SetRemapComponentsDstX => (SetRemapComponentsDst)((SetRemapComponents >> 0) & 0x7);
public SetRemapComponentsDst SetRemapComponentsDstY => (SetRemapComponentsDst)((SetRemapComponents >> 4) & 0x7);
public SetRemapComponentsDst SetRemapComponentsDstZ => (SetRemapComponentsDst)((SetRemapComponents >> 8) & 0x7);
public SetRemapComponentsDst SetRemapComponentsDstW => (SetRemapComponentsDst)((SetRemapComponents >> 12) & 0x7);
@@ -239,7 +239,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public SetRemapComponentsNumComponents SetRemapComponentsNumSrcComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 20) & 0x3);
public SetRemapComponentsNumComponents SetRemapComponentsNumDstComponents => (SetRemapComponentsNumComponents)((SetRemapComponents >> 24) & 0x3);
public uint SetDstBlockSize;
public SetBlockSizeWidth SetDstBlockSizeWidth => (SetBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetBlockSizeWidth SetDstBlockSizeWidth => (SetBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF);
public SetBlockSizeHeight SetDstBlockSizeHeight => (SetBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetBlockSizeDepth SetDstBlockSizeDepth => (SetBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public SetBlockSizeGobHeight SetDstBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetDstBlockSize >> 12) & 0xF);
@@ -248,11 +248,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint SetDstDepth;
public uint SetDstLayer;
public uint SetDstOrigin;
public int SetDstOriginX => (int)(SetDstOrigin & 0xFFFF);
public int SetDstOriginX => (int)((SetDstOrigin >> 0) & 0xFFFF);
public int SetDstOriginY => (int)((SetDstOrigin >> 16) & 0xFFFF);
public uint Reserved724;
public uint SetSrcBlockSize;
public SetBlockSizeWidth SetSrcBlockSizeWidth => (SetBlockSizeWidth)(SetSrcBlockSize & 0xF);
public SetBlockSizeWidth SetSrcBlockSizeWidth => (SetBlockSizeWidth)((SetSrcBlockSize >> 0) & 0xF);
public SetBlockSizeHeight SetSrcBlockSizeHeight => (SetBlockSizeHeight)((SetSrcBlockSize >> 4) & 0xF);
public SetBlockSizeDepth SetSrcBlockSizeDepth => (SetBlockSizeDepth)((SetSrcBlockSize >> 8) & 0xF);
public SetBlockSizeGobHeight SetSrcBlockSizeGobHeight => (SetBlockSizeGobHeight)((SetSrcBlockSize >> 12) & 0xF);
@@ -261,7 +261,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
public uint SetSrcDepth;
public uint SetSrcLayer;
public uint SetSrcOrigin;
public int SetSrcOriginX => (int)(SetSrcOrigin & 0xFFFF);
public int SetSrcOriginX => (int)((SetSrcOrigin >> 0) & 0xFFFF);
public int SetSrcOriginY => (int)((SetSrcOrigin >> 16) & 0xFFFF);
public fixed uint Reserved740[629];
public uint PmTriggerEnd;

View File

@@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public uint Method;
#pragma warning restore CS0649
public int MethodAddressOld => (int)((Method >> 2) & 0x7FF);
public int MethodAddress => (int)(Method & 0xFFF);
public int MethodAddress => (int)((Method >> 0) & 0xFFF);
public int SubdeviceMask => (int)((Method >> 4) & 0xFFF);
public int MethodSubchannel => (int)((Method >> 13) & 0x7);
public TertOp TertOp => (TertOp)((Method >> 16) & 0x3);

View File

@@ -39,17 +39,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
#pragma warning disable CS0649
public uint Entry0;
#pragma warning restore CS0649
public Entry0Fetch Entry0Fetch => (Entry0Fetch)(Entry0 & 0x1);
public Entry0Fetch Entry0Fetch => (Entry0Fetch)((Entry0 >> 0) & 0x1);
public int Entry0Get => (int)((Entry0 >> 2) & 0x3FFFFFFF);
public int Entry0Operand => (int)(Entry0);
#pragma warning disable CS0649
public uint Entry1;
#pragma warning restore CS0649
public int Entry1GetHi => (int)(Entry1 & 0xFF);
public int Entry1GetHi => (int)((Entry1 >> 0) & 0xFF);
public Entry1Priv Entry1Priv => (Entry1Priv)((Entry1 >> 8) & 0x1);
public Entry1Level Entry1Level => (Entry1Level)((Entry1 >> 9) & 0x1);
public int Entry1Length => (int)((Entry1 >> 10) & 0x1FFFFF);
public Entry1Sync Entry1Sync => (Entry1Sync)((Entry1 >> 31) & 0x1);
public Entry1Opcode Entry1Opcode => (Entry1Opcode)(Entry1 & 0xFF);
public Entry1Opcode Entry1Opcode => (Entry1Opcode)((Entry1 >> 0) & 0xFF);
}
}

View File

@@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
{
#pragma warning disable CS0649
public uint SetObject;
public int SetObjectNvclass => (int)(SetObject & 0xFFFF);
public int SetObjectNvclass => (int)((SetObject >> 0) & 0xFFFF);
public int SetObjectEngine => (int)((SetObject >> 16) & 0x1F);
public uint Illegal;
public int IllegalHandle => (int)(Illegal);
@@ -161,13 +161,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public int NopHandle => (int)(Nop);
public uint Reserved0C;
public uint Semaphorea;
public int SemaphoreaOffsetUpper => (int)(Semaphorea & 0xFF);
public int SemaphoreaOffsetUpper => (int)((Semaphorea >> 0) & 0xFF);
public uint Semaphoreb;
public int SemaphorebOffsetLower => (int)((Semaphoreb >> 2) & 0x3FFFFFFF);
public uint Semaphorec;
public int SemaphorecPayload => (int)(Semaphorec);
public uint Semaphored;
public SemaphoredOperation SemaphoredOperation => (SemaphoredOperation)(Semaphored & 0x1F);
public SemaphoredOperation SemaphoredOperation => (SemaphoredOperation)((Semaphored >> 0) & 0x1F);
public SemaphoredAcquireSwitch SemaphoredAcquireSwitch => (SemaphoredAcquireSwitch)((Semaphored >> 12) & 0x1);
public SemaphoredReleaseWfi SemaphoredReleaseWfi => (SemaphoredReleaseWfi)((Semaphored >> 20) & 0x1);
public SemaphoredReleaseSize SemaphoredReleaseSize => (SemaphoredReleaseSize)((Semaphored >> 24) & 0x1);
@@ -181,14 +181,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public uint Reserved2C;
public uint MemOpC;
public int MemOpCOperandLow => (int)((MemOpC >> 2) & 0x3FFFFFFF);
public MemOpCTlbInvalidatePdb MemOpCTlbInvalidatePdb => (MemOpCTlbInvalidatePdb)(MemOpC & 0x1);
public MemOpCTlbInvalidatePdb MemOpCTlbInvalidatePdb => (MemOpCTlbInvalidatePdb)((MemOpC >> 0) & 0x1);
public MemOpCTlbInvalidateGpc MemOpCTlbInvalidateGpc => (MemOpCTlbInvalidateGpc)((MemOpC >> 1) & 0x1);
public MemOpCTlbInvalidateTarget MemOpCTlbInvalidateTarget => (MemOpCTlbInvalidateTarget)((MemOpC >> 10) & 0x3);
public int MemOpCTlbInvalidateAddrLo => (int)((MemOpC >> 12) & 0xFFFFF);
public uint MemOpD;
public int MemOpDOperandHigh => (int)(MemOpD & 0xFF);
public int MemOpDOperandHigh => (int)((MemOpD >> 0) & 0xFF);
public MemOpDOperation MemOpDOperation => (MemOpDOperation)((MemOpD >> 27) & 0x1F);
public int MemOpDTlbInvalidateAddrHi => (int)(MemOpD & 0xFF);
public int MemOpDTlbInvalidateAddrHi => (int)((MemOpD >> 0) & 0xFF);
public uint Reserved38;
public uint Reserved3C;
public uint Reserved40;
@@ -207,15 +207,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
public uint Syncpointa;
public int SyncpointaPayload => (int)(Syncpointa);
public uint Syncpointb;
public SyncpointbOperation SyncpointbOperation => (SyncpointbOperation)(Syncpointb & 0x1);
public SyncpointbOperation SyncpointbOperation => (SyncpointbOperation)((Syncpointb >> 0) & 0x1);
public SyncpointbWaitSwitch SyncpointbWaitSwitch => (SyncpointbWaitSwitch)((Syncpointb >> 4) & 0x1);
public int SyncpointbSyncptIndex => (int)((Syncpointb >> 8) & 0xFFF);
public uint Wfi;
public WfiScope WfiScope => (WfiScope)(Wfi & 0x1);
public WfiScope WfiScope => (WfiScope)((Wfi >> 0) & 0x1);
public uint CrcCheck;
public int CrcCheckValue => (int)(CrcCheck);
public uint Yield;
public YieldOp YieldOp => (YieldOp)(Yield & 0x3);
public YieldOp YieldOp => (YieldOp)((Yield >> 0) & 0x3);
// TODO: Eventually move this to per-engine state.
public Array31<uint> Reserved84;
public uint NoOperation;

View File

@@ -113,22 +113,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
{
#pragma warning disable CS0649
public uint SetObject;
public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63];
public uint NoOperation;
public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF);
public uint SetNotifyB;
public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify);
public uint WaitForIdle;
public fixed uint Reserved114[7];
public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF);
public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7);
public uint SendGoIdle;
public uint PmTrigger;
public uint PmTriggerWfi;
@@ -139,11 +139,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
public uint LineLengthIn;
public uint LineCount;
public uint OffsetOutUpper;
public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF);
public uint OffsetOut;
public uint PitchOut;
public uint SetDstBlockSize;
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF);
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public uint SetDstWidth;
@@ -151,11 +151,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
public uint SetDstDepth;
public uint SetDstLayer;
public uint SetDstOriginBytesX;
public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF);
public uint SetDstOriginSamplesY;
public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF);
public uint LaunchDma;
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1);
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);
@@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
public uint LoadInlineData;
public fixed uint Reserved1B8[9];
public uint SetI2mSemaphoreA;
public int SetI2mSemaphoreAOffsetUpper => (int)(SetI2mSemaphoreA & 0xFF);
public int SetI2mSemaphoreAOffsetUpper => (int)((SetI2mSemaphoreA >> 0) & 0xFF);
public uint SetI2mSemaphoreB;
public uint SetI2mSemaphoreC;
public fixed uint Reserved1E8[2];

View File

@@ -771,11 +771,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
/// </summary>
private void UpdateDepthMode()
{
DepthMode mode = GetDepthMode();
_pipeline.DepthMode = mode;
_context.Renderer.Pipeline.SetDepthMode(mode);
_context.Renderer.Pipeline.SetDepthMode(GetDepthMode());
}
/// <summary>

View File

@@ -746,12 +746,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{
#pragma warning disable CS0649
public uint SetObject;
public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63];
public uint NoOperation;
public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0xFF);
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0xFF);
public uint SetNotifyB;
public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify);
@@ -761,13 +761,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public uint LoadMmeStartAddressRamPointer;
public uint LoadMmeStartAddressRam;
public uint SetMmeShadowRamControl;
public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)(SetMmeShadowRamControl & 0x3);
public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)((SetMmeShadowRamControl >> 0) & 0x3);
public fixed uint Reserved128[2];
public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF);
public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7);
public uint SendGoIdle;
public uint PmTrigger;
public uint PmTriggerWfi;
@@ -778,11 +778,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public uint LineLengthIn;
public uint LineCount;
public uint OffsetOutUpper;
public int OffsetOutUpperValue => (int)(OffsetOutUpper & 0xFF);
public int OffsetOutUpperValue => (int)((OffsetOutUpper >> 0) & 0xFF);
public uint OffsetOut;
public uint PitchOut;
public uint SetDstBlockSize;
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)(SetDstBlockSize & 0xF);
public SetDstBlockSizeWidth SetDstBlockSizeWidth => (SetDstBlockSizeWidth)((SetDstBlockSize >> 0) & 0xF);
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0xF);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0xF);
public uint SetDstWidth;
@@ -790,11 +790,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public uint SetDstDepth;
public uint SetDstLayer;
public uint SetDstOriginBytesX;
public int SetDstOriginBytesXV => (int)(SetDstOriginBytesX & 0xFFFFF);
public int SetDstOriginBytesXV => (int)((SetDstOriginBytesX >> 0) & 0xFFFFF);
public uint SetDstOriginSamplesY;
public int SetDstOriginSamplesYV => (int)(SetDstOriginSamplesY & 0xFFFF);
public int SetDstOriginSamplesYV => (int)((SetDstOriginSamplesY >> 0) & 0xFFFF);
public uint LaunchDma;
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)(LaunchDma & 0x1);
public LaunchDmaDstMemoryLayout LaunchDmaDstMemoryLayout => (LaunchDmaDstMemoryLayout)((LaunchDma >> 0) & 0x1);
public LaunchDmaCompletionType LaunchDmaCompletionType => (LaunchDmaCompletionType)((LaunchDma >> 4) & 0x3);
public LaunchDmaInterruptType LaunchDmaInterruptType => (LaunchDmaInterruptType)((LaunchDma >> 8) & 0x3);
public LaunchDmaSemaphoreStructSize LaunchDmaSemaphoreStructSize => (LaunchDmaSemaphoreStructSize)((LaunchDma >> 12) & 0x1);

View File

@@ -499,12 +499,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
{
#pragma warning disable CS0649
public uint SetObject;
public int SetObjectClassId => (int)(SetObject & 0xFFFF);
public int SetObjectClassId => (int)((SetObject >> 0) & 0xFFFF);
public int SetObjectEngineId => (int)((SetObject >> 16) & 0x1F);
public fixed uint Reserved04[63];
public uint NoOperation;
public uint SetNotifyA;
public int SetNotifyAAddressUpper => (int)(SetNotifyA & 0x1FFFFFF);
public int SetNotifyAAddressUpper => (int)((SetNotifyA >> 0) & 0x1FFFFFF);
public uint SetNotifyB;
public uint Notify;
public NotifyType NotifyType => (NotifyType)(Notify);
@@ -514,13 +514,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint LoadMmeStartAddressRamPointer;
public uint LoadMmeStartAddressRam;
public uint SetMmeShadowRamControl;
public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)(SetMmeShadowRamControl & 0x3);
public SetMmeShadowRamControlMode SetMmeShadowRamControlMode => (SetMmeShadowRamControlMode)((SetMmeShadowRamControl >> 0) & 0x3);
public fixed uint Reserved128[2];
public uint SetGlobalRenderEnableA;
public int SetGlobalRenderEnableAOffsetUpper => (int)(SetGlobalRenderEnableA & 0xFF);
public int SetGlobalRenderEnableAOffsetUpper => (int)((SetGlobalRenderEnableA >> 0) & 0xFF);
public uint SetGlobalRenderEnableB;
public uint SetGlobalRenderEnableC;
public int SetGlobalRenderEnableCMode => (int)(SetGlobalRenderEnableC & 0x7);
public int SetGlobalRenderEnableCMode => (int)((SetGlobalRenderEnableC >> 0) & 0x7);
public uint SendGoIdle;
public uint PmTrigger;
public fixed uint Reserved144[3];
@@ -533,9 +533,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public int SetMmeSwitchStateRestoreMacro => (int)((SetMmeSwitchState >> 12) & 0xFF);
public fixed uint Reserved1F0[4];
public uint SetDstFormat;
public SetDstFormatV SetDstFormatV => (SetDstFormatV)(SetDstFormat & 0xFF);
public SetDstFormatV SetDstFormatV => (SetDstFormatV)((SetDstFormat >> 0) & 0xFF);
public uint SetDstMemoryLayout;
public SetDstMemoryLayoutV SetDstMemoryLayoutV => (SetDstMemoryLayoutV)(SetDstMemoryLayout & 0x1);
public SetDstMemoryLayoutV SetDstMemoryLayoutV => (SetDstMemoryLayoutV)((SetDstMemoryLayout >> 0) & 0x1);
public uint SetDstBlockSize;
public SetDstBlockSizeHeight SetDstBlockSizeHeight => (SetDstBlockSizeHeight)((SetDstBlockSize >> 4) & 0x7);
public SetDstBlockSizeDepth SetDstBlockSizeDepth => (SetDstBlockSizeDepth)((SetDstBlockSize >> 8) & 0x7);
@@ -545,37 +545,37 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint SetDstWidth;
public uint SetDstHeight;
public uint SetDstOffsetUpper;
public int SetDstOffsetUpperV => (int)(SetDstOffsetUpper & 0xFF);
public int SetDstOffsetUpperV => (int)((SetDstOffsetUpper >> 0) & 0xFF);
public uint SetDstOffsetLower;
public uint FlushAndInvalidateRopMiniCache;
public bool FlushAndInvalidateRopMiniCacheV => (FlushAndInvalidateRopMiniCache & 0x1) != 0;
public uint SetSpareNoop06;
public uint SetSrcFormat;
public SetSrcFormatV SetSrcFormatV => (SetSrcFormatV)(SetSrcFormat & 0xFF);
public SetSrcFormatV SetSrcFormatV => (SetSrcFormatV)((SetSrcFormat >> 0) & 0xFF);
public uint SetSrcMemoryLayout;
public SetSrcMemoryLayoutV SetSrcMemoryLayoutV => (SetSrcMemoryLayoutV)(SetSrcMemoryLayout & 0x1);
public SetSrcMemoryLayoutV SetSrcMemoryLayoutV => (SetSrcMemoryLayoutV)((SetSrcMemoryLayout >> 0) & 0x1);
public uint SetSrcBlockSize;
public SetSrcBlockSizeHeight SetSrcBlockSizeHeight => (SetSrcBlockSizeHeight)((SetSrcBlockSize >> 4) & 0x7);
public SetSrcBlockSizeDepth SetSrcBlockSizeDepth => (SetSrcBlockSizeDepth)((SetSrcBlockSize >> 8) & 0x7);
public uint SetSrcDepth;
public uint TwodInvalidateTextureDataCache;
public TwodInvalidateTextureDataCacheV TwodInvalidateTextureDataCacheV => (TwodInvalidateTextureDataCacheV)(TwodInvalidateTextureDataCache & 0x3);
public TwodInvalidateTextureDataCacheV TwodInvalidateTextureDataCacheV => (TwodInvalidateTextureDataCacheV)((TwodInvalidateTextureDataCache >> 0) & 0x3);
public uint SetSrcPitch;
public uint SetSrcWidth;
public uint SetSrcHeight;
public uint SetSrcOffsetUpper;
public int SetSrcOffsetUpperV => (int)(SetSrcOffsetUpper & 0xFF);
public int SetSrcOffsetUpperV => (int)((SetSrcOffsetUpper >> 0) & 0xFF);
public uint SetSrcOffsetLower;
public uint SetPixelsFromMemorySectorPromotion;
public SetPixelsFromMemorySectorPromotionV SetPixelsFromMemorySectorPromotionV => (SetPixelsFromMemorySectorPromotionV)(SetPixelsFromMemorySectorPromotion & 0x3);
public SetPixelsFromMemorySectorPromotionV SetPixelsFromMemorySectorPromotionV => (SetPixelsFromMemorySectorPromotionV)((SetPixelsFromMemorySectorPromotion >> 0) & 0x3);
public uint SetSpareNoop12;
public uint SetNumProcessingClusters;
public SetNumProcessingClustersV SetNumProcessingClustersV => (SetNumProcessingClustersV)(SetNumProcessingClusters & 0x1);
public SetNumProcessingClustersV SetNumProcessingClustersV => (SetNumProcessingClustersV)((SetNumProcessingClusters >> 0) & 0x1);
public uint SetRenderEnableA;
public int SetRenderEnableAOffsetUpper => (int)(SetRenderEnableA & 0xFF);
public int SetRenderEnableAOffsetUpper => (int)((SetRenderEnableA >> 0) & 0xFF);
public uint SetRenderEnableB;
public uint SetRenderEnableC;
public int SetRenderEnableCMode => (int)(SetRenderEnableC & 0x7);
public int SetRenderEnableCMode => (int)((SetRenderEnableC >> 0) & 0x7);
public uint SetSpareNoop08;
public uint SetSpareNoop01;
public uint SetSpareNoop11;
@@ -587,25 +587,25 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint SetClipEnable;
public bool SetClipEnableV => (SetClipEnable & 0x1) != 0;
public uint SetColorKeyFormat;
public SetColorKeyFormatV SetColorKeyFormatV => (SetColorKeyFormatV)(SetColorKeyFormat & 0x7);
public SetColorKeyFormatV SetColorKeyFormatV => (SetColorKeyFormatV)((SetColorKeyFormat >> 0) & 0x7);
public uint SetColorKey;
public uint SetColorKeyEnable;
public bool SetColorKeyEnableV => (SetColorKeyEnable & 0x1) != 0;
public uint SetRop;
public int SetRopV => (int)(SetRop & 0xFF);
public int SetRopV => (int)((SetRop >> 0) & 0xFF);
public uint SetBeta1;
public uint SetBeta4;
public int SetBeta4B => (int)(SetBeta4 & 0xFF);
public int SetBeta4B => (int)((SetBeta4 >> 0) & 0xFF);
public int SetBeta4G => (int)((SetBeta4 >> 8) & 0xFF);
public int SetBeta4R => (int)((SetBeta4 >> 16) & 0xFF);
public int SetBeta4A => (int)((SetBeta4 >> 24) & 0xFF);
public uint SetOperation;
public SetOperationV SetOperationV => (SetOperationV)(SetOperation & 0x7);
public SetOperationV SetOperationV => (SetOperationV)((SetOperation >> 0) & 0x7);
public uint SetPatternOffset;
public int SetPatternOffsetX => (int)(SetPatternOffset & 0x3F);
public int SetPatternOffsetX => (int)((SetPatternOffset >> 0) & 0x3F);
public int SetPatternOffsetY => (int)((SetPatternOffset >> 8) & 0x3F);
public uint SetPatternSelect;
public SetPatternSelectV SetPatternSelectV => (SetPatternSelectV)(SetPatternSelect & 0x3);
public SetPatternSelectV SetPatternSelectV => (SetPatternSelectV)((SetPatternSelect >> 0) & 0x3);
public uint SetDstColorRenderToZetaSurface;
public bool SetDstColorRenderToZetaSurfaceV => (SetDstColorRenderToZetaSurface & 0x1) != 0;
public uint SetSpareNoop04;
@@ -618,15 +618,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public bool SetCompressionEnable => (SetCompression & 0x1) != 0;
public uint SetSpareNoop09;
public uint SetRenderEnableOverride;
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)(SetRenderEnableOverride & 0x3);
public SetRenderEnableOverrideMode SetRenderEnableOverrideMode => (SetRenderEnableOverrideMode)((SetRenderEnableOverride >> 0) & 0x3);
public uint SetPixelsFromMemoryDirection;
public SetPixelsFromMemoryDirectionHorizontal SetPixelsFromMemoryDirectionHorizontal => (SetPixelsFromMemoryDirectionHorizontal)(SetPixelsFromMemoryDirection & 0x3);
public SetPixelsFromMemoryDirectionHorizontal SetPixelsFromMemoryDirectionHorizontal => (SetPixelsFromMemoryDirectionHorizontal)((SetPixelsFromMemoryDirection >> 0) & 0x3);
public SetPixelsFromMemoryDirectionVertical SetPixelsFromMemoryDirectionVertical => (SetPixelsFromMemoryDirectionVertical)((SetPixelsFromMemoryDirection >> 4) & 0x3);
public uint SetSpareNoop10;
public uint SetMonochromePatternColorFormat;
public SetMonochromePatternColorFormatV SetMonochromePatternColorFormatV => (SetMonochromePatternColorFormatV)(SetMonochromePatternColorFormat & 0x7);
public SetMonochromePatternColorFormatV SetMonochromePatternColorFormatV => (SetMonochromePatternColorFormatV)((SetMonochromePatternColorFormat >> 0) & 0x7);
public uint SetMonochromePatternFormat;
public SetMonochromePatternFormatV SetMonochromePatternFormatV => (SetMonochromePatternFormatV)(SetMonochromePatternFormat & 0x1);
public SetMonochromePatternFormatV SetMonochromePatternFormatV => (SetMonochromePatternFormatV)((SetMonochromePatternFormat >> 0) & 0x1);
public uint SetMonochromePatternColor0;
public uint SetMonochromePatternColor1;
public uint SetMonochromePattern0;
@@ -662,26 +662,26 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public uint SetRenderSolidPrimColor2;
public uint SetRenderSolidPrimColor3;
public uint SetMmeMemAddressA;
public int SetMmeMemAddressAUpper => (int)(SetMmeMemAddressA & 0x1FFFFFF);
public int SetMmeMemAddressAUpper => (int)((SetMmeMemAddressA >> 0) & 0x1FFFFFF);
public uint SetMmeMemAddressB;
public uint SetMmeDataRamAddress;
public uint MmeDmaRead;
public uint MmeDmaReadFifoed;
public uint MmeDmaWrite;
public uint MmeDmaReduction;
public MmeDmaReductionReductionOp MmeDmaReductionReductionOp => (MmeDmaReductionReductionOp)(MmeDmaReduction & 0x7);
public MmeDmaReductionReductionOp MmeDmaReductionReductionOp => (MmeDmaReductionReductionOp)((MmeDmaReduction >> 0) & 0x7);
public MmeDmaReductionReductionFormat MmeDmaReductionReductionFormat => (MmeDmaReductionReductionFormat)((MmeDmaReduction >> 4) & 0x3);
public MmeDmaReductionReductionSize MmeDmaReductionReductionSize => (MmeDmaReductionReductionSize)((MmeDmaReduction >> 8) & 0x1);
public uint MmeDmaSysmembar;
public bool MmeDmaSysmembarV => (MmeDmaSysmembar & 0x1) != 0;
public uint MmeDmaSync;
public uint SetMmeDataFifoConfig;
public SetMmeDataFifoConfigFifoSize SetMmeDataFifoConfigFifoSize => (SetMmeDataFifoConfigFifoSize)(SetMmeDataFifoConfig & 0x7);
public SetMmeDataFifoConfigFifoSize SetMmeDataFifoConfigFifoSize => (SetMmeDataFifoConfigFifoSize)((SetMmeDataFifoConfig >> 0) & 0x7);
public fixed uint Reserved578[2];
public uint RenderSolidPrimMode;
public RenderSolidPrimModeV RenderSolidPrimModeV => (RenderSolidPrimModeV)(RenderSolidPrimMode & 0x7);
public RenderSolidPrimModeV RenderSolidPrimModeV => (RenderSolidPrimModeV)((RenderSolidPrimMode >> 0) & 0x7);
public uint SetRenderSolidPrimColorFormat;
public SetRenderSolidPrimColorFormatV SetRenderSolidPrimColorFormatV => (SetRenderSolidPrimColorFormatV)(SetRenderSolidPrimColorFormat & 0xFF);
public SetRenderSolidPrimColorFormatV SetRenderSolidPrimColorFormatV => (SetRenderSolidPrimColorFormatV)((SetRenderSolidPrimColorFormat >> 0) & 0xFF);
public uint SetRenderSolidPrimColor;
public uint SetRenderSolidLineTieBreakBits;
public bool SetRenderSolidLineTieBreakBitsXmajXincYinc => (SetRenderSolidLineTieBreakBits & 0x1) != 0;
@@ -690,24 +690,24 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public bool SetRenderSolidLineTieBreakBitsYmajXdecYinc => (SetRenderSolidLineTieBreakBits & 0x1000) != 0;
public fixed uint Reserved590[20];
public uint RenderSolidPrimPointXY;
public int RenderSolidPrimPointXYX => (int)(RenderSolidPrimPointXY & 0xFFFF);
public int RenderSolidPrimPointXYX => (int)((RenderSolidPrimPointXY >> 0) & 0xFFFF);
public int RenderSolidPrimPointXYY => (int)((RenderSolidPrimPointXY >> 16) & 0xFFFF);
public fixed uint Reserved5E4[7];
public Array64<RenderSolidPrimPoint> RenderSolidPrimPoint;
public uint SetPixelsFromCpuDataType;
public SetPixelsFromCpuDataTypeV SetPixelsFromCpuDataTypeV => (SetPixelsFromCpuDataTypeV)(SetPixelsFromCpuDataType & 0x1);
public SetPixelsFromCpuDataTypeV SetPixelsFromCpuDataTypeV => (SetPixelsFromCpuDataTypeV)((SetPixelsFromCpuDataType >> 0) & 0x1);
public uint SetPixelsFromCpuColorFormat;
public SetPixelsFromCpuColorFormatV SetPixelsFromCpuColorFormatV => (SetPixelsFromCpuColorFormatV)(SetPixelsFromCpuColorFormat & 0xFF);
public SetPixelsFromCpuColorFormatV SetPixelsFromCpuColorFormatV => (SetPixelsFromCpuColorFormatV)((SetPixelsFromCpuColorFormat >> 0) & 0xFF);
public uint SetPixelsFromCpuIndexFormat;
public SetPixelsFromCpuIndexFormatV SetPixelsFromCpuIndexFormatV => (SetPixelsFromCpuIndexFormatV)(SetPixelsFromCpuIndexFormat & 0x3);
public SetPixelsFromCpuIndexFormatV SetPixelsFromCpuIndexFormatV => (SetPixelsFromCpuIndexFormatV)((SetPixelsFromCpuIndexFormat >> 0) & 0x3);
public uint SetPixelsFromCpuMonoFormat;
public SetPixelsFromCpuMonoFormatV SetPixelsFromCpuMonoFormatV => (SetPixelsFromCpuMonoFormatV)(SetPixelsFromCpuMonoFormat & 0x1);
public SetPixelsFromCpuMonoFormatV SetPixelsFromCpuMonoFormatV => (SetPixelsFromCpuMonoFormatV)((SetPixelsFromCpuMonoFormat >> 0) & 0x1);
public uint SetPixelsFromCpuWrap;
public SetPixelsFromCpuWrapV SetPixelsFromCpuWrapV => (SetPixelsFromCpuWrapV)(SetPixelsFromCpuWrap & 0x3);
public SetPixelsFromCpuWrapV SetPixelsFromCpuWrapV => (SetPixelsFromCpuWrapV)((SetPixelsFromCpuWrap >> 0) & 0x3);
public uint SetPixelsFromCpuColor0;
public uint SetPixelsFromCpuColor1;
public uint SetPixelsFromCpuMonoOpacity;
public SetPixelsFromCpuMonoOpacityV SetPixelsFromCpuMonoOpacityV => (SetPixelsFromCpuMonoOpacityV)(SetPixelsFromCpuMonoOpacity & 0x1);
public SetPixelsFromCpuMonoOpacityV SetPixelsFromCpuMonoOpacityV => (SetPixelsFromCpuMonoOpacityV)((SetPixelsFromCpuMonoOpacity >> 0) & 0x1);
public fixed uint Reserved820[6];
public uint SetPixelsFromCpuSrcWidth;
public uint SetPixelsFromCpuSrcHeight;
@@ -753,13 +753,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
public bool SetBigEndianControlOverride => (SetBigEndianControl & 0x10000000) != 0;
public fixed uint Reserved874[3];
public uint SetPixelsFromMemoryBlockShape;
public SetPixelsFromMemoryBlockShapeV SetPixelsFromMemoryBlockShapeV => (SetPixelsFromMemoryBlockShapeV)(SetPixelsFromMemoryBlockShape & 0x7);
public SetPixelsFromMemoryBlockShapeV SetPixelsFromMemoryBlockShapeV => (SetPixelsFromMemoryBlockShapeV)((SetPixelsFromMemoryBlockShape >> 0) & 0x7);
public uint SetPixelsFromMemoryCorralSize;
public int SetPixelsFromMemoryCorralSizeV => (int)(SetPixelsFromMemoryCorralSize & 0x3FF);
public int SetPixelsFromMemoryCorralSizeV => (int)((SetPixelsFromMemoryCorralSize >> 0) & 0x3FF);
public uint SetPixelsFromMemorySafeOverlap;
public bool SetPixelsFromMemorySafeOverlapV => (SetPixelsFromMemorySafeOverlap & 0x1) != 0;
public uint SetPixelsFromMemorySampleMode;
public SetPixelsFromMemorySampleModeOrigin SetPixelsFromMemorySampleModeOrigin => (SetPixelsFromMemorySampleModeOrigin)(SetPixelsFromMemorySampleMode & 0x1);
public SetPixelsFromMemorySampleModeOrigin SetPixelsFromMemorySampleModeOrigin => (SetPixelsFromMemorySampleModeOrigin)((SetPixelsFromMemorySampleMode >> 0) & 0x1);
public SetPixelsFromMemorySampleModeFilter SetPixelsFromMemorySampleModeFilter => (SetPixelsFromMemorySampleModeFilter)((SetPixelsFromMemorySampleMode >> 4) & 0x1);
public fixed uint Reserved890[8];
public uint SetPixelsFromMemoryDstX0;

View File

@@ -390,6 +390,7 @@ namespace Ryujinx.Graphics.Gpu
/// </summary>
public void Dispose()
{
Renderer.Dispose();
GPFifo.Dispose();
HostInitalized.Dispose();
@@ -402,8 +403,6 @@ namespace Ryujinx.Graphics.Gpu
PhysicalMemoryRegistry.Clear();
RunDeferredActions();
Renderer.Dispose();
}
}
}

View File

@@ -541,8 +541,7 @@ namespace Ryujinx.Graphics.Gpu.Image
depth,
lhs.FormatInfo.BlockHeight,
lhs.GobBlocksInY,
lhs.GobBlocksInZ,
level);
lhs.GobBlocksInZ);
return gobBlocksInY == rhs.GobBlocksInY &&
gobBlocksInZ == rhs.GobBlocksInZ;
@@ -588,8 +587,7 @@ namespace Ryujinx.Graphics.Gpu.Image
lhsDepth,
lhs.FormatInfo.BlockHeight,
lhs.GobBlocksInY,
lhs.GobBlocksInZ,
lhsLevel);
lhs.GobBlocksInZ);
int rhsHeight = Math.Max(1, rhs.Height >> rhsLevel);
int rhsDepth = Math.Max(1, rhs.GetDepth() >> rhsLevel);
@@ -599,8 +597,7 @@ namespace Ryujinx.Graphics.Gpu.Image
rhsDepth,
rhs.FormatInfo.BlockHeight,
rhs.GobBlocksInY,
rhs.GobBlocksInZ,
rhsLevel);
rhs.GobBlocksInZ);
return lhsGobBlocksInY == rhsGobBlocksInY &&
lhsGobBlocksInZ == rhsGobBlocksInZ;

View File

@@ -484,7 +484,7 @@ namespace Ryujinx.Graphics.Gpu.Image
depthOrLayers = Math.Max(1, depthOrLayers >> minLod);
}
(gobBlocksInY, gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(height, depth, formatInfo.BlockHeight, gobBlocksInY, gobBlocksInZ, minLod);
(gobBlocksInY, gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(height, depth, formatInfo.BlockHeight, gobBlocksInY, gobBlocksInZ);
}
levels = (maxLod - minLod) + 1;

View File

@@ -222,7 +222,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
private void RecordStorageAlignment(BuffersPerStage buffers, int index, ulong gpuVa)
{
bool unaligned = (gpuVa & ((ulong)_context.Capabilities.StorageBufferOffsetAlignment - 1)) != 0;
bool unaligned = (gpuVa & (Constants.StorageAlignment - 1)) != 0;
if (unaligned || HasUnalignedStorageBuffers)
{

View File

@@ -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 = 5044;
private const uint CodeGenVersion = 5027;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";

View File

@@ -17,6 +17,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
private readonly ResourceCounts _resourceCounts;
private readonly int _stageIndex;
private readonly int[] _constantBufferBindings;
/// <summary>
/// Creates a new GPU accessor.
/// </summary>
@@ -26,6 +28,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
_context = context;
_resourceCounts = resourceCounts;
_stageIndex = stageIndex;
if (context.Capabilities.Api != TargetApi.Vulkan)
{
_constantBufferBindings = new int[Constants.TotalGpUniformBuffers];
_constantBufferBindings.AsSpan().Fill(-1);
}
}
public int QueryBindingConstantBuffer(int index)
@@ -37,7 +45,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
else
{
return _resourceCounts.UniformBuffersCount++;
int binding = _constantBufferBindings[index];
if (binding < 0)
{
binding = _resourceCounts.UniformBuffersCount++;
_constantBufferBindings[index] = binding;
}
return binding;
}
}
@@ -141,10 +157,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot;
public bool QueryHostSupportsShaderBarrierDivergence() => _context.Capabilities.SupportsShaderBarrierDivergence;
public bool QueryHostSupportsShaderFloat64() => _context.Capabilities.SupportsShaderFloat64;
public bool QueryHostSupportsSnormBufferTextureFormat() => _context.Capabilities.SupportsSnormBufferTextureFormat;
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;

View File

@@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
int imageBinding = stageIndex * imagesPerStage * 2;
AddDescriptor(stages, ResourceType.UniformBuffer, UniformSetIndex, uniformBinding, uniformsPerStage);
AddDescriptor(stages, ResourceType.StorageBuffer, StorageSetIndex, storageBinding, storagesPerStage);
AddArrayDescriptor(stages, ResourceType.StorageBuffer, StorageSetIndex, storageBinding, storagesPerStage);
AddDualDescriptor(stages, ResourceType.TextureAndSampler, ResourceType.BufferTexture, TextureSetIndex, textureBinding, texturesPerStage);
AddDualDescriptor(stages, ResourceType.Image, ResourceType.BufferImage, ImageSetIndex, imageBinding, imagesPerStage);
@@ -133,6 +133,19 @@ namespace Ryujinx.Graphics.Gpu.Shader
AddDescriptor(stages, type2, setIndex, binding + count, count);
}
/// <summary>
/// Adds an array resource to the list of descriptors.
/// </summary>
/// <param name="stages">Shader stages where the resource is used</param>
/// <param name="type">Type of the resource</param>
/// <param name="setIndex">Descriptor set number where the resource will be bound</param>
/// <param name="binding">Binding number where the resource will be bound</param>
/// <param name="count">Number of resources bound at the binding location</param>
private void AddArrayDescriptor(ResourceStages stages, ResourceType type, int setIndex, int binding, int count)
{
_resourceDescriptors[setIndex].Add(new ResourceDescriptor(binding, count, type, stages));
}
/// <summary>
/// Adds buffer usage information to the list of usages.
/// </summary>

View File

@@ -736,19 +736,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
return MatchesTexture(specializationState, descriptor);
}
/// <summary>
/// Populates pipeline state that doesn't exist in older caches with default values
/// based on specialization state.
/// </summary>
/// <param name="pipelineState">Pipeline state to prepare</param>
private void PreparePipelineState(ref ProgramPipelineState pipelineState)
{
if (!_compute)
{
pipelineState.DepthMode = GraphicsState.DepthMode ? DepthMode.MinusOneToOne : DepthMode.ZeroToOne;
}
}
/// <summary>
/// Reads shader specialization state that has been serialized.
/// </summary>
@@ -789,8 +776,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
{
ProgramPipelineState pipelineState = default;
dataReader.ReadWithMagicAndSize(ref pipelineState, PgpsMagic);
specState.PreparePipelineState(ref pipelineState);
specState.PipelineState = pipelineState;
}

View File

@@ -127,7 +127,6 @@ namespace Ryujinx.Graphics.OpenGL
public Capabilities GetCapabilities()
{
bool intelWindows = HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows;
bool intelUnix = HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelUnix;
bool amdWindows = HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows;
return new Capabilities(
@@ -159,8 +158,6 @@ namespace Ryujinx.Graphics.OpenGL
supportsCubemapView: true,
supportsNonConstantTextureOffset: HwCapabilities.SupportsNonConstantTextureOffset,
supportsShaderBallot: HwCapabilities.SupportsShaderBallot,
supportsShaderBarrierDivergence: !(intelWindows || intelUnix),
supportsShaderFloat64: true,
supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod,
supportsViewportIndexVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
supportsViewportMask: HwCapabilities.SupportsViewportArray2,

View File

@@ -104,7 +104,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
DeclareConstantBuffers(context, context.Config.Properties.ConstantBuffers.Values);
DeclareStorageBuffers(context, context.Config.Properties.StorageBuffers.Values);
var sBufferDescriptors = context.Config.GetStorageBufferDescriptors();
if (sBufferDescriptors.Length != 0)
{
DeclareStorages(context, sBufferDescriptors);
context.AppendLine();
}
var textureDescriptors = context.Config.GetTextureDescriptors();
if (textureDescriptors.Length != 0)
@@ -243,6 +250,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Shared.glsl");
}
if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Storage) != 0)
{
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Storage.glsl");
}
if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0)
{
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl");
@@ -278,6 +290,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/StoreSharedSmallInt.glsl");
}
if ((info.HelperFunctionsMask & HelperFunctionsMask.StoreStorageSmallInt) != 0)
{
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/StoreStorageSmallInt.glsl");
}
if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0)
{
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl");
@@ -339,16 +356,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
private static void DeclareConstantBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers)
{
DeclareBuffers(context, buffers, "uniform");
}
private static void DeclareStorageBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers)
{
DeclareBuffers(context, buffers, "buffer");
}
private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, string declType)
{
foreach (BufferDefinition buffer in buffers)
{
@@ -358,7 +365,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
_ => "std430"
};
context.AppendLine($"layout (binding = {buffer.Binding}, {layout}) {declType} _{buffer.Name}");
context.AppendLine($"layout (binding = {buffer.Binding}, {layout}) uniform _{buffer.Name}");
context.EnterScope();
foreach (StructureField field in buffer.Type.Fields)
@@ -366,17 +373,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (field.Type.HasFlag(AggregateType.Array))
{
string typeName = GetVarTypeName(context, field.Type & ~AggregateType.Array);
string arraySize = field.ArrayLength.ToString(CultureInfo.InvariantCulture);
if (field.ArrayLength > 0)
{
string arraySize = field.ArrayLength.ToString(CultureInfo.InvariantCulture);
context.AppendLine($"{typeName} {field.Name}[{arraySize}];");
}
else
{
context.AppendLine($"{typeName} {field.Name}[];");
}
context.AppendLine($"{typeName} {field.Name}[{arraySize}];");
}
else
{
@@ -391,6 +390,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
}
private static void DeclareStorages(CodeGenContext context, BufferDescriptor[] descriptors)
{
string sbName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
sbName += "_" + DefaultNames.StorageNamePrefix;
string blockName = $"{sbName}_{DefaultNames.BlockSuffix}";
string layout = context.Config.Options.TargetApi == TargetApi.Vulkan ? ", set = 1" : string.Empty;
context.AppendLine($"layout (binding = {context.Config.FirstStorageBufferBinding}{layout}, std430) buffer {blockName}");
context.EnterScope();
context.AppendLine("uint " + DefaultNames.DataName + "[];");
context.LeaveScope($" {sbName}[{NumberFormatter.FormatInt(descriptors.Max(x => x.Slot) + 1)}];");
}
private static void DeclareSamplers(CodeGenContext context, TextureDescriptor[] descriptors)
{
int arraySize = 0;
@@ -718,6 +733,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
code = code.Replace("\t", CodeGenContext.Tab);
code = code.Replace("$SHARED_MEM$", DefaultNames.SharedMemoryName);
code = code.Replace("$STORAGE_MEM$", OperandManager.GetShaderStagePrefix(context.Config.Stage) + "_" + DefaultNames.StorageNamePrefix);
if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot())
{

View File

@@ -11,6 +11,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public const string IAttributePrefix = "in_attr";
public const string OAttributePrefix = "out_attr";
public const string StorageNamePrefix = "s";
public const string DataName = "data";
public const string BlockSuffix = "block";
public const string LocalMemoryName = "local_mem";
public const string SharedMemoryName = "shared_mem";

View File

@@ -28,18 +28,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
for (int i = 1; i < info.Functions.Count; i++)
{
PrintFunction(context, info.Functions[i]);
PrintFunction(context, info, info.Functions[i]);
context.AppendLine();
}
}
PrintFunction(context, info.Functions[0], MainFunctionName);
PrintFunction(context, info, info.Functions[0], MainFunctionName);
return context.GetCode();
}
private static void PrintFunction(CodeGenContext context, StructuredFunction function, string funcName = null)
private static void PrintFunction(CodeGenContext context, StructuredProgramInfo info, StructuredFunction function, string funcName = null)
{
context.CurrentFunction = function;
@@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
Declarations.DeclareLocals(context, function);
PrintBlock(context, function.MainBlock, funcName == MainFunctionName);
PrintBlock(context, function.MainBlock);
context.LeaveScope();
}
@@ -72,7 +72,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return $"{Declarations.GetVarTypeName(context, function.ReturnType)} {funcName ?? function.Name}({string.Join(", ", args)})";
}
private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction)
private static void PrintBlock(CodeGenContext context, AstBlock block)
{
AstBlockVisitor visitor = new AstBlockVisitor(block);
@@ -112,32 +112,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
};
bool supportsBarrierDivergence = context.Config.GpuAccessor.QueryHostSupportsShaderBarrierDivergence();
bool mayHaveReturned = false;
foreach (IAstNode node in visitor.Visit())
{
if (node is AstOperation operation)
{
if (!supportsBarrierDivergence)
{
if (operation.Inst == IntermediateRepresentation.Instruction.Barrier)
{
// Barrier on divergent control flow paths may cause the GPU to hang,
// so skip emitting the barrier for those cases.
if (visitor.Block.Type != AstBlockType.Main || mayHaveReturned || !isMainFunction)
{
context.Config.GpuAccessor.Log($"Shader has barrier on potentially divergent block, the barrier will be removed.");
continue;
}
}
else if (operation.Inst == IntermediateRepresentation.Instruction.Return)
{
mayHaveReturned = true;
}
}
string expr = InstGen.GetExpression(context, operation);
if (expr != null)

View File

@@ -0,0 +1,21 @@
int Helper_AtomicMaxS32(int index, int offset, int value)
{
uint oldValue, newValue;
do
{
oldValue = $STORAGE_MEM$[index].data[offset];
newValue = uint(max(int(oldValue), value));
} while (atomicCompSwap($STORAGE_MEM$[index].data[offset], oldValue, newValue) != oldValue);
return int(oldValue);
}
int Helper_AtomicMinS32(int index, int offset, int value)
{
uint oldValue, newValue;
do
{
oldValue = $STORAGE_MEM$[index].data[offset];
newValue = uint(min(int(oldValue), value));
} while (atomicCompSwap($STORAGE_MEM$[index].data[offset], oldValue, newValue) != oldValue);
return int(oldValue);
}

View File

@@ -0,0 +1,23 @@
void Helper_StoreStorage16(int index, int offset, uint value)
{
int wordOffset = offset >> 2;
int bitOffset = (offset & 3) * 8;
uint oldValue, newValue;
do
{
oldValue = $STORAGE_MEM$[index].data[wordOffset];
newValue = bitfieldInsert(oldValue, value, bitOffset, 16);
} while (atomicCompSwap($STORAGE_MEM$[index].data[wordOffset], oldValue, newValue) != oldValue);
}
void Helper_StoreStorage8(int index, int offset, uint value)
{
int wordOffset = offset >> 2;
int bitOffset = (offset & 3) * 8;
uint oldValue, newValue;
do
{
oldValue = $STORAGE_MEM$[index].data[wordOffset];
newValue = bitfieldInsert(oldValue, value, bitOffset, 8);
} while (atomicCompSwap($STORAGE_MEM$[index].data[wordOffset], oldValue, newValue) != oldValue);
}

View File

@@ -68,45 +68,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string args = string.Empty;
if (atomic && operation.StorageKind == StorageKind.StorageBuffer)
for (int argIndex = 0; argIndex < arity; argIndex++)
{
args = GenerateLoadOrStore(context, operation, isStore: false);
AggregateType dstType = operation.Inst == Instruction.AtomicMaxS32 || operation.Inst == Instruction.AtomicMinS32
? AggregateType.S32
: AggregateType.U32;
for (int argIndex = operation.SourcesCount - arity + 2; argIndex < operation.SourcesCount; argIndex++)
{
args += ", " + GetSoureExpr(context, operation.GetSource(argIndex), dstType);
}
}
else if (atomic && operation.StorageKind == StorageKind.SharedMemory)
{
args = LoadShared(context, operation);
// For shared memory access, the second argument is unused and should be ignored.
// It is there to make both storage and shared access have the same number of arguments.
// For storage, both inputs are consumed when the argument index is 0, so we should skip it here.
if (argIndex == 1 && (atomic || operation.StorageKind == StorageKind.SharedMemory))
{
continue;
}
for (int argIndex = 2; argIndex < arity; argIndex++)
if (argIndex != 0)
{
args += ", ";
AggregateType dstType = GetSrcVarType(inst, argIndex);
args += GetSoureExpr(context, operation.GetSource(argIndex), dstType);
}
}
else
{
for (int argIndex = 0; argIndex < arity; argIndex++)
{
if (argIndex != 0)
{
args += ", ";
}
if (argIndex == 0 && atomic)
{
switch (operation.StorageKind)
{
case StorageKind.SharedMemory: args += LoadShared(context, operation); break;
case StorageKind.StorageBuffer: args += LoadStorage(context, operation); break;
default: throw new InvalidOperationException($"Invalid storage kind \"{operation.StorageKind}\".");
}
}
else
{
AggregateType dstType = GetSrcVarType(inst, argIndex);
args += GetSoureExpr(context, operation.GetSource(argIndex), dstType);
@@ -185,6 +173,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.LoadShared:
return LoadShared(context, operation);
case Instruction.LoadStorage:
return LoadStorage(context, operation);
case Instruction.Lod:
return Lod(context, operation);
@@ -212,6 +203,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.StoreShared8:
return StoreShared8(context, operation);
case Instruction.StoreStorage:
return StoreStorage(context, operation);
case Instruction.StoreStorage16:
return StoreStorage16(context, operation);
case Instruction.StoreStorage8:
return StoreStorage8(context, operation);
case Instruction.TextureSample:
return TextureSample(context, operation);

View File

@@ -85,6 +85,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.Load, InstType.Special);
Add(Instruction.LoadLocal, InstType.Special);
Add(Instruction.LoadShared, InstType.Special);
Add(Instruction.LoadStorage, InstType.Special);
Add(Instruction.Lod, InstType.Special);
Add(Instruction.LogarithmB2, InstType.CallUnary, "log2");
Add(Instruction.LogicalAnd, InstType.OpBinaryCom, "&&", 9);
@@ -122,6 +123,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.StoreShared, InstType.Special);
Add(Instruction.StoreShared16, InstType.Special);
Add(Instruction.StoreShared8, InstType.Special);
Add(Instruction.StoreStorage, InstType.Special);
Add(Instruction.StoreStorage16, InstType.Special);
Add(Instruction.StoreStorage8, InstType.Special);
Add(Instruction.Subtract, InstType.OpBinary, "-", 2);
Add(Instruction.SwizzleAdd, InstType.CallTernary, HelperFunctionNames.SwizzleAdd);
Add(Instruction.TextureSample, InstType.Special);

View File

@@ -210,6 +210,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return $"{arrayName}[{offsetExpr}]";
}
public static string LoadStorage(CodeGenContext context, AstOperation operation)
{
IAstNode src1 = operation.GetSource(0);
IAstNode src2 = operation.GetSource(1);
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
return GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
}
public static string Lod(CodeGenContext context, AstOperation operation)
{
AstTextureOperation texOp = (AstTextureOperation)operation;
@@ -315,6 +326,60 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return $"{HelperFunctionNames.StoreShared8}({offsetExpr}, {src})";
}
public static string StoreStorage(CodeGenContext context, AstOperation operation)
{
IAstNode src1 = operation.GetSource(0);
IAstNode src2 = operation.GetSource(1);
IAstNode src3 = operation.GetSource(2);
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
AggregateType srcType = OperandManager.GetNodeDestType(context, src3);
string src = TypeConversion.ReinterpretCast(context, src3, srcType, AggregateType.U32);
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
return $"{sb} = {src}";
}
public static string StoreStorage16(CodeGenContext context, AstOperation operation)
{
IAstNode src1 = operation.GetSource(0);
IAstNode src2 = operation.GetSource(1);
IAstNode src3 = operation.GetSource(2);
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
AggregateType srcType = OperandManager.GetNodeDestType(context, src3);
string src = TypeConversion.ReinterpretCast(context, src3, srcType, AggregateType.U32);
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
return $"{HelperFunctionNames.StoreStorage16}({indexExpr}, {offsetExpr}, {src})";
}
public static string StoreStorage8(CodeGenContext context, AstOperation operation)
{
IAstNode src1 = operation.GetSource(0);
IAstNode src2 = operation.GetSource(1);
IAstNode src3 = operation.GetSource(2);
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
AggregateType srcType = OperandManager.GetNodeDestType(context, src3);
string src = TypeConversion.ReinterpretCast(context, src3, srcType, AggregateType.U32);
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
return $"{HelperFunctionNames.StoreStorage8}({indexExpr}, {offsetExpr}, {src})";
}
public static string TextureSample(CodeGenContext context, AstOperation operation)
{
AstTextureOperation texOp = (AstTextureOperation)operation;
@@ -636,34 +701,25 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
}
}
public static string GenerateLoadOrStore(CodeGenContext context, AstOperation operation, bool isStore)
private static string GenerateLoadOrStore(CodeGenContext context, AstOperation operation, bool isStore)
{
StorageKind storageKind = operation.StorageKind;
string varName;
AggregateType varType;
int srcIndex = 0;
bool isStoreOrAtomic = operation.Inst == Instruction.Store || operation.Inst.IsAtomic();
int inputsCount = isStoreOrAtomic ? operation.SourcesCount - 1 : operation.SourcesCount;
if (operation.Inst == Instruction.AtomicCompareAndSwap)
{
inputsCount--;
}
int inputsCount = isStore ? operation.SourcesCount - 1 : operation.SourcesCount;
switch (storageKind)
{
case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
{
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
}
int binding = bindingIndex.Value;
BufferDefinition buffer = storageKind == StorageKind.ConstantBuffer
? context.Config.Properties.ConstantBuffers[binding]
: context.Config.Properties.StorageBuffers[binding];
BufferDefinition buffer = context.Config.Properties.ConstantBuffers[binding];
if (!(operation.GetSource(srcIndex++) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
{
@@ -769,6 +825,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return varName;
}
private static string GetStorageBufferAccessor(string slotExpr, string offsetExpr, ShaderStage stage)
{
string sbName = OperandManager.GetShaderStagePrefix(stage);
sbName += "_" + DefaultNames.StorageNamePrefix;
return $"{sbName}[{slotExpr}].{DefaultNames.DataName}[{offsetExpr}]";
}
private static string GetMask(int index)
{
return $".{"rgba".AsSpan(index, 1)}";

View File

@@ -118,7 +118,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
switch (operation.StorageKind)
{
case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer:
if (!(operation.GetSource(0) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
{
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
@@ -129,9 +128,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
}
BufferDefinition buffer = operation.StorageKind == StorageKind.ConstantBuffer
? context.Config.Properties.ConstantBuffers[bindingIndex.Value]
: context.Config.Properties.StorageBuffers[bindingIndex.Value];
BufferDefinition buffer = context.Config.Properties.ConstantBuffers[bindingIndex.Value];
StructureField field = buffer.Type.Fields[fieldIndex.Value];
return field.Type & AggregateType.ElementTypeMask;

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public int InputVertices { get; }
public Dictionary<int, Instruction> ConstantBuffers { get; } = new Dictionary<int, Instruction>();
public Dictionary<int, Instruction> StorageBuffers { get; } = new Dictionary<int, Instruction>();
public Instruction StorageBuffersArray { get; set; }
public Instruction LocalMemory { get; set; }
public Instruction SharedMemory { get; set; }
public Dictionary<TextureMeta, SamplerType> SamplersTypes { get; } = new Dictionary<TextureMeta, SamplerType>();
@@ -76,9 +76,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public SpirvDelegates Delegates { get; }
public bool IsMainFunction { get; private set; }
public bool MayHaveReturned { get; set; }
public CodeGenContext(
StructuredProgramInfo info,
ShaderConfig config,
@@ -111,10 +108,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Delegates = new SpirvDelegates(this);
}
public void StartFunction(bool isMainFunction)
public void StartFunction()
{
IsMainFunction = isMainFunction;
MayHaveReturned = false;
_locals.Clear();
_localForArgs.Clear();
_funcArgs.Clear();
@@ -313,14 +308,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
if ((type & AggregateType.Array) != 0)
{
if (length > 0)
{
return TypeArray(GetType(type & ~AggregateType.Array), Constant(TypeU32(), length));
}
else
{
return TypeRuntimeArray(GetType(type & ~AggregateType.Array));
}
return TypeArray(GetType(type & ~AggregateType.Array), Constant(TypeU32(), length));
}
else if ((type & AggregateType.ElementCountMask) != 0)
{

View File

@@ -5,7 +5,6 @@ using Ryujinx.Graphics.Shader.Translation;
using Spv.Generator;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using static Spv.Specification;
@@ -100,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
DeclareConstantBuffers(context, context.Config.Properties.ConstantBuffers.Values);
DeclareStorageBuffers(context, context.Config.Properties.StorageBuffers.Values);
DeclareStorageBuffers(context, context.Config.GetStorageBufferDescriptors());
DeclareSamplers(context, context.Config.GetTextureDescriptors());
DeclareImages(context, context.Config.GetImageDescriptors());
DeclareInputsAndOutputs(context, info);
@@ -128,16 +127,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
private static void DeclareConstantBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers)
{
DeclareBuffers(context, buffers, isBuffer: false);
}
private static void DeclareStorageBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers)
{
DeclareBuffers(context, buffers, isBuffer: true);
}
private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer)
{
HashSet<SpvInstruction> decoratedTypes = new HashSet<SpvInstruction>();
@@ -166,12 +155,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.Decorate(structFieldTypes[fieldIndex], Decoration.ArrayStride, (LiteralInteger)fieldSize);
}
// Zero lengths are assumed to be a "runtime array" (which does not have a explicit length
// specified on the shader, and instead assumes the bound buffer length).
// It is only valid as the last struct element.
Debug.Assert(field.ArrayLength > 0 || fieldIndex == buffer.Type.Fields.Length - 1);
offset += fieldSize * field.ArrayLength;
}
else
@@ -180,37 +163,56 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
}
var structType = context.TypeStruct(false, structFieldTypes);
var ubStructType = context.TypeStruct(false, structFieldTypes);
if (decoratedTypes.Add(structType))
if (decoratedTypes.Add(ubStructType))
{
context.Decorate(structType, isBuffer ? Decoration.BufferBlock : Decoration.Block);
context.Decorate(ubStructType, Decoration.Block);
for (int fieldIndex = 0; fieldIndex < structFieldOffsets.Length; fieldIndex++)
{
context.MemberDecorate(structType, fieldIndex, Decoration.Offset, (LiteralInteger)structFieldOffsets[fieldIndex]);
context.MemberDecorate(ubStructType, fieldIndex, Decoration.Offset, (LiteralInteger)structFieldOffsets[fieldIndex]);
}
}
var pointerType = context.TypePointer(StorageClass.Uniform, structType);
var variable = context.Variable(pointerType, StorageClass.Uniform);
var ubPointerType = context.TypePointer(StorageClass.Uniform, ubStructType);
var ubVariable = context.Variable(ubPointerType, StorageClass.Uniform);
context.Name(variable, buffer.Name);
context.Decorate(variable, Decoration.DescriptorSet, (LiteralInteger)buffer.Set);
context.Decorate(variable, Decoration.Binding, (LiteralInteger)buffer.Binding);
context.AddGlobalVariable(variable);
if (isBuffer)
{
context.StorageBuffers.Add(buffer.Binding, variable);
}
else
{
context.ConstantBuffers.Add(buffer.Binding, variable);
}
context.Name(ubVariable, buffer.Name);
context.Decorate(ubVariable, Decoration.DescriptorSet, (LiteralInteger)buffer.Set);
context.Decorate(ubVariable, Decoration.Binding, (LiteralInteger)buffer.Binding);
context.AddGlobalVariable(ubVariable);
context.ConstantBuffers.Add(buffer.Binding, ubVariable);
}
}
private static void DeclareStorageBuffers(CodeGenContext context, BufferDescriptor[] descriptors)
{
if (descriptors.Length == 0)
{
return;
}
int setIndex = context.Config.Options.TargetApi == TargetApi.Vulkan ? 1 : 0;
int count = descriptors.Max(x => x.Slot) + 1;
var sbArrayType = context.TypeRuntimeArray(context.TypeU32());
context.Decorate(sbArrayType, Decoration.ArrayStride, (LiteralInteger)4);
var sbStructType = context.TypeStruct(true, sbArrayType);
context.Decorate(sbStructType, Decoration.BufferBlock);
context.MemberDecorate(sbStructType, 0, Decoration.Offset, (LiteralInteger)0);
var sbStructArrayType = context.TypeArray(sbStructType, context.Constant(context.TypeU32(), count));
var sbPointerType = context.TypePointer(StorageClass.Uniform, sbStructArrayType);
var sbVariable = context.Variable(sbPointerType, StorageClass.Uniform);
context.Name(sbVariable, $"{GetStagePrefix(context.Config.Stage)}_s");
context.Decorate(sbVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex);
context.Decorate(sbVariable, Decoration.Binding, (LiteralInteger)context.Config.FirstStorageBufferBinding);
context.AddGlobalVariable(sbVariable);
context.StorageBuffersArray = sbVariable;
}
private static void DeclareSamplers(CodeGenContext context, TextureDescriptor[] descriptors)
{
foreach (var descriptor in descriptors)

View File

@@ -99,6 +99,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Add(Instruction.Load, GenerateLoad);
Add(Instruction.LoadLocal, GenerateLoadLocal);
Add(Instruction.LoadShared, GenerateLoadShared);
Add(Instruction.LoadStorage, GenerateLoadStorage);
Add(Instruction.Lod, GenerateLod);
Add(Instruction.LogarithmB2, GenerateLogarithmB2);
Add(Instruction.LogicalAnd, GenerateLogicalAnd);
@@ -136,6 +137,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Add(Instruction.StoreShared, GenerateStoreShared);
Add(Instruction.StoreShared16, GenerateStoreShared16);
Add(Instruction.StoreShared8, GenerateStoreShared8);
Add(Instruction.StoreStorage, GenerateStoreStorage);
Add(Instruction.StoreStorage16, GenerateStoreStorage16);
Add(Instruction.StoreStorage8, GenerateStoreStorage8);
Add(Instruction.Subtract, GenerateSubtract);
Add(Instruction.SwizzleAdd, GenerateSwizzleAdd);
Add(Instruction.TextureSample, GenerateTextureSample);
@@ -242,16 +246,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static OperationResult GenerateBarrier(CodeGenContext context, AstOperation operation)
{
// Barrier on divergent control flow paths may cause the GPU to hang,
// so skip emitting the barrier for those cases.
if (!context.Config.GpuAccessor.QueryHostSupportsShaderBarrierDivergence() &&
(context.CurrentBlock.Type != AstBlockType.Main || context.MayHaveReturned || !context.IsMainFunction))
{
context.Config.GpuAccessor.Log($"Shader has barrier on potentially divergent block, the barrier will be removed.");
return OperationResult.Invalid;
}
context.ControlBarrier(
context.Constant(context.TypeU32(), Scope.Workgroup),
context.Constant(context.TypeU32(), Scope.Workgroup),
@@ -895,6 +889,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return new OperationResult(AggregateType.U32, value);
}
private static OperationResult GenerateLoadStorage(CodeGenContext context, AstOperation operation)
{
var elemPointer = GetStorageElemPointer(context, operation);
var value = context.Load(context.TypeU32(), elemPointer);
return new OperationResult(AggregateType.U32, value);
}
private static OperationResult GenerateLod(CodeGenContext context, AstOperation operation)
{
AstTextureOperation texOp = (AstTextureOperation)operation;
@@ -1102,8 +1104,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static OperationResult GenerateReturn(CodeGenContext context, AstOperation operation)
{
context.MayHaveReturned = true;
if (operation.SourcesCount != 0)
{
context.ReturnValue(context.Get(context.CurrentFunction.ReturnType, operation.GetSource(0)));
@@ -1307,6 +1307,28 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return OperationResult.Invalid;
}
private static OperationResult GenerateStoreStorage(CodeGenContext context, AstOperation operation)
{
var elemPointer = GetStorageElemPointer(context, operation);
context.Store(elemPointer, context.Get(AggregateType.U32, operation.GetSource(2)));
return OperationResult.Invalid;
}
private static OperationResult GenerateStoreStorage16(CodeGenContext context, AstOperation operation)
{
GenerateStoreStorageSmallInt(context, operation, 16);
return OperationResult.Invalid;
}
private static OperationResult GenerateStoreStorage8(CodeGenContext context, AstOperation operation)
{
GenerateStoreStorageSmallInt(context, operation, 8);
return OperationResult.Invalid;
}
private static OperationResult GenerateSubtract(CodeGenContext context, AstOperation operation)
{
return GenerateBinary(context, operation, context.Delegates.FSub, context.Delegates.ISub);
@@ -1827,13 +1849,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AstOperation operation,
Func<SpvInstruction, SpvInstruction, SpvInstruction, SpvInstruction, SpvInstruction, SpvInstruction> emitU)
{
var value = context.GetU32(operation.GetSource(operation.SourcesCount - 1));
var value = context.GetU32(operation.GetSource(2));
SpvInstruction elemPointer;
if (operation.StorageKind == StorageKind.StorageBuffer)
{
elemPointer = GetStoragePointer(context, operation, out _);
elemPointer = GetStorageElemPointer(context, operation);
}
else if (operation.StorageKind == StorageKind.SharedMemory)
{
@@ -1853,14 +1875,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static OperationResult GenerateAtomicMemoryCas(CodeGenContext context, AstOperation operation)
{
var value0 = context.GetU32(operation.GetSource(operation.SourcesCount - 2));
var value1 = context.GetU32(operation.GetSource(operation.SourcesCount - 1));
var value0 = context.GetU32(operation.GetSource(2));
var value1 = context.GetU32(operation.GetSource(3));
SpvInstruction elemPointer;
if (operation.StorageKind == StorageKind.StorageBuffer)
{
elemPointer = GetStoragePointer(context, operation, out _);
elemPointer = GetStorageElemPointer(context, operation);
}
else if (operation.StorageKind == StorageKind.SharedMemory)
{
@@ -1879,33 +1901,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
private static OperationResult GenerateLoadOrStore(CodeGenContext context, AstOperation operation, bool isStore)
{
SpvInstruction pointer = GetStoragePointer(context, operation, out AggregateType varType);
if (isStore)
{
context.Store(pointer, context.Get(varType, operation.GetSource(operation.SourcesCount - 1)));
return OperationResult.Invalid;
}
else
{
var result = context.Load(context.GetType(varType), pointer);
return new OperationResult(varType, result);
}
}
private static SpvInstruction GetStoragePointer(CodeGenContext context, AstOperation operation, out AggregateType varType)
{
StorageKind storageKind = operation.StorageKind;
StorageClass storageClass;
SpvInstruction baseObj;
AggregateType varType;
int srcIndex = 0;
switch (storageKind)
{
case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
{
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
@@ -1916,16 +1922,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
}
BufferDefinition buffer = storageKind == StorageKind.ConstantBuffer
? context.Config.Properties.ConstantBuffers[bindingIndex.Value]
: context.Config.Properties.StorageBuffers[bindingIndex.Value];
BufferDefinition buffer = context.Config.Properties.ConstantBuffers[bindingIndex.Value];
StructureField field = buffer.Type.Fields[fieldIndex.Value];
storageClass = StorageClass.Uniform;
varType = field.Type & AggregateType.ElementTypeMask;
baseObj = storageKind == StorageKind.ConstantBuffer
? context.ConstantBuffers[bindingIndex.Value]
: context.StorageBuffers[bindingIndex.Value];
baseObj = context.ConstantBuffers[bindingIndex.Value];
break;
case StorageKind.Input:
@@ -1991,14 +1993,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
throw new InvalidOperationException($"Invalid storage kind {storageKind}.");
}
bool isStoreOrAtomic = operation.Inst == Instruction.Store || operation.Inst.IsAtomic();
int inputsCount = (isStoreOrAtomic ? operation.SourcesCount - 1 : operation.SourcesCount) - srcIndex;
if (operation.Inst == Instruction.AtomicCompareAndSwap)
{
inputsCount--;
}
int inputsCount = (isStore ? operation.SourcesCount - 1 : operation.SourcesCount) - srcIndex;
SpvInstruction e0, e1, e2;
SpvInstruction pointer;
@@ -2035,7 +2030,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
break;
}
return pointer;
if (isStore)
{
context.Store(pointer, context.Get(varType, operation.GetSource(srcIndex)));
return OperationResult.Invalid;
}
else
{
var result = context.Load(context.GetType(varType), pointer);
return new OperationResult(varType, result);
}
}
private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable)
@@ -2064,6 +2068,25 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
GenerateStoreSmallInt(context, elemPointer, bitOffset, value, bitSize);
}
private static void GenerateStoreStorageSmallInt(CodeGenContext context, AstOperation operation, int bitSize)
{
var i0 = context.Get(AggregateType.S32, operation.GetSource(0));
var offset = context.Get(AggregateType.U32, operation.GetSource(1));
var value = context.Get(AggregateType.U32, operation.GetSource(2));
var wordOffset = context.ShiftRightLogical(context.TypeU32(), offset, context.Constant(context.TypeU32(), 2));
var bitOffset = context.BitwiseAnd(context.TypeU32(), offset, context.Constant(context.TypeU32(), 3));
bitOffset = context.ShiftLeftLogical(context.TypeU32(), bitOffset, context.Constant(context.TypeU32(), 3));
var sbVariable = context.StorageBuffersArray;
var i1 = context.Constant(context.TypeS32(), 0);
var elemPointer = context.AccessChain(context.TypePointer(StorageClass.Uniform, context.TypeU32()), sbVariable, i0, i1, wordOffset);
GenerateStoreSmallInt(context, elemPointer, bitOffset, value, bitSize);
}
private static void GenerateStoreSmallInt(
CodeGenContext context,
SpvInstruction elemPointer,
@@ -2150,6 +2173,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
}
private static SpvInstruction GetStorageElemPointer(CodeGenContext context, AstOperation operation)
{
var sbVariable = context.StorageBuffersArray;
var i0 = context.Get(AggregateType.S32, operation.GetSource(0));
var i1 = context.Constant(context.TypeS32(), 0);
var i2 = context.Get(AggregateType.S32, operation.GetSource(1));
return context.AccessChain(context.TypePointer(StorageClass.Uniform, context.TypeU32()), sbVariable, i0, i1, i2);
}
private static OperationResult GenerateUnary(
CodeGenContext context,
AstOperation operation,

View File

@@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.CurrentFunction = function;
context.AddFunction(spvFunc);
context.StartFunction(isMainFunction: funcIndex == 0);
context.StartFunction();
Declarations.DeclareParameters(context, function);

View File

@@ -10,5 +10,7 @@ namespace Ryujinx.Graphics.Shader
public const int NvnBaseVertexByteOffset = 0x640;
public const int NvnBaseInstanceByteOffset = 0x644;
public const int NvnDrawIndexByteOffset = 0x648;
public const int StorageAlignment = 16;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -79,7 +79,7 @@ namespace Ryujinx.Graphics.Shader
/// <returns>Binding number</returns>
int QueryBindingConstantBuffer(int index)
{
return index + 1;
return index;
}
/// <summary>
@@ -331,24 +331,6 @@ namespace Ryujinx.Graphics.Shader
return true;
}
/// <summary>
/// Queries host GPU shader support for barrier instructions on divergent control flow paths.
/// </summary>
/// <returns>True if the GPU supports barriers on divergent control flow paths, false otherwise</returns>
bool QueryHostSupportsShaderBarrierDivergence()
{
return true;
}
/// <summary>
/// Queries host GPU support for 64-bit floating point (double precision) operations on the shader.
/// </summary>
/// <returns>True if the GPU and driver supports double operations, false otherwise</returns>
bool QueryHostSupportsShaderFloat64()
{
return true;
}
/// <summary>
/// Queries host GPU support for signed normalized buffer texture formats.
/// </summary>

View File

@@ -164,7 +164,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Ccc == Ccc.T)
{
context.PrepareForReturn();
context.Return();
}
else
@@ -176,7 +175,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
Operand lblSkip = Label();
context.BranchIfFalse(lblSkip, cond);
context.PrepareForReturn();
context.Return();
context.MarkLabel(lblSkip);
}

View File

@@ -336,12 +336,13 @@ namespace Ryujinx.Graphics.Shader.Instructions
int offset,
bool extended)
{
bool isSmallInt = size < LsSize.B32;
int count = GetVectorCount(size);
StorageKind storageKind = GetStorageKind(size);
(_, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset);
(Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset);
Operand srcA = context.Copy(new Operand(new Register(ra, RegisterType.Gpr)));
Operand bitOffset = GetBitOffset(context, addrLow);
for (int index = 0; index < count; index++)
{
@@ -352,7 +353,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
break;
}
Operand value = context.Load(storageKind, context.IAdd(srcA, Const(offset + index * 4)), addrHigh);
Operand value = context.LoadGlobal(context.IAdd(addrLow, Const(index * 4)), addrHigh);
if (isSmallInt)
{
value = ExtractSmallInt(context, size, bitOffset, value);
}
context.Copy(Register(dest), value);
}
@@ -439,11 +445,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
int count = GetVectorCount((LsSize)size);
StorageKind storageKind = GetStorageKind((LsSize)size);
(_, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset);
(Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset);
Operand srcA = context.Copy(new Operand(new Register(ra, RegisterType.Gpr)));
Operand bitOffset = GetBitOffset(context, addrLow);
for (int index = 0; index < count; index++)
{
@@ -451,24 +456,23 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand value = Register(isRz ? rd : rd + index, RegisterType.Gpr);
Operand addrLowOffset = context.IAdd(srcA, Const(offset + index * 4));
Operand addrLowOffset = context.IAdd(addrLow, Const(index * 4));
context.Store(storageKind, addrLowOffset, addrHigh, value);
if (size == LsSize2.U8 || size == LsSize2.S8)
{
context.StoreGlobal8(addrLowOffset, addrHigh, value);
}
else if (size == LsSize2.U16 || size == LsSize2.S16)
{
context.StoreGlobal16(addrLowOffset, addrHigh, value);
}
else
{
context.StoreGlobal(addrLowOffset, addrHigh, value);
}
}
}
private static StorageKind GetStorageKind(LsSize size)
{
return size switch
{
LsSize.U8 => StorageKind.GlobalMemoryU8,
LsSize.S8 => StorageKind.GlobalMemoryS8,
LsSize.U16 => StorageKind.GlobalMemoryU16,
LsSize.S16 => StorageKind.GlobalMemoryS16,
_ => StorageKind.GlobalMemory
};
}
private static int GetVectorCount(LsSize size)
{
switch (size)

View File

@@ -79,8 +79,10 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
ImageAtomic,
IsNan,
Load,
LoadGlobal,
LoadLocal,
LoadShared,
LoadStorage,
Lod,
LogarithmB2,
LogicalAnd,
@@ -115,10 +117,16 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
Sine,
SquareRoot,
Store,
StoreGlobal,
StoreGlobal16,
StoreGlobal8,
StoreLocal,
StoreShared,
StoreShared16,
StoreShared8,
StoreStorage,
StoreStorage16,
StoreStorage8,
Subtract,
SwizzleAdd,
TextureSample,

View File

@@ -255,35 +255,5 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
_sources = new Operand[] { source };
}
public void TurnDoubleIntoFloat()
{
if ((Inst & ~Instruction.Mask) == Instruction.FP64)
{
Inst = (Inst & Instruction.Mask) | Instruction.FP32;
}
else
{
switch (Inst)
{
case Instruction.ConvertFP32ToFP64:
case Instruction.ConvertFP64ToFP32:
Inst = Instruction.Copy;
break;
case Instruction.ConvertFP64ToS32:
Inst = Instruction.ConvertFP32ToS32;
break;
case Instruction.ConvertFP64ToU32:
Inst = Instruction.ConvertFP32ToU32;
break;
case Instruction.ConvertS32ToFP64:
Inst = Instruction.ConvertS32ToFP32;
break;
case Instruction.ConvertU32ToFP64:
Inst = Instruction.ConvertU32ToFP32;
break;
}
}
}
}
}

View File

@@ -11,12 +11,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
StorageBuffer,
LocalMemory,
SharedMemory,
GlobalMemory,
// TODO: Remove those and store type as a field on the Operation class itself.
GlobalMemoryS8,
GlobalMemoryS16,
GlobalMemoryU8,
GlobalMemoryU16
GlobalMemory
}
static class StorageKindExtensions

View File

@@ -11,6 +11,7 @@
<ItemGroup>
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\AtomicMinMaxS32Shared.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\AtomicMinMaxS32Storage.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\MultiplyHighS32.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\MultiplyHighU32.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\Shuffle.glsl" />
@@ -18,6 +19,7 @@
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\ShuffleUp.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\ShuffleXor.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\StoreSharedSmallInt.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\StoreStorageSmallInt.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\SwizzleAdd.glsl" />
</ItemGroup>

View File

@@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
enum HelperFunctionsMask
{
AtomicMinMaxS32Shared = 1 << 0,
AtomicMinMaxS32Storage = 1 << 1,
MultiplyHighS32 = 1 << 2,
MultiplyHighU32 = 1 << 3,
Shuffle = 1 << 4,
@@ -13,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
ShuffleUp = 1 << 6,
ShuffleXor = 1 << 7,
StoreSharedSmallInt = 1 << 8,
StoreStorageSmallInt = 1 << 9,
SwizzleAdd = 1 << 10,
FSI = 1 << 11
}

View File

@@ -90,8 +90,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Add(Instruction.ImageAtomic, AggregateType.S32);
Add(Instruction.IsNan, AggregateType.Bool, AggregateType.Scalar);
Add(Instruction.Load, AggregateType.FP32);
Add(Instruction.LoadGlobal, AggregateType.U32, AggregateType.S32, AggregateType.S32);
Add(Instruction.LoadLocal, AggregateType.U32, AggregateType.S32);
Add(Instruction.LoadShared, AggregateType.U32, AggregateType.S32);
Add(Instruction.LoadStorage, AggregateType.U32, AggregateType.S32, AggregateType.S32);
Add(Instruction.Lod, AggregateType.FP32);
Add(Instruction.LogarithmB2, AggregateType.Scalar, AggregateType.Scalar);
Add(Instruction.LogicalAnd, AggregateType.Bool, AggregateType.Bool, AggregateType.Bool);
@@ -121,10 +123,14 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Add(Instruction.Sine, AggregateType.Scalar, AggregateType.Scalar);
Add(Instruction.SquareRoot, AggregateType.Scalar, AggregateType.Scalar);
Add(Instruction.Store, AggregateType.Void);
Add(Instruction.StoreGlobal, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
Add(Instruction.StoreLocal, AggregateType.Void, AggregateType.S32, AggregateType.U32);
Add(Instruction.StoreShared, AggregateType.Void, AggregateType.S32, AggregateType.U32);
Add(Instruction.StoreShared16, AggregateType.Void, AggregateType.S32, AggregateType.U32);
Add(Instruction.StoreShared8, AggregateType.Void, AggregateType.S32, AggregateType.U32);
Add(Instruction.StoreStorage, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
Add(Instruction.StoreStorage16, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
Add(Instruction.StoreStorage8, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
Add(Instruction.Subtract, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
Add(Instruction.SwizzleAdd, AggregateType.FP32, AggregateType.FP32, AggregateType.FP32, AggregateType.S32);
Add(Instruction.TextureSample, AggregateType.FP32);
@@ -160,7 +166,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{
return AggregateType.FP32;
}
else if (inst == Instruction.Call || inst == Instruction.Load || inst == Instruction.Store || inst.IsAtomic())
else if (inst == Instruction.Call || inst == Instruction.Load || inst == Instruction.Store)
{
return AggregateType.S32;
}

View File

@@ -5,25 +5,17 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
class ShaderProperties
{
private readonly Dictionary<int, BufferDefinition> _constantBuffers;
private readonly Dictionary<int, BufferDefinition> _storageBuffers;
public IReadOnlyDictionary<int, BufferDefinition> ConstantBuffers => _constantBuffers;
public IReadOnlyDictionary<int, BufferDefinition> StorageBuffers => _storageBuffers;
public ShaderProperties()
{
_constantBuffers = new Dictionary<int, BufferDefinition>();
_storageBuffers = new Dictionary<int, BufferDefinition>();
}
public void AddConstantBuffer(int binding, BufferDefinition definition)
{
_constantBuffers[binding] = definition;
}
public void AddStorageBuffer(int binding, BufferDefinition definition)
{
_storageBuffers[binding] = definition;
}
}
}

View File

@@ -280,6 +280,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{
context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared;
}
else if (operation.StorageKind == StorageKind.StorageBuffer)
{
context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage;
}
break;
case Instruction.MultiplyHighS32:
context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32;
@@ -303,6 +307,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
case Instruction.StoreShared8:
context.Info.HelperFunctionsMask |= HelperFunctionsMask.StoreSharedSmallInt;
break;
case Instruction.StoreStorage16:
case Instruction.StoreStorage8:
context.Info.HelperFunctionsMask |= HelperFunctionsMask.StoreStorageSmallInt;
break;
case Instruction.SwizzleAdd:
context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd;
break;

View File

@@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Shader
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int UnpackTextureId(int packedId)
{
return packedId & 0xfffff;
return (packedId >> 0) & 0xfffff;
}
/// <summary>

View File

@@ -57,56 +57,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return context.Add(Instruction.AtomicXor, storageKind, Local(), a, b, c);
}
public static Operand AtomicAdd(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicAdd, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicAnd(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicAnd, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicCompareAndSwap(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand compare, Operand value)
{
return context.Add(Instruction.AtomicCompareAndSwap, storageKind, Local(), Const(binding), e0, e1, compare, value);
}
public static Operand AtomicMaxS32(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicMaxS32, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicMaxU32(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicMaxU32, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicMinS32(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicMinS32, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicMinU32(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicMinU32, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicOr(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicOr, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicSwap(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicSwap, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand AtomicXor(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.AtomicXor, storageKind, Local(), Const(binding), e0, e1, value);
}
public static Operand Ballot(this EmitterContext context, Operand a)
{
return context.Add(Instruction.Ballot, Local(), a);
@@ -604,11 +554,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return context.Add(fpType | Instruction.IsNan, Local(), a);
}
public static Operand Load(this EmitterContext context, StorageKind storageKind, Operand e0, Operand e1)
{
return context.Add(Instruction.Load, storageKind, Local(), e0, e1);
}
public static Operand Load(this EmitterContext context, StorageKind storageKind, int binding)
{
return context.Add(Instruction.Load, storageKind, Local(), Const(binding));
@@ -661,6 +606,11 @@ namespace Ryujinx.Graphics.Shader.Translation
: context.Load(storageKind, (int)ioVariable, arrayIndex, elemIndex);
}
public static Operand LoadGlobal(this EmitterContext context, Operand a, Operand b)
{
return context.Add(Instruction.LoadGlobal, Local(), a, b);
}
public static Operand LoadLocal(this EmitterContext context, Operand a)
{
return context.Add(Instruction.LoadLocal, Local(), a);
@@ -705,6 +655,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public static void Return(this EmitterContext context)
{
context.PrepareForReturn();
context.Add(Instruction.Return);
}
@@ -748,16 +699,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return context.Add(Instruction.ShuffleXor, (Local(), Local()), a, b, c);
}
public static Operand Store(this EmitterContext context, StorageKind storageKind, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.Store, storageKind, null, e0, e1, value);
}
public static Operand Store(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand value)
{
return context.Add(Instruction.Store, storageKind, null, Const(binding), e0, e1, value);
}
public static Operand Store(
this EmitterContext context,
StorageKind storageKind,
@@ -797,6 +738,21 @@ namespace Ryujinx.Graphics.Shader.Translation
: context.Add(Instruction.Store, storageKind, null, Const((int)ioVariable), arrayIndex, elemIndex, value);
}
public static Operand StoreGlobal(this EmitterContext context, Operand a, Operand b, Operand c)
{
return context.Add(Instruction.StoreGlobal, null, a, b, c);
}
public static Operand StoreGlobal16(this EmitterContext context, Operand a, Operand b, Operand c)
{
return context.Add(Instruction.StoreGlobal16, null, a, b, c);
}
public static Operand StoreGlobal8(this EmitterContext context, Operand a, Operand b, Operand c)
{
return context.Add(Instruction.StoreGlobal8, null, a, b, c);
}
public static Operand StoreLocal(this EmitterContext context, Operand a, Operand b)
{
return context.Add(Instruction.StoreLocal, null, a, b);

View File

@@ -0,0 +1,54 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
namespace Ryujinx.Graphics.Shader.Translation
{
static class GlobalMemory
{
private const int StorageDescsBaseOffset = 0x44; // In words.
public const int StorageDescSize = 4; // In words.
public const int StorageMaxCount = 16;
public const int StorageDescsSize = StorageDescSize * StorageMaxCount;
public const int UbeBaseOffset = 0x98; // In words.
public const int UbeMaxCount = 9;
public const int UbeDescsSize = StorageDescSize * UbeMaxCount;
public const int UbeFirstCbuf = 8;
public const int DriverReservedCb = 0;
public static bool UsesGlobalMemory(Instruction inst, StorageKind storageKind)
{
return (inst.IsAtomic() && storageKind == StorageKind.GlobalMemory) ||
inst == Instruction.LoadGlobal ||
inst == Instruction.StoreGlobal ||
inst == Instruction.StoreGlobal16 ||
inst == Instruction.StoreGlobal8;
}
public static int GetStorageCbOffset(ShaderStage stage, int slot)
{
return GetStorageBaseCbOffset(stage) + slot * StorageDescSize;
}
public static int GetStorageBaseCbOffset(ShaderStage stage)
{
return stage switch
{
ShaderStage.Compute => StorageDescsBaseOffset + 2 * StorageDescsSize,
ShaderStage.Vertex => StorageDescsBaseOffset,
ShaderStage.TessellationControl => StorageDescsBaseOffset + 1 * StorageDescsSize,
ShaderStage.TessellationEvaluation => StorageDescsBaseOffset + 2 * StorageDescsSize,
ShaderStage.Geometry => StorageDescsBaseOffset + 3 * StorageDescsSize,
ShaderStage.Fragment => StorageDescsBaseOffset + 4 * StorageDescsSize,
_ => 0
};
}
public static int GetConstantUbeOffset(int slot)
{
return UbeBaseOffset + slot * StorageDescSize;
}
}
}

View File

@@ -19,14 +19,6 @@ namespace Ryujinx.Graphics.Shader.Translation
_stage = stage;
}
public int AddFunction(Function function)
{
int functionId = _functionList.Count;
_functionList.Add(function);
return functionId;
}
public int GetOrCreateFunctionId(HelperFunctionName functionName)
{
if (_functionIds.TryGetValue(functionName, out int functionId))
@@ -35,7 +27,8 @@ namespace Ryujinx.Graphics.Shader.Translation
}
Function function = GenerateFunction(functionName);
functionId = AddFunction(function);
functionId = _functionList.Count;
_functionList.Add(function);
_functionIds.Add(functionName, functionId);
return functionId;
@@ -45,101 +38,12 @@ namespace Ryujinx.Graphics.Shader.Translation
{
return functionName switch
{
HelperFunctionName.ConvertDoubleToFloat => GenerateConvertDoubleToFloatFunction(),
HelperFunctionName.ConvertFloatToDouble => GenerateConvertFloatToDoubleFunction(),
HelperFunctionName.TexelFetchScale => GenerateTexelFetchScaleFunction(),
HelperFunctionName.TextureSizeUnscale => GenerateTextureSizeUnscaleFunction(),
_ => throw new ArgumentException($"Invalid function name {functionName}")
};
}
private Function GenerateConvertDoubleToFloatFunction()
{
EmitterContext context = new EmitterContext();
Operand valueLow = Argument(0);
Operand valueHigh = Argument(1);
Operand mantissaLow = context.BitwiseAnd(valueLow, Const(((1 << 22) - 1)));
Operand mantissa = context.ShiftRightU32(valueLow, Const(22));
mantissa = context.BitwiseOr(mantissa, context.ShiftLeft(context.BitwiseAnd(valueHigh, Const(0xfffff)), Const(10)));
mantissa = context.BitwiseOr(mantissa, context.ConditionalSelect(mantissaLow, Const(1), Const(0)));
Operand exp = context.BitwiseAnd(context.ShiftRightU32(valueHigh, Const(20)), Const(0x7ff));
Operand sign = context.ShiftRightS32(valueHigh, Const(31));
Operand resultSign = context.ShiftLeft(sign, Const(31));
Operand notZero = context.BitwiseOr(mantissa, exp);
Operand lblNotZero = Label();
context.BranchIfTrue(lblNotZero, notZero);
context.Return(resultSign);
context.MarkLabel(lblNotZero);
Operand notNaNOrInf = context.ICompareNotEqual(exp, Const(0x7ff));
mantissa = context.BitwiseOr(mantissa, Const(0x40000000));
exp = context.ISubtract(exp, Const(0x381));
// Note: Overflow cases are not handled here and might produce incorrect results.
Operand roundBits = context.BitwiseAnd(mantissa, Const(0x7f));
Operand roundBitsXor64 = context.BitwiseExclusiveOr(roundBits, Const(0x40));
mantissa = context.ShiftRightU32(context.IAdd(mantissa, Const(0x40)), Const(7));
mantissa = context.BitwiseAnd(mantissa, context.ConditionalSelect(roundBitsXor64, Const(~0), Const(~1)));
exp = context.ConditionalSelect(mantissa, exp, Const(0));
exp = context.ConditionalSelect(notNaNOrInf, exp, Const(0xff));
Operand result = context.IAdd(context.IAdd(mantissa, context.ShiftLeft(exp, Const(23))), resultSign);
context.Return(result);
return new Function(ControlFlowGraph.Create(context.GetOperations()).Blocks, "ConvertDoubleToFloat", true, 2, 0);
}
private Function GenerateConvertFloatToDoubleFunction()
{
EmitterContext context = new EmitterContext();
Operand value = Argument(0);
Operand mantissa = context.BitwiseAnd(value, Const(0x7fffff));
Operand exp = context.BitwiseAnd(context.ShiftRightU32(value, Const(23)), Const(0xff));
Operand sign = context.ShiftRightS32(value, Const(31));
Operand notNaNOrInf = context.ICompareNotEqual(exp, Const(0xff));
Operand expNotZero = context.ICompareNotEqual(exp, Const(0));
Operand notDenorm = context.BitwiseOr(expNotZero, context.ICompareEqual(mantissa, Const(0)));
exp = context.IAdd(exp, Const(0x380));
Operand shiftDist = context.ISubtract(Const(32), context.FindMSBU32(mantissa));
Operand normExp = context.ISubtract(context.ISubtract(Const(1), shiftDist), Const(1));
Operand normMant = context.ShiftLeft(mantissa, shiftDist);
exp = context.ConditionalSelect(notNaNOrInf, exp, Const(0x7ff));
exp = context.ConditionalSelect(notDenorm, exp, normExp);
mantissa = context.ConditionalSelect(expNotZero, mantissa, normMant);
Operand resultLow = context.ShiftLeft(mantissa, Const(29));
Operand resultHigh = context.ShiftRightU32(mantissa, Const(3));
resultHigh = context.IAdd(resultHigh, context.ShiftLeft(exp, Const(20)));
resultHigh = context.IAdd(resultHigh, context.ShiftLeft(sign, Const(31)));
context.Copy(Argument(1), resultLow);
context.Copy(Argument(2), resultHigh);
context.Return();
return new Function(ControlFlowGraph.Create(context.GetOperations()).Blocks, "ConvertFloatToDouble", false, 1, 2);
}
private Function GenerateTexelFetchScaleFunction()
{
EmitterContext context = new EmitterContext();

View File

@@ -1,9 +1,10 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.Translation
{
enum HelperFunctionName
{
ConvertDoubleToFloat,
ConvertFloatToDouble,
TexelFetchScale,
TextureSizeUnscale
}

View File

@@ -1,70 +0,0 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{
static class DoubleToFloat
{
public static void RunPass(HelperFunctionManager hfm, BasicBlock block)
{
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
{
if (node.Value is not Operation operation)
{
continue;
}
node = InsertSoftFloat64(hfm, node);
}
}
private static LinkedListNode<INode> InsertSoftFloat64(HelperFunctionManager hfm, LinkedListNode<INode> node)
{
Operation operation = (Operation)node.Value;
if (operation.Inst == Instruction.PackDouble2x32)
{
int functionId = hfm.GetOrCreateFunctionId(HelperFunctionName.ConvertDoubleToFloat);
Operand[] callArgs = new Operand[] { Const(functionId), operation.GetSource(0), operation.GetSource(1) };
Operand floatValue = operation.Dest;
operation.Dest = null;
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, floatValue, callArgs));
Utils.DeleteNode(node, operation);
return newNode;
}
else if (operation.Inst == Instruction.UnpackDouble2x32)
{
int functionId = hfm.GetOrCreateFunctionId(HelperFunctionName.ConvertFloatToDouble);
// TODO: Allow UnpackDouble2x32 to produce two outputs and get rid of "operation.Index".
Operand resultLow = operation.Index == 0 ? operation.Dest : Local();
Operand resultHigh = operation.Index == 1 ? operation.Dest : Local();
operation.Dest = null;
Operand[] callArgs = new Operand[] { Const(functionId), operation.GetSource(0), resultLow, resultHigh };
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs));
Utils.DeleteNode(node, operation);
return newNode;
}
else
{
operation.TurnDoubleIntoFloat();
return node;
}
}
}
}

View File

@@ -7,19 +7,17 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{
static class Optimizer
{
public static void RunPass(HelperFunctionManager hfm, BasicBlock[] blocks, ShaderConfig config)
public static void RunPass(BasicBlock[] blocks, ShaderConfig config)
{
RunOptimizationPasses(blocks, config);
// TODO: Some of those are not optimizations and shouldn't be here.
GlobalToStorage.RunPass(hfm, blocks, config);
bool hostSupportsShaderFloat64 = config.GpuAccessor.QueryHostSupportsShaderFloat64();
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, ref ubeUseMask);
BindlessToIndexed.RunPass(blocks[blkIndex], config);
BindlessElimination.RunPass(blocks[blkIndex], config);
@@ -28,14 +26,10 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{
EliminateMultiplyByFragmentCoordW(blocks[blkIndex]);
}
// If the host does not support double operations, we need to turn them into float operations.
if (!hostSupportsShaderFloat64)
{
DoubleToFloat.RunPass(hfm, blocks[blkIndex]);
}
}
config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask);
// Run optimizations one last time to remove any code that is now optimizable after above passes.
RunOptimizationPasses(blocks, config);
}

View File

@@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
switch (operation.Inst)
{
case Instruction.Add:
case Instruction.BitwiseExclusiveOr:
TryEliminateBinaryOpCommutative(operation, 0);
break;
@@ -20,13 +21,6 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
TryEliminateBitwiseAnd(operation);
break;
case Instruction.BitwiseExclusiveOr:
if (!TryEliminateXorSwap(operation))
{
TryEliminateBinaryOpCommutative(operation, 0);
}
break;
case Instruction.BitwiseOr:
TryEliminateBitwiseOr(operation);
break;
@@ -55,9 +49,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static void TryEliminateBitwiseAnd(Operation operation)
{
// Try to recognize and optimize those 3 patterns (in order):
// x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y,
// x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000
// x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y,
// x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000
Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1);
@@ -75,62 +68,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
}
}
private static bool TryEliminateXorSwap(Operation xCopyOp)
{
// Try to recognize XOR swap pattern:
// x = x ^ y
// y = x ^ y
// x = x ^ y
// Or, in SSA:
// x2 = x ^ y
// y2 = x2 ^ y
// x3 = x2 ^ y2
// Transform it into something more sane:
// temp = y
// y = x
// x = temp
// Note that because XOR is commutative, there are actually
// multiple possible combinations of this pattern, for
// simplicity this only catches one of them.
Operand x = xCopyOp.GetSource(0);
Operand y = xCopyOp.GetSource(1);
if (x.AsgOp is not Operation tCopyOp || tCopyOp.Inst != Instruction.BitwiseExclusiveOr ||
y.AsgOp is not Operation yCopyOp || yCopyOp.Inst != Instruction.BitwiseExclusiveOr)
{
return false;
}
if (tCopyOp == yCopyOp)
{
return false;
}
if (yCopyOp.GetSource(0) != x ||
yCopyOp.GetSource(1) != tCopyOp.GetSource(1) ||
x.UseOps.Count != 2)
{
return false;
}
x = tCopyOp.GetSource(0);
y = tCopyOp.GetSource(1);
tCopyOp.TurnIntoCopy(y); // Temp = Y
yCopyOp.TurnIntoCopy(x); // Y = X
xCopyOp.TurnIntoCopy(tCopyOp.Dest); // X = Temp
return true;
}
private static void TryEliminateBitwiseOr(Operation operation)
{
// Try to recognize and optimize those 3 patterns (in order):
// x | 0x00000000 == x, 0x00000000 | y == y,
// x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF
// x | 0x00000000 == x, 0x00000000 | y == y,
// x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF
Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1);

View File

@@ -1,5 +1,4 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{
@@ -94,17 +93,5 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
return source;
}
public static void DeleteNode(LinkedListNode<INode> node, Operation operation)
{
node.List.Remove(node);
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
{
operation.SetSource(srcIndex, null);
}
operation.Dest = null;
}
}
}

View File

@@ -14,16 +14,9 @@ namespace Ryujinx.Graphics.Shader.Translation
private readonly string _stagePrefix;
private readonly int[] _cbSlotToBindingMap;
private readonly int[] _sbSlotToBindingMap;
private uint _sbSlotWritten;
private readonly Dictionary<int, int> _sbSlots;
private readonly Dictionary<int, int> _sbSlotsReverse;
private readonly HashSet<int> _usedConstantBufferBindings;
public ShaderProperties Properties => _properties;
public ResourceManager(ShaderStage stage, IGpuAccessor gpuAccessor, ShaderProperties properties)
{
_gpuAccessor = gpuAccessor;
@@ -31,12 +24,7 @@ namespace Ryujinx.Graphics.Shader.Translation
_stagePrefix = GetShaderStagePrefix(stage);
_cbSlotToBindingMap = new int[18];
_sbSlotToBindingMap = new int[16];
_cbSlotToBindingMap.AsSpan().Fill(-1);
_sbSlotToBindingMap.AsSpan().Fill(-1);
_sbSlots = new Dictionary<int, int>();
_sbSlotsReverse = new Dictionary<int, int>();
_usedConstantBufferBindings = new HashSet<int>();
@@ -57,52 +45,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return binding;
}
public bool TryGetStorageBufferBinding(int sbCbSlot, int sbCbOffset, bool write, out int binding)
{
if (!TryGetSbSlot((byte)sbCbSlot, (ushort)sbCbOffset, out int slot))
{
binding = 0;
return false;
}
binding = _sbSlotToBindingMap[slot];
if (binding < 0)
{
binding = _gpuAccessor.QueryBindingStorageBuffer(slot);
_sbSlotToBindingMap[slot] = binding;
string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
AddNewStorageBuffer(binding, $"{_stagePrefix}_s{slotNumber}");
}
if (write)
{
_sbSlotWritten |= 1u << slot;
}
return true;
}
private bool TryGetSbSlot(byte sbCbSlot, ushort sbCbOffset, out int slot)
{
int key = PackSbCbInfo(sbCbSlot, sbCbOffset);
if (!_sbSlots.TryGetValue(key, out slot))
{
slot = _sbSlots.Count;
if (slot >= _sbSlotToBindingMap.Length)
{
return false;
}
_sbSlots.Add(key, slot);
_sbSlotsReverse.Add(slot, key);
}
return true;
}
public bool TryGetConstantBufferSlot(int binding, out int slot)
{
for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
@@ -146,34 +88,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return descriptors;
}
public BufferDescriptor[] GetStorageBufferDescriptors()
{
var descriptors = new BufferDescriptor[_sbSlots.Count];
int descriptorIndex = 0;
foreach ((int key, int slot) in _sbSlots)
{
int binding = _sbSlotToBindingMap[slot];
if (binding >= 0)
{
(int sbCbSlot, int sbCbOffset) = UnpackSbCbInfo(key);
descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot, sbCbSlot, sbCbOffset)
{
Flags = (_sbSlotWritten & (1u << slot)) != 0 ? BufferUsageFlags.Write : BufferUsageFlags.None
};
}
}
if (descriptors.Length != descriptorIndex)
{
Array.Resize(ref descriptors, descriptorIndex);
}
return descriptors;
}
private void AddNewConstantBuffer(int binding, string name)
{
StructureType type = new StructureType(new[]
@@ -184,14 +98,17 @@ namespace Ryujinx.Graphics.Shader.Translation
_properties.AddConstantBuffer(binding, new BufferDefinition(BufferLayout.Std140, 0, binding, name, type));
}
private void AddNewStorageBuffer(int binding, string name)
public void InheritFrom(ResourceManager other)
{
StructureType type = new StructureType(new[]
for (int i = 0; i < other._cbSlotToBindingMap.Length; i++)
{
new StructureField(AggregateType.Array | AggregateType.U32, "data", 0)
});
int binding = other._cbSlotToBindingMap[i];
_properties.AddStorageBuffer(binding, new BufferDefinition(BufferLayout.Std430, 1, binding, name, type));
if (binding >= 0)
{
_cbSlotToBindingMap[i] = binding;
}
}
}
public static string GetShaderStagePrefix(ShaderStage stage)
@@ -205,15 +122,5 @@ namespace Ryujinx.Graphics.Shader.Translation
return _stagePrefixes[index];
}
private static int PackSbCbInfo(int sbCbSlot, int sbCbOffset)
{
return sbCbOffset | ((int)sbCbSlot << 16);
}
private static (int, int) UnpackSbCbInfo(int key)
{
return ((byte)(key >> 16), (ushort)key);
}
}
}

View File

@@ -2,8 +2,10 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
using static Ryujinx.Graphics.Shader.Translation.GlobalMemory;
namespace Ryujinx.Graphics.Shader.Translation
{
@@ -21,10 +23,11 @@ namespace Ryujinx.Graphics.Shader.Translation
{
BasicBlock block = blocks[blkIndex];
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
for (LinkedListNode<INode> node = block.Operations.First; node != null;)
{
if (node.Value is not Operation operation)
{
node = node.Next;
continue;
}
@@ -53,6 +56,8 @@ namespace Ryujinx.Graphics.Shader.Translation
InsertVectorComponentSelect(node, config);
}
LinkedListNode<INode> nextNode = node.Next;
if (operation is TextureOperation texOp)
{
node = InsertTexelFetchScale(hfm, node, config);
@@ -69,7 +74,15 @@ namespace Ryujinx.Graphics.Shader.Translation
node = InsertSnormNormalization(node, config);
}
}
nextNode = node.Next;
}
else if (UsesGlobalMemory(operation.Inst, operation.StorageKind))
{
nextNode = RewriteGlobalAccess(node, config)?.Next ?? nextNode;
}
node = nextNode;
}
}
}
@@ -171,6 +184,196 @@ namespace Ryujinx.Graphics.Shader.Translation
operation.TurnIntoCopy(result);
}
private static LinkedListNode<INode> RewriteGlobalAccess(LinkedListNode<INode> node, ShaderConfig config)
{
Operation operation = (Operation)node.Value;
bool isAtomic = operation.Inst.IsAtomic();
bool isStg16Or8 = operation.Inst == Instruction.StoreGlobal16 || operation.Inst == Instruction.StoreGlobal8;
bool isWrite = isAtomic || operation.Inst == Instruction.StoreGlobal || isStg16Or8;
Operation storageOp = null;
Operand PrependOperation(Instruction inst, params Operand[] sources)
{
Operand local = Local();
node.List.AddBefore(node, new Operation(inst, local, sources));
return local;
}
Operand PrependStorageOperation(Instruction inst, StorageKind storageKind, params Operand[] sources)
{
Operand local = Local();
node.List.AddBefore(node, new Operation(inst, storageKind, local, sources));
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(DriverReservedCb, cbOffset);
Operand baseAddrHigh = Cbuf(DriverReservedCb, cbOffset + 1);
Operand size = Cbuf(DriverReservedCb, 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)
{
int slot = BitOperations.TrailingZeroCount(sbUseMask);
sbUseMask &= ~(1 << slot);
int cbOffset = GetStorageCbOffset(config.Stage, slot);
slot = config.GetSbSlot(DriverReservedCb, (ushort)cbOffset);
config.SetUsedStorageBuffer(slot, isWrite);
Operand inRange = BindingRangeCheck(cbOffset, out Operand baseAddrLow);
sbBaseAddrLow = PrependOperation(Instruction.ConditionalSelect, inRange, baseAddrLow, sbBaseAddrLow);
sbSlot = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot);
}
if (config.AccessibleStorageBuffersMask != 0)
{
Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
Operand[] sources = new Operand[operation.SourcesCount];
sources[0] = sbSlot;
if (isStg16Or8)
{
sources[1] = byteOffset;
}
else
{
sources[1] = PrependOperation(Instruction.ShiftRightU32, byteOffset, Const(2));
}
for (int index = 2; index < operation.SourcesCount; index++)
{
sources[index] = operation.GetSource(index);
}
if (isAtomic)
{
storageOp = new Operation(operation.Inst, StorageKind.StorageBuffer, operation.Dest, sources);
}
else if (operation.Inst == Instruction.LoadGlobal)
{
storageOp = new Operation(Instruction.LoadStorage, operation.Dest, sources);
}
else
{
Instruction storeInst = operation.Inst switch
{
Instruction.StoreGlobal16 => Instruction.StoreStorage16,
Instruction.StoreGlobal8 => Instruction.StoreStorage8,
_ => Instruction.StoreStorage
};
storageOp = new Operation(storeInst, null, sources);
}
}
else if (operation.Dest != null)
{
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);
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 vecIndex = PrependOperation(Instruction.ShiftRightU32, cbIndex, Const(2));
Operand elemIndex = PrependOperation(Instruction.BitwiseAnd, cbIndex, Const(3));
Operand[] sourcesCb = new Operand[4];
sourcesCb[0] = Const(config.ResourceManager.GetConstantBufferBinding(cbSlot));
sourcesCb[1] = Const(0);
sourcesCb[2] = vecIndex;
sourcesCb[3] = elemIndex;
Operand ldcResult = PrependStorageOperation(Instruction.Load, StorageKind.ConstantBuffer, sourcesCb);
storageOp = new Operation(Instruction.ConditionalSelect, operation.Dest, inRange, ldcResult, previousResult);
}
}
for (int index = 0; index < operation.SourcesCount; index++)
{
operation.SetSource(index, null);
}
LinkedListNode<INode> oldNode = node;
LinkedList<INode> oldNodeList = oldNode.List;
if (storageOp != null)
{
node = node.List.AddBefore(node, storageOp);
}
else
{
node = null;
}
oldNodeList.Remove(oldNode);
return node;
}
private static LinkedListNode<INode> InsertTexelFetchScale(HelperFunctionManager hfm, LinkedListNode<INode> node, ShaderConfig config)
{
TextureOperation texOp = (TextureOperation)node.Value;

View File

@@ -39,9 +39,9 @@ namespace Ryujinx.Graphics.Shader.Translation
public TranslationOptions Options { get; }
public ShaderProperties Properties => ResourceManager.Properties;
public ShaderProperties Properties { get; }
public ResourceManager ResourceManager { get; set; }
public ResourceManager ResourceManager { get; }
public bool TransformFeedbackEnabled { get; }
@@ -110,6 +110,12 @@ namespace Ryujinx.Graphics.Shader.Translation
public UInt128 NextInputAttributesComponents { get; private set; }
public UInt128 ThisInputAttributesComponents { get; private set; }
public int AccessibleStorageBuffersMask { get; private set; }
public int AccessibleConstantBuffersMask { get; private set; }
private int _usedStorageBuffers;
private int _usedStorageBuffersWrite;
private readonly record struct TextureInfo(int CbufSlot, int Handle, bool Indexed, TextureFormat Format);
private struct TextureMeta
@@ -121,9 +127,18 @@ namespace Ryujinx.Graphics.Shader.Translation
private readonly Dictionary<TextureInfo, TextureMeta> _usedTextures;
private readonly Dictionary<TextureInfo, TextureMeta> _usedImages;
private readonly Dictionary<int, int> _sbSlots;
private readonly Dictionary<int, int> _sbSlotsReverse;
private BufferDescriptor[] _cachedStorageBufferDescriptors;
private TextureDescriptor[] _cachedTextureDescriptors;
private TextureDescriptor[] _cachedImageDescriptors;
private int _firstStorageBufferBinding;
public int FirstStorageBufferBinding => _firstStorageBufferBinding;
public ShaderConfig(ShaderStage stage, IGpuAccessor gpuAccessor, TranslationOptions options)
{
Stage = stage;
@@ -132,13 +147,20 @@ namespace Ryujinx.Graphics.Shader.Translation
_transformFeedbackDefinitions = new Dictionary<TransformFeedbackVariable, TransformFeedbackOutput>();
AccessibleStorageBuffersMask = (1 << GlobalMemory.StorageMaxCount) - 1;
AccessibleConstantBuffersMask = (1 << GlobalMemory.UbeMaxCount) - 1;
UsedInputAttributesPerPatch = new HashSet<int>();
UsedOutputAttributesPerPatch = new HashSet<int>();
_usedTextures = new Dictionary<TextureInfo, TextureMeta>();
_usedImages = new Dictionary<TextureInfo, TextureMeta>();
ResourceManager = new ResourceManager(stage, gpuAccessor, new ShaderProperties());
_sbSlots = new Dictionary<int, int>();
_sbSlotsReverse = new Dictionary<int, int>();
Properties = new ShaderProperties();
ResourceManager = new ResourceManager(stage, gpuAccessor, Properties);
}
public ShaderConfig(
@@ -152,6 +174,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(header.Stage, gpuAccessor, options)
@@ -402,11 +429,15 @@ namespace Ryujinx.Graphics.Shader.Translation
public void InheritFrom(ShaderConfig other)
{
ResourceManager.InheritFrom(other.ResourceManager);
ClipDistancesWritten |= other.ClipDistancesWritten;
UsedFeatures |= other.UsedFeatures;
UsedInputAttributes |= other.UsedInputAttributes;
UsedOutputAttributes |= other.UsedOutputAttributes;
_usedStorageBuffers |= other._usedStorageBuffers;
_usedStorageBuffersWrite |= other._usedStorageBuffersWrite;
foreach (var kv in other._usedTextures)
{
@@ -606,6 +637,23 @@ namespace Ryujinx.Graphics.Shader.Translation
UsedFeatures |= flags;
}
public void SetAccessibleBufferMasks(int sbMask, int ubeMask)
{
AccessibleStorageBuffersMask = sbMask;
AccessibleConstantBuffersMask = ubeMask;
}
public void SetUsedStorageBuffer(int slot, bool write)
{
int mask = 1 << slot;
_usedStorageBuffers |= mask;
if (write)
{
_usedStorageBuffersWrite |= mask;
}
}
public void SetUsedTexture(
Instruction inst,
SamplerType type,
@@ -711,6 +759,76 @@ namespace Ryujinx.Graphics.Shader.Translation
return meta;
}
public BufferDescriptor[] GetStorageBufferDescriptors()
{
if (_cachedStorageBufferDescriptors != null)
{
return _cachedStorageBufferDescriptors;
}
return _cachedStorageBufferDescriptors = GetStorageBufferDescriptors(
_usedStorageBuffers,
_usedStorageBuffersWrite,
true,
out _firstStorageBufferBinding,
GpuAccessor.QueryBindingStorageBuffer);
}
private BufferDescriptor[] GetStorageBufferDescriptors(
int usedMask,
int writtenMask,
bool isArray,
out int firstBinding,
Func<int, int> getBindingCallback)
{
firstBinding = 0;
bool hasFirstBinding = false;
var descriptors = new BufferDescriptor[BitOperations.PopCount((uint)usedMask)];
int lastSlot = -1;
for (int i = 0; i < descriptors.Length; i++)
{
int slot = BitOperations.TrailingZeroCount(usedMask);
if (isArray)
{
// The next array entries also consumes bindings, even if they are unused.
for (int j = lastSlot + 1; j < slot; j++)
{
int binding = getBindingCallback(j);
if (!hasFirstBinding)
{
firstBinding = binding;
hasFirstBinding = true;
}
}
}
lastSlot = slot;
(int sbCbSlot, int sbCbOffset) = GetSbCbInfo(slot);
descriptors[i] = new BufferDescriptor(getBindingCallback(slot), slot, sbCbSlot, sbCbOffset);
if (!hasFirstBinding)
{
firstBinding = descriptors[i].Binding;
hasFirstBinding = true;
}
if ((writtenMask & (1 << slot)) != 0)
{
descriptors[i].SetFlag(BufferUsageFlags.Write);
}
usedMask &= ~(1 << slot);
}
return descriptors;
}
public TextureDescriptor[] GetTextureDescriptors()
{
return _cachedTextureDescriptors ??= GetTextureOrImageDescriptors(_usedTextures, GpuAccessor.QueryBindingTexture);
@@ -807,11 +925,45 @@ namespace Ryujinx.Graphics.Shader.Translation
return FindDescriptorIndex(GetImageDescriptors(), texOp);
}
public int GetSbSlot(byte sbCbSlot, ushort sbCbOffset)
{
int key = PackSbCbInfo(sbCbSlot, sbCbOffset);
if (!_sbSlots.TryGetValue(key, out int slot))
{
slot = _sbSlots.Count;
_sbSlots.Add(key, slot);
_sbSlotsReverse.Add(slot, key);
}
return slot;
}
public (int, int) GetSbCbInfo(int slot)
{
if (_sbSlotsReverse.TryGetValue(slot, out int key))
{
return UnpackSbCbInfo(key);
}
throw new ArgumentException($"Invalid slot {slot}.", nameof(slot));
}
private static int PackSbCbInfo(int sbCbSlot, int sbCbOffset)
{
return sbCbOffset | ((int)sbCbSlot << 16);
}
private static (int, int) UnpackSbCbInfo(int key)
{
return ((byte)(key >> 16), (ushort)key);
}
public ShaderProgramInfo CreateProgramInfo(ShaderIdentification identification = ShaderIdentification.None)
{
return new ShaderProgramInfo(
ResourceManager.GetConstantBufferDescriptors(),
ResourceManager.GetStorageBufferDescriptors(),
GetStorageBufferDescriptors(),
GetTextureDescriptors(),
GetImageDescriptors(),
identification,

View File

@@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.Translation
continue;
}
if (IsResourceWrite(operation.Inst, operation.StorageKind))
if (IsResourceWrite(operation.Inst))
{
return false;
}
@@ -154,7 +154,7 @@ namespace Ryujinx.Graphics.Shader.Translation
return totalVerticesCount + verticesCount == 3 && writesLayer;
}
private static bool IsResourceWrite(Instruction inst, StorageKind storageKind)
private static bool IsResourceWrite(Instruction inst)
{
switch (inst)
{
@@ -170,11 +170,13 @@ namespace Ryujinx.Graphics.Shader.Translation
case Instruction.AtomicXor:
case Instruction.ImageAtomic:
case Instruction.ImageStore:
case Instruction.StoreGlobal:
case Instruction.StoreGlobal16:
case Instruction.StoreGlobal8:
case Instruction.StoreStorage:
case Instruction.StoreStorage16:
case Instruction.StoreStorage8:
return true;
case Instruction.Store:
return storageKind == StorageKind.StorageBuffer ||
storageKind == StorageKind.SharedMemory ||
storageKind == StorageKind.LocalMemory;
}
return false;

View File

@@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Shader.Translation
Ssa.Rename(cfg.Blocks);
Optimizer.RunPass(hfm, cfg.Blocks, config);
Optimizer.RunPass(cfg.Blocks, config);
Rewriter.RunPass(hfm, cfg.Blocks, config);
}

View File

@@ -155,9 +155,6 @@ namespace Ryujinx.Graphics.Shader.Translation
{
other._config.MergeOutputUserAttributes(_config.UsedOutputAttributes, Enumerable.Empty<int>());
// We need to share the resource manager since both shaders accesses the same constant buffers.
other._config.ResourceManager = _config.ResourceManager;
FunctionCode[] otherCode = EmitShader(other._program, other._config, initializeOutputs: true, out int aStart);
code = Combine(otherCode, code, aStart);

View File

@@ -143,7 +143,7 @@ namespace Ryujinx.Graphics.Texture
mipGobBlocksInY >>= 1;
}
if (level > 0 && d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1)
while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1)
{
mipGobBlocksInZ >>= 1;
}
@@ -407,7 +407,7 @@ namespace Ryujinx.Graphics.Texture
mipGobBlocksInY >>= 1;
}
if (level > 0 && d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1)
while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1)
{
mipGobBlocksInZ >>= 1;
}

View File

@@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Texture
int gobBlocksInTileX,
int gpuLayerSize = 0)
{
bool is3D = depth > 1 || gobBlocksInZ > 1;
bool is3D = depth > 1;
int layerSize = 0;
@@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Texture
mipGobBlocksInY >>= 1;
}
if (level > 0 && d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1)
while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1)
{
mipGobBlocksInZ >>= 1;
}
@@ -88,10 +88,6 @@ namespace Ryujinx.Graphics.Texture
int robSize = widthInGobs * mipGobBlocksInY * mipGobBlocksInZ * GobSize;
mipOffsets[level] = layerSize;
sliceSizes[level] = totalBlocksOfGobsInY * robSize;
levelSizes[level] = totalBlocksOfGobsInZ * sliceSizes[level];
if (is3D)
{
int gobSize = mipGobBlocksInY * GobSize;
@@ -109,23 +105,12 @@ namespace Ryujinx.Graphics.Texture
allOffsets[z + depthLevelOffset] = baseOffset + zLow * gobSize + zHigh * sliceSize;
}
int gobRemainderZ = d % mipGobBlocksInZ;
if (gobRemainderZ != 0 && level == levels - 1)
{
// The slice only covers up to the end of this slice's depth, rather than the full aligned size.
// Avoids size being too large on partial views of 3d textures.
levelSizes[level] -= gobSize * (mipGobBlocksInZ - gobRemainderZ);
if (sliceSizes[level] > levelSizes[level])
{
sliceSizes[level] = levelSizes[level];
}
}
}
mipOffsets[level] = layerSize;
sliceSizes[level] = totalBlocksOfGobsInY * robSize;
levelSizes[level] = totalBlocksOfGobsInZ * sliceSizes[level];
layerSize += levelSizes[level];
depthLevelOffset += d;
@@ -282,8 +267,7 @@ namespace Ryujinx.Graphics.Texture
int depth,
int blockHeight,
int gobBlocksInY,
int gobBlocksInZ,
int level = int.MaxValue)
int gobBlocksInZ)
{
height = BitUtils.DivRoundUp(height, blockHeight);
@@ -292,7 +276,7 @@ namespace Ryujinx.Graphics.Texture
gobBlocksInY >>= 1;
}
while (level-- > 0 && depth <= (gobBlocksInZ >> 1) && gobBlocksInZ != 1)
while (depth <= (gobBlocksInZ >> 1) && gobBlocksInZ != 1)
{
gobBlocksInZ >>= 1;
}

Some files were not shown because too many files have changed in this diff Show More