Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f1d1670b0b | ||
|
b8de72de8f | ||
|
eebc39228d | ||
|
9daf029f35 | ||
|
51a27032f0 |
@@ -10,6 +10,7 @@ using Ryujinx.Ava.Ui.Windows;
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
|
using Ryujinx.Ui.Common.Helper;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -64,8 +65,7 @@ namespace Ryujinx.Ava
|
|||||||
if (result == UserResult.Yes)
|
if (result == UserResult.Yes)
|
||||||
{
|
{
|
||||||
var path = Process.GetCurrentProcess().MainModule.FileName;
|
var path = Process.GetCurrentProcess().MainModule.FileName;
|
||||||
var info = new ProcessStartInfo() { FileName = path, UseShellExecute = false };
|
var proc = Process.Start(path, CommandLineState.Arguments);
|
||||||
var proc = Process.Start(info);
|
|
||||||
desktop.Shutdown();
|
desktop.Shutdown();
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
|
@@ -587,10 +587,12 @@
|
|||||||
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
|
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
|
||||||
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
||||||
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
||||||
"SettingsGpuBackendRestartMessage": "Graphics Backend or Gpu settings have been modified. This will require a restart to be applied",
|
"SettingsGpuBackendRestartMessage": "Graphics Backend or GPU settings have been modified. This will require a restart to be applied",
|
||||||
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
|
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
|
||||||
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
|
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
|
||||||
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
|
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
|
||||||
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
|
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
|
||||||
"VolumeShort": "Vol"
|
"VolumeShort": "Vol",
|
||||||
|
"SettingsEnableMacroHLE": "Enable Macro HLE",
|
||||||
|
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure."
|
||||||
}
|
}
|
||||||
|
@@ -556,5 +556,7 @@
|
|||||||
"SettingsSelectThemeFileDialogTitle" : "Selecionar arquivo do tema",
|
"SettingsSelectThemeFileDialogTitle" : "Selecionar arquivo do tema",
|
||||||
"SettingsXamlThemeFile" : "Arquivo de tema Xaml",
|
"SettingsXamlThemeFile" : "Arquivo de tema Xaml",
|
||||||
"SettingsTabHotkeysResScaleUpHotkey": "Aumentar a resolução:",
|
"SettingsTabHotkeysResScaleUpHotkey": "Aumentar a resolução:",
|
||||||
"SettingsTabHotkeysResScaleDownHotkey": "Diminuir a resolução:"
|
"SettingsTabHotkeysResScaleDownHotkey": "Diminuir a resolução:",
|
||||||
|
"SettingsEnableMacroHLE": "Habilitar emulação de alto nível para Macros",
|
||||||
|
"SettingsEnableMacroHLETooltip": "Habilita emulação de alto nível de códigos Macro da GPU.\n\nMelhora a performance, mas pode causar problemas gráficos em alguns jogos.\n\nEm caso de dúvida, deixe ATIVADO."
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ using Ryujinx.Common.SystemInfo;
|
|||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
using Ryujinx.Ui.Common;
|
using Ryujinx.Ui.Common;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
|
using Ryujinx.Ui.Common.Helper;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@@ -26,7 +27,6 @@ namespace Ryujinx.Ava
|
|||||||
public static double ActualScaleFactor { get; set; }
|
public static double ActualScaleFactor { get; set; }
|
||||||
public static string Version { get; private set; }
|
public static string Version { get; private set; }
|
||||||
public static string ConfigurationPath { get; private set; }
|
public static string ConfigurationPath { get; private set; }
|
||||||
public static string CommandLineProfile { get; set; }
|
|
||||||
public static bool PreviewerDetached { get; private set; }
|
public static bool PreviewerDetached { get; private set; }
|
||||||
|
|
||||||
public static RenderTimer RenderTimer { get; private set; }
|
public static RenderTimer RenderTimer { get; private set; }
|
||||||
@@ -87,46 +87,8 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private static void Initialize(string[] args)
|
private static void Initialize(string[] args)
|
||||||
{
|
{
|
||||||
// Parse Arguments.
|
// Parse arguments
|
||||||
string launchPathArg = null;
|
CommandLineState.ParseArguments(args);
|
||||||
string baseDirPathArg = null;
|
|
||||||
bool startFullscreenArg = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < args.Length; ++i)
|
|
||||||
{
|
|
||||||
string arg = args[i];
|
|
||||||
|
|
||||||
if (arg == "-r" || arg == "--root-data-dir")
|
|
||||||
{
|
|
||||||
if (i + 1 >= args.Length)
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
baseDirPathArg = args[++i];
|
|
||||||
}
|
|
||||||
else if (arg == "-p" || arg == "--profile")
|
|
||||||
{
|
|
||||||
if (i + 1 >= args.Length)
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandLineProfile = args[++i];
|
|
||||||
}
|
|
||||||
else if (arg == "-f" || arg == "--fullscreen")
|
|
||||||
{
|
|
||||||
startFullscreenArg = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
launchPathArg = arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete backup files after updating.
|
// Delete backup files after updating.
|
||||||
Task.Run(Updater.CleanupUpdate);
|
Task.Run(Updater.CleanupUpdate);
|
||||||
@@ -135,10 +97,10 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
// Hook unhandled exception and process exit events.
|
// Hook unhandled exception and process exit events.
|
||||||
AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
||||||
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
|
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
|
||||||
|
|
||||||
// Setup base data directory.
|
// Setup base data directory.
|
||||||
AppDataManager.Initialize(baseDirPathArg);
|
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
|
||||||
|
|
||||||
// Initialize the configuration.
|
// Initialize the configuration.
|
||||||
ConfigurationState.Initialize();
|
ConfigurationState.Initialize();
|
||||||
@@ -173,9 +135,9 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (launchPathArg != null)
|
if (CommandLineState.LaunchPathArg != null)
|
||||||
{
|
{
|
||||||
MainWindow.DeferLoadApplication(launchPathArg, startFullscreenArg);
|
MainWindow.DeferLoadApplication(CommandLineState.LaunchPathArg, CommandLineState.StartFullscreenArg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +177,19 @@ namespace Ryujinx.Ava
|
|||||||
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}");
|
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if graphics backend was overridden
|
||||||
|
if (CommandLineState.OverrideGraphicsBackend != null)
|
||||||
|
{
|
||||||
|
if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl")
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
|
||||||
|
}
|
||||||
|
else if (CommandLineState.OverrideGraphicsBackend.ToLower() == "vulkan")
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.Vulkan;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PrintSystemInfo()
|
private static void PrintSystemInfo()
|
||||||
|
@@ -21,14 +21,10 @@ using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
|||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
using Ryujinx.Ui.Common.Configuration.System;
|
using Ryujinx.Ui.Common.Configuration.System;
|
||||||
using Silk.NET.Vulkan;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone;
|
using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Ui.ViewModels
|
namespace Ryujinx.Ava.Ui.ViewModels
|
||||||
@@ -138,6 +134,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
public bool ExpandDramSize { get; set; }
|
public bool ExpandDramSize { get; set; }
|
||||||
public bool EnableShaderCache { get; set; }
|
public bool EnableShaderCache { get; set; }
|
||||||
public bool EnableTextureRecompression { get; set; }
|
public bool EnableTextureRecompression { get; set; }
|
||||||
|
public bool EnableMacroHLE { get; set; }
|
||||||
public bool EnableFileLog { get; set; }
|
public bool EnableFileLog { get; set; }
|
||||||
public bool EnableStub { get; set; }
|
public bool EnableStub { get; set; }
|
||||||
public bool EnableInfo { get; set; }
|
public bool EnableInfo { get; set; }
|
||||||
@@ -339,6 +336,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
ExpandDramSize = config.System.ExpandRam;
|
ExpandDramSize = config.System.ExpandRam;
|
||||||
EnableShaderCache = config.Graphics.EnableShaderCache;
|
EnableShaderCache = config.Graphics.EnableShaderCache;
|
||||||
EnableTextureRecompression = config.Graphics.EnableTextureRecompression;
|
EnableTextureRecompression = config.Graphics.EnableTextureRecompression;
|
||||||
|
EnableMacroHLE = config.Graphics.EnableMacroHLE;
|
||||||
EnableFileLog = config.Logger.EnableFileLog;
|
EnableFileLog = config.Logger.EnableFileLog;
|
||||||
EnableStub = config.Logger.EnableStub;
|
EnableStub = config.Logger.EnableStub;
|
||||||
EnableInfo = config.Logger.EnableInfo;
|
EnableInfo = config.Logger.EnableInfo;
|
||||||
@@ -422,6 +420,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
|||||||
config.Graphics.EnableVsync.Value = EnableVsync;
|
config.Graphics.EnableVsync.Value = EnableVsync;
|
||||||
config.Graphics.EnableShaderCache.Value = EnableShaderCache;
|
config.Graphics.EnableShaderCache.Value = EnableShaderCache;
|
||||||
config.Graphics.EnableTextureRecompression.Value = EnableTextureRecompression;
|
config.Graphics.EnableTextureRecompression.Value = EnableTextureRecompression;
|
||||||
|
config.Graphics.EnableMacroHLE.Value = EnableMacroHLE;
|
||||||
config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
|
config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
|
||||||
config.System.EnablePtc.Value = EnablePptc;
|
config.System.EnablePtc.Value = EnablePptc;
|
||||||
config.System.EnableInternetAccess.Value = EnableInternetAccess;
|
config.System.EnableInternetAccess.Value = EnableInternetAccess;
|
||||||
|
@@ -23,6 +23,7 @@ using Ryujinx.Modules;
|
|||||||
using Ryujinx.Ui.App.Common;
|
using Ryujinx.Ui.App.Common;
|
||||||
using Ryujinx.Ui.Common;
|
using Ryujinx.Ui.Common;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
|
using Ryujinx.Ui.Common.Helper;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@@ -247,7 +248,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
{
|
{
|
||||||
RendererControl.CreateVulkan();
|
RendererControl.CreateVulkan();
|
||||||
}
|
}
|
||||||
|
|
||||||
AppHost = new AppHost(RendererControl, InputManager, path, VirtualFileSystem, ContentManager, AccountManager, _userChannelPersistence, this);
|
AppHost = new AppHost(RendererControl, InputManager, path, VirtualFileSystem, ContentManager, AccountManager, _userChannelPersistence, this);
|
||||||
|
|
||||||
if (!AppHost.LoadGuestApplication().Result)
|
if (!AppHost.LoadGuestApplication().Result)
|
||||||
@@ -432,7 +433,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
// Consider removing this at some point in the future when we don't need to worry about old saves.
|
// Consider removing this at some point in the future when we don't need to worry about old saves.
|
||||||
VirtualFileSystem.FixExtraData(LibHacHorizonManager.RyujinxClient);
|
VirtualFileSystem.FixExtraData(LibHacHorizonManager.RyujinxClient);
|
||||||
|
|
||||||
AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient, Program.CommandLineProfile);
|
AccountManager = new AccountManager(LibHacHorizonManager.RyujinxClient, CommandLineState.Profile);
|
||||||
|
|
||||||
VirtualFileSystem.ReloadKeySet();
|
VirtualFileSystem.ReloadKeySet();
|
||||||
|
|
||||||
@@ -525,6 +526,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
|||||||
GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
|
GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
|
||||||
GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
|
GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
|
||||||
GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
|
GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
|
||||||
|
GraphicsConfig.EnableMacroHLE = ConfigurationState.Instance.Graphics.EnableMacroHLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadHotKeys()
|
public void LoadHotKeys()
|
||||||
|
@@ -568,6 +568,10 @@
|
|||||||
ToolTip.Tip="{locale:Locale SettingsEnableTextureRecompressionTooltip}">
|
ToolTip.Tip="{locale:Locale SettingsEnableTextureRecompressionTooltip}">
|
||||||
<TextBlock Text="{locale:Locale SettingsEnableTextureRecompression}" />
|
<TextBlock Text="{locale:Locale SettingsEnableTextureRecompression}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
<CheckBox IsChecked="{Binding EnableMacroHLE}"
|
||||||
|
ToolTip.Tip="{locale:Locale SettingsEnableMacroHLETooltip}">
|
||||||
|
<TextBlock Text="{locale:Locale SettingsEnableMacroHLE}" />
|
||||||
|
</CheckBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock VerticalAlignment="Center"
|
<TextBlock VerticalAlignment="Center"
|
||||||
|
@@ -34,13 +34,14 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
int firstIndex,
|
int firstIndex,
|
||||||
int firstVertex,
|
int firstVertex,
|
||||||
int firstInstance);
|
int firstInstance);
|
||||||
|
void DrawIndexedIndirect(BufferRange indirectBuffer);
|
||||||
|
void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride);
|
||||||
|
void DrawIndirect(BufferRange indirectBuffer);
|
||||||
|
void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride);
|
||||||
void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion);
|
void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion);
|
||||||
|
|
||||||
void EndTransformFeedback();
|
void EndTransformFeedback();
|
||||||
|
|
||||||
void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride);
|
|
||||||
void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride);
|
|
||||||
|
|
||||||
void SetAlphaTest(bool enable, float reference, CompareOp op);
|
void SetAlphaTest(bool enable, float reference, CompareOp op);
|
||||||
|
|
||||||
void SetBlendState(int index, BlendDescriptor blend);
|
void SetBlendState(int index, BlendDescriptor blend);
|
||||||
|
@@ -141,16 +141,20 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
DrawCommand.Run(ref GetCommand<DrawCommand>(memory), threaded, renderer);
|
DrawCommand.Run(ref GetCommand<DrawCommand>(memory), threaded, renderer);
|
||||||
_lookup[(int)CommandType.DrawIndexed] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
_lookup[(int)CommandType.DrawIndexed] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
DrawIndexedCommand.Run(ref GetCommand<DrawIndexedCommand>(memory), threaded, renderer);
|
DrawIndexedCommand.Run(ref GetCommand<DrawIndexedCommand>(memory), threaded, renderer);
|
||||||
|
_lookup[(int)CommandType.DrawIndexedIndirect] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
|
DrawIndexedIndirectCommand.Run(ref GetCommand<DrawIndexedIndirectCommand>(memory), threaded, renderer);
|
||||||
|
_lookup[(int)CommandType.DrawIndexedIndirectCount] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
|
DrawIndexedIndirectCountCommand.Run(ref GetCommand<DrawIndexedIndirectCountCommand>(memory), threaded, renderer);
|
||||||
|
_lookup[(int)CommandType.DrawIndirect] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
|
DrawIndirectCommand.Run(ref GetCommand<DrawIndirectCommand>(memory), threaded, renderer);
|
||||||
|
_lookup[(int)CommandType.DrawIndirectCount] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
|
DrawIndirectCountCommand.Run(ref GetCommand<DrawIndirectCountCommand>(memory), threaded, renderer);
|
||||||
_lookup[(int)CommandType.DrawTexture] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
_lookup[(int)CommandType.DrawTexture] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
DrawTextureCommand.Run(ref GetCommand<DrawTextureCommand>(memory), threaded, renderer);
|
DrawTextureCommand.Run(ref GetCommand<DrawTextureCommand>(memory), threaded, renderer);
|
||||||
_lookup[(int)CommandType.EndHostConditionalRendering] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
_lookup[(int)CommandType.EndHostConditionalRendering] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
EndHostConditionalRenderingCommand.Run(renderer);
|
EndHostConditionalRenderingCommand.Run(renderer);
|
||||||
_lookup[(int)CommandType.EndTransformFeedback] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
_lookup[(int)CommandType.EndTransformFeedback] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
EndTransformFeedbackCommand.Run(ref GetCommand<EndTransformFeedbackCommand>(memory), threaded, renderer);
|
EndTransformFeedbackCommand.Run(ref GetCommand<EndTransformFeedbackCommand>(memory), threaded, renderer);
|
||||||
_lookup[(int)CommandType.MultiDrawIndirectCount] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
|
||||||
MultiDrawIndirectCountCommand.Run(ref GetCommand<MultiDrawIndirectCountCommand>(memory), threaded, renderer);
|
|
||||||
_lookup[(int)CommandType.MultiDrawIndexedIndirectCount] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
|
||||||
MultiDrawIndexedIndirectCountCommand.Run(ref GetCommand<MultiDrawIndexedIndirectCountCommand>(memory), threaded, renderer);
|
|
||||||
_lookup[(int)CommandType.SetAlphaTest] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
_lookup[(int)CommandType.SetAlphaTest] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
SetAlphaTestCommand.Run(ref GetCommand<SetAlphaTestCommand>(memory), threaded, renderer);
|
SetAlphaTestCommand.Run(ref GetCommand<SetAlphaTestCommand>(memory), threaded, renderer);
|
||||||
_lookup[(int)CommandType.SetBlendState] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
_lookup[(int)CommandType.SetBlendState] = (Span<byte> memory, ThreadedRenderer threaded, IRenderer renderer) =>
|
||||||
|
@@ -52,11 +52,13 @@
|
|||||||
DispatchCompute,
|
DispatchCompute,
|
||||||
Draw,
|
Draw,
|
||||||
DrawIndexed,
|
DrawIndexed,
|
||||||
|
DrawIndexedIndirect,
|
||||||
|
DrawIndexedIndirectCount,
|
||||||
|
DrawIndirect,
|
||||||
|
DrawIndirectCount,
|
||||||
DrawTexture,
|
DrawTexture,
|
||||||
EndHostConditionalRendering,
|
EndHostConditionalRendering,
|
||||||
EndTransformFeedback,
|
EndTransformFeedback,
|
||||||
MultiDrawIndirectCount,
|
|
||||||
MultiDrawIndexedIndirectCount,
|
|
||||||
SetAlphaTest,
|
SetAlphaTest,
|
||||||
SetBlendState,
|
SetBlendState,
|
||||||
SetDepthBias,
|
SetDepthBias,
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
|
{
|
||||||
|
struct DrawIndexedIndirectCommand : IGALCommand
|
||||||
|
{
|
||||||
|
public CommandType CommandType => CommandType.DrawIndexedIndirect;
|
||||||
|
private BufferRange _indirectBuffer;
|
||||||
|
|
||||||
|
public void Set(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
_indirectBuffer = indirectBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(ref DrawIndexedIndirectCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
|
{
|
||||||
|
renderer.Pipeline.DrawIndexedIndirect(threaded.Buffers.MapBufferRange(command._indirectBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
{
|
{
|
||||||
struct MultiDrawIndexedIndirectCountCommand : IGALCommand
|
struct DrawIndexedIndirectCountCommand : IGALCommand
|
||||||
{
|
{
|
||||||
public CommandType CommandType => CommandType.MultiDrawIndexedIndirectCount;
|
public CommandType CommandType => CommandType.DrawIndexedIndirectCount;
|
||||||
private BufferRange _indirectBuffer;
|
private BufferRange _indirectBuffer;
|
||||||
private BufferRange _parameterBuffer;
|
private BufferRange _parameterBuffer;
|
||||||
private int _maxDrawCount;
|
private int _maxDrawCount;
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
_stride = stride;
|
_stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Run(ref MultiDrawIndexedIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
public static void Run(ref DrawIndexedIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
{
|
{
|
||||||
renderer.Pipeline.MultiDrawIndexedIndirectCount(
|
renderer.Pipeline.DrawIndexedIndirectCount(
|
||||||
threaded.Buffers.MapBufferRange(command._indirectBuffer),
|
threaded.Buffers.MapBufferRange(command._indirectBuffer),
|
||||||
threaded.Buffers.MapBufferRange(command._parameterBuffer),
|
threaded.Buffers.MapBufferRange(command._parameterBuffer),
|
||||||
command._maxDrawCount,
|
command._maxDrawCount,
|
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
|
{
|
||||||
|
struct DrawIndirectCommand : IGALCommand
|
||||||
|
{
|
||||||
|
public CommandType CommandType => CommandType.DrawIndirect;
|
||||||
|
private BufferRange _indirectBuffer;
|
||||||
|
|
||||||
|
public void Set(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
_indirectBuffer = indirectBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(ref DrawIndirectCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
|
{
|
||||||
|
renderer.Pipeline.DrawIndirect(threaded.Buffers.MapBufferRange(command._indirectBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
{
|
{
|
||||||
struct MultiDrawIndirectCountCommand : IGALCommand
|
struct DrawIndirectCountCommand : IGALCommand
|
||||||
{
|
{
|
||||||
public CommandType CommandType => CommandType.MultiDrawIndirectCount;
|
public CommandType CommandType => CommandType.DrawIndirectCount;
|
||||||
private BufferRange _indirectBuffer;
|
private BufferRange _indirectBuffer;
|
||||||
private BufferRange _parameterBuffer;
|
private BufferRange _parameterBuffer;
|
||||||
private int _maxDrawCount;
|
private int _maxDrawCount;
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
_stride = stride;
|
_stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Run(ref MultiDrawIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
public static void Run(ref DrawIndirectCountCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
{
|
{
|
||||||
renderer.Pipeline.MultiDrawIndirectCount(
|
renderer.Pipeline.DrawIndirectCount(
|
||||||
threaded.Buffers.MapBufferRange(command._indirectBuffer),
|
threaded.Buffers.MapBufferRange(command._indirectBuffer),
|
||||||
threaded.Buffers.MapBufferRange(command._parameterBuffer),
|
threaded.Buffers.MapBufferRange(command._parameterBuffer),
|
||||||
command._maxDrawCount,
|
command._maxDrawCount,
|
@@ -83,6 +83,30 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawIndexedIndirect(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
_renderer.New<DrawIndexedIndirectCommand>().Set(indirectBuffer);
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||||
|
{
|
||||||
|
_renderer.New<DrawIndexedIndirectCountCommand>().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndirect(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
_renderer.New<DrawIndirectCommand>().Set(indirectBuffer);
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||||
|
{
|
||||||
|
_renderer.New<DrawIndirectCountCommand>().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
||||||
{
|
{
|
||||||
_renderer.New<DrawTextureCommand>().Set(Ref(texture), Ref(sampler), srcRegion, dstRegion);
|
_renderer.New<DrawTextureCommand>().Set(Ref(texture), Ref(sampler), srcRegion, dstRegion);
|
||||||
@@ -101,18 +125,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
|
||||||
{
|
|
||||||
_renderer.New<MultiDrawIndirectCountCommand>().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
|
||||||
_renderer.QueueCommand();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
|
||||||
{
|
|
||||||
_renderer.New<MultiDrawIndexedIndirectCountCommand>().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
|
||||||
_renderer.QueueCommand();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetAlphaTest(bool enable, float reference, CompareOp op)
|
public void SetAlphaTest(bool enable, float reference, CompareOp op)
|
||||||
{
|
{
|
||||||
_renderer.New<SetAlphaTestCommand>().Set(enable, reference, op);
|
_renderer.New<SetAlphaTestCommand>().Set(enable, reference, op);
|
||||||
|
@@ -62,10 +62,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_hleFunction == MacroHLEFunctionName.MultiDrawElementsIndirectCount)
|
// We don't consume the parameter buffer value, so we don't need to flush it.
|
||||||
|
// Doing so improves performance if the value was written by a GPU shader.
|
||||||
|
if (_hleFunction == MacroHLEFunctionName.DrawElementsIndirect)
|
||||||
|
{
|
||||||
|
context.GPFifo.SetFlushSkips(1);
|
||||||
|
}
|
||||||
|
else if (_hleFunction == MacroHLEFunctionName.MultiDrawElementsIndirectCount)
|
||||||
{
|
{
|
||||||
// We don't consume the parameter buffer value, so we don't need to flush it.
|
|
||||||
// Doing so improves performance if the value was written by a GPU shader.
|
|
||||||
context.GPFifo.SetFlushSkips(2);
|
context.GPFifo.SetFlushSkips(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
private const int ColorStructSize = 0x40;
|
private const int ColorStructSize = 0x40;
|
||||||
private const int ZetaLayerCountOffset = 0x1230;
|
private const int ZetaLayerCountOffset = 0x1230;
|
||||||
|
|
||||||
|
private const int IndirectDataEntrySize = 0x10;
|
||||||
|
private const int IndirectIndexedDataEntrySize = 0x14;
|
||||||
|
|
||||||
private readonly GPFifoProcessor _processor;
|
private readonly GPFifoProcessor _processor;
|
||||||
private readonly MacroHLEFunctionName _functionName;
|
private readonly MacroHLEFunctionName _functionName;
|
||||||
|
|
||||||
@@ -27,9 +30,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the HLE macro handler.
|
/// Creates a new instance of the HLE macro handler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">GPU context the macro is being executed on</param>
|
/// <param name="processor">GPU GP FIFO command processor</param>
|
||||||
/// <param name="memoryManager">GPU memory manager</param>
|
|
||||||
/// <param name="engine">3D engine where this macro is being called</param>
|
|
||||||
/// <param name="functionName">Name of the HLE macro function to be called</param>
|
/// <param name="functionName">Name of the HLE macro function to be called</param>
|
||||||
public MacroHLE(GPFifoProcessor processor, MacroHLEFunctionName functionName)
|
public MacroHLE(GPFifoProcessor processor, MacroHLEFunctionName functionName)
|
||||||
{
|
{
|
||||||
@@ -55,12 +56,24 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
case MacroHLEFunctionName.ClearDepthStencil:
|
case MacroHLEFunctionName.ClearDepthStencil:
|
||||||
ClearDepthStencil(state, arg0);
|
ClearDepthStencil(state, arg0);
|
||||||
break;
|
break;
|
||||||
|
case MacroHLEFunctionName.DrawArraysInstanced:
|
||||||
|
DrawArraysInstanced(state, arg0);
|
||||||
|
break;
|
||||||
|
case MacroHLEFunctionName.DrawElementsInstanced:
|
||||||
|
DrawElementsInstanced(state, arg0);
|
||||||
|
break;
|
||||||
|
case MacroHLEFunctionName.DrawElementsIndirect:
|
||||||
|
DrawElementsIndirect(state, arg0);
|
||||||
|
break;
|
||||||
case MacroHLEFunctionName.MultiDrawElementsIndirectCount:
|
case MacroHLEFunctionName.MultiDrawElementsIndirectCount:
|
||||||
MultiDrawElementsIndirectCount(state, arg0);
|
MultiDrawElementsIndirectCount(state, arg0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException(_functionName.ToString());
|
throw new NotImplementedException(_functionName.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It should be empty at this point, but clear it just to be safe.
|
||||||
|
Fifo.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -89,7 +102,118 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a indirect multi-draw, with parameters from a GPU buffer.
|
/// Performs a draw.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">GPU state at the time of the call</param>
|
||||||
|
/// <param name="arg0">First argument of the call</param>
|
||||||
|
private void DrawArraysInstanced(IDeviceState state, int arg0)
|
||||||
|
{
|
||||||
|
var topology = (PrimitiveTopology)arg0;
|
||||||
|
|
||||||
|
var count = FetchParam();
|
||||||
|
var instanceCount = FetchParam();
|
||||||
|
var firstVertex = FetchParam();
|
||||||
|
var firstInstance = FetchParam();
|
||||||
|
|
||||||
|
if (ShouldSkipDraw(state, instanceCount.Word))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_processor.ThreedClass.Draw(
|
||||||
|
topology,
|
||||||
|
count.Word,
|
||||||
|
instanceCount.Word,
|
||||||
|
0,
|
||||||
|
firstVertex.Word,
|
||||||
|
firstInstance.Word,
|
||||||
|
indexed: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a indexed draw.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">GPU state at the time of the call</param>
|
||||||
|
/// <param name="arg0">First argument of the call</param>
|
||||||
|
private void DrawElementsInstanced(IDeviceState state, int arg0)
|
||||||
|
{
|
||||||
|
var topology = (PrimitiveTopology)arg0;
|
||||||
|
|
||||||
|
var count = FetchParam();
|
||||||
|
var instanceCount = FetchParam();
|
||||||
|
var firstIndex = FetchParam();
|
||||||
|
var firstVertex = FetchParam();
|
||||||
|
var firstInstance = FetchParam();
|
||||||
|
|
||||||
|
if (ShouldSkipDraw(state, instanceCount.Word))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_processor.ThreedClass.Draw(
|
||||||
|
topology,
|
||||||
|
count.Word,
|
||||||
|
instanceCount.Word,
|
||||||
|
firstIndex.Word,
|
||||||
|
firstVertex.Word,
|
||||||
|
firstInstance.Word,
|
||||||
|
indexed: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a indirect indexed draw, with parameters from a GPU buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">GPU state at the time of the call</param>
|
||||||
|
/// <param name="arg0">First argument of the call</param>
|
||||||
|
private void DrawElementsIndirect(IDeviceState state, int arg0)
|
||||||
|
{
|
||||||
|
var topology = (PrimitiveTopology)arg0;
|
||||||
|
|
||||||
|
var count = FetchParam();
|
||||||
|
var instanceCount = FetchParam();
|
||||||
|
var firstIndex = FetchParam();
|
||||||
|
var firstVertex = FetchParam();
|
||||||
|
var firstInstance = FetchParam();
|
||||||
|
|
||||||
|
ulong indirectBufferGpuVa = count.GpuVa;
|
||||||
|
|
||||||
|
var bufferCache = _processor.MemoryManager.Physical.BufferCache;
|
||||||
|
|
||||||
|
bool useBuffer = bufferCache.CheckModified(_processor.MemoryManager, indirectBufferGpuVa, IndirectIndexedDataEntrySize, out ulong indirectBufferAddress);
|
||||||
|
|
||||||
|
if (useBuffer)
|
||||||
|
{
|
||||||
|
int indexCount = firstIndex.Word + count.Word;
|
||||||
|
|
||||||
|
_processor.ThreedClass.DrawIndirect(
|
||||||
|
topology,
|
||||||
|
indirectBufferAddress,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
IndirectIndexedDataEntrySize,
|
||||||
|
indexCount,
|
||||||
|
Threed.IndirectDrawType.DrawIndexedIndirect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ShouldSkipDraw(state, instanceCount.Word))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_processor.ThreedClass.Draw(
|
||||||
|
topology,
|
||||||
|
count.Word,
|
||||||
|
instanceCount.Word,
|
||||||
|
firstIndex.Word,
|
||||||
|
firstVertex.Word,
|
||||||
|
firstInstance.Word,
|
||||||
|
indexed: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a indirect indexed multi-draw, with parameters from a GPU buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">GPU state at the time of the call</param>
|
/// <param name="state">GPU state at the time of the call</param>
|
||||||
/// <param name="arg0">First argument of the call</param>
|
/// <param name="arg0">First argument of the call</param>
|
||||||
@@ -132,8 +256,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int indirectBufferSize = maxDrawCount * stride;
|
|
||||||
|
|
||||||
ulong indirectBufferGpuVa = 0;
|
ulong indirectBufferGpuVa = 0;
|
||||||
int indexCount = 0;
|
int indexCount = 0;
|
||||||
|
|
||||||
@@ -142,8 +264,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
var count = FetchParam();
|
var count = FetchParam();
|
||||||
var instanceCount = FetchParam();
|
var instanceCount = FetchParam();
|
||||||
var firstIndex = FetchParam();
|
var firstIndex = FetchParam();
|
||||||
var baseVertex = FetchParam();
|
var firstVertex = FetchParam();
|
||||||
var baseInstance = FetchParam();
|
var firstInstance = FetchParam();
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
@@ -161,15 +283,32 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// It should be empty at this point, but clear it just to be safe.
|
|
||||||
Fifo.Clear();
|
|
||||||
|
|
||||||
var bufferCache = _processor.MemoryManager.Physical.BufferCache;
|
var bufferCache = _processor.MemoryManager.Physical.BufferCache;
|
||||||
|
|
||||||
var parameterBuffer = bufferCache.GetGpuBufferRange(_processor.MemoryManager, parameterBufferGpuVa, 4);
|
ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride;
|
||||||
var indirectBuffer = bufferCache.GetGpuBufferRange(_processor.MemoryManager, indirectBufferGpuVa, (ulong)indirectBufferSize);
|
|
||||||
|
|
||||||
_processor.ThreedClass.MultiDrawIndirectCount(indexCount, topology, indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
ulong indirectBufferAddress = bufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize);
|
||||||
|
ulong parameterBufferAddress = bufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, parameterBufferGpuVa, 4);
|
||||||
|
|
||||||
|
_processor.ThreedClass.DrawIndirect(
|
||||||
|
topology,
|
||||||
|
indirectBufferAddress,
|
||||||
|
parameterBufferAddress,
|
||||||
|
maxDrawCount,
|
||||||
|
stride,
|
||||||
|
indexCount,
|
||||||
|
Threed.IndirectDrawType.DrawIndexedIndirectCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the draw should be skipped, because the masked instance count is zero.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="instanceCount">Draw instance count</param>
|
||||||
|
/// <returns>True if the draw should be skipped, false otherwise</returns>
|
||||||
|
private static bool ShouldSkipDraw(IDeviceState state, int instanceCount)
|
||||||
|
{
|
||||||
|
return (Read(state, 0xd1b) & instanceCount) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -189,14 +328,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a GPU method call.
|
/// Reads data from a GPU register.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">Current GPU state</param>
|
/// <param name="state">Current GPU state</param>
|
||||||
/// <param name="methAddr">Address, in words, of the method</param>
|
/// <param name="reg">Register offset to read</param>
|
||||||
/// <param name="value">Call argument</param>
|
/// <returns>GPU register value</returns>
|
||||||
private static void Send(IDeviceState state, int methAddr, int value)
|
private static int Read(IDeviceState state, int reg)
|
||||||
{
|
{
|
||||||
state.Write(methAddr * 4, value);
|
return state.Read(reg * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,9 @@
|
|||||||
None,
|
None,
|
||||||
ClearColor,
|
ClearColor,
|
||||||
ClearDepthStencil,
|
ClearDepthStencil,
|
||||||
|
DrawArraysInstanced,
|
||||||
|
DrawElementsInstanced,
|
||||||
|
DrawElementsIndirect,
|
||||||
MultiDrawElementsIndirectCount
|
MultiDrawElementsIndirectCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,17 +44,29 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly TableEntry[] Table = new TableEntry[]
|
private static readonly TableEntry[] _table = new TableEntry[]
|
||||||
{
|
{
|
||||||
new TableEntry(MacroHLEFunctionName.ClearColor, new Hash128(0xA9FB28D1DC43645A, 0xB177E5D2EAE67FB0), 0x28),
|
new TableEntry(MacroHLEFunctionName.ClearColor, new Hash128(0xA9FB28D1DC43645A, 0xB177E5D2EAE67FB0), 0x28),
|
||||||
new TableEntry(MacroHLEFunctionName.ClearDepthStencil, new Hash128(0x1B96CB77D4879F4F, 0x8557032FE0C965FB), 0x24),
|
new TableEntry(MacroHLEFunctionName.ClearDepthStencil, new Hash128(0x1B96CB77D4879F4F, 0x8557032FE0C965FB), 0x24),
|
||||||
|
new TableEntry(MacroHLEFunctionName.DrawArraysInstanced, new Hash128(0x197FB416269DBC26, 0x34288C01DDA82202), 0x48),
|
||||||
|
new TableEntry(MacroHLEFunctionName.DrawElementsInstanced, new Hash128(0x1A501FD3D54EC8E0, 0x6CF570CF79DA74D6), 0x5c),
|
||||||
|
new TableEntry(MacroHLEFunctionName.DrawElementsIndirect, new Hash128(0x86A3E8E903AF8F45, 0xD35BBA07C23860A4), 0x7c),
|
||||||
new TableEntry(MacroHLEFunctionName.MultiDrawElementsIndirectCount, new Hash128(0x890AF57ED3FB1C37, 0x35D0C95C61F5386F), 0x19C)
|
new TableEntry(MacroHLEFunctionName.MultiDrawElementsIndirectCount, new Hash128(0x890AF57ED3FB1C37, 0x35D0C95C61F5386F), 0x19C)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the host supports all features required by the HLE macro.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="caps">Host capabilities</param>
|
||||||
|
/// <param name="name">Name of the HLE macro to be checked</param>
|
||||||
|
/// <returns>True if the host supports the HLE macro, false otherwise</returns>
|
||||||
private static bool IsMacroHLESupported(Capabilities caps, MacroHLEFunctionName name)
|
private static bool IsMacroHLESupported(Capabilities caps, MacroHLEFunctionName name)
|
||||||
{
|
{
|
||||||
if (name == MacroHLEFunctionName.ClearColor ||
|
if (name == MacroHLEFunctionName.ClearColor ||
|
||||||
name == MacroHLEFunctionName.ClearDepthStencil)
|
name == MacroHLEFunctionName.ClearDepthStencil ||
|
||||||
|
name == MacroHLEFunctionName.DrawArraysInstanced ||
|
||||||
|
name == MacroHLEFunctionName.DrawElementsInstanced ||
|
||||||
|
name == MacroHLEFunctionName.DrawElementsIndirect)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -77,15 +89,20 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
{
|
{
|
||||||
var mc = MemoryMarshal.Cast<int, byte>(code);
|
var mc = MemoryMarshal.Cast<int, byte>(code);
|
||||||
|
|
||||||
for (int i = 0; i < Table.Length; i++)
|
for (int i = 0; i < _table.Length; i++)
|
||||||
{
|
{
|
||||||
ref var entry = ref Table[i];
|
ref var entry = ref _table[i];
|
||||||
|
|
||||||
var hash = XXHash128.ComputeHash(mc.Slice(0, entry.Length));
|
var hash = XXHash128.ComputeHash(mc.Slice(0, entry.Length));
|
||||||
if (hash == entry.Hash)
|
if (hash == entry.Hash)
|
||||||
{
|
{
|
||||||
name = entry.Name;
|
if (IsMacroHLESupported(caps, entry.Name))
|
||||||
return IsMacroHLESupported(caps, name);
|
{
|
||||||
|
name = entry.Name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
evt.Flush();
|
evt.Flush();
|
||||||
return (memoryManager.Read<ulong>(gpuVa) != 0) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False;
|
return (memoryManager.Read<ulong>(gpuVa, true) != 0) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +108,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
evt?.Flush();
|
evt?.Flush();
|
||||||
evt2?.Flush();
|
evt2?.Flush();
|
||||||
|
|
||||||
ulong x = memoryManager.Read<ulong>(gpuVa);
|
ulong x = memoryManager.Read<ulong>(gpuVa, true);
|
||||||
ulong y = memoryManager.Read<ulong>(gpuVa + 16);
|
ulong y = memoryManager.Read<ulong>(gpuVa + 16, true);
|
||||||
|
|
||||||
return (isEqual ? x == y : x != y) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False;
|
return (isEqual ? x == y : x != y) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||||
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
@@ -9,6 +10,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class DrawManager
|
class DrawManager
|
||||||
{
|
{
|
||||||
|
// Since we don't know the index buffer size for indirect draws,
|
||||||
|
// we must assume a minimum and maximum size and use that for buffer data update purposes.
|
||||||
|
private const int MinIndirectIndexCount = 0x10000;
|
||||||
|
private const int MaxIndirectIndexCount = 0x4000000;
|
||||||
|
|
||||||
private readonly GpuContext _context;
|
private readonly GpuContext _context;
|
||||||
private readonly GpuChannel _channel;
|
private readonly GpuChannel _channel;
|
||||||
private readonly DeviceStateWithShadow<ThreedClassState> _state;
|
private readonly DeviceStateWithShadow<ThreedClassState> _state;
|
||||||
@@ -28,6 +34,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
private int _instanceIndex;
|
private int _instanceIndex;
|
||||||
|
|
||||||
|
private const int VertexBufferFirstMethodOffset = 0x35d;
|
||||||
private const int IndexBufferCountMethodOffset = 0x5f8;
|
private const int IndexBufferCountMethodOffset = 0x5f8;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -237,6 +244,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
_instanceIndex = 0;
|
_instanceIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateTopology(topology);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the current primitive topology if needed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="topology">New primitive topology</param>
|
||||||
|
private void UpdateTopology(PrimitiveTopology topology)
|
||||||
|
{
|
||||||
if (_drawState.Topology != topology || !_topologySet)
|
if (_drawState.Topology != topology || !_topologySet)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetPrimitiveTopology(topology);
|
_context.Renderer.Pipeline.SetPrimitiveTopology(topology);
|
||||||
@@ -383,28 +399,27 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a indirect multi-draw, with parameters from a GPU buffer.
|
/// Performs a indexed or non-indexed draw.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="engine">3D engine where this method is being called</param>
|
/// <param name="engine">3D engine where this method is being called</param>
|
||||||
/// <param name="topology">Primitive topology</param>
|
/// <param name="topology">Primitive topology</param>
|
||||||
/// <param name="indirectBuffer">GPU buffer with the draw parameters, such as count, first index, etc</param>
|
/// <param name="count">Index count for indexed draws, vertex count for non-indexed draws</param>
|
||||||
/// <param name="parameterBuffer">GPU buffer with the draw count</param>
|
/// <param name="instanceCount">Instance count</param>
|
||||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
/// <param name="firstIndex">First index on the index buffer for indexed draws, ignored for non-indexed draws</param>
|
||||||
/// <param name="stride">Distance in bytes between each element on the <paramref name="indirectBuffer"/> array</param>
|
/// <param name="firstVertex">First vertex on the vertex buffer</param>
|
||||||
public void MultiDrawIndirectCount(
|
/// <param name="firstInstance">First instance</param>
|
||||||
|
/// <param name="indexed">True if the draw is indexed, false otherwise</param>
|
||||||
|
public void Draw(
|
||||||
ThreedClass engine,
|
ThreedClass engine,
|
||||||
int indexCount,
|
|
||||||
PrimitiveTopology topology,
|
PrimitiveTopology topology,
|
||||||
BufferRange indirectBuffer,
|
int count,
|
||||||
BufferRange parameterBuffer,
|
int instanceCount,
|
||||||
int maxDrawCount,
|
int firstIndex,
|
||||||
int stride)
|
int firstVertex,
|
||||||
|
int firstInstance,
|
||||||
|
bool indexed)
|
||||||
{
|
{
|
||||||
engine.Write(IndexBufferCountMethodOffset * 4, indexCount);
|
UpdateTopology(topology);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetPrimitiveTopology(topology);
|
|
||||||
_drawState.Topology = topology;
|
|
||||||
_topologySet = true;
|
|
||||||
|
|
||||||
ConditionalRenderEnabled renderEnable = ConditionalRendering.GetRenderEnable(
|
ConditionalRenderEnabled renderEnable = ConditionalRendering.GetRenderEnable(
|
||||||
_context,
|
_context,
|
||||||
@@ -418,21 +433,133 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_drawState.FirstIndex = _state.State.IndexBufferState.First;
|
if (indexed)
|
||||||
_drawState.IndexCount = indexCount;
|
|
||||||
|
|
||||||
engine.UpdateState();
|
|
||||||
|
|
||||||
if (_drawState.DrawIndexed)
|
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.MultiDrawIndexedIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
_drawState.FirstIndex = firstIndex;
|
||||||
|
_drawState.IndexCount = count;
|
||||||
|
_state.State.FirstVertex = (uint)firstVertex;
|
||||||
|
engine.ForceStateDirty(IndexBufferCountMethodOffset * 4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.MultiDrawIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
_state.State.VertexBufferDrawState.First = firstVertex;
|
||||||
|
_state.State.VertexBufferDrawState.Count = count;
|
||||||
|
engine.ForceStateDirty(VertexBufferFirstMethodOffset * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
_state.State.FirstInstance = (uint)firstInstance;
|
||||||
|
|
||||||
|
_drawState.DrawIndexed = indexed;
|
||||||
|
_drawState.HasConstantBufferDrawParameters = true;
|
||||||
|
|
||||||
|
engine.UpdateState();
|
||||||
|
|
||||||
|
if (indexed)
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.DrawIndexed(count, instanceCount, firstIndex, firstVertex, firstInstance);
|
||||||
|
_state.State.FirstVertex = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.Draw(count, instanceCount, firstVertex, firstInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
_state.State.FirstInstance = 0;
|
||||||
|
|
||||||
|
_drawState.DrawIndexed = false;
|
||||||
|
_drawState.HasConstantBufferDrawParameters = false;
|
||||||
|
|
||||||
|
if (renderEnable == ConditionalRenderEnabled.Host)
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.EndHostConditionalRendering();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a indirect draw, with parameters from a GPU buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="engine">3D engine where this method is being called</param>
|
||||||
|
/// <param name="topology">Primitive topology</param>
|
||||||
|
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
||||||
|
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
||||||
|
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||||
|
/// <param name="stride">Distance in bytes between each entry on the data pointed to by <paramref name="indirectBufferAddress"/></param>
|
||||||
|
/// <param name="indexCount">Maximum number of indices that the draw can consume</param>
|
||||||
|
/// <param name="drawType">Type of the indirect draw, which can be indexed or non-indexed, with or without a draw count</param>
|
||||||
|
public void DrawIndirect(
|
||||||
|
ThreedClass engine,
|
||||||
|
PrimitiveTopology topology,
|
||||||
|
ulong indirectBufferAddress,
|
||||||
|
ulong parameterBufferAddress,
|
||||||
|
int maxDrawCount,
|
||||||
|
int stride,
|
||||||
|
int indexCount,
|
||||||
|
IndirectDrawType drawType)
|
||||||
|
{
|
||||||
|
UpdateTopology(topology);
|
||||||
|
|
||||||
|
ConditionalRenderEnabled renderEnable = ConditionalRendering.GetRenderEnable(
|
||||||
|
_context,
|
||||||
|
_channel.MemoryManager,
|
||||||
|
_state.State.RenderEnableAddress,
|
||||||
|
_state.State.RenderEnableCondition);
|
||||||
|
|
||||||
|
if (renderEnable == ConditionalRenderEnabled.False)
|
||||||
|
{
|
||||||
|
_drawState.DrawIndexed = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalMemory memory = _channel.MemoryManager.Physical;
|
||||||
|
|
||||||
|
bool hasCount = (drawType & IndirectDrawType.Count) != 0;
|
||||||
|
bool indexed = (drawType & IndirectDrawType.Indexed) != 0;
|
||||||
|
|
||||||
|
if (indexed)
|
||||||
|
{
|
||||||
|
indexCount = Math.Clamp(indexCount, MinIndirectIndexCount, MaxIndirectIndexCount);
|
||||||
|
_drawState.FirstIndex = 0;
|
||||||
|
_drawState.IndexCount = indexCount;
|
||||||
|
engine.ForceStateDirty(IndexBufferCountMethodOffset * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
_drawState.DrawIndexed = indexed;
|
||||||
|
_drawState.DrawIndirect = true;
|
||||||
|
_drawState.HasConstantBufferDrawParameters = true;
|
||||||
|
|
||||||
|
engine.UpdateState();
|
||||||
|
|
||||||
|
if (hasCount)
|
||||||
|
{
|
||||||
|
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferAddress, (ulong)maxDrawCount * (ulong)stride);
|
||||||
|
var parameterBuffer = memory.BufferCache.GetBufferRange(parameterBufferAddress, 4);
|
||||||
|
|
||||||
|
if (indexed)
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.DrawIndexedIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.DrawIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferAddress, (ulong)stride);
|
||||||
|
|
||||||
|
if (indexed)
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.DrawIndexedIndirect(indirectBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.DrawIndirect(indirectBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_drawState.DrawIndexed = false;
|
_drawState.DrawIndexed = false;
|
||||||
|
_drawState.DrawIndirect = false;
|
||||||
|
_drawState.HasConstantBufferDrawParameters = false;
|
||||||
|
|
||||||
if (renderEnable == ConditionalRenderEnabled.Host)
|
if (renderEnable == ConditionalRenderEnabled.Host)
|
||||||
{
|
{
|
||||||
|
@@ -22,6 +22,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DrawIndexed;
|
public bool DrawIndexed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the next draw will be a indirect draw.
|
||||||
|
/// </summary>
|
||||||
|
public bool DrawIndirect;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if any of the currently used vertex shaders reads the instance ID.
|
/// Indicates if any of the currently used vertex shaders reads the instance ID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -32,6 +37,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsAnyVbInstanced;
|
public bool IsAnyVbInstanced;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasConstantBufferDrawParameters;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Primitive topology for the next draw.
|
/// Primitive topology for the next draw.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
38
Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs
Normal file
38
Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indirect draw type, which can be indexed or non-indexed, with or without a draw count.
|
||||||
|
/// </summary>
|
||||||
|
enum IndirectDrawType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Non-indexed draw without draw count.
|
||||||
|
/// </summary>
|
||||||
|
DrawIndirect = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indexed draw without draw count.
|
||||||
|
/// </summary>
|
||||||
|
DrawIndexedIndirect = Indexed,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Non-indexed draw with draw count.
|
||||||
|
/// </summary>
|
||||||
|
DrawIndirectCount = Count,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indexed draw with draw count.
|
||||||
|
/// </summary>
|
||||||
|
DrawIndexedIndirectCount = Indexed | Count,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indexed flag.
|
||||||
|
/// </summary>
|
||||||
|
Indexed = 1 << 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw count flag.
|
||||||
|
/// </summary>
|
||||||
|
Count = 1 << 1
|
||||||
|
}
|
||||||
|
}
|
@@ -34,10 +34,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
private ProgramPipelineState _pipeline;
|
private ProgramPipelineState _pipeline;
|
||||||
|
|
||||||
|
private bool _vsUsesDrawParameters;
|
||||||
private bool _vtgWritesRtLayer;
|
private bool _vtgWritesRtLayer;
|
||||||
private byte _vsClipDistancesWritten;
|
private byte _vsClipDistancesWritten;
|
||||||
|
|
||||||
private bool _prevDrawIndexed;
|
private bool _prevDrawIndexed;
|
||||||
|
private bool _prevDrawIndirect;
|
||||||
private IndexType _prevIndexType;
|
private IndexType _prevIndexType;
|
||||||
private uint _prevFirstVertex;
|
private uint _prevFirstVertex;
|
||||||
private bool _prevTfEnable;
|
private bool _prevTfEnable;
|
||||||
@@ -210,7 +212,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
// of the shader for the new state.
|
// of the shader for the new state.
|
||||||
if (_shaderSpecState != null)
|
if (_shaderSpecState != null)
|
||||||
{
|
{
|
||||||
if (!_shaderSpecState.MatchesGraphics(_channel, GetPoolState(), GetGraphicsState(), false))
|
if (!_shaderSpecState.MatchesGraphics(_channel, GetPoolState(), GetGraphicsState(), _vsUsesDrawParameters, false))
|
||||||
{
|
{
|
||||||
ForceShaderUpdate();
|
ForceShaderUpdate();
|
||||||
}
|
}
|
||||||
@@ -237,6 +239,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
_prevDrawIndexed = _drawState.DrawIndexed;
|
_prevDrawIndexed = _drawState.DrawIndexed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some draw parameters are used to restrict the vertex buffer size,
|
||||||
|
// but they can't be used on indirect draws because their values are unknown in this case.
|
||||||
|
// When switching between indirect and non-indirect draw, we need to
|
||||||
|
// make sure the vertex buffer sizes are still correct.
|
||||||
|
if (_drawState.DrawIndirect != _prevDrawIndirect)
|
||||||
|
{
|
||||||
|
_updateTracker.ForceDirty(VertexBufferStateIndex);
|
||||||
|
}
|
||||||
|
|
||||||
// In some cases, the index type is also used to guess the
|
// In some cases, the index type is also used to guess the
|
||||||
// vertex buffer size, so we must update it if the type changed too.
|
// vertex buffer size, so we must update it if the type changed too.
|
||||||
if (_drawState.DrawIndexed &&
|
if (_drawState.DrawIndexed &&
|
||||||
@@ -938,6 +949,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
_drawState.IsAnyVbInstanced = false;
|
_drawState.IsAnyVbInstanced = false;
|
||||||
|
|
||||||
|
bool drawIndexed = _drawState.DrawIndexed;
|
||||||
|
bool drawIndirect = _drawState.DrawIndirect;
|
||||||
|
|
||||||
for (int index = 0; index < Constants.TotalVertexBuffers; index++)
|
for (int index = 0; index < Constants.TotalVertexBuffers; index++)
|
||||||
{
|
{
|
||||||
var vertexBuffer = _state.State.VertexBufferState[index];
|
var vertexBuffer = _state.State.VertexBufferState[index];
|
||||||
@@ -965,14 +979,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
ulong vbSize = endAddress.Pack() - address + 1;
|
ulong vbSize = endAddress.Pack() - address + 1;
|
||||||
ulong size;
|
ulong size;
|
||||||
|
|
||||||
if (_drawState.IbStreamer.HasInlineIndexData || _drawState.DrawIndexed || stride == 0 || instanced)
|
if (_drawState.IbStreamer.HasInlineIndexData || drawIndexed || stride == 0 || instanced)
|
||||||
{
|
{
|
||||||
// This size may be (much) larger than the real vertex buffer size.
|
// This size may be (much) larger than the real vertex buffer size.
|
||||||
// Avoid calculating it this way, unless we don't have any other option.
|
// Avoid calculating it this way, unless we don't have any other option.
|
||||||
|
|
||||||
size = vbSize;
|
size = vbSize;
|
||||||
|
|
||||||
if (stride > 0 && indexTypeSmall && _drawState.DrawIndexed && !instanced)
|
if (stride > 0 && indexTypeSmall && drawIndexed && !drawIndirect && !instanced)
|
||||||
{
|
{
|
||||||
// If the index type is a small integer type, then we might be still able
|
// If the index type is a small integer type, then we might be still able
|
||||||
// to reduce the vertex buffer size based on the maximum possible index value.
|
// to reduce the vertex buffer size based on the maximum possible index value.
|
||||||
@@ -1207,6 +1221,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
byte oldVsClipDistancesWritten = _vsClipDistancesWritten;
|
byte oldVsClipDistancesWritten = _vsClipDistancesWritten;
|
||||||
|
|
||||||
_drawState.VsUsesInstanceId = gs.Shaders[1]?.Info.UsesInstanceId ?? false;
|
_drawState.VsUsesInstanceId = gs.Shaders[1]?.Info.UsesInstanceId ?? false;
|
||||||
|
_vsUsesDrawParameters = gs.Shaders[1]?.Info.UsesDrawParameters ?? false;
|
||||||
_vsClipDistancesWritten = gs.Shaders[1]?.Info.ClipDistancesWritten ?? 0;
|
_vsClipDistancesWritten = gs.Shaders[1]?.Info.ClipDistancesWritten ?? 0;
|
||||||
|
|
||||||
if (oldVsClipDistancesWritten != _vsClipDistancesWritten)
|
if (oldVsClipDistancesWritten != _vsClipDistancesWritten)
|
||||||
@@ -1222,6 +1237,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
_context.Renderer.Pipeline.SetProgram(gs.HostProgram);
|
_context.Renderer.Pipeline.SetProgram(gs.HostProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates bindings consumed by the shader stage on the texture and buffer managers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stage">Shader stage to have the bindings updated</param>
|
||||||
|
/// <param name="info">Shader stage bindings info</param>
|
||||||
private void UpdateStageBindings(int stage, ShaderProgramInfo info)
|
private void UpdateStageBindings(int stage, ShaderProgramInfo info)
|
||||||
{
|
{
|
||||||
_currentProgramInfo[stage] = info;
|
_currentProgramInfo[stage] = info;
|
||||||
@@ -1340,7 +1360,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
_state.State.AlphaTestEnable,
|
_state.State.AlphaTestEnable,
|
||||||
_state.State.AlphaTestFunc,
|
_state.State.AlphaTestFunc,
|
||||||
_state.State.AlphaTestRef,
|
_state.State.AlphaTestRef,
|
||||||
ref attributeTypes);
|
ref attributeTypes,
|
||||||
|
_drawState.HasConstantBufferDrawParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -497,6 +497,50 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a indexed or non-indexed draw.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="topology">Primitive topology</param>
|
||||||
|
/// <param name="count">Index count for indexed draws, vertex count for non-indexed draws</param>
|
||||||
|
/// <param name="instanceCount">Instance count</param>
|
||||||
|
/// <param name="firstIndex">First index on the index buffer for indexed draws, ignored for non-indexed draws</param>
|
||||||
|
/// <param name="firstVertex">First vertex on the vertex buffer</param>
|
||||||
|
/// <param name="firstInstance">First instance</param>
|
||||||
|
/// <param name="indexed">True if the draw is indexed, false otherwise</param>
|
||||||
|
public void Draw(
|
||||||
|
PrimitiveTopology topology,
|
||||||
|
int count,
|
||||||
|
int instanceCount,
|
||||||
|
int firstIndex,
|
||||||
|
int firstVertex,
|
||||||
|
int firstInstance,
|
||||||
|
bool indexed)
|
||||||
|
{
|
||||||
|
_drawManager.Draw(this, topology, count, instanceCount, firstIndex, firstVertex, firstInstance, indexed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a indirect draw, with parameters from a GPU buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="topology">Primitive topology</param>
|
||||||
|
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
||||||
|
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
||||||
|
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||||
|
/// <param name="stride">Distance in bytes between each entry on the data pointed to by <paramref name="indirectBufferAddress"/></param>
|
||||||
|
/// <param name="indexCount">Maximum number of indices that the draw can consume</param>
|
||||||
|
/// <param name="drawType">Type of the indirect draw, which can be indexed or non-indexed, with or without a draw count</param>
|
||||||
|
public void DrawIndirect(
|
||||||
|
PrimitiveTopology topology,
|
||||||
|
ulong indirectBufferAddress,
|
||||||
|
ulong parameterBufferAddress,
|
||||||
|
int maxDrawCount,
|
||||||
|
int stride,
|
||||||
|
int indexCount,
|
||||||
|
IndirectDrawType drawType)
|
||||||
|
{
|
||||||
|
_drawManager.DrawIndirect(this, topology, indirectBufferAddress, parameterBufferAddress, maxDrawCount, stride, indexCount, drawType);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clears the current color and depth-stencil buffers.
|
/// Clears the current color and depth-stencil buffers.
|
||||||
/// Which buffers should be cleared can also specified with the arguments.
|
/// Which buffers should be cleared can also specified with the arguments.
|
||||||
@@ -507,25 +551,5 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
{
|
{
|
||||||
_drawManager.Clear(this, argument, layerCount);
|
_drawManager.Clear(this, argument, layerCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs a indirect multi-draw, with parameters from a GPU buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="indexCount">Index Buffer Count</param>
|
|
||||||
/// <param name="topology">Primitive topology</param>
|
|
||||||
/// <param name="indirectBuffer">GPU buffer with the draw parameters, such as count, first index, etc</param>
|
|
||||||
/// <param name="parameterBuffer">GPU buffer with the draw count</param>
|
|
||||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
|
||||||
/// <param name="stride">Distance in bytes between each element on the <paramref name="indirectBuffer"/> array</param>
|
|
||||||
public void MultiDrawIndirectCount(
|
|
||||||
int indexCount,
|
|
||||||
PrimitiveTopology topology,
|
|
||||||
BufferRange indirectBuffer,
|
|
||||||
BufferRange parameterBuffer,
|
|
||||||
int maxDrawCount,
|
|
||||||
int stride)
|
|
||||||
{
|
|
||||||
_drawManager.MultiDrawIndirectCount(this, indexCount, topology, indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
private Buffer[] _bufferOverlaps;
|
private Buffer[] _bufferOverlaps;
|
||||||
|
|
||||||
private readonly Dictionary<ulong, BufferCacheEntry> _dirtyCache;
|
private readonly Dictionary<ulong, BufferCacheEntry> _dirtyCache;
|
||||||
|
private readonly Dictionary<ulong, BufferCacheEntry> _modifiedCache;
|
||||||
|
|
||||||
public event Action NotifyBuffersModified;
|
public event Action NotifyBuffersModified;
|
||||||
|
|
||||||
@@ -45,6 +46,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
_bufferOverlaps = new Buffer[OverlapsBufferInitialCapacity];
|
_bufferOverlaps = new Buffer[OverlapsBufferInitialCapacity];
|
||||||
|
|
||||||
_dirtyCache = new Dictionary<ulong, BufferCacheEntry>();
|
_dirtyCache = new Dictionary<ulong, BufferCacheEntry>();
|
||||||
|
|
||||||
|
// There are a lot more entries on the modified cache, so it is separate from the one for ForceDirty.
|
||||||
|
_modifiedCache = new Dictionary<ulong, BufferCacheEntry>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -145,6 +149,30 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
result.Buffer.ForceDirty(result.Address, size);
|
result.Buffer.ForceDirty(result.Address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the given buffer range has been GPU modifed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
||||||
|
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
||||||
|
/// <param name="size">Size in bytes of the buffer</param>
|
||||||
|
/// <returns>True if modified, false otherwise</returns>
|
||||||
|
public bool CheckModified(MemoryManager memoryManager, ulong gpuVa, ulong size, out ulong outAddr)
|
||||||
|
{
|
||||||
|
if (!_modifiedCache.TryGetValue(gpuVa, out BufferCacheEntry result) ||
|
||||||
|
result.EndGpuAddress < gpuVa + size ||
|
||||||
|
result.UnmappedSequence != result.Buffer.UnmappedSequence)
|
||||||
|
{
|
||||||
|
ulong address = TranslateAndCreateBuffer(memoryManager, gpuVa, size);
|
||||||
|
result = new BufferCacheEntry(address, gpuVa, GetBuffer(address, size));
|
||||||
|
|
||||||
|
_modifiedCache[gpuVa] = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
outAddr = result.Address;
|
||||||
|
|
||||||
|
return result.Buffer.IsModified(result.Address, size);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new buffer for the specified range, if needed.
|
/// Creates a new buffer for the specified range, if needed.
|
||||||
/// If a buffer where this range can be fully contained already exists,
|
/// If a buffer where this range can be fully contained already exists,
|
||||||
@@ -326,18 +354,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
buffer.SignalModified(address, size);
|
buffer.SignalModified(address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a buffer sub-range for a given GPU memory range.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
|
||||||
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
|
||||||
/// <param name="size">Size in bytes of the buffer</param>
|
|
||||||
/// <returns>The buffer sub-range for the given range</returns>
|
|
||||||
public BufferRange GetGpuBufferRange(MemoryManager memoryManager, ulong gpuVa, ulong size)
|
|
||||||
{
|
|
||||||
return GetBufferRange(TranslateAndCreateBuffer(memoryManager, gpuVa, size), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a buffer sub-range starting at a given memory address.
|
/// Gets a buffer sub-range starting at a given memory address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -129,6 +129,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
return _oldSpecState.ConstantBufferUse[_stageIndex];
|
return _oldSpecState.ConstantBufferUse[_stageIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool QueryHasConstantBufferDrawParameters()
|
||||||
|
{
|
||||||
|
return _oldSpecState.GraphicsState.HasConstantBufferDrawParameters;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public InputTopology QueryPrimitiveTopology()
|
public InputTopology QueryPrimitiveTopology()
|
||||||
{
|
{
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 3807;
|
private const uint CodeGenVersion = 3747;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
@@ -159,6 +159,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
/// Bit mask of the render target components written by the fragment stage.
|
/// Bit mask of the render target components written by the fragment stage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int FragmentOutputMap;
|
public int FragmentOutputMap;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the vertex shader accesses draw parameters.
|
||||||
|
/// </summary>
|
||||||
|
public bool UsesDrawParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly DiskCacheGuestStorage _guestStorage;
|
private readonly DiskCacheGuestStorage _guestStorage;
|
||||||
@@ -771,6 +776,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
images,
|
images,
|
||||||
dataInfo.Stage,
|
dataInfo.Stage,
|
||||||
dataInfo.UsesInstanceId,
|
dataInfo.UsesInstanceId,
|
||||||
|
dataInfo.UsesDrawParameters,
|
||||||
dataInfo.UsesRtLayer,
|
dataInfo.UsesRtLayer,
|
||||||
dataInfo.ClipDistancesWritten,
|
dataInfo.ClipDistancesWritten,
|
||||||
dataInfo.FragmentOutputMap);
|
dataInfo.FragmentOutputMap);
|
||||||
@@ -796,6 +802,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
dataInfo.ImagesCount = (ushort)info.Images.Count;
|
dataInfo.ImagesCount = (ushort)info.Images.Count;
|
||||||
dataInfo.Stage = info.Stage;
|
dataInfo.Stage = info.Stage;
|
||||||
dataInfo.UsesInstanceId = info.UsesInstanceId;
|
dataInfo.UsesInstanceId = info.UsesInstanceId;
|
||||||
|
dataInfo.UsesDrawParameters = info.UsesDrawParameters;
|
||||||
dataInfo.UsesRtLayer = info.UsesRtLayer;
|
dataInfo.UsesRtLayer = info.UsesRtLayer;
|
||||||
dataInfo.ClipDistancesWritten = info.ClipDistancesWritten;
|
dataInfo.ClipDistancesWritten = info.ClipDistancesWritten;
|
||||||
dataInfo.FragmentOutputMap = info.FragmentOutputMap;
|
dataInfo.FragmentOutputMap = info.FragmentOutputMap;
|
||||||
|
@@ -139,6 +139,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
return useMask;
|
return useMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool QueryHasConstantBufferDrawParameters()
|
||||||
|
{
|
||||||
|
return _state.GraphicsState.HasConstantBufferDrawParameters;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public InputTopology QueryPrimitiveTopology()
|
public InputTopology QueryPrimitiveTopology()
|
||||||
{
|
{
|
||||||
|
@@ -77,6 +77,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Array32<AttributeType> AttributeTypes;
|
public Array32<AttributeType> AttributeTypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0.
|
||||||
|
/// </summary>
|
||||||
|
public readonly bool HasConstantBufferDrawParameters;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new GPU graphics state.
|
/// Creates a new GPU graphics state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -93,6 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// <param name="alphaTestCompare">When alpha test is enabled, indicates the comparison that decides if the fragment should be discarded</param>
|
/// <param name="alphaTestCompare">When alpha test is enabled, indicates the comparison that decides if the fragment should be discarded</param>
|
||||||
/// <param name="alphaTestReference">When alpha test is enabled, indicates the value to compare with the fragment output alpha</param>
|
/// <param name="alphaTestReference">When alpha test is enabled, indicates the value to compare with the fragment output alpha</param>
|
||||||
/// <param name="attributeTypes">Type of the vertex attributes consumed by the shader</param>
|
/// <param name="attributeTypes">Type of the vertex attributes consumed by the shader</param>
|
||||||
|
/// <param name="hasConstantBufferDrawParameters">Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0</param>
|
||||||
public GpuChannelGraphicsState(
|
public GpuChannelGraphicsState(
|
||||||
bool earlyZForce,
|
bool earlyZForce,
|
||||||
PrimitiveTopology topology,
|
PrimitiveTopology topology,
|
||||||
@@ -106,7 +112,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
bool alphaTestEnable,
|
bool alphaTestEnable,
|
||||||
CompareOp alphaTestCompare,
|
CompareOp alphaTestCompare,
|
||||||
float alphaTestReference,
|
float alphaTestReference,
|
||||||
ref Array32<AttributeType> attributeTypes)
|
ref Array32<AttributeType> attributeTypes,
|
||||||
|
bool hasConstantBufferDrawParameters)
|
||||||
{
|
{
|
||||||
EarlyZForce = earlyZForce;
|
EarlyZForce = earlyZForce;
|
||||||
Topology = topology;
|
Topology = topology;
|
||||||
@@ -121,6 +128,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
AlphaTestCompare = alphaTestCompare;
|
AlphaTestCompare = alphaTestCompare;
|
||||||
AlphaTestReference = alphaTestReference;
|
AlphaTestReference = alphaTestReference;
|
||||||
AttributeTypes = attributeTypes;
|
AttributeTypes = attributeTypes;
|
||||||
|
HasConstantBufferDrawParameters = hasConstantBufferDrawParameters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -520,7 +520,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gpShaders.SpecializationState.MatchesGraphics(channel, poolState, graphicsState, true);
|
bool usesDrawParameters = gpShaders.Shaders[1]?.Info.UsesDrawParameters ?? false;
|
||||||
|
|
||||||
|
return gpShaders.SpecializationState.MatchesGraphics(channel, poolState, graphicsState, usesDrawParameters, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -35,7 +35,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
{
|
{
|
||||||
foreach (var entry in _entries)
|
foreach (var entry in _entries)
|
||||||
{
|
{
|
||||||
if (entry.SpecializationState.MatchesGraphics(channel, poolState, graphicsState, true))
|
bool usesDrawParameters = entry.Shaders[1]?.Info.UsesDrawParameters ?? false;
|
||||||
|
|
||||||
|
if (entry.SpecializationState.MatchesGraphics(channel, poolState, graphicsState, usesDrawParameters, true))
|
||||||
{
|
{
|
||||||
program = entry;
|
program = entry;
|
||||||
return true;
|
return true;
|
||||||
|
@@ -481,9 +481,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// <param name="channel">GPU channel</param>
|
/// <param name="channel">GPU channel</param>
|
||||||
/// <param name="poolState">Texture pool state</param>
|
/// <param name="poolState">Texture pool state</param>
|
||||||
/// <param name="graphicsState">Graphics state</param>
|
/// <param name="graphicsState">Graphics state</param>
|
||||||
|
/// <param name="usesDrawParameters">Indicates whether the vertex shader accesses draw parameters</param>
|
||||||
/// <param name="checkTextures">Indicates whether texture descriptors should be checked</param>
|
/// <param name="checkTextures">Indicates whether texture descriptors should be checked</param>
|
||||||
/// <returns>True if the state matches, false otherwise</returns>
|
/// <returns>True if the state matches, false otherwise</returns>
|
||||||
public bool MatchesGraphics(GpuChannel channel, GpuChannelPoolState poolState, GpuChannelGraphicsState graphicsState, bool checkTextures)
|
public bool MatchesGraphics(
|
||||||
|
GpuChannel channel,
|
||||||
|
GpuChannelPoolState poolState,
|
||||||
|
GpuChannelGraphicsState graphicsState,
|
||||||
|
bool usesDrawParameters,
|
||||||
|
bool checkTextures)
|
||||||
{
|
{
|
||||||
if (graphicsState.ViewportTransformDisable != GraphicsState.ViewportTransformDisable)
|
if (graphicsState.ViewportTransformDisable != GraphicsState.ViewportTransformDisable)
|
||||||
{
|
{
|
||||||
@@ -520,6 +526,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (usesDrawParameters && graphicsState.HasConstantBufferDrawParameters != GraphicsState.HasConstantBufferDrawParameters)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return Matches(channel, poolState, checkTextures, isCompute: false);
|
return Matches(channel, poolState, checkTextures, isCompute: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -586,6 +586,95 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawIndexedIndirect(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreDrawVbUnbounded();
|
||||||
|
|
||||||
|
_vertexArray.SetRangeOfIndexBuffer();
|
||||||
|
|
||||||
|
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
||||||
|
|
||||||
|
GL.DrawElementsIndirect(_primitiveType, _elementsType, (IntPtr)indirectBuffer.Offset);
|
||||||
|
|
||||||
|
_vertexArray.RestoreIndexBuffer();
|
||||||
|
|
||||||
|
PostDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreDrawVbUnbounded();
|
||||||
|
|
||||||
|
_vertexArray.SetRangeOfIndexBuffer();
|
||||||
|
|
||||||
|
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
||||||
|
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32());
|
||||||
|
|
||||||
|
GL.MultiDrawElementsIndirectCount(
|
||||||
|
_primitiveType,
|
||||||
|
(All)_elementsType,
|
||||||
|
(IntPtr)indirectBuffer.Offset,
|
||||||
|
(IntPtr)parameterBuffer.Offset,
|
||||||
|
maxDrawCount,
|
||||||
|
stride);
|
||||||
|
|
||||||
|
_vertexArray.RestoreIndexBuffer();
|
||||||
|
|
||||||
|
PostDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndirect(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreDrawVbUnbounded();
|
||||||
|
|
||||||
|
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
||||||
|
|
||||||
|
GL.DrawArraysIndirect(_primitiveType, (IntPtr)indirectBuffer.Offset);
|
||||||
|
|
||||||
|
PostDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreDrawVbUnbounded();
|
||||||
|
|
||||||
|
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
||||||
|
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32());
|
||||||
|
|
||||||
|
GL.MultiDrawArraysIndirectCount(
|
||||||
|
_primitiveType,
|
||||||
|
(IntPtr)indirectBuffer.Offset,
|
||||||
|
(IntPtr)parameterBuffer.Offset,
|
||||||
|
maxDrawCount,
|
||||||
|
stride);
|
||||||
|
|
||||||
|
PostDraw();
|
||||||
|
}
|
||||||
|
|
||||||
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
||||||
{
|
{
|
||||||
if (texture is TextureView view && sampler is Sampler samp)
|
if (texture is TextureView view && sampler is Sampler samp)
|
||||||
@@ -683,57 +772,6 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_tfEnabled = false;
|
_tfEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
|
||||||
{
|
|
||||||
if (!_program.IsLinked)
|
|
||||||
{
|
|
||||||
Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PreDrawVbUnbounded();
|
|
||||||
|
|
||||||
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
|
||||||
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32());
|
|
||||||
|
|
||||||
GL.MultiDrawArraysIndirectCount(
|
|
||||||
_primitiveType,
|
|
||||||
(IntPtr)indirectBuffer.Offset,
|
|
||||||
(IntPtr)parameterBuffer.Offset,
|
|
||||||
maxDrawCount,
|
|
||||||
stride);
|
|
||||||
|
|
||||||
PostDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
|
||||||
{
|
|
||||||
if (!_program.IsLinked)
|
|
||||||
{
|
|
||||||
Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PreDrawVbUnbounded();
|
|
||||||
|
|
||||||
_vertexArray.SetRangeOfIndexBuffer();
|
|
||||||
|
|
||||||
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
|
|
||||||
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32());
|
|
||||||
|
|
||||||
GL.MultiDrawElementsIndirectCount(
|
|
||||||
_primitiveType,
|
|
||||||
(All)_elementsType,
|
|
||||||
(IntPtr)indirectBuffer.Offset,
|
|
||||||
(IntPtr)parameterBuffer.Offset,
|
|
||||||
maxDrawCount,
|
|
||||||
stride);
|
|
||||||
|
|
||||||
_vertexArray.RestoreIndexBuffer();
|
|
||||||
|
|
||||||
PostDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetAlphaTest(bool enable, float reference, CompareOp op)
|
public void SetAlphaTest(bool enable, float reference, CompareOp op)
|
||||||
{
|
{
|
||||||
if (!enable)
|
if (!enable)
|
||||||
|
@@ -10,12 +10,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
public StructuredFunction CurrentFunction { get; set; }
|
public StructuredFunction CurrentFunction { get; set; }
|
||||||
|
|
||||||
|
public StructuredProgramInfo Info { get; }
|
||||||
|
|
||||||
public ShaderConfig Config { get; }
|
public ShaderConfig Config { get; }
|
||||||
|
|
||||||
public OperandManager OperandManager { get; }
|
public OperandManager OperandManager { get; }
|
||||||
|
|
||||||
private readonly StructuredProgramInfo _info;
|
|
||||||
|
|
||||||
private readonly StringBuilder _sb;
|
private readonly StringBuilder _sb;
|
||||||
|
|
||||||
private int _level;
|
private int _level;
|
||||||
@@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
public CodeGenContext(StructuredProgramInfo info, ShaderConfig config)
|
public CodeGenContext(StructuredProgramInfo info, ShaderConfig config)
|
||||||
{
|
{
|
||||||
_info = info;
|
Info = info;
|
||||||
Config = config;
|
Config = config;
|
||||||
|
|
||||||
OperandManager = new OperandManager();
|
OperandManager = new OperandManager();
|
||||||
@@ -72,19 +72,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
public StructuredFunction GetFunction(int id)
|
public StructuredFunction GetFunction(int id)
|
||||||
{
|
{
|
||||||
return _info.Functions[id];
|
return Info.Functions[id];
|
||||||
}
|
|
||||||
|
|
||||||
public TransformFeedbackOutput GetTransformFeedbackOutput(int location, int component)
|
|
||||||
{
|
|
||||||
int index = (AttributeConsts.UserAttributeBase / 4) + location * 4 + component;
|
|
||||||
return _info.TransformFeedbackOutputs[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformFeedbackOutput GetTransformFeedbackOutput(int location)
|
|
||||||
{
|
|
||||||
int index = location / 4;
|
|
||||||
return _info.TransformFeedbackOutputs[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateIndentation()
|
private void UpdateIndentation()
|
||||||
|
@@ -46,6 +46,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (context.Config.Stage == ShaderStage.Vertex)
|
||||||
|
{
|
||||||
|
context.AppendLine("#extension GL_ARB_shader_draw_parameters : enable");
|
||||||
|
}
|
||||||
|
|
||||||
context.AppendLine("#extension GL_ARB_shader_viewport_layer_array : enable");
|
context.AppendLine("#extension GL_ARB_shader_viewport_layer_array : enable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +215,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
|
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
|
||||||
{
|
{
|
||||||
var tfOutput = context.GetTransformFeedbackOutput(AttributeConsts.PositionX);
|
var tfOutput = context.Info.GetTransformFeedbackOutput(AttributeConsts.PositionX);
|
||||||
if (tfOutput.Valid)
|
if (tfOutput.Valid)
|
||||||
{
|
{
|
||||||
context.AppendLine($"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) out gl_PerVertex");
|
context.AppendLine($"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) out gl_PerVertex");
|
||||||
@@ -604,19 +609,45 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
|
|
||||||
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
|
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
|
||||||
{
|
{
|
||||||
for (int c = 0; c < 4; c++)
|
int attrOffset = AttributeConsts.UserAttributeBase + attr * 16;
|
||||||
|
int components = context.Config.LastInPipeline ? context.Info.GetTransformFeedbackOutputComponents(attrOffset) : 1;
|
||||||
|
|
||||||
|
if (components > 1)
|
||||||
{
|
{
|
||||||
char swzMask = "xyzw"[c];
|
string type = components switch
|
||||||
|
{
|
||||||
|
2 => "vec2",
|
||||||
|
3 => "vec3",
|
||||||
|
4 => "vec4",
|
||||||
|
_ => "float"
|
||||||
|
};
|
||||||
|
|
||||||
string xfb = string.Empty;
|
string xfb = string.Empty;
|
||||||
|
|
||||||
var tfOutput = context.GetTransformFeedbackOutput(attr, c);
|
var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset);
|
||||||
if (tfOutput.Valid)
|
if (tfOutput.Valid)
|
||||||
{
|
{
|
||||||
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
|
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
|
||||||
}
|
}
|
||||||
|
|
||||||
context.AppendLine($"layout (location = {attr}, component = {c}{xfb}) out float {name}_{swzMask};");
|
context.AppendLine($"layout (location = {attr}{xfb}) out {type} {name};");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int c = 0; c < 4; c++)
|
||||||
|
{
|
||||||
|
char swzMask = "xyzw"[c];
|
||||||
|
|
||||||
|
string xfb = string.Empty;
|
||||||
|
|
||||||
|
var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset + c * 4);
|
||||||
|
if (tfOutput.Valid)
|
||||||
|
{
|
||||||
|
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
|
||||||
|
}
|
||||||
|
|
||||||
|
context.AppendLine($"layout (location = {attr}, component = {c}{xfb}) out float {name}_{swzMask};");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
if (assignment.Destination is AstOperand operand && operand.Type.IsAttribute())
|
if (assignment.Destination is AstOperand operand && operand.Type.IsAttribute())
|
||||||
{
|
{
|
||||||
bool perPatch = operand.Type == OperandType.AttributePerPatch;
|
bool perPatch = operand.Type == OperandType.AttributePerPatch;
|
||||||
dest = OperandManager.GetOutAttributeName(operand.Value, context.Config, perPatch);
|
dest = OperandManager.GetOutAttributeName(context, operand.Value, perPatch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
}
|
}
|
||||||
else if (node is AstOperand operand)
|
else if (node is AstOperand operand)
|
||||||
{
|
{
|
||||||
return context.OperandManager.GetExpression(operand, context.Config);
|
return context.OperandManager.GetExpression(context, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Invalid node type \"{node?.GetType().Name ?? "null"}\".");
|
throw new ArgumentException($"Invalid node type \"{node?.GetType().Name ?? "null"}\".");
|
||||||
|
@@ -205,7 +205,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
if (src2 is AstOperand operand && operand.Type == OperandType.Constant)
|
if (src2 is AstOperand operand && operand.Type == OperandType.Constant)
|
||||||
{
|
{
|
||||||
int attrOffset = baseAttr.Value + (operand.Value << 2);
|
int attrOffset = baseAttr.Value + (operand.Value << 2);
|
||||||
return OperandManager.GetAttributeName(attrOffset, context.Config, perPatch: false, isOutAttr: false, indexExpr);
|
return OperandManager.GetAttributeName(context, attrOffset, perPatch: false, isOutAttr: false, indexExpr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -332,7 +332,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
if (src2 is AstOperand operand && operand.Type == OperandType.Constant)
|
if (src2 is AstOperand operand && operand.Type == OperandType.Constant)
|
||||||
{
|
{
|
||||||
int attrOffset = baseAttr.Value + (operand.Value << 2);
|
int attrOffset = baseAttr.Value + (operand.Value << 2);
|
||||||
attrName = OperandManager.GetAttributeName(attrOffset, context.Config, perPatch: false, isOutAttr: true);
|
attrName = OperandManager.GetAttributeName(context, attrOffset, perPatch: false, isOutAttr: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -48,6 +48,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
{ AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) },
|
{ AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) },
|
||||||
{ AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) },
|
{ AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) },
|
||||||
{ AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) },
|
{ AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) },
|
||||||
|
{ AttributeConsts.BaseInstance, new BuiltInAttribute("gl_BaseInstanceARB", VariableType.S32) },
|
||||||
|
{ AttributeConsts.BaseVertex, new BuiltInAttribute("gl_BaseVertexARB", VariableType.S32) },
|
||||||
|
{ AttributeConsts.InstanceIndex, new BuiltInAttribute("gl_InstanceIndex", VariableType.S32) },
|
||||||
|
{ AttributeConsts.VertexIndex, new BuiltInAttribute("gl_VertexIndex", VariableType.S32) },
|
||||||
|
{ AttributeConsts.DrawIndex, new BuiltInAttribute("gl_DrawIDARB", VariableType.S32) },
|
||||||
{ AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) },
|
{ AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) },
|
||||||
|
|
||||||
// Special.
|
// Special.
|
||||||
@@ -99,15 +104,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetExpression(AstOperand operand, ShaderConfig config)
|
public string GetExpression(CodeGenContext context, AstOperand operand)
|
||||||
{
|
{
|
||||||
return operand.Type switch
|
return operand.Type switch
|
||||||
{
|
{
|
||||||
OperandType.Argument => GetArgumentName(operand.Value),
|
OperandType.Argument => GetArgumentName(operand.Value),
|
||||||
OperandType.Attribute => GetAttributeName(operand.Value, config, perPatch: false),
|
OperandType.Attribute => GetAttributeName(context, operand.Value, perPatch: false),
|
||||||
OperandType.AttributePerPatch => GetAttributeName(operand.Value, config, perPatch: true),
|
OperandType.AttributePerPatch => GetAttributeName(context, operand.Value, perPatch: true),
|
||||||
OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
|
OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
|
||||||
OperandType.ConstantBuffer => GetConstantBufferName(operand, config),
|
OperandType.ConstantBuffer => GetConstantBufferName(operand, context.Config),
|
||||||
OperandType.LocalVariable => _locals[operand],
|
OperandType.LocalVariable => _locals[operand],
|
||||||
OperandType.Undefined => DefaultNames.UndefinedName,
|
OperandType.Undefined => DefaultNames.UndefinedName,
|
||||||
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
|
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
|
||||||
@@ -149,13 +154,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement);
|
return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetOutAttributeName(int value, ShaderConfig config, bool perPatch)
|
public static string GetOutAttributeName(CodeGenContext context, int value, bool perPatch)
|
||||||
{
|
{
|
||||||
return GetAttributeName(value, config, perPatch, isOutAttr: true);
|
return GetAttributeName(context, value, perPatch, isOutAttr: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetAttributeName(int value, ShaderConfig config, bool perPatch, bool isOutAttr = false, string indexExpr = "0")
|
public static string GetAttributeName(CodeGenContext context, int value, bool perPatch, bool isOutAttr = false, string indexExpr = "0")
|
||||||
{
|
{
|
||||||
|
ShaderConfig config = context.Config;
|
||||||
|
|
||||||
if ((value & AttributeConsts.LoadOutputMask) != 0)
|
if ((value & AttributeConsts.LoadOutputMask) != 0)
|
||||||
{
|
{
|
||||||
isOutAttr = true;
|
isOutAttr = true;
|
||||||
@@ -188,6 +195,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
}
|
}
|
||||||
else if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
|
else if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
|
||||||
{
|
{
|
||||||
|
int attrOffset = value;
|
||||||
value -= AttributeConsts.UserAttributeBase;
|
value -= AttributeConsts.UserAttributeBase;
|
||||||
|
|
||||||
string prefix = isOutAttr
|
string prefix = isOutAttr
|
||||||
@@ -211,14 +219,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||||||
((config.LastInVertexPipeline && isOutAttr) ||
|
((config.LastInVertexPipeline && isOutAttr) ||
|
||||||
(config.Stage == ShaderStage.Fragment && !isOutAttr)))
|
(config.Stage == ShaderStage.Fragment && !isOutAttr)))
|
||||||
{
|
{
|
||||||
string name = $"{prefix}{(value >> 4)}_{swzMask}";
|
int components = config.LastInPipeline ? context.Info.GetTransformFeedbackOutputComponents(attrOffset) : 1;
|
||||||
|
string name = components > 1 ? $"{prefix}{(value >> 4)}" : $"{prefix}{(value >> 4)}_{swzMask}";
|
||||||
|
|
||||||
if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
|
if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
|
||||||
{
|
{
|
||||||
name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]";
|
name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return components > 1 ? name + '.' + swzMask : name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -17,7 +17,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
private const uint SpirvVersionRevision = 0;
|
private const uint SpirvVersionRevision = 0;
|
||||||
private const uint SpirvVersionPacked = (SpirvVersionMajor << 16) | (SpirvVersionMinor << 8) | SpirvVersionRevision;
|
private const uint SpirvVersionPacked = (SpirvVersionMajor << 16) | (SpirvVersionMinor << 8) | SpirvVersionRevision;
|
||||||
|
|
||||||
private readonly StructuredProgramInfo _info;
|
public StructuredProgramInfo Info { get; }
|
||||||
|
|
||||||
public ShaderConfig Config { get; }
|
public ShaderConfig Config { get; }
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
GeneratorPool<Instruction> instPool,
|
GeneratorPool<Instruction> instPool,
|
||||||
GeneratorPool<LiteralInteger> integerPool) : base(SpirvVersionPacked, instPool, integerPool)
|
GeneratorPool<LiteralInteger> integerPool) : base(SpirvVersionPacked, instPool, integerPool)
|
||||||
{
|
{
|
||||||
_info = info;
|
Info = info;
|
||||||
Config = config;
|
Config = config;
|
||||||
|
|
||||||
if (config.Stage == ShaderStage.Geometry)
|
if (config.Stage == ShaderStage.Geometry)
|
||||||
@@ -317,6 +317,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
attrOffset = attr;
|
attrOffset = attr;
|
||||||
type = elemType;
|
type = elemType;
|
||||||
|
|
||||||
|
if (Config.LastInPipeline && isOutAttr)
|
||||||
|
{
|
||||||
|
int components = Info.GetTransformFeedbackOutputComponents(attr);
|
||||||
|
|
||||||
|
if (components > 1)
|
||||||
|
{
|
||||||
|
attrOffset &= ~0xf;
|
||||||
|
type = AggregateType.Vector | AggregateType.FP32;
|
||||||
|
attrInfo = new AttributeInfo(attrOffset, (attr - attrOffset) / 4, components, type, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ioVariable = isOutAttr ? Outputs[attrOffset] : Inputs[attrOffset];
|
ioVariable = isOutAttr ? Outputs[attrOffset] : Inputs[attrOffset];
|
||||||
@@ -536,18 +548,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return _functions[funcIndex];
|
return _functions[funcIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransformFeedbackOutput GetTransformFeedbackOutput(int location, int component)
|
|
||||||
{
|
|
||||||
int index = (AttributeConsts.UserAttributeBase / 4) + location * 4 + component;
|
|
||||||
return _info.TransformFeedbackOutputs[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformFeedbackOutput GetTransformFeedbackOutput(int location)
|
|
||||||
{
|
|
||||||
int index = location / 4;
|
|
||||||
return _info.TransformFeedbackOutputs[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public Instruction GetType(AggregateType type, int length = 1)
|
public Instruction GetType(AggregateType type, int length = 1)
|
||||||
{
|
{
|
||||||
if (type.HasFlag(AggregateType.Array))
|
if (type.HasFlag(AggregateType.Array))
|
||||||
|
@@ -440,11 +440,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
PixelImap iq = PixelImap.Unused;
|
PixelImap iq = PixelImap.Unused;
|
||||||
|
|
||||||
if (context.Config.Stage == ShaderStage.Fragment &&
|
if (context.Config.Stage == ShaderStage.Fragment)
|
||||||
attr >= AttributeConsts.UserAttributeBase &&
|
|
||||||
attr < AttributeConsts.UserAttributeEnd)
|
|
||||||
{
|
{
|
||||||
iq = context.Config.ImapTypes[(attr - AttributeConsts.UserAttributeBase) / 16].GetFirstUsedType();
|
if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd)
|
||||||
|
{
|
||||||
|
iq = context.Config.ImapTypes[(attr - AttributeConsts.UserAttributeBase) / 16].GetFirstUsedType();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AttributeInfo attrInfo = AttributeInfo.From(context.Config, attr, isOutAttr: false);
|
||||||
|
AggregateType elemType = attrInfo.Type & AggregateType.ElementTypeMask;
|
||||||
|
|
||||||
|
if (attrInfo.IsBuiltin && (elemType == AggregateType.S32 || elemType == AggregateType.U32))
|
||||||
|
{
|
||||||
|
iq = PixelImap.Constant;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclareInputOrOutput(context, attr, perPatch, isOutAttr: false, iq);
|
DeclareInputOrOutput(context, attr, perPatch, isOutAttr: false, iq);
|
||||||
@@ -516,7 +527,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
((isOutAttr && context.Config.LastInVertexPipeline) ||
|
((isOutAttr && context.Config.LastInVertexPipeline) ||
|
||||||
(!isOutAttr && context.Config.Stage == ShaderStage.Fragment)))
|
(!isOutAttr && context.Config.Stage == ShaderStage.Fragment)))
|
||||||
{
|
{
|
||||||
DeclareInputOrOutput(context, attr, (attr >> 2) & 3, isOutAttr, iq);
|
DeclareTransformFeedbackInputOrOutput(context, attr, isOutAttr, iq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,7 +583,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline && isOutAttr)
|
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline && isOutAttr)
|
||||||
{
|
{
|
||||||
var tfOutput = context.GetTransformFeedbackOutput(attrInfo.BaseValue);
|
var tfOutput = context.Info.GetTransformFeedbackOutput(attrInfo.BaseValue);
|
||||||
if (tfOutput.Valid)
|
if (tfOutput.Valid)
|
||||||
{
|
{
|
||||||
context.Decorate(spvVar, Decoration.XfbBuffer, (LiteralInteger)tfOutput.Buffer);
|
context.Decorate(spvVar, Decoration.XfbBuffer, (LiteralInteger)tfOutput.Buffer);
|
||||||
@@ -595,24 +606,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)location);
|
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)location);
|
||||||
|
|
||||||
if (!isOutAttr)
|
if (!isOutAttr &&
|
||||||
|
!perPatch &&
|
||||||
|
(context.Config.PassthroughAttributes & (1 << location)) != 0 &&
|
||||||
|
context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
if (!perPatch &&
|
context.Decorate(spvVar, Decoration.PassthroughNV);
|
||||||
(context.Config.PassthroughAttributes & (1 << location)) != 0 &&
|
|
||||||
context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
|
||||||
{
|
|
||||||
context.Decorate(spvVar, Decoration.PassthroughNV);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (iq)
|
|
||||||
{
|
|
||||||
case PixelImap.Constant:
|
|
||||||
context.Decorate(spvVar, Decoration.Flat);
|
|
||||||
break;
|
|
||||||
case PixelImap.ScreenLinear:
|
|
||||||
context.Decorate(spvVar, Decoration.NoPerspective);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (attr >= AttributeConsts.FragmentOutputColorBase && attr < AttributeConsts.FragmentOutputColorEnd)
|
else if (attr >= AttributeConsts.FragmentOutputColorBase && attr < AttributeConsts.FragmentOutputColorEnd)
|
||||||
@@ -621,22 +620,52 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)location);
|
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isOutAttr)
|
||||||
|
{
|
||||||
|
switch (iq)
|
||||||
|
{
|
||||||
|
case PixelImap.Constant:
|
||||||
|
context.Decorate(spvVar, Decoration.Flat);
|
||||||
|
break;
|
||||||
|
case PixelImap.ScreenLinear:
|
||||||
|
context.Decorate(spvVar, Decoration.NoPerspective);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context.AddGlobalVariable(spvVar);
|
context.AddGlobalVariable(spvVar);
|
||||||
dict.Add(attrInfo.BaseValue, spvVar);
|
dict.Add(attrInfo.BaseValue, spvVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DeclareInputOrOutput(CodeGenContext context, int attr, int component, bool isOutAttr, PixelImap iq = PixelImap.Unused)
|
private static void DeclareTransformFeedbackInputOrOutput(CodeGenContext context, int attr, bool isOutAttr, PixelImap iq = PixelImap.Unused)
|
||||||
{
|
{
|
||||||
var dict = isOutAttr ? context.Outputs : context.Inputs;
|
var dict = isOutAttr ? context.Outputs : context.Inputs;
|
||||||
var attrInfo = AttributeInfo.From(context.Config, attr, isOutAttr);
|
var attrInfo = AttributeInfo.From(context.Config, attr, isOutAttr);
|
||||||
|
|
||||||
|
bool hasComponent = true;
|
||||||
|
int component = (attr >> 2) & 3;
|
||||||
|
int components = 1;
|
||||||
|
var type = attrInfo.Type & AggregateType.ElementTypeMask;
|
||||||
|
|
||||||
|
if (context.Config.LastInPipeline && isOutAttr)
|
||||||
|
{
|
||||||
|
components = context.Info.GetTransformFeedbackOutputComponents(attr);
|
||||||
|
|
||||||
|
if (components > 1)
|
||||||
|
{
|
||||||
|
attr &= ~0xf;
|
||||||
|
type = AggregateType.Vector | AggregateType.FP32;
|
||||||
|
hasComponent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dict.ContainsKey(attr))
|
if (dict.ContainsKey(attr))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;
|
var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;
|
||||||
var attrType = context.GetType(attrInfo.Type & AggregateType.ElementTypeMask);
|
var attrType = context.GetType(type, components);
|
||||||
|
|
||||||
if (AttributeInfo.IsArrayAttributeSpirv(context.Config.Stage, isOutAttr) && (!attrInfo.IsBuiltin || AttributeInfo.IsArrayBuiltIn(attr)))
|
if (AttributeInfo.IsArrayAttributeSpirv(context.Config.Stage, isOutAttr) && (!attrInfo.IsBuiltin || AttributeInfo.IsArrayBuiltIn(attr)))
|
||||||
{
|
{
|
||||||
@@ -656,11 +685,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
int location = (attr - AttributeConsts.UserAttributeBase) / 16;
|
int location = (attr - AttributeConsts.UserAttributeBase) / 16;
|
||||||
|
|
||||||
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)location);
|
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)location);
|
||||||
context.Decorate(spvVar, Decoration.Component, (LiteralInteger)component);
|
|
||||||
|
if (hasComponent)
|
||||||
|
{
|
||||||
|
context.Decorate(spvVar, Decoration.Component, (LiteralInteger)component);
|
||||||
|
}
|
||||||
|
|
||||||
if (isOutAttr)
|
if (isOutAttr)
|
||||||
{
|
{
|
||||||
var tfOutput = context.GetTransformFeedbackOutput(location, component);
|
var tfOutput = context.Info.GetTransformFeedbackOutput(attr);
|
||||||
if (tfOutput.Valid)
|
if (tfOutput.Valid)
|
||||||
{
|
{
|
||||||
context.Decorate(spvVar, Decoration.XfbBuffer, (LiteralInteger)tfOutput.Buffer);
|
context.Decorate(spvVar, Decoration.XfbBuffer, (LiteralInteger)tfOutput.Buffer);
|
||||||
@@ -704,8 +737,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
AttributeConsts.ClipDistance0 => BuiltIn.ClipDistance,
|
AttributeConsts.ClipDistance0 => BuiltIn.ClipDistance,
|
||||||
AttributeConsts.PointCoordX => BuiltIn.PointCoord,
|
AttributeConsts.PointCoordX => BuiltIn.PointCoord,
|
||||||
AttributeConsts.TessCoordX => BuiltIn.TessCoord,
|
AttributeConsts.TessCoordX => BuiltIn.TessCoord,
|
||||||
AttributeConsts.InstanceId => BuiltIn.InstanceId, // FIXME: Invalid
|
AttributeConsts.InstanceId => BuiltIn.InstanceId,
|
||||||
AttributeConsts.VertexId => BuiltIn.VertexId, // FIXME: Invalid
|
AttributeConsts.VertexId => BuiltIn.VertexId,
|
||||||
|
AttributeConsts.BaseInstance => BuiltIn.BaseInstance,
|
||||||
|
AttributeConsts.BaseVertex => BuiltIn.BaseVertex,
|
||||||
|
AttributeConsts.InstanceIndex => BuiltIn.InstanceIndex,
|
||||||
|
AttributeConsts.VertexIndex => BuiltIn.VertexIndex,
|
||||||
|
AttributeConsts.DrawIndex => BuiltIn.DrawIndex,
|
||||||
AttributeConsts.FrontFacing => BuiltIn.FrontFacing,
|
AttributeConsts.FrontFacing => BuiltIn.FrontFacing,
|
||||||
AttributeConsts.FragmentOutputDepth => BuiltIn.FragDepth,
|
AttributeConsts.FragmentOutputDepth => BuiltIn.FragDepth,
|
||||||
AttributeConsts.ThreadKill => BuiltIn.HelperInvocation,
|
AttributeConsts.ThreadKill => BuiltIn.HelperInvocation,
|
||||||
|
@@ -62,10 +62,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
context.AddCapability(Capability.TransformFeedback);
|
context.AddCapability(Capability.TransformFeedback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.Stage == ShaderStage.Fragment && context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
|
if (config.Stage == ShaderStage.Fragment)
|
||||||
{
|
{
|
||||||
context.AddCapability(Capability.FragmentShaderPixelInterlockEXT);
|
if (context.Info.Inputs.Contains(AttributeConsts.Layer))
|
||||||
context.AddExtension("SPV_EXT_fragment_shader_interlock");
|
{
|
||||||
|
context.AddCapability(Capability.Geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
|
||||||
|
{
|
||||||
|
context.AddCapability(Capability.FragmentShaderPixelInterlockEXT);
|
||||||
|
context.AddExtension("SPV_EXT_fragment_shader_interlock");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (config.Stage == ShaderStage.Geometry)
|
else if (config.Stage == ShaderStage.Geometry)
|
||||||
{
|
{
|
||||||
@@ -81,6 +89,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
context.AddCapability(Capability.Tessellation);
|
context.AddCapability(Capability.Tessellation);
|
||||||
}
|
}
|
||||||
|
else if (config.Stage == ShaderStage.Vertex)
|
||||||
|
{
|
||||||
|
context.AddCapability(Capability.DrawParameters);
|
||||||
|
}
|
||||||
|
|
||||||
context.AddExtension("SPV_KHR_shader_ballot");
|
context.AddExtension("SPV_KHR_shader_ballot");
|
||||||
context.AddExtension("SPV_KHR_subgroup_vote");
|
context.AddExtension("SPV_KHR_subgroup_vote");
|
||||||
|
@@ -6,5 +6,9 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
|
|
||||||
public const int MaxAttributes = 16;
|
public const int MaxAttributes = 16;
|
||||||
public const int AllAttributesMask = (int)(uint.MaxValue >> (32 - MaxAttributes));
|
public const int AllAttributesMask = (int)(uint.MaxValue >> (32 - MaxAttributes));
|
||||||
|
|
||||||
|
public const int NvnBaseVertexByteOffset = 0x640;
|
||||||
|
public const int NvnBaseInstanceByteOffset = 0x644;
|
||||||
|
public const int NvnDrawIndexByteOffset = 0x648;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -168,6 +168,15 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries whenever the current draw has written the base vertex and base instance into Constant Buffer 0.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the shader translator can assume that the constant buffer contains the base IDs, false otherwise</returns>
|
||||||
|
bool QueryHasConstantBufferDrawParameters()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries host about the presence of the FrontFacing built-in variable bug.
|
/// Queries host about the presence of the FrontFacing built-in variable bug.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
offset |= AttributeConsts.LoadOutputMask;
|
offset |= AttributeConsts.LoadOutputMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand src = op.P ? AttributePerPatch(offset) : Attribute(offset);
|
Operand src = op.P ? AttributePerPatch(offset) : CreateInputAttribute(context, offset);
|
||||||
|
|
||||||
context.Copy(Register(rd), src);
|
context.Copy(Register(rd), src);
|
||||||
}
|
}
|
||||||
@@ -312,5 +312,22 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Operand CreateInputAttribute(EmitterContext context, int attr)
|
||||||
|
{
|
||||||
|
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||||
|
{
|
||||||
|
if (attr == AttributeConsts.InstanceId)
|
||||||
|
{
|
||||||
|
return context.ISubtract(Attribute(AttributeConsts.InstanceIndex), Attribute(AttributeConsts.BaseInstance));
|
||||||
|
}
|
||||||
|
else if (attr == AttributeConsts.VertexId)
|
||||||
|
{
|
||||||
|
return Attribute(AttributeConsts.VertexIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Attribute(attr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -12,6 +12,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
|
|
||||||
public ShaderStage Stage { get; }
|
public ShaderStage Stage { get; }
|
||||||
public bool UsesInstanceId { get; }
|
public bool UsesInstanceId { get; }
|
||||||
|
public bool UsesDrawParameters { get; }
|
||||||
public bool UsesRtLayer { get; }
|
public bool UsesRtLayer { get; }
|
||||||
public byte ClipDistancesWritten { get; }
|
public byte ClipDistancesWritten { get; }
|
||||||
public int FragmentOutputMap { get; }
|
public int FragmentOutputMap { get; }
|
||||||
@@ -23,6 +24,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
TextureDescriptor[] images,
|
TextureDescriptor[] images,
|
||||||
ShaderStage stage,
|
ShaderStage stage,
|
||||||
bool usesInstanceId,
|
bool usesInstanceId,
|
||||||
|
bool usesDrawParameters,
|
||||||
bool usesRtLayer,
|
bool usesRtLayer,
|
||||||
byte clipDistancesWritten,
|
byte clipDistancesWritten,
|
||||||
int fragmentOutputMap)
|
int fragmentOutputMap)
|
||||||
@@ -34,6 +36,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
|
|
||||||
Stage = stage;
|
Stage = stage;
|
||||||
UsesInstanceId = usesInstanceId;
|
UsesInstanceId = usesInstanceId;
|
||||||
|
UsesDrawParameters = usesDrawParameters;
|
||||||
UsesRtLayer = usesRtLayer;
|
UsesRtLayer = usesRtLayer;
|
||||||
ClipDistancesWritten = clipDistancesWritten;
|
ClipDistancesWritten = clipDistancesWritten;
|
||||||
FragmentOutputMap = fragmentOutputMap;
|
FragmentOutputMap = fragmentOutputMap;
|
||||||
|
@@ -71,12 +71,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
var locations = config.GpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex);
|
var locations = config.GpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex);
|
||||||
var stride = config.GpuAccessor.QueryTransformFeedbackStride(tfbIndex);
|
var stride = config.GpuAccessor.QueryTransformFeedbackStride(tfbIndex);
|
||||||
|
|
||||||
for (int j = 0; j < locations.Length; j++)
|
for (int i = 0; i < locations.Length; i++)
|
||||||
{
|
{
|
||||||
byte location = locations[j];
|
byte location = locations[i];
|
||||||
if (location < 0xc0)
|
if (location < 0xc0)
|
||||||
{
|
{
|
||||||
context.Info.TransformFeedbackOutputs[location] = new TransformFeedbackOutput(tfbIndex, j * 4, stride);
|
context.Info.TransformFeedbackOutputs[location] = new TransformFeedbackOutput(tfbIndex, i * 4, stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,5 +42,40 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
|
|
||||||
TransformFeedbackOutputs = new TransformFeedbackOutput[0xc0];
|
TransformFeedbackOutputs = new TransformFeedbackOutput[0xc0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TransformFeedbackOutput GetTransformFeedbackOutput(int attr)
|
||||||
|
{
|
||||||
|
int index = attr / 4;
|
||||||
|
return TransformFeedbackOutputs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetTransformFeedbackOutputComponents(int attr)
|
||||||
|
{
|
||||||
|
int index = attr / 4;
|
||||||
|
int baseIndex = index & ~3;
|
||||||
|
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
for (; count < 4; count++)
|
||||||
|
{
|
||||||
|
ref var prev = ref TransformFeedbackOutputs[baseIndex + count - 1];
|
||||||
|
ref var curr = ref TransformFeedbackOutputs[baseIndex + count];
|
||||||
|
|
||||||
|
int prevOffset = prev.Offset;
|
||||||
|
int currOffset = curr.Offset;
|
||||||
|
|
||||||
|
if (!prev.Valid || !curr.Valid || prevOffset + 4 != currOffset)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseIndex + count <= index)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -95,5 +95,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
public const int LtMask = 0x2000040;
|
public const int LtMask = 0x2000040;
|
||||||
|
|
||||||
public const int ThreadKill = 0x2000044;
|
public const int ThreadKill = 0x2000044;
|
||||||
|
|
||||||
|
public const int BaseInstance = 0x2000050;
|
||||||
|
public const int BaseVertex = 0x2000054;
|
||||||
|
public const int InstanceIndex = 0x2000058;
|
||||||
|
public const int VertexIndex = 0x200005c;
|
||||||
|
public const int DrawIndex = 0x2000060;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -27,6 +27,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
{ AttributeConsts.TessCoordY, new AttributeInfo(AttributeConsts.TessCoordX, 1, 3, AggregateType.Vector | AggregateType.FP32) },
|
{ AttributeConsts.TessCoordY, new AttributeInfo(AttributeConsts.TessCoordX, 1, 3, AggregateType.Vector | AggregateType.FP32) },
|
||||||
{ AttributeConsts.InstanceId, new AttributeInfo(AttributeConsts.InstanceId, 0, 1, AggregateType.S32) },
|
{ AttributeConsts.InstanceId, new AttributeInfo(AttributeConsts.InstanceId, 0, 1, AggregateType.S32) },
|
||||||
{ AttributeConsts.VertexId, new AttributeInfo(AttributeConsts.VertexId, 0, 1, AggregateType.S32) },
|
{ AttributeConsts.VertexId, new AttributeInfo(AttributeConsts.VertexId, 0, 1, AggregateType.S32) },
|
||||||
|
{ AttributeConsts.BaseInstance, new AttributeInfo(AttributeConsts.BaseInstance, 0, 1, AggregateType.S32) },
|
||||||
|
{ AttributeConsts.BaseVertex, new AttributeInfo(AttributeConsts.BaseVertex, 0, 1, AggregateType.S32) },
|
||||||
|
{ AttributeConsts.InstanceIndex, new AttributeInfo(AttributeConsts.InstanceIndex, 0, 1, AggregateType.S32) },
|
||||||
|
{ AttributeConsts.VertexIndex, new AttributeInfo(AttributeConsts.VertexIndex, 0, 1, AggregateType.S32) },
|
||||||
|
{ AttributeConsts.DrawIndex, new AttributeInfo(AttributeConsts.DrawIndex, 0, 1, AggregateType.S32) },
|
||||||
{ AttributeConsts.FrontFacing, new AttributeInfo(AttributeConsts.FrontFacing, 0, 1, AggregateType.Bool) },
|
{ AttributeConsts.FrontFacing, new AttributeInfo(AttributeConsts.FrontFacing, 0, 1, AggregateType.Bool) },
|
||||||
|
|
||||||
// Special.
|
// Special.
|
||||||
|
@@ -17,10 +17,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
Bindless = 1 << 2,
|
Bindless = 1 << 2,
|
||||||
InstanceId = 1 << 3,
|
InstanceId = 1 << 3,
|
||||||
RtLayer = 1 << 4,
|
DrawParameters = 1 << 4,
|
||||||
CbIndexing = 1 << 5,
|
RtLayer = 1 << 5,
|
||||||
IaIndexing = 1 << 6,
|
CbIndexing = 1 << 6,
|
||||||
OaIndexing = 1 << 7,
|
IaIndexing = 1 << 7,
|
||||||
FixedFuncAttr = 1 << 8
|
OaIndexing = 1 << 8,
|
||||||
|
FixedFuncAttr = 1 << 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,9 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
{
|
{
|
||||||
public static void RunPass(BasicBlock[] blocks, ShaderConfig config)
|
public static void RunPass(BasicBlock[] blocks, ShaderConfig config)
|
||||||
{
|
{
|
||||||
|
bool isVertexShader = config.Stage == ShaderStage.Vertex;
|
||||||
|
bool hasConstantBufferDrawParameters = config.GpuAccessor.QueryHasConstantBufferDrawParameters();
|
||||||
|
|
||||||
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
|
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
|
||||||
{
|
{
|
||||||
BasicBlock block = blocks[blkIndex];
|
BasicBlock block = blocks[blkIndex];
|
||||||
@@ -23,6 +26,21 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isVertexShader)
|
||||||
|
{
|
||||||
|
if (hasConstantBufferDrawParameters)
|
||||||
|
{
|
||||||
|
if (ReplaceConstantBufferWithDrawParameters(operation))
|
||||||
|
{
|
||||||
|
config.SetUsedFeature(FeatureFlags.DrawParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (HasConstantBufferDrawParameters(operation))
|
||||||
|
{
|
||||||
|
config.SetUsedFeature(FeatureFlags.DrawParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (UsesGlobalMemory(operation.Inst))
|
if (UsesGlobalMemory(operation.Inst))
|
||||||
{
|
{
|
||||||
node = RewriteGlobalAccess(node, config);
|
node = RewriteGlobalAccess(node, config);
|
||||||
@@ -528,5 +546,57 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool ReplaceConstantBufferWithDrawParameters(Operation operation)
|
||||||
|
{
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
|
||||||
|
{
|
||||||
|
Operand src = operation.GetSource(srcIndex);
|
||||||
|
|
||||||
|
if (src.Type == OperandType.ConstantBuffer && src.GetCbufSlot() == 0)
|
||||||
|
{
|
||||||
|
switch (src.GetCbufOffset())
|
||||||
|
{
|
||||||
|
case Constants.NvnBaseVertexByteOffset / 4:
|
||||||
|
operation.SetSource(srcIndex, Attribute(AttributeConsts.BaseVertex));
|
||||||
|
modified = true;
|
||||||
|
break;
|
||||||
|
case Constants.NvnBaseInstanceByteOffset / 4:
|
||||||
|
operation.SetSource(srcIndex, Attribute(AttributeConsts.BaseInstance));
|
||||||
|
modified = true;
|
||||||
|
break;
|
||||||
|
case Constants.NvnDrawIndexByteOffset / 4:
|
||||||
|
operation.SetSource(srcIndex, Attribute(AttributeConsts.DrawIndex));
|
||||||
|
modified = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool HasConstantBufferDrawParameters(Operation operation)
|
||||||
|
{
|
||||||
|
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
|
||||||
|
{
|
||||||
|
Operand src = operation.GetSource(srcIndex);
|
||||||
|
|
||||||
|
if (src.Type == OperandType.ConstantBuffer && src.GetCbufSlot() == 0)
|
||||||
|
{
|
||||||
|
switch (src.GetCbufOffset())
|
||||||
|
{
|
||||||
|
case Constants.NvnBaseVertexByteOffset / 4:
|
||||||
|
case Constants.NvnBaseInstanceByteOffset / 4:
|
||||||
|
case Constants.NvnDrawIndexByteOffset / 4:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -17,6 +17,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
public ShaderStage Stage { get; }
|
public ShaderStage Stage { get; }
|
||||||
|
|
||||||
public bool GpPassthrough { get; }
|
public bool GpPassthrough { get; }
|
||||||
|
public bool LastInPipeline { get; private set; }
|
||||||
public bool LastInVertexPipeline { get; private set; }
|
public bool LastInVertexPipeline { get; private set; }
|
||||||
|
|
||||||
public int ThreadsPerInputPrimitive { get; }
|
public int ThreadsPerInputPrimitive { get; }
|
||||||
@@ -143,6 +144,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
OmapSampleMask = header.OmapSampleMask;
|
OmapSampleMask = header.OmapSampleMask;
|
||||||
OmapDepth = header.OmapDepth;
|
OmapDepth = header.OmapDepth;
|
||||||
TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
|
TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
|
||||||
|
LastInPipeline = true;
|
||||||
LastInVertexPipeline = header.Stage < ShaderStage.Fragment;
|
LastInVertexPipeline = header.Stage < ShaderStage.Fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,6 +308,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
config._perPatchAttributeLocations = locationsMap;
|
config._perPatchAttributeLocations = locationsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LastInPipeline = false;
|
||||||
|
|
||||||
// We don't consider geometry shaders using the geometry shader passthrough feature
|
// We don't consider geometry shaders using the geometry shader passthrough feature
|
||||||
// as being the last because when this feature is used, it can't actually modify any of the outputs,
|
// as being the last because when this feature is used, it can't actually modify any of the outputs,
|
||||||
// so the stage that comes before it is the last one that can do modifications.
|
// so the stage that comes before it is the last one that can do modifications.
|
||||||
|
@@ -86,6 +86,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
config.GetImageDescriptors(),
|
config.GetImageDescriptors(),
|
||||||
config.Stage,
|
config.Stage,
|
||||||
config.UsedFeatures.HasFlag(FeatureFlags.InstanceId),
|
config.UsedFeatures.HasFlag(FeatureFlags.InstanceId),
|
||||||
|
config.UsedFeatures.HasFlag(FeatureFlags.DrawParameters),
|
||||||
config.UsedFeatures.HasFlag(FeatureFlags.RtLayer),
|
config.UsedFeatures.HasFlag(FeatureFlags.RtLayer),
|
||||||
config.ClipDistancesWritten,
|
config.ClipDistancesWritten,
|
||||||
config.OmapTargets);
|
config.OmapTargets);
|
||||||
|
@@ -477,6 +477,26 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return holder.GetBuffer();
|
return holder.GetBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetCachedConvertedBuffer(int offset, int size, ICacheKey key, out BufferHolder holder)
|
||||||
|
{
|
||||||
|
return _cachedConvertedBuffers.TryGetValue(offset, size, key, out holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCachedConvertedBuffer(int offset, int size, ICacheKey key, BufferHolder holder)
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.Add(offset, size, key, holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCachedConvertedBufferDependency(int offset, int size, ICacheKey key, Dependency dependency)
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.AddDependency(offset, size, key, dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveCachedConvertedBuffer(int offset, int size, ICacheKey key)
|
||||||
|
{
|
||||||
|
_cachedConvertedBuffers.Remove(offset, size, key);
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_gd.PipelineInternal?.FlushCommandsIfWeightExceeding(_buffer, (ulong)Size);
|
_gd.PipelineInternal?.FlushCommandsIfWeightExceeding(_buffer, (ulong)Size);
|
||||||
|
@@ -52,7 +52,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public BufferHandle CreateWithHandle(VulkanRenderer gd, int size, bool deviceLocal)
|
public BufferHandle CreateWithHandle(VulkanRenderer gd, int size, bool deviceLocal)
|
||||||
{
|
{
|
||||||
var holder = Create(gd, size, deviceLocal: deviceLocal);
|
return CreateWithHandle(gd, size, deviceLocal, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferHandle CreateWithHandle(VulkanRenderer gd, int size, bool deviceLocal, out BufferHolder holder)
|
||||||
|
{
|
||||||
|
holder = Create(gd, size, deviceLocal: deviceLocal);
|
||||||
if (holder == null)
|
if (holder == null)
|
||||||
{
|
{
|
||||||
return BufferHandle.Null;
|
return BufferHandle.Null;
|
||||||
@@ -164,6 +169,141 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (Auto<DisposableBuffer>, Auto<DisposableBuffer>) GetBufferTopologyConversionIndirect(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
BufferRange indexBuffer,
|
||||||
|
BufferRange indirectBuffer,
|
||||||
|
BufferRange drawCountBuffer,
|
||||||
|
IndexBufferPattern pattern,
|
||||||
|
int indexSize,
|
||||||
|
bool hasDrawCount,
|
||||||
|
int maxDrawCount,
|
||||||
|
int indirectDataStride)
|
||||||
|
{
|
||||||
|
BufferHolder drawCountBufferHolder = null;
|
||||||
|
|
||||||
|
if (!TryGetBuffer(indexBuffer.Handle, out var indexBufferHolder) ||
|
||||||
|
!TryGetBuffer(indirectBuffer.Handle, out var indirectBufferHolder) ||
|
||||||
|
(hasDrawCount && !TryGetBuffer(drawCountBuffer.Handle, out drawCountBufferHolder)))
|
||||||
|
{
|
||||||
|
return (null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var indexBufferKey = new TopologyConversionIndirectCacheKey(
|
||||||
|
gd,
|
||||||
|
pattern,
|
||||||
|
indexSize,
|
||||||
|
indirectBufferHolder,
|
||||||
|
indirectBuffer.Offset,
|
||||||
|
indirectBuffer.Size);
|
||||||
|
|
||||||
|
bool hasConvertedIndexBuffer = indexBufferHolder.TryGetCachedConvertedBuffer(
|
||||||
|
indexBuffer.Offset,
|
||||||
|
indexBuffer.Size,
|
||||||
|
indexBufferKey,
|
||||||
|
out var convertedIndexBuffer);
|
||||||
|
|
||||||
|
var indirectBufferKey = new IndirectDataCacheKey(pattern);
|
||||||
|
bool hasConvertedIndirectBuffer = indirectBufferHolder.TryGetCachedConvertedBuffer(
|
||||||
|
indirectBuffer.Offset,
|
||||||
|
indirectBuffer.Size,
|
||||||
|
indirectBufferKey,
|
||||||
|
out var convertedIndirectBuffer);
|
||||||
|
|
||||||
|
var drawCountBufferKey = new DrawCountCacheKey();
|
||||||
|
bool hasCachedDrawCount = true;
|
||||||
|
|
||||||
|
if (hasDrawCount)
|
||||||
|
{
|
||||||
|
hasCachedDrawCount = drawCountBufferHolder.TryGetCachedConvertedBuffer(
|
||||||
|
drawCountBuffer.Offset,
|
||||||
|
drawCountBuffer.Size,
|
||||||
|
drawCountBufferKey,
|
||||||
|
out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasConvertedIndexBuffer || !hasConvertedIndirectBuffer || !hasCachedDrawCount)
|
||||||
|
{
|
||||||
|
// The destination index size is always I32.
|
||||||
|
|
||||||
|
int indexCount = indexBuffer.Size / indexSize;
|
||||||
|
|
||||||
|
int convertedCount = pattern.GetConvertedCount(indexCount);
|
||||||
|
|
||||||
|
if (!hasConvertedIndexBuffer)
|
||||||
|
{
|
||||||
|
convertedIndexBuffer = Create(gd, convertedCount * 4);
|
||||||
|
indexBufferKey.SetBuffer(convertedIndexBuffer.GetBuffer());
|
||||||
|
indexBufferHolder.AddCachedConvertedBuffer(indexBuffer.Offset, indexBuffer.Size, indexBufferKey, convertedIndexBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasConvertedIndirectBuffer)
|
||||||
|
{
|
||||||
|
convertedIndirectBuffer = Create(gd, indirectBuffer.Size);
|
||||||
|
indirectBufferHolder.AddCachedConvertedBuffer(indirectBuffer.Offset, indirectBuffer.Size, indirectBufferKey, convertedIndirectBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
gd.PipelineInternal.EndRenderPass();
|
||||||
|
gd.HelperShader.ConvertIndexBufferIndirect(
|
||||||
|
gd,
|
||||||
|
cbs,
|
||||||
|
indirectBufferHolder,
|
||||||
|
convertedIndirectBuffer,
|
||||||
|
drawCountBuffer,
|
||||||
|
indexBufferHolder,
|
||||||
|
convertedIndexBuffer,
|
||||||
|
pattern,
|
||||||
|
indexSize,
|
||||||
|
indexBuffer.Offset,
|
||||||
|
indexBuffer.Size,
|
||||||
|
indirectBuffer.Offset,
|
||||||
|
hasDrawCount,
|
||||||
|
maxDrawCount,
|
||||||
|
indirectDataStride);
|
||||||
|
|
||||||
|
// Any modification of the indirect buffer should invalidate the index buffers that are associated with it,
|
||||||
|
// since we used the indirect data to find the range of the index buffer that is used.
|
||||||
|
|
||||||
|
var indexBufferDependency = new Dependency(
|
||||||
|
indexBufferHolder,
|
||||||
|
indexBuffer.Offset,
|
||||||
|
indexBuffer.Size,
|
||||||
|
indexBufferKey);
|
||||||
|
|
||||||
|
indirectBufferHolder.AddCachedConvertedBufferDependency(
|
||||||
|
indirectBuffer.Offset,
|
||||||
|
indirectBuffer.Size,
|
||||||
|
indirectBufferKey,
|
||||||
|
indexBufferDependency);
|
||||||
|
|
||||||
|
if (hasDrawCount)
|
||||||
|
{
|
||||||
|
if (!hasCachedDrawCount)
|
||||||
|
{
|
||||||
|
drawCountBufferHolder.AddCachedConvertedBuffer(drawCountBuffer.Offset, drawCountBuffer.Size, drawCountBufferKey, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a draw count, any modification of the draw count should invalidate all indirect buffers
|
||||||
|
// where we used it to find the range of indirect data that is actually used.
|
||||||
|
|
||||||
|
var indirectBufferDependency = new Dependency(
|
||||||
|
indirectBufferHolder,
|
||||||
|
indirectBuffer.Offset,
|
||||||
|
indirectBuffer.Size,
|
||||||
|
indirectBufferKey);
|
||||||
|
|
||||||
|
drawCountBufferHolder.AddCachedConvertedBufferDependency(
|
||||||
|
drawCountBuffer.Offset,
|
||||||
|
drawCountBuffer.Size,
|
||||||
|
drawCountBufferKey,
|
||||||
|
indirectBufferDependency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (convertedIndexBuffer.GetBuffer(), convertedIndirectBuffer.GetBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, BufferHandle handle, bool isWrite, out int size)
|
public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, BufferHandle handle, bool isWrite, out int size)
|
||||||
{
|
{
|
||||||
if (TryGetBuffer(handle, out var holder))
|
if (TryGetBuffer(handle, out var holder))
|
||||||
|
@@ -106,17 +106,125 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TopologyConversionIndirectCacheKey : ICacheKey
|
||||||
|
{
|
||||||
|
private readonly TopologyConversionCacheKey _baseKey;
|
||||||
|
private readonly BufferHolder _indirectDataBuffer;
|
||||||
|
private readonly int _indirectDataOffset;
|
||||||
|
private readonly int _indirectDataSize;
|
||||||
|
|
||||||
|
public TopologyConversionIndirectCacheKey(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
IndexBufferPattern pattern,
|
||||||
|
int indexSize,
|
||||||
|
BufferHolder indirectDataBuffer,
|
||||||
|
int indirectDataOffset,
|
||||||
|
int indirectDataSize)
|
||||||
|
{
|
||||||
|
_baseKey = new TopologyConversionCacheKey(gd, pattern, indexSize);
|
||||||
|
_indirectDataBuffer = indirectDataBuffer;
|
||||||
|
_indirectDataOffset = indirectDataOffset;
|
||||||
|
_indirectDataSize = indirectDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool KeyEqual(ICacheKey other)
|
||||||
|
{
|
||||||
|
return other is TopologyConversionIndirectCacheKey entry &&
|
||||||
|
entry._baseKey.KeyEqual(_baseKey) &&
|
||||||
|
entry._indirectDataBuffer == _indirectDataBuffer &&
|
||||||
|
entry._indirectDataOffset == _indirectDataOffset &&
|
||||||
|
entry._indirectDataSize == _indirectDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBuffer(Auto<DisposableBuffer> buffer)
|
||||||
|
{
|
||||||
|
_baseKey.SetBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_baseKey.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IndirectDataCacheKey : ICacheKey
|
||||||
|
{
|
||||||
|
private IndexBufferPattern _pattern;
|
||||||
|
|
||||||
|
public IndirectDataCacheKey(IndexBufferPattern pattern)
|
||||||
|
{
|
||||||
|
_pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool KeyEqual(ICacheKey other)
|
||||||
|
{
|
||||||
|
return other is IndirectDataCacheKey entry && entry._pattern == _pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DrawCountCacheKey : ICacheKey
|
||||||
|
{
|
||||||
|
public bool KeyEqual(ICacheKey other)
|
||||||
|
{
|
||||||
|
return other is DrawCountCacheKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Dependency
|
||||||
|
{
|
||||||
|
private readonly BufferHolder _buffer;
|
||||||
|
private readonly int _offset;
|
||||||
|
private readonly int _size;
|
||||||
|
private readonly ICacheKey _key;
|
||||||
|
|
||||||
|
public Dependency(BufferHolder buffer, int offset, int size, ICacheKey key)
|
||||||
|
{
|
||||||
|
_buffer = buffer;
|
||||||
|
_offset = offset;
|
||||||
|
_size = size;
|
||||||
|
_key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFromOwner()
|
||||||
|
{
|
||||||
|
_buffer.RemoveCachedConvertedBuffer(_offset, _size, _key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct CacheByRange<T> where T : IDisposable
|
struct CacheByRange<T> where T : IDisposable
|
||||||
{
|
{
|
||||||
private struct Entry
|
private struct Entry
|
||||||
{
|
{
|
||||||
public ICacheKey Key;
|
public ICacheKey Key;
|
||||||
public T Value;
|
public T Value;
|
||||||
|
public List<Dependency> DependencyList;
|
||||||
|
|
||||||
public Entry(ICacheKey key, T value)
|
public Entry(ICacheKey key, T value)
|
||||||
{
|
{
|
||||||
Key = key;
|
Key = key;
|
||||||
Value = value;
|
Value = value;
|
||||||
|
DependencyList = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InvalidateDependencies()
|
||||||
|
{
|
||||||
|
if (DependencyList != null)
|
||||||
|
{
|
||||||
|
foreach (Dependency dependency in DependencyList)
|
||||||
|
{
|
||||||
|
dependency.RemoveFromOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
DependencyList.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +237,51 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
entries.Add(new Entry(key, value));
|
entries.Add(new Entry(key, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddDependency(int offset, int size, ICacheKey key, Dependency dependency)
|
||||||
|
{
|
||||||
|
List<Entry> entries = GetEntries(offset, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < entries.Count; i++)
|
||||||
|
{
|
||||||
|
Entry entry = entries[i];
|
||||||
|
|
||||||
|
if (entry.Key.KeyEqual(key))
|
||||||
|
{
|
||||||
|
if (entry.DependencyList == null)
|
||||||
|
{
|
||||||
|
entry.DependencyList = new List<Dependency>();
|
||||||
|
entries[i] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.DependencyList.Add(dependency);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(int offset, int size, ICacheKey key)
|
||||||
|
{
|
||||||
|
List<Entry> entries = GetEntries(offset, size);
|
||||||
|
|
||||||
|
for (int i = 0; i < entries.Count; i++)
|
||||||
|
{
|
||||||
|
Entry entry = entries[i];
|
||||||
|
|
||||||
|
if (entry.Key.KeyEqual(key))
|
||||||
|
{
|
||||||
|
entries.RemoveAt(i--);
|
||||||
|
|
||||||
|
DestroyEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.Count == 0)
|
||||||
|
{
|
||||||
|
_ranges.Remove(PackRange(offset, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGetValue(int offset, int size, ICacheKey key, out T value)
|
public bool TryGetValue(int offset, int size, ICacheKey key, out T value)
|
||||||
{
|
{
|
||||||
List<Entry> entries = GetEntries(offset, size);
|
List<Entry> entries = GetEntries(offset, size);
|
||||||
@@ -155,8 +308,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
foreach (Entry entry in entries)
|
foreach (Entry entry in entries)
|
||||||
{
|
{
|
||||||
entry.Key.Dispose();
|
DestroyEntry(entry);
|
||||||
entry.Value.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,8 +337,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
foreach (Entry entry in entries)
|
foreach (Entry entry in entries)
|
||||||
{
|
{
|
||||||
entry.Key.Dispose();
|
DestroyEntry(entry);
|
||||||
entry.Value.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(toRemove ??= new List<ulong>()).Add(range.Key);
|
(toRemove ??= new List<ulong>()).Add(range.Key);
|
||||||
@@ -222,6 +373,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DestroyEntry(Entry entry)
|
||||||
|
{
|
||||||
|
entry.Key.Dispose();
|
||||||
|
entry.Value?.Dispose();
|
||||||
|
entry.InvalidateDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
private static ulong PackRange(int offset, int size)
|
private static ulong PackRange(int offset, int size)
|
||||||
{
|
{
|
||||||
return (uint)offset | ((ulong)size << 32);
|
return (uint)offset | ((ulong)size << 32);
|
||||||
|
@@ -11,6 +11,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
class HelperShader : IDisposable
|
class HelperShader : IDisposable
|
||||||
{
|
{
|
||||||
|
private const int UniformBufferAlignment = 256;
|
||||||
|
|
||||||
private readonly PipelineHelperShader _pipeline;
|
private readonly PipelineHelperShader _pipeline;
|
||||||
private readonly ISampler _samplerLinear;
|
private readonly ISampler _samplerLinear;
|
||||||
private readonly ISampler _samplerNearest;
|
private readonly ISampler _samplerNearest;
|
||||||
@@ -19,6 +21,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly IProgram _programColorClear;
|
private readonly IProgram _programColorClear;
|
||||||
private readonly IProgram _programStrideChange;
|
private readonly IProgram _programStrideChange;
|
||||||
private readonly IProgram _programColorCopyBetweenMsNonMs;
|
private readonly IProgram _programColorCopyBetweenMsNonMs;
|
||||||
|
private readonly IProgram _programConvertIndexBuffer;
|
||||||
|
private readonly IProgram _programConvertIndirectData;
|
||||||
|
|
||||||
public HelperShader(VulkanRenderer gd, Device device)
|
public HelperShader(VulkanRenderer gd, Device device)
|
||||||
{
|
{
|
||||||
@@ -88,6 +92,28 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
new SpecDescription((0, SpecConstType.Int32))
|
new SpecDescription((0, SpecConstType.Int32))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var convertIndexBufferBindings = new ShaderBindings(
|
||||||
|
new[] { 0 },
|
||||||
|
new[] { 1, 2 },
|
||||||
|
Array.Empty<int>(),
|
||||||
|
Array.Empty<int>());
|
||||||
|
|
||||||
|
_programConvertIndexBuffer = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ConvertIndexBufferShaderSource, convertIndexBufferBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
|
||||||
|
var convertIndirectDataBindings = new ShaderBindings(
|
||||||
|
new[] { 0 },
|
||||||
|
new[] { 1, 2, 3 },
|
||||||
|
Array.Empty<int>(),
|
||||||
|
Array.Empty<int>());
|
||||||
|
|
||||||
|
_programConvertIndirectData = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ConvertIndirectDataShaderSource, convertIndirectDataBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Blit(
|
public void Blit(
|
||||||
@@ -408,10 +434,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
int srcOffset,
|
int srcOffset,
|
||||||
int indexCount)
|
int indexCount)
|
||||||
{
|
{
|
||||||
|
// TODO: Support conversion with primitive restart enabled.
|
||||||
|
// TODO: Convert with a compute shader?
|
||||||
|
|
||||||
int convertedCount = pattern.GetConvertedCount(indexCount);
|
int convertedCount = pattern.GetConvertedCount(indexCount);
|
||||||
int outputIndexSize = 4;
|
int outputIndexSize = 4;
|
||||||
|
|
||||||
// TODO: Do this with a compute shader?
|
|
||||||
var srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value;
|
var srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value;
|
||||||
var dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
|
var dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
|
||||||
|
|
||||||
@@ -671,6 +699,133 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ConvertIndexBufferIndirect(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
BufferHolder srcIndirectBuffer,
|
||||||
|
BufferHolder dstIndirectBuffer,
|
||||||
|
BufferRange drawCountBuffer,
|
||||||
|
BufferHolder srcIndexBuffer,
|
||||||
|
BufferHolder dstIndexBuffer,
|
||||||
|
IndexBufferPattern pattern,
|
||||||
|
int indexSize,
|
||||||
|
int srcIndexBufferOffset,
|
||||||
|
int srcIndexBufferSize,
|
||||||
|
int srcIndirectBufferOffset,
|
||||||
|
bool hasDrawCount,
|
||||||
|
int maxDrawCount,
|
||||||
|
int indirectDataStride)
|
||||||
|
{
|
||||||
|
// TODO: Support conversion with primitive restart enabled.
|
||||||
|
|
||||||
|
BufferRange drawCountBufferAligned = new BufferRange(
|
||||||
|
drawCountBuffer.Handle,
|
||||||
|
drawCountBuffer.Offset & ~(UniformBufferAlignment - 1),
|
||||||
|
UniformBufferAlignment);
|
||||||
|
|
||||||
|
int indirectDataSize = maxDrawCount * indirectDataStride;
|
||||||
|
|
||||||
|
int indexCount = srcIndexBufferSize / indexSize;
|
||||||
|
int primitivesCount = pattern.GetPrimitiveCount(indexCount);
|
||||||
|
int convertedCount = pattern.GetConvertedCount(indexCount);
|
||||||
|
int outputIndexSize = 4;
|
||||||
|
|
||||||
|
var srcBuffer = srcIndexBuffer.GetBuffer().Get(cbs, srcIndexBufferOffset, indexCount * indexSize).Value;
|
||||||
|
var dstBuffer = dstIndexBuffer.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
|
||||||
|
|
||||||
|
const int ParamsBufferSize = 24 * sizeof(int);
|
||||||
|
const int ParamsIndirectDispatchOffset = 16 * sizeof(int);
|
||||||
|
const int ParamsIndirectDispatchSize = 3 * sizeof(int);
|
||||||
|
|
||||||
|
Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)];
|
||||||
|
|
||||||
|
shaderParams[8] = pattern.PrimitiveVertices;
|
||||||
|
shaderParams[9] = pattern.PrimitiveVerticesOut;
|
||||||
|
shaderParams[10] = indexSize;
|
||||||
|
shaderParams[11] = outputIndexSize;
|
||||||
|
shaderParams[12] = pattern.BaseIndex;
|
||||||
|
shaderParams[13] = pattern.IndexStride;
|
||||||
|
shaderParams[14] = srcIndexBufferOffset;
|
||||||
|
shaderParams[15] = primitivesCount;
|
||||||
|
shaderParams[16] = 1;
|
||||||
|
shaderParams[17] = 1;
|
||||||
|
shaderParams[18] = 1;
|
||||||
|
shaderParams[19] = hasDrawCount ? 1 : 0;
|
||||||
|
shaderParams[20] = maxDrawCount;
|
||||||
|
shaderParams[21] = (drawCountBuffer.Offset & (UniformBufferAlignment - 1)) / 4;
|
||||||
|
shaderParams[22] = indirectDataStride / 4;
|
||||||
|
shaderParams[23] = srcIndirectBufferOffset / 4;
|
||||||
|
|
||||||
|
pattern.OffsetIndex.CopyTo(shaderParams.Slice(0, pattern.OffsetIndex.Length));
|
||||||
|
|
||||||
|
var patternBufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize, false, out var patternBuffer);
|
||||||
|
var patternBufferAuto = patternBuffer.GetBuffer();
|
||||||
|
|
||||||
|
gd.BufferManager.SetData<int>(patternBufferHandle, 0, shaderParams);
|
||||||
|
|
||||||
|
_pipeline.SetCommandBuffer(cbs);
|
||||||
|
|
||||||
|
BufferHolder.InsertBufferBarrier(
|
||||||
|
gd,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
srcIndirectBuffer.GetBuffer().Get(cbs, srcIndirectBufferOffset, indirectDataSize).Value,
|
||||||
|
BufferHolder.DefaultAccessFlags,
|
||||||
|
AccessFlags.AccessShaderReadBit,
|
||||||
|
PipelineStageFlags.PipelineStageAllCommandsBit,
|
||||||
|
PipelineStageFlags.PipelineStageComputeShaderBit,
|
||||||
|
srcIndirectBufferOffset,
|
||||||
|
indirectDataSize);
|
||||||
|
|
||||||
|
_pipeline.SetUniformBuffers(0, stackalloc[] { drawCountBufferAligned });
|
||||||
|
_pipeline.SetStorageBuffers(1, new[] { srcIndirectBuffer.GetBuffer(), dstIndirectBuffer.GetBuffer(), patternBuffer.GetBuffer() });
|
||||||
|
|
||||||
|
_pipeline.SetProgram(_programConvertIndirectData);
|
||||||
|
_pipeline.DispatchCompute(1, 1, 1);
|
||||||
|
|
||||||
|
BufferHolder.InsertBufferBarrier(
|
||||||
|
gd,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
patternBufferAuto.Get(cbs, ParamsIndirectDispatchOffset, ParamsIndirectDispatchSize).Value,
|
||||||
|
AccessFlags.AccessShaderWriteBit,
|
||||||
|
AccessFlags.AccessIndirectCommandReadBit,
|
||||||
|
PipelineStageFlags.PipelineStageComputeShaderBit,
|
||||||
|
PipelineStageFlags.PipelineStageDrawIndirectBit,
|
||||||
|
ParamsIndirectDispatchOffset,
|
||||||
|
ParamsIndirectDispatchSize);
|
||||||
|
|
||||||
|
BufferHolder.InsertBufferBarrier(
|
||||||
|
gd,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
dstBuffer,
|
||||||
|
BufferHolder.DefaultAccessFlags,
|
||||||
|
AccessFlags.AccessTransferWriteBit,
|
||||||
|
PipelineStageFlags.PipelineStageAllCommandsBit,
|
||||||
|
PipelineStageFlags.PipelineStageTransferBit,
|
||||||
|
0,
|
||||||
|
convertedCount * outputIndexSize);
|
||||||
|
|
||||||
|
_pipeline.SetUniformBuffers(0, stackalloc[] { new BufferRange(patternBufferHandle, 0, ParamsBufferSize) });
|
||||||
|
_pipeline.SetStorageBuffers(1, new[] { srcIndexBuffer.GetBuffer(), dstIndexBuffer.GetBuffer() });
|
||||||
|
|
||||||
|
_pipeline.SetProgram(_programConvertIndexBuffer);
|
||||||
|
_pipeline.DispatchComputeIndirect(patternBufferAuto, ParamsIndirectDispatchOffset);
|
||||||
|
|
||||||
|
BufferHolder.InsertBufferBarrier(
|
||||||
|
gd,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
dstBuffer,
|
||||||
|
AccessFlags.AccessTransferWriteBit,
|
||||||
|
BufferHolder.DefaultAccessFlags,
|
||||||
|
PipelineStageFlags.PipelineStageTransferBit,
|
||||||
|
PipelineStageFlags.PipelineStageAllCommandsBit,
|
||||||
|
0,
|
||||||
|
convertedCount * outputIndexSize);
|
||||||
|
|
||||||
|
gd.BufferManager.Delete(patternBufferHandle);
|
||||||
|
|
||||||
|
_pipeline.Finish(gd, cbs);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
@@ -680,6 +835,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_programColorClear.Dispose();
|
_programColorClear.Dispose();
|
||||||
_programStrideChange.Dispose();
|
_programStrideChange.Dispose();
|
||||||
_programColorCopyBetweenMsNonMs.Dispose();
|
_programColorCopyBetweenMsNonMs.Dispose();
|
||||||
|
_programConvertIndexBuffer.Dispose();
|
||||||
|
_programConvertIndirectData.Dispose();
|
||||||
_samplerNearest.Dispose();
|
_samplerNearest.Dispose();
|
||||||
_samplerLinear.Dispose();
|
_samplerLinear.Dispose();
|
||||||
_pipeline.Dispose();
|
_pipeline.Dispose();
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
@@ -68,17 +67,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindConvertedIndexBuffer(VulkanRenderer gd, CommandBufferScoped cbs, int firstIndex, int indexCount, int convertedCount, IndexBufferPattern pattern)
|
public void BindConvertedIndexBuffer(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
int firstIndex,
|
||||||
|
int indexCount,
|
||||||
|
int convertedCount,
|
||||||
|
IndexBufferPattern pattern)
|
||||||
{
|
{
|
||||||
Auto<DisposableBuffer> autoBuffer;
|
Auto<DisposableBuffer> autoBuffer;
|
||||||
|
|
||||||
// Convert the index buffer using the given pattern.
|
// Convert the index buffer using the given pattern.
|
||||||
int indexSize = _type switch
|
int indexSize = GetIndexSize();
|
||||||
{
|
|
||||||
IndexType.Uint32 => 4,
|
|
||||||
IndexType.Uint16 => 2,
|
|
||||||
_ => 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
int firstIndexOffset = firstIndex * indexSize;
|
int firstIndexOffset = firstIndex * indexSize;
|
||||||
|
|
||||||
@@ -94,6 +94,54 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Auto<DisposableBuffer> BindConvertedIndexBufferIndirect(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
GAL.BufferRange indirectBuffer,
|
||||||
|
GAL.BufferRange drawCountBuffer,
|
||||||
|
IndexBufferPattern pattern,
|
||||||
|
bool hasDrawCount,
|
||||||
|
int maxDrawCount,
|
||||||
|
int indirectDataStride)
|
||||||
|
{
|
||||||
|
// Convert the index buffer using the given pattern.
|
||||||
|
int indexSize = GetIndexSize();
|
||||||
|
|
||||||
|
(var indexBufferAuto, var indirectBufferAuto) = gd.BufferManager.GetBufferTopologyConversionIndirect(
|
||||||
|
gd,
|
||||||
|
cbs,
|
||||||
|
new GAL.BufferRange(_handle, _offset, _size),
|
||||||
|
indirectBuffer,
|
||||||
|
drawCountBuffer,
|
||||||
|
pattern,
|
||||||
|
indexSize,
|
||||||
|
hasDrawCount,
|
||||||
|
maxDrawCount,
|
||||||
|
indirectDataStride);
|
||||||
|
|
||||||
|
int convertedCount = pattern.GetConvertedCount(_size / indexSize);
|
||||||
|
int size = convertedCount * 4;
|
||||||
|
|
||||||
|
_buffer = indexBufferAuto;
|
||||||
|
|
||||||
|
if (indexBufferAuto != null)
|
||||||
|
{
|
||||||
|
gd.Api.CmdBindIndexBuffer(cbs.CommandBuffer, indexBufferAuto.Get(cbs, 0, size).Value, 0, IndexType.Uint32);
|
||||||
|
}
|
||||||
|
|
||||||
|
return indirectBufferAuto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetIndexSize()
|
||||||
|
{
|
||||||
|
return _type switch
|
||||||
|
{
|
||||||
|
IndexType.Uint32 => 4,
|
||||||
|
IndexType.Uint16 => 2,
|
||||||
|
_ => 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public bool BoundEquals(Auto<DisposableBuffer> buffer)
|
public bool BoundEquals(Auto<DisposableBuffer> buffer)
|
||||||
{
|
{
|
||||||
return _buffer == buffer;
|
return _buffer == buffer;
|
||||||
|
@@ -294,6 +294,19 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Gd.Api.CmdDispatch(CommandBuffer, (uint)groupsX, (uint)groupsY, (uint)groupsZ);
|
Gd.Api.CmdDispatch(CommandBuffer, (uint)groupsX, (uint)groupsY, (uint)groupsZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DispatchComputeIndirect(Auto<DisposableBuffer> indirectBuffer, int indirectBufferOffset)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndRenderPass();
|
||||||
|
RecreatePipelineIfNeeded(PipelineBindPoint.Compute);
|
||||||
|
|
||||||
|
Gd.Api.CmdDispatchIndirect(CommandBuffer, indirectBuffer.Get(Cbs, indirectBufferOffset, 12).Value, (ulong)indirectBufferOffset);
|
||||||
|
}
|
||||||
|
|
||||||
public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
|
public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
|
||||||
{
|
{
|
||||||
if (!_program.IsLinked)
|
if (!_program.IsLinked)
|
||||||
@@ -395,6 +408,204 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawIndexedIndirect(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateIndexBufferPattern();
|
||||||
|
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
||||||
|
BeginRenderPass();
|
||||||
|
DrawCount++;
|
||||||
|
|
||||||
|
if (_indexBufferPattern != null)
|
||||||
|
{
|
||||||
|
// Convert the index buffer into a supported topology.
|
||||||
|
IndexBufferPattern pattern = _indexBufferPattern;
|
||||||
|
|
||||||
|
Auto<DisposableBuffer> indirectBufferAuto = _indexBuffer.BindConvertedIndexBufferIndirect(
|
||||||
|
Gd,
|
||||||
|
Cbs,
|
||||||
|
indirectBuffer,
|
||||||
|
BufferRange.Empty,
|
||||||
|
pattern,
|
||||||
|
false,
|
||||||
|
1,
|
||||||
|
indirectBuffer.Size);
|
||||||
|
|
||||||
|
_needsIndexBufferRebind = false;
|
||||||
|
|
||||||
|
BeginRenderPass(); // May have been interrupted to set buffer data.
|
||||||
|
ResumeTransformFeedbackInternal();
|
||||||
|
|
||||||
|
Gd.Api.CmdDrawIndexedIndirect(CommandBuffer, indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value, 0, 1, (uint)indirectBuffer.Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var buffer = Gd.BufferManager
|
||||||
|
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
|
||||||
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||||
|
|
||||||
|
ResumeTransformFeedbackInternal();
|
||||||
|
|
||||||
|
Gd.Api.CmdDrawIndexedIndirect(CommandBuffer, buffer, (ulong)indirectBuffer.Offset, 1, (uint)indirectBuffer.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateIndexBufferPattern();
|
||||||
|
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
||||||
|
BeginRenderPass();
|
||||||
|
DrawCount++;
|
||||||
|
|
||||||
|
var countBuffer = Gd.BufferManager
|
||||||
|
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, false)
|
||||||
|
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
||||||
|
|
||||||
|
if (_indexBufferPattern != null)
|
||||||
|
{
|
||||||
|
// Convert the index buffer into a supported topology.
|
||||||
|
IndexBufferPattern pattern = _indexBufferPattern;
|
||||||
|
|
||||||
|
Auto<DisposableBuffer> indirectBufferAuto = _indexBuffer.BindConvertedIndexBufferIndirect(
|
||||||
|
Gd,
|
||||||
|
Cbs,
|
||||||
|
indirectBuffer,
|
||||||
|
parameterBuffer,
|
||||||
|
pattern,
|
||||||
|
true,
|
||||||
|
maxDrawCount,
|
||||||
|
stride);
|
||||||
|
|
||||||
|
_needsIndexBufferRebind = false;
|
||||||
|
|
||||||
|
BeginRenderPass(); // May have been interrupted to set buffer data.
|
||||||
|
ResumeTransformFeedbackInternal();
|
||||||
|
|
||||||
|
if (Gd.Capabilities.SupportsIndirectParameters)
|
||||||
|
{
|
||||||
|
Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount(
|
||||||
|
CommandBuffer,
|
||||||
|
indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value,
|
||||||
|
0,
|
||||||
|
countBuffer,
|
||||||
|
(ulong)parameterBuffer.Offset,
|
||||||
|
(uint)maxDrawCount,
|
||||||
|
(uint)stride);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is also fine because the indirect data conversion always zeros
|
||||||
|
// the entries that are past the current draw count.
|
||||||
|
|
||||||
|
Gd.Api.CmdDrawIndexedIndirect(
|
||||||
|
CommandBuffer,
|
||||||
|
indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value,
|
||||||
|
0,
|
||||||
|
(uint)maxDrawCount,
|
||||||
|
(uint)stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var buffer = Gd.BufferManager
|
||||||
|
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
|
||||||
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||||
|
|
||||||
|
ResumeTransformFeedbackInternal();
|
||||||
|
|
||||||
|
if (Gd.Capabilities.SupportsIndirectParameters)
|
||||||
|
{
|
||||||
|
Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount(
|
||||||
|
CommandBuffer,
|
||||||
|
buffer,
|
||||||
|
(ulong)indirectBuffer.Offset,
|
||||||
|
countBuffer,
|
||||||
|
(ulong)parameterBuffer.Offset,
|
||||||
|
(uint)maxDrawCount,
|
||||||
|
(uint)stride);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not fully correct, but we can't do much better if the host does not support indirect count.
|
||||||
|
Gd.Api.CmdDrawIndexedIndirect(
|
||||||
|
CommandBuffer,
|
||||||
|
buffer,
|
||||||
|
(ulong)indirectBuffer.Offset,
|
||||||
|
(uint)maxDrawCount,
|
||||||
|
(uint)stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndirect(BufferRange indirectBuffer)
|
||||||
|
{
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Support quads and other unsupported topologies.
|
||||||
|
|
||||||
|
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
||||||
|
BeginRenderPass();
|
||||||
|
ResumeTransformFeedbackInternal();
|
||||||
|
DrawCount++;
|
||||||
|
|
||||||
|
var buffer = Gd.BufferManager
|
||||||
|
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
|
||||||
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||||
|
|
||||||
|
Gd.Api.CmdDrawIndirect(CommandBuffer, buffer, (ulong)indirectBuffer.Offset, 1, (uint)indirectBuffer.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||||
|
{
|
||||||
|
if (!Gd.Capabilities.SupportsIndirectParameters)
|
||||||
|
{
|
||||||
|
// TODO: Fallback for when this is not supported.
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_program.IsLinked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Support quads and other unsupported topologies.
|
||||||
|
|
||||||
|
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
||||||
|
BeginRenderPass();
|
||||||
|
ResumeTransformFeedbackInternal();
|
||||||
|
DrawCount++;
|
||||||
|
|
||||||
|
var buffer = Gd.BufferManager
|
||||||
|
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
|
||||||
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||||
|
|
||||||
|
var countBuffer = Gd.BufferManager
|
||||||
|
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, false)
|
||||||
|
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
||||||
|
|
||||||
|
Gd.DrawIndirectCountApi.CmdDrawIndirectCount(
|
||||||
|
CommandBuffer,
|
||||||
|
buffer,
|
||||||
|
(ulong)indirectBuffer.Offset,
|
||||||
|
countBuffer,
|
||||||
|
(ulong)parameterBuffer.Offset,
|
||||||
|
(uint)maxDrawCount,
|
||||||
|
(uint)stride);
|
||||||
|
}
|
||||||
|
|
||||||
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
||||||
{
|
{
|
||||||
if (texture is TextureView srcTexture)
|
if (texture is TextureView srcTexture)
|
||||||
@@ -449,76 +660,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return CommandBuffer.Handle == cb.Handle;
|
return CommandBuffer.Handle == cb.Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
|
||||||
{
|
|
||||||
if (!Gd.Capabilities.SupportsIndirectParameters)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_program.LinkStatus != ProgramLinkStatus.Success)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
||||||
BeginRenderPass();
|
|
||||||
ResumeTransformFeedbackInternal();
|
|
||||||
DrawCount++;
|
|
||||||
|
|
||||||
var buffer = Gd.BufferManager
|
|
||||||
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, true)
|
|
||||||
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
|
||||||
|
|
||||||
var countBuffer = Gd.BufferManager
|
|
||||||
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
|
|
||||||
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
|
||||||
|
|
||||||
Gd.DrawIndirectCountApi.CmdDrawIndirectCount(
|
|
||||||
CommandBuffer,
|
|
||||||
buffer,
|
|
||||||
(ulong)indirectBuffer.Offset,
|
|
||||||
countBuffer,
|
|
||||||
(ulong)parameterBuffer.Offset,
|
|
||||||
(uint)maxDrawCount,
|
|
||||||
(uint)stride);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
|
||||||
{
|
|
||||||
if (!Gd.Capabilities.SupportsIndirectParameters)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_program.LinkStatus != ProgramLinkStatus.Success)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
||||||
BeginRenderPass();
|
|
||||||
ResumeTransformFeedbackInternal();
|
|
||||||
DrawCount++;
|
|
||||||
|
|
||||||
var buffer = Gd.BufferManager
|
|
||||||
.GetBuffer(CommandBuffer, indirectBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
|
|
||||||
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
|
||||||
|
|
||||||
var countBuffer = Gd.BufferManager
|
|
||||||
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
|
|
||||||
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
|
||||||
|
|
||||||
Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount(
|
|
||||||
CommandBuffer,
|
|
||||||
buffer,
|
|
||||||
(ulong)indirectBuffer.Offset,
|
|
||||||
countBuffer,
|
|
||||||
(ulong)parameterBuffer.Offset,
|
|
||||||
(uint)maxDrawCount,
|
|
||||||
(uint)stride);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetAlphaTest(bool enable, float reference, GAL.CompareOp op)
|
public void SetAlphaTest(bool enable, float reference, GAL.CompareOp op)
|
||||||
{
|
{
|
||||||
// This is currently handled using shader specialization, as Vulkan does not support alpha test.
|
// This is currently handled using shader specialization, as Vulkan does not support alpha test.
|
||||||
@@ -706,7 +847,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
if (!dataSpan.SequenceEqual(_newState.SpecializationData.Span))
|
if (!dataSpan.SequenceEqual(_newState.SpecializationData.Span))
|
||||||
{
|
{
|
||||||
_newState.SpecializationData = new SpecData(dataSpan);
|
_newState.SpecializationData = new SpecData(dataSpan);
|
||||||
|
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,58 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
#extension GL_EXT_scalar_block_layout : require
|
||||||
|
#extension GL_EXT_shader_8bit_storage : require
|
||||||
|
|
||||||
|
layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout (std430, set = 0, binding = 0) uniform index_buffer_pattern
|
||||||
|
{
|
||||||
|
int ibp_pattern[8];
|
||||||
|
int ibp_primitive_vertices;
|
||||||
|
int ibp_primitive_vertices_out;
|
||||||
|
int ibp_index_size;
|
||||||
|
int ibp_index_size_out;
|
||||||
|
int ibp_base_index;
|
||||||
|
int ibp_index_stride;
|
||||||
|
int src_offset;
|
||||||
|
int total_primitives;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std430, set = 1, binding = 1) buffer in_s
|
||||||
|
{
|
||||||
|
uint8_t[] in_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std430, set = 1, binding = 2) buffer out_s
|
||||||
|
{
|
||||||
|
uint8_t[] out_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
int primitiveIndex = int(gl_GlobalInvocationID.x);
|
||||||
|
if (primitiveIndex >= total_primitives)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int inOffset = primitiveIndex * ibp_index_stride;
|
||||||
|
int outOffset = primitiveIndex * ibp_primitive_vertices_out;
|
||||||
|
|
||||||
|
for (int i = 0; i < ibp_primitive_vertices_out; i++)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
int io = max(0, inOffset + ibp_base_index + ibp_pattern[i]) * ibp_index_size;
|
||||||
|
int oo = (outOffset + i) * ibp_index_size_out;
|
||||||
|
|
||||||
|
for (j = 0; j < ibp_index_size; j++)
|
||||||
|
{
|
||||||
|
out_data[oo + j] = in_data[src_offset + io + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; j < ibp_index_size_out; j++)
|
||||||
|
{
|
||||||
|
out_data[oo + j] = uint8_t(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,103 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
#extension GL_EXT_scalar_block_layout : require
|
||||||
|
|
||||||
|
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout (std430, set = 0, binding = 0) uniform draw_count_uniform
|
||||||
|
{
|
||||||
|
uint[64] draw_count_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std430, set = 1, binding = 1) buffer indirect_in
|
||||||
|
{
|
||||||
|
int[] indirect_data_in;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std430, set = 1, binding = 2) buffer indirect_out
|
||||||
|
{
|
||||||
|
int[] indirect_data_out;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std430, set = 1, binding = 3) buffer index_buffer_pattern
|
||||||
|
{
|
||||||
|
int ibp_pattern[8];
|
||||||
|
int ibp_primitive_vertices;
|
||||||
|
int ibp_primitive_vertices_out;
|
||||||
|
int ibp_index_size;
|
||||||
|
int ibp_index_size_out;
|
||||||
|
int ibp_base_index;
|
||||||
|
int ibp_index_stride;
|
||||||
|
int src_offset;
|
||||||
|
int total_primitives;
|
||||||
|
int dispatch_x;
|
||||||
|
int dispatch_y;
|
||||||
|
int dispatch_z;
|
||||||
|
int has_draw_count;
|
||||||
|
uint max_draw_count;
|
||||||
|
int draw_count_offset;
|
||||||
|
int indirect_data_stride;
|
||||||
|
int indirect_data_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
int GetPrimitiveCount(int vertexCount)
|
||||||
|
{
|
||||||
|
return max(0, (vertexCount - ibp_base_index) / ibp_index_stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetConvertedCount(int indexCount)
|
||||||
|
{
|
||||||
|
int primitiveCount = GetPrimitiveCount(indexCount);
|
||||||
|
return primitiveCount * ibp_primitive_vertices_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint drawCount = has_draw_count != 0 ? min(draw_count_buffer[draw_count_offset], max_draw_count) : max_draw_count;
|
||||||
|
uint i = 0;
|
||||||
|
|
||||||
|
if (drawCount != 0)
|
||||||
|
{
|
||||||
|
int firstIndex = indirect_data_in[indirect_data_offset + 2];
|
||||||
|
int endIndex = firstIndex + indirect_data_in[indirect_data_offset];
|
||||||
|
|
||||||
|
for (i = 1; i < drawCount; i++)
|
||||||
|
{
|
||||||
|
int offset = int(i) * indirect_data_stride;
|
||||||
|
int inOffset = indirect_data_offset + offset;
|
||||||
|
|
||||||
|
int currentFirstIndex = indirect_data_in[inOffset + 2];
|
||||||
|
firstIndex = min(firstIndex, currentFirstIndex);
|
||||||
|
endIndex = max(endIndex, currentFirstIndex + indirect_data_in[inOffset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int indexCount = endIndex - firstIndex;
|
||||||
|
|
||||||
|
dispatch_x = (indexCount + 15) / 16;
|
||||||
|
src_offset += firstIndex * ibp_index_size;
|
||||||
|
total_primitives = GetPrimitiveCount(indexCount);
|
||||||
|
|
||||||
|
for (i = 0; i < drawCount; i++)
|
||||||
|
{
|
||||||
|
int offset = int(i) * indirect_data_stride;
|
||||||
|
int inOffset = indirect_data_offset + offset;
|
||||||
|
|
||||||
|
indirect_data_out[offset] = GetConvertedCount(indirect_data_in[inOffset]); // Index count
|
||||||
|
indirect_data_out[offset + 1] = indirect_data_in[inOffset + 1]; // Instance count
|
||||||
|
indirect_data_out[offset + 2] = GetConvertedCount(indirect_data_in[inOffset + 2] - firstIndex); // First index
|
||||||
|
indirect_data_out[offset + 3] = indirect_data_in[inOffset + 3]; // Vertex offset
|
||||||
|
indirect_data_out[offset + 4] = indirect_data_in[inOffset + 4]; // First instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < max_draw_count; i++)
|
||||||
|
{
|
||||||
|
int offset = int(i) * indirect_data_stride;
|
||||||
|
|
||||||
|
indirect_data_out[offset] = 0;
|
||||||
|
indirect_data_out[offset + 1] = 0;
|
||||||
|
indirect_data_out[offset + 2] = 0;
|
||||||
|
indirect_data_out[offset + 3] = 0;
|
||||||
|
indirect_data_out[offset + 4] = 0;
|
||||||
|
}
|
||||||
|
}
|
@@ -870,5 +870,543 @@ namespace Ryujinx.Graphics.Vulkan.Shaders
|
|||||||
0x1E, 0x01, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1E, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00,
|
0x1E, 0x01, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1E, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00,
|
||||||
0x38, 0x00, 0x01, 0x00,
|
0x38, 0x00, 0x01, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] ConvertIndexBufferShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x91, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x61, 0x11, 0x00, 0x00, 0x0A, 0x00, 0x07, 0x00, 0x53, 0x50, 0x56, 0x5F, 0x4B, 0x48, 0x52, 0x5F,
|
||||||
|
0x38, 0x62, 0x69, 0x74, 0x5F, 0x73, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64,
|
||||||
|
0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x45, 0x58, 0x54, 0x5F, 0x73, 0x63, 0x61, 0x6C, 0x61,
|
||||||
|
0x72, 0x5F, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x5F, 0x6C, 0x61, 0x79, 0x6F, 0x75, 0x74, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x45, 0x58, 0x54, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65,
|
||||||
|
0x72, 0x5F, 0x38, 0x62, 0x69, 0x74, 0x5F, 0x73, 0x74, 0x6F, 0x72, 0x61, 0x67, 0x65, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x47, 0x6C, 0x6F, 0x62, 0x61,
|
||||||
|
0x6C, 0x49, 0x6E, 0x76, 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49, 0x44, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x62, 0x75,
|
||||||
|
0x66, 0x66, 0x65, 0x72, 0x5F, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F,
|
||||||
|
0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x00, 0x06, 0x00, 0x09, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F, 0x70, 0x72, 0x69, 0x6D, 0x69, 0x74, 0x69, 0x76,
|
||||||
|
0x65, 0x5F, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F, 0x70, 0x72, 0x69, 0x6D,
|
||||||
|
0x69, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x5F, 0x6F,
|
||||||
|
0x75, 0x74, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x69, 0x62, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F,
|
||||||
|
0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x6F, 0x75, 0x74, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F,
|
||||||
|
0x62, 0x61, 0x73, 0x65, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65,
|
||||||
|
0x78, 0x5F, 0x73, 0x74, 0x72, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x5F, 0x6F, 0x66, 0x66, 0x73,
|
||||||
|
0x65, 0x74, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x74, 0x6F, 0x74, 0x61, 0x6C, 0x5F, 0x70, 0x72, 0x69, 0x6D, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x04, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x6F, 0x75, 0x74, 0x5F, 0x73, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x06, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x75, 0x74, 0x5F,
|
||||||
|
0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x5D, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x73,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x69, 0x6E, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x00, 0x05, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x38, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x5B, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x62, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x87, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x0B, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
|
||||||
|
0x59, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x03, 0x00,
|
||||||
|
0x5A, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, 0x5B, 0x00, 0x00, 0x00,
|
||||||
|
0x5A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x5B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x03, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x6C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00,
|
||||||
|
0x0A, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
|
||||||
|
0x86, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||||
|
0xF7, 0x00, 0x03, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x03, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x89, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x1B, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x1D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00,
|
||||||
|
0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1E, 0x00, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0x88, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x2A, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x2F, 0x00, 0x00, 0x00,
|
||||||
|
0xF5, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
|
||||||
|
0x1F, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x05, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
|
||||||
|
0xF6, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFA, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x2E, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00,
|
||||||
|
0x2E, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x44, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
|
||||||
|
0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
|
||||||
|
0x8E, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x4D, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x4E, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||||
|
0x50, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
|
||||||
|
0x72, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x58, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00,
|
||||||
|
0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00,
|
||||||
|
0x58, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0x51, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||||
|
0x4E, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x66, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
|
||||||
|
0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
|
||||||
|
0x8F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x59, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
|
||||||
|
0x6C, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
|
||||||
|
0x60, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00,
|
||||||
|
0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00,
|
||||||
|
0x71, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0x52, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x73, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0x73, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
|
||||||
|
0x8F, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
|
||||||
|
0xB1, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
|
||||||
|
0x4D, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00, 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
|
||||||
|
0x75, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x74, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
|
||||||
|
0x71, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00,
|
||||||
|
0x2E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x00,
|
||||||
|
0x7F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
|
||||||
|
0x90, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x73, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x75, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x32, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x84, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||||
|
0x2F, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x31, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||||
|
0x88, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x88, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00,
|
||||||
|
0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] ConvertIndirectDataShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x3D, 0x01, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x45,
|
||||||
|
0x58, 0x54, 0x5F, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x72, 0x5F, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x5F,
|
||||||
|
0x6C, 0x61, 0x79, 0x6F, 0x75, 0x74, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x70, 0x61, 0x74,
|
||||||
|
0x74, 0x65, 0x72, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x00,
|
||||||
|
0x06, 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F,
|
||||||
|
0x70, 0x72, 0x69, 0x6D, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63,
|
||||||
|
0x65, 0x73, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x69, 0x62, 0x70, 0x5F, 0x70, 0x72, 0x69, 0x6D, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x76, 0x65,
|
||||||
|
0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x5F, 0x6F, 0x75, 0x74, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65,
|
||||||
|
0x78, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x73, 0x69,
|
||||||
|
0x7A, 0x65, 0x5F, 0x6F, 0x75, 0x74, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00, 0x69, 0x62, 0x70, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x5F, 0x69, 0x6E, 0x64,
|
||||||
|
0x65, 0x78, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x69, 0x62, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x73, 0x74, 0x72, 0x69, 0x64, 0x65,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x73, 0x72, 0x63, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x5F, 0x70, 0x72,
|
||||||
|
0x69, 0x6D, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68,
|
||||||
|
0x5F, 0x78, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5F, 0x79, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68,
|
||||||
|
0x5F, 0x7A, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x68, 0x61, 0x73, 0x5F, 0x64, 0x72, 0x61, 0x77, 0x5F, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x78, 0x5F,
|
||||||
|
0x64, 0x72, 0x61, 0x77, 0x5F, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x64, 0x72, 0x61, 0x77, 0x5F, 0x63, 0x6F, 0x75,
|
||||||
|
0x6E, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||||
|
0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x73, 0x74, 0x72, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x69,
|
||||||
|
0x72, 0x65, 0x63, 0x74, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x07, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x64, 0x72, 0x61, 0x77, 0x5F, 0x63, 0x6F, 0x75,
|
||||||
|
0x6E, 0x74, 0x5F, 0x75, 0x6E, 0x69, 0x66, 0x6F, 0x72, 0x6D, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
|
||||||
|
0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x72, 0x61, 0x77, 0x5F, 0x63, 0x6F, 0x75,
|
||||||
|
0x6E, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
|
||||||
|
0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x53, 0x00, 0x00, 0x00,
|
||||||
|
0x69, 0x6E, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5F, 0x69, 0x6E, 0x00, 0x06, 0x00, 0x08, 0x00,
|
||||||
|
0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||||
|
0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
|
||||||
|
0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xB6, 0x00, 0x00, 0x00,
|
||||||
|
0x69, 0x6E, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5F, 0x6F, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x08, 0x00, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x69,
|
||||||
|
0x72, 0x65, 0x63, 0x74, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x6F, 0x75, 0x74, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x03, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x30, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x50, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x39, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x03, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x3C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x3C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x52, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x03, 0x00, 0x53, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x55, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x55, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0xB5, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||||
|
0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x03, 0x00, 0xB6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0xB8, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0xB8, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x03, 0x01, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x15, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00,
|
||||||
|
0x33, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x38, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x1D, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00,
|
||||||
|
0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x54, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x54, 0x00, 0x00, 0x00,
|
||||||
|
0x55, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x56, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x6F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x8E, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x93, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x95, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x9D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x03, 0x00, 0xB5, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, 0xB6, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0xB7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0xB7, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x04, 0x00, 0x02, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x2C, 0x00, 0x06, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
|
||||||
|
0x63, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00,
|
||||||
|
0x34, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00,
|
||||||
|
0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x34, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00,
|
||||||
|
0x3E, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
|
||||||
|
0x3C, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
|
||||||
|
0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x26, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||||
|
0x37, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x47, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0x37, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x37, 0x00, 0x00, 0x00,
|
||||||
|
0xF5, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x05, 0x00,
|
||||||
|
0x33, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00,
|
||||||
|
0xF7, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00,
|
||||||
|
0x4E, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0x4F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x58, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x59, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x59, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00,
|
||||||
|
0x5A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00,
|
||||||
|
0x57, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||||
|
0x55, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00,
|
||||||
|
0xF5, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00,
|
||||||
|
0x4F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00,
|
||||||
|
0x86, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x37, 0x01, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00,
|
||||||
|
0x65, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00,
|
||||||
|
0x37, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00, 0x66, 0x00, 0x00, 0x00,
|
||||||
|
0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x6B, 0x00, 0x00, 0x00,
|
||||||
|
0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
|
||||||
|
0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x6F, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
|
||||||
|
0x6E, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x75, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x77, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x7C, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x7F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
|
||||||
|
0x7C, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00,
|
||||||
|
0x55, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
|
||||||
|
0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x2A, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x66, 0x00, 0x00, 0x00,
|
||||||
|
0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00,
|
||||||
|
0x39, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
|
||||||
|
0x8D, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x87, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x91, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00,
|
||||||
|
0x3E, 0x00, 0x03, 0x00, 0x92, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
|
||||||
|
0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
|
||||||
|
0x97, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x9A, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x9B, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00,
|
||||||
|
0x99, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x07, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00,
|
||||||
|
0x0A, 0x01, 0x00, 0x00, 0x87, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00,
|
||||||
|
0x09, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x0C, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x01, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00,
|
||||||
|
0xA2, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00,
|
||||||
|
0x4C, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00,
|
||||||
|
0xB0, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00,
|
||||||
|
0x36, 0x01, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0xA9, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00,
|
||||||
|
0xA4, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00,
|
||||||
|
0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00,
|
||||||
|
0xAE, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00,
|
||||||
|
0x57, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00,
|
||||||
|
0xB2, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0xBC, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00,
|
||||||
|
0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00,
|
||||||
|
0x0A, 0x01, 0x00, 0x00, 0x87, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
||||||
|
0x1D, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x21, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0xAF, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00,
|
||||||
|
0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00,
|
||||||
|
0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00,
|
||||||
|
0xB4, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0xC4, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xC6, 0x00, 0x00, 0x00,
|
||||||
|
0xC5, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00,
|
||||||
|
0xAF, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0xCA, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0xCA, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00,
|
||||||
|
0xCB, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00,
|
||||||
|
0xCC, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x30, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x31, 0x01, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x87, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00,
|
||||||
|
0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x2A, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xD1, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00,
|
||||||
|
0xAF, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0xD5, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0xD5, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00,
|
||||||
|
0xD6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00,
|
||||||
|
0xB8, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00,
|
||||||
|
0xD8, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0xDB, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0xDF, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0xE0, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00,
|
||||||
|
0x3E, 0x00, 0x03, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xA4, 0x00, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00,
|
||||||
|
0xF5, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00,
|
||||||
|
0x37, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||||
|
0xE3, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x01, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||||
|
0xE9, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x05, 0x00,
|
||||||
|
0x33, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00,
|
||||||
|
0xF6, 0x00, 0x04, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFA, 0x00, 0x04, 0x00, 0xEB, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0xEE, 0x00, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0xEF, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xF3, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00,
|
||||||
|
0xF1, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0xF6, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00,
|
||||||
|
0x3E, 0x00, 0x03, 0x00, 0xF6, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xF9, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00,
|
||||||
|
0xF1, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0xFC, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00,
|
||||||
|
0x3E, 0x00, 0x03, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xFF, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
|
||||||
|
0x3B, 0x01, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xE3, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -444,7 +444,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SType = StructureType.PhysicalDeviceVulkan12Features,
|
SType = StructureType.PhysicalDeviceVulkan12Features,
|
||||||
PNext = pExtendedFeatures,
|
PNext = pExtendedFeatures,
|
||||||
DescriptorIndexing = supportedExtensions.Contains("VK_EXT_descriptor_indexing"),
|
DescriptorIndexing = supportedExtensions.Contains("VK_EXT_descriptor_indexing"),
|
||||||
DrawIndirectCount = supportedExtensions.Contains(KhrDrawIndirectCount.ExtensionName)
|
DrawIndirectCount = supportedExtensions.Contains(KhrDrawIndirectCount.ExtensionName),
|
||||||
|
UniformBufferStandardLayout = supportedExtensions.Contains("VK_KHR_uniform_buffer_standard_layout")
|
||||||
};
|
};
|
||||||
|
|
||||||
pExtendedFeatures = &featuresVk12;
|
pExtendedFeatures = &featuresVk12;
|
||||||
|
@@ -403,7 +403,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
supportsTextureShadowLod: false,
|
supportsTextureShadowLod: false,
|
||||||
supportsViewportIndex: featuresVk12.ShaderOutputViewportIndex,
|
supportsViewportIndex: featuresVk12.ShaderOutputViewportIndex,
|
||||||
supportsViewportSwizzle: false,
|
supportsViewportSwizzle: false,
|
||||||
supportsIndirectParameters: Capabilities.SupportsIndirectParameters,
|
supportsIndirectParameters: true,
|
||||||
maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage,
|
maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage,
|
||||||
maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage,
|
maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage,
|
||||||
maximumTexturesPerStage: Constants.MaxTexturesPerStage,
|
maximumTexturesPerStage: Constants.MaxTexturesPerStage,
|
||||||
|
@@ -14,7 +14,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 41;
|
public const int CurrentVersion = 42;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the configuration file format
|
/// Version of the configuration file format
|
||||||
@@ -166,6 +166,11 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableTextureRecompression { get; set; }
|
public bool EnableTextureRecompression { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables Macro high-level emulation
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableMacroHLE { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables or disables profiled translation cache persistency
|
/// Enables or disables profiled translation cache persistency
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -416,6 +416,11 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> EnableTextureRecompression { get; private set; }
|
public ReactiveObject<bool> EnableTextureRecompression { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables Macro high-level emulation
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> EnableMacroHLE { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Graphics backend
|
/// Graphics backend
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -449,6 +454,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend));
|
GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend));
|
||||||
PreferredGpu = new ReactiveObject<string>();
|
PreferredGpu = new ReactiveObject<string>();
|
||||||
PreferredGpu.Event += static (sender, e) => LogValueChange(sender, e, nameof(PreferredGpu));
|
PreferredGpu.Event += static (sender, e) => LogValueChange(sender, e, nameof(PreferredGpu));
|
||||||
|
EnableMacroHLE = new ReactiveObject<bool>();
|
||||||
|
EnableMacroHLE.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableMacroHLE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,6 +556,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
EnableVsync = Graphics.EnableVsync,
|
EnableVsync = Graphics.EnableVsync,
|
||||||
EnableShaderCache = Graphics.EnableShaderCache,
|
EnableShaderCache = Graphics.EnableShaderCache,
|
||||||
EnableTextureRecompression = Graphics.EnableTextureRecompression,
|
EnableTextureRecompression = Graphics.EnableTextureRecompression,
|
||||||
|
EnableMacroHLE = Graphics.EnableMacroHLE,
|
||||||
EnablePtc = System.EnablePtc,
|
EnablePtc = System.EnablePtc,
|
||||||
EnableInternetAccess = System.EnableInternetAccess,
|
EnableInternetAccess = System.EnableInternetAccess,
|
||||||
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
|
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
|
||||||
@@ -634,6 +642,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
Graphics.EnableVsync.Value = true;
|
Graphics.EnableVsync.Value = true;
|
||||||
Graphics.EnableShaderCache.Value = true;
|
Graphics.EnableShaderCache.Value = true;
|
||||||
Graphics.EnableTextureRecompression.Value = false;
|
Graphics.EnableTextureRecompression.Value = false;
|
||||||
|
Graphics.EnableMacroHLE.Value = true;
|
||||||
System.EnablePtc.Value = true;
|
System.EnablePtc.Value = true;
|
||||||
System.EnableInternetAccess.Value = false;
|
System.EnableInternetAccess.Value = false;
|
||||||
System.EnableFsIntegrityChecks.Value = true;
|
System.EnableFsIntegrityChecks.Value = true;
|
||||||
@@ -1176,6 +1185,13 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configurationFileFormat.Version < 42)
|
||||||
|
{
|
||||||
|
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42.");
|
||||||
|
|
||||||
|
configurationFileFormat.EnableMacroHLE = true;
|
||||||
|
}
|
||||||
|
|
||||||
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
||||||
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
||||||
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
|
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
|
||||||
@@ -1207,6 +1223,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||||||
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
|
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
|
||||||
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
|
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
|
||||||
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
|
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
|
||||||
|
Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;
|
||||||
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
|
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
|
||||||
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
|
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
|
||||||
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
|
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
|
||||||
|
81
Ryujinx.Ui.Common/Helper/CommandLineState.cs
Normal file
81
Ryujinx.Ui.Common/Helper/CommandLineState.cs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ui.Common.Helper
|
||||||
|
{
|
||||||
|
public static class CommandLineState
|
||||||
|
{
|
||||||
|
public static string[] Arguments { get; private set; }
|
||||||
|
|
||||||
|
public static string OverrideGraphicsBackend { get; private set; }
|
||||||
|
public static string BaseDirPathArg { get; private set; }
|
||||||
|
public static string Profile { get; private set; }
|
||||||
|
public static string LaunchPathArg { get; private set; }
|
||||||
|
public static bool StartFullscreenArg { get; private set; }
|
||||||
|
|
||||||
|
public static void ParseArguments(string[] args)
|
||||||
|
{
|
||||||
|
List<string> arguments = new();
|
||||||
|
|
||||||
|
// Parse Arguments.
|
||||||
|
for (int i = 0; i < args.Length; ++i)
|
||||||
|
{
|
||||||
|
string arg = args[i];
|
||||||
|
|
||||||
|
switch (arg)
|
||||||
|
{
|
||||||
|
case "-r":
|
||||||
|
case "--root-data-dir":
|
||||||
|
if (i + 1 >= args.Length)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseDirPathArg = args[++i];
|
||||||
|
|
||||||
|
arguments.Add(arg);
|
||||||
|
arguments.Add(args[i]);
|
||||||
|
break;
|
||||||
|
case "-p":
|
||||||
|
case "--profile":
|
||||||
|
if (i + 1 >= args.Length)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Profile = args[++i];
|
||||||
|
|
||||||
|
arguments.Add(arg);
|
||||||
|
arguments.Add(args[i]);
|
||||||
|
break;
|
||||||
|
case "-f":
|
||||||
|
case "--fullscreen":
|
||||||
|
StartFullscreenArg = true;
|
||||||
|
|
||||||
|
arguments.Add(arg);
|
||||||
|
break;
|
||||||
|
case "-g":
|
||||||
|
case "--graphics-backend":
|
||||||
|
if (i + 1 >= args.Length)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverrideGraphicsBackend = args[++i];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LaunchPathArg = arg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Arguments = arguments.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,9 +2,9 @@ using Gdk;
|
|||||||
using Gtk;
|
using Gtk;
|
||||||
using Ryujinx.Ui;
|
using Ryujinx.Ui;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
|
using Ryujinx.Ui.Common.Helper;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Ryujinx.Modules
|
namespace Ryujinx.Modules
|
||||||
@@ -48,9 +48,8 @@ namespace Ryujinx.Modules
|
|||||||
{
|
{
|
||||||
string ryuName = OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx";
|
string ryuName = OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx";
|
||||||
string ryuExe = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
|
string ryuExe = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
|
||||||
var ryuArg = Environment.GetCommandLineArgs().AsEnumerable().Skip(1);
|
|
||||||
|
|
||||||
Process.Start(ryuExe, ryuArg);
|
Process.Start(ryuExe, CommandLineState.Arguments);
|
||||||
|
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
@@ -81,4 +80,4 @@ namespace Ryujinx.Modules
|
|||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -6,10 +6,11 @@ using Ryujinx.Common.GraphicsDriver;
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.System;
|
using Ryujinx.Common.System;
|
||||||
using Ryujinx.Common.SystemInfo;
|
using Ryujinx.Common.SystemInfo;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
using Ryujinx.Ui;
|
using Ryujinx.Ui;
|
||||||
using Ryujinx.Ui.Common;
|
using Ryujinx.Ui.Common;
|
||||||
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
|
using Ryujinx.Ui.Common.Helper;
|
||||||
using Ryujinx.Ui.Widgets;
|
using Ryujinx.Ui.Widgets;
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
using System;
|
using System;
|
||||||
@@ -28,8 +29,6 @@ namespace Ryujinx
|
|||||||
|
|
||||||
public static string ConfigurationPath { get; set; }
|
public static string ConfigurationPath { get; set; }
|
||||||
|
|
||||||
public static string CommandLineProfile { get; set; }
|
|
||||||
|
|
||||||
[DllImport("libX11")]
|
[DllImport("libX11")]
|
||||||
private extern static int XInitThreads();
|
private extern static int XInitThreads();
|
||||||
|
|
||||||
@@ -47,46 +46,13 @@ namespace Ryujinx
|
|||||||
MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MB_ICONWARNING);
|
MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MB_ICONWARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse Arguments.
|
// Parse arguments
|
||||||
string launchPathArg = null;
|
CommandLineState.ParseArguments(args);
|
||||||
string baseDirPathArg = null;
|
|
||||||
bool startFullscreenArg = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < args.Length; ++i)
|
// Hook unhandled exception and process exit events.
|
||||||
{
|
GLib.ExceptionManager.UnhandledException += (GLib.UnhandledExceptionArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
||||||
string arg = args[i];
|
AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
||||||
|
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
|
||||||
if (arg == "-r" || arg == "--root-data-dir")
|
|
||||||
{
|
|
||||||
if (i + 1 >= args.Length)
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
baseDirPathArg = args[++i];
|
|
||||||
}
|
|
||||||
else if (arg == "-p" || arg == "--profile")
|
|
||||||
{
|
|
||||||
if (i + 1 >= args.Length)
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandLineProfile = args[++i];
|
|
||||||
}
|
|
||||||
else if (arg == "-f" || arg == "--fullscreen")
|
|
||||||
{
|
|
||||||
startFullscreenArg = true;
|
|
||||||
}
|
|
||||||
else if (launchPathArg == null)
|
|
||||||
{
|
|
||||||
launchPathArg = arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make process DPI aware for proper window sizing on high-res screens.
|
// Make process DPI aware for proper window sizing on high-res screens.
|
||||||
ForceDpiAware.Windows();
|
ForceDpiAware.Windows();
|
||||||
@@ -95,8 +61,6 @@ namespace Ryujinx
|
|||||||
// Delete backup files after updating.
|
// Delete backup files after updating.
|
||||||
Task.Run(Updater.CleanupUpdate);
|
Task.Run(Updater.CleanupUpdate);
|
||||||
|
|
||||||
Console.Title = $"Ryujinx Console {Version}";
|
|
||||||
|
|
||||||
// NOTE: GTK3 doesn't init X11 in a multi threaded way.
|
// NOTE: GTK3 doesn't init X11 in a multi threaded way.
|
||||||
// This ends up causing race condition and abort of XCB when a context is created by SPB (even if SPB do call XInitThreads).
|
// This ends up causing race condition and abort of XCB when a context is created by SPB (even if SPB do call XInitThreads).
|
||||||
if (OperatingSystem.IsLinux())
|
if (OperatingSystem.IsLinux())
|
||||||
@@ -107,13 +71,8 @@ namespace Ryujinx
|
|||||||
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
|
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
|
||||||
Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}");
|
Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}");
|
||||||
|
|
||||||
// Hook unhandled exception and process exit events.
|
|
||||||
GLib.ExceptionManager.UnhandledException += (GLib.UnhandledExceptionArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
|
||||||
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => Exit();
|
|
||||||
|
|
||||||
// Setup base data directory.
|
// Setup base data directory.
|
||||||
AppDataManager.Initialize(baseDirPathArg);
|
AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
|
||||||
|
|
||||||
// Initialize the configuration.
|
// Initialize the configuration.
|
||||||
ConfigurationState.Initialize();
|
ConfigurationState.Initialize();
|
||||||
@@ -173,6 +132,21 @@ namespace Ryujinx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if graphics backend was overridden
|
||||||
|
if (CommandLineState.OverrideGraphicsBackend != null)
|
||||||
|
{
|
||||||
|
if (CommandLineState.OverrideGraphicsBackend.ToLower() == "opengl")
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
|
||||||
|
showVulkanPrompt = false;
|
||||||
|
}
|
||||||
|
else if (CommandLineState.OverrideGraphicsBackend.ToLower() == "vulkan")
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.Vulkan;
|
||||||
|
showVulkanPrompt = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Logging system information.
|
// Logging system information.
|
||||||
PrintSystemInfo();
|
PrintSystemInfo();
|
||||||
|
|
||||||
@@ -195,9 +169,9 @@ namespace Ryujinx
|
|||||||
MainWindow mainWindow = new MainWindow();
|
MainWindow mainWindow = new MainWindow();
|
||||||
mainWindow.Show();
|
mainWindow.Show();
|
||||||
|
|
||||||
if (launchPathArg != null)
|
if (CommandLineState.LaunchPathArg != null)
|
||||||
{
|
{
|
||||||
mainWindow.LoadApplication(launchPathArg, startFullscreenArg);
|
mainWindow.LoadApplication(CommandLineState.LaunchPathArg, CommandLineState.StartFullscreenArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
|
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
|
||||||
|
@@ -179,7 +179,7 @@ namespace Ryujinx.Ui
|
|||||||
VirtualFileSystem.FixExtraData(_libHacHorizonManager.RyujinxClient);
|
VirtualFileSystem.FixExtraData(_libHacHorizonManager.RyujinxClient);
|
||||||
|
|
||||||
_contentManager = new ContentManager(_virtualFileSystem);
|
_contentManager = new ContentManager(_virtualFileSystem);
|
||||||
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, Program.CommandLineProfile);
|
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, CommandLineState.Profile);
|
||||||
_userChannelPersistence = new UserChannelPersistence();
|
_userChannelPersistence = new UserChannelPersistence();
|
||||||
|
|
||||||
// Instantiate GUI objects.
|
// Instantiate GUI objects.
|
||||||
@@ -1039,6 +1039,7 @@ namespace Ryujinx.Ui
|
|||||||
Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
|
Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
|
||||||
Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
|
Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
|
||||||
Graphics.Gpu.GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
|
Graphics.Gpu.GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
|
||||||
|
Graphics.Gpu.GraphicsConfig.EnableMacroHLE = ConfigurationState.Instance.Graphics.EnableMacroHLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveConfig()
|
public void SaveConfig()
|
||||||
@@ -1752,4 +1753,4 @@ namespace Ryujinx.Ui
|
|||||||
UpdateGameTable();
|
UpdateGameTable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
2
Ryujinx/Ui/Windows/AboutWindow.Designer.cs
generated
2
Ryujinx/Ui/Windows/AboutWindow.Designer.cs
generated
@@ -113,7 +113,7 @@ namespace Ryujinx.Ui.Windows
|
|||||||
//
|
//
|
||||||
// _ryujinxPhoneticLabel
|
// _ryujinxPhoneticLabel
|
||||||
//
|
//
|
||||||
_ryujinxPhoneticLabel = new Label("(REE-YOU-JI-NX)")
|
_ryujinxPhoneticLabel = new Label("(REE-YOU-JINX)")
|
||||||
{
|
{
|
||||||
Justify = Justification.Center
|
Justify = Justification.Center
|
||||||
};
|
};
|
||||||
|
@@ -56,6 +56,7 @@ namespace Ryujinx.Ui.Windows
|
|||||||
[GUI] CheckButton _vSyncToggle;
|
[GUI] CheckButton _vSyncToggle;
|
||||||
[GUI] CheckButton _shaderCacheToggle;
|
[GUI] CheckButton _shaderCacheToggle;
|
||||||
[GUI] CheckButton _textureRecompressionToggle;
|
[GUI] CheckButton _textureRecompressionToggle;
|
||||||
|
[GUI] CheckButton _macroHLEToggle;
|
||||||
[GUI] CheckButton _ptcToggle;
|
[GUI] CheckButton _ptcToggle;
|
||||||
[GUI] CheckButton _internetToggle;
|
[GUI] CheckButton _internetToggle;
|
||||||
[GUI] CheckButton _fsicToggle;
|
[GUI] CheckButton _fsicToggle;
|
||||||
@@ -239,6 +240,11 @@ namespace Ryujinx.Ui.Windows
|
|||||||
_textureRecompressionToggle.Click();
|
_textureRecompressionToggle.Click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ConfigurationState.Instance.Graphics.EnableMacroHLE)
|
||||||
|
{
|
||||||
|
_macroHLEToggle.Click();
|
||||||
|
}
|
||||||
|
|
||||||
if (ConfigurationState.Instance.System.EnablePtc)
|
if (ConfigurationState.Instance.System.EnablePtc)
|
||||||
{
|
{
|
||||||
_ptcToggle.Click();
|
_ptcToggle.Click();
|
||||||
@@ -566,6 +572,7 @@ namespace Ryujinx.Ui.Windows
|
|||||||
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
|
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
|
||||||
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
|
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
|
||||||
ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active;
|
ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active;
|
||||||
|
ConfigurationState.Instance.Graphics.EnableMacroHLE.Value = _macroHLEToggle.Active;
|
||||||
ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
|
ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
|
||||||
ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active;
|
ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active;
|
||||||
ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
|
ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
|
||||||
|
@@ -2070,6 +2070,24 @@
|
|||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="_macroHLEToggle">
|
||||||
|
<property name="label" translatable="yes">Enable Macro HLE</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="tooltip-text" translatable="yes">Enables or disables high-level emulation of Macro code. Improves performance but may cause graphical glitches in some games</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="margin-top">5</property>
|
||||||
|
<property name="margin-bottom">5</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@@ -2131,7 +2149,7 @@
|
|||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="padding">5</property>
|
<property name="padding">5</property>
|
||||||
<property name="position">2</property>
|
<property name="position">3</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -2179,7 +2197,7 @@
|
|||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="padding">5</property>
|
<property name="padding">5</property>
|
||||||
<property name="position">3</property>
|
<property name="position">4</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -2228,7 +2246,7 @@
|
|||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="padding">5</property>
|
<property name="padding">5</property>
|
||||||
<property name="position">4</property>
|
<property name="position">5</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
Reference in New Issue
Block a user