Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f663a5cd38 | ||
|
f7c2e867f4 | ||
|
cedd200745 | ||
|
58207685c0 | ||
|
095ad923ad | ||
|
f07ae7d53f | ||
|
c308f09722 | ||
|
f1eef29409 | ||
|
1f8d66db7c | ||
|
c3a5716a95 |
@@ -22,14 +22,14 @@
|
|||||||
<PackageVersion Include="LibHac" Version="0.17.0" />
|
<PackageVersion Include="LibHac" Version="0.17.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||||
<PackageVersion Include="OpenTK.Core" Version="4.7.5" />
|
<PackageVersion Include="OpenTK.Core" Version="4.7.7" />
|
||||||
<PackageVersion Include="OpenTK.Graphics" Version="4.7.5" />
|
<PackageVersion Include="OpenTK.Graphics" Version="4.7.7" />
|
||||||
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.5" />
|
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.7" />
|
||||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.5" />
|
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.7" />
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
<PackageVersion Include="System.Management" Version="7.0.0" />
|
<PackageVersion Include="System.Management" Version="7.0.0" />
|
||||||
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
|
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
|
||||||
<PackageVersion Include="System.Threading.ThreadPool" Version="4.3.0" />
|
<PackageVersion Include="System.Threading.ThreadPool" Version="4.3.0" />
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-9c9356d" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-a913199" />
|
||||||
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" />
|
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@@ -21,6 +21,7 @@ using System.Net.Http;
|
|||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -57,7 +58,7 @@ namespace Ryujinx.Modules
|
|||||||
// Detect current platform
|
// Detect current platform
|
||||||
if (OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
_platformExt = "osx_x64.zip";
|
_platformExt = "macos_universal.app.tar.gz";
|
||||||
}
|
}
|
||||||
else if (OperatingSystem.IsWindows())
|
else if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
@@ -286,22 +287,40 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
if (_updateSuccessful)
|
if (_updateSuccessful)
|
||||||
{
|
{
|
||||||
var shouldRestart = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
bool shouldRestart = true;
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterCompleteMessage],
|
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterRestartMessage]);
|
if (!OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
shouldRestart = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterCompleteMessage],
|
||||||
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterRestartMessage]);
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldRestart)
|
if (shouldRestart)
|
||||||
{
|
{
|
||||||
|
List<string> arguments = CommandLineState.Arguments.ToList();
|
||||||
string ryuName = Path.GetFileName(Environment.ProcessPath);
|
string ryuName = Path.GetFileName(Environment.ProcessPath);
|
||||||
string ryuExe = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
|
string executableDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
string executablePath = Path.Combine(executableDirectory, ryuName);
|
||||||
|
|
||||||
if (!Path.Exists(ryuExe))
|
if (!Path.Exists(executablePath))
|
||||||
{
|
{
|
||||||
ryuExe = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx");
|
executablePath = Path.Combine(executableDirectory, OperatingSystem.IsWindows() ? "Ryujinx.exe" : "Ryujinx");
|
||||||
}
|
}
|
||||||
|
|
||||||
Process.Start(ryuExe, CommandLineState.Arguments);
|
// On macOS we perform the update at relaunch.
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
string baseBundlePath = Path.GetFullPath(Path.Combine(executableDirectory, "..", ".."));
|
||||||
|
string newBundlePath = Path.Combine(UpdateDir, "Ryujinx.app");
|
||||||
|
string updaterScriptPath = Path.Combine(newBundlePath, "Contents", "Resources", "updater.sh");
|
||||||
|
string currentPid = Process.GetCurrentProcess().Id.ToString();
|
||||||
|
|
||||||
|
executablePath = "/bin/bash";
|
||||||
|
arguments.InsertRange(0, new List<string> { updaterScriptPath, baseBundlePath, newBundlePath, currentPid });
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.Start(executablePath, arguments);
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,6 +400,15 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
File.WriteAllBytes(updateFile, mergedFileBytes);
|
File.WriteAllBytes(updateFile, mergedFileBytes);
|
||||||
|
|
||||||
|
// On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution.
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
using (Process xattrProcess = Process.Start("xattr", new List<string> { "-d", "com.apple.quarantine", updateFile }))
|
||||||
|
{
|
||||||
|
xattrProcess.WaitForExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
InstallUpdate(taskDialog, updateFile);
|
InstallUpdate(taskDialog, updateFile);
|
||||||
@@ -470,82 +498,98 @@ namespace Ryujinx.Modules
|
|||||||
worker.Start();
|
worker.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("linux")]
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
private static void ExtractTarGzipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath)
|
||||||
|
{
|
||||||
|
using Stream inStream = File.OpenRead(archivePath);
|
||||||
|
using GZipInputStream gzipStream = new(inStream);
|
||||||
|
using TarInputStream tarStream = new(gzipStream, Encoding.ASCII);
|
||||||
|
|
||||||
|
TarEntry tarEntry;
|
||||||
|
|
||||||
|
while ((tarEntry = tarStream.GetNextEntry()) is not null)
|
||||||
|
{
|
||||||
|
if (tarEntry.IsDirectory)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string outPath = Path.Combine(outputDirectoryPath, tarEntry.Name);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
|
||||||
|
|
||||||
|
using (FileStream outStream = File.OpenWrite(outPath))
|
||||||
|
{
|
||||||
|
tarStream.CopyEntryContents(outStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.SetUnixFileMode(outPath, (UnixFileMode)tarEntry.TarHeader.Mode);
|
||||||
|
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
|
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
if (tarEntry is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskDialog.SetProgressBarState(GetPercentage(tarEntry.Size, inStream.Length), TaskDialogProgressState.Normal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExtractZipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath)
|
||||||
|
{
|
||||||
|
using Stream inStream = File.OpenRead(archivePath);
|
||||||
|
using ZipFile zipFile = new(inStream);
|
||||||
|
|
||||||
|
double count = 0;
|
||||||
|
foreach (ZipEntry zipEntry in zipFile)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
if (zipEntry.IsDirectory) continue;
|
||||||
|
|
||||||
|
string outPath = Path.Combine(outputDirectoryPath, zipEntry.Name);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
|
||||||
|
|
||||||
|
using (Stream zipStream = zipFile.GetInputStream(zipEntry))
|
||||||
|
using (FileStream outStream = File.OpenWrite(outPath))
|
||||||
|
{
|
||||||
|
zipStream.CopyTo(outStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc));
|
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
taskDialog.SetProgressBarState(GetPercentage(count, zipFile.Count), TaskDialogProgressState.Normal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static async void InstallUpdate(TaskDialog taskDialog, string updateFile)
|
private static async void InstallUpdate(TaskDialog taskDialog, string updateFile)
|
||||||
{
|
{
|
||||||
// Extract Update
|
// Extract Update
|
||||||
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterExtracting];
|
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterExtracting];
|
||||||
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||||
|
|
||||||
if (OperatingSystem.IsLinux())
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
using Stream inStream = File.OpenRead(updateFile);
|
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||||
using GZipInputStream gzipStream = new(inStream);
|
|
||||||
using TarInputStream tarStream = new(gzipStream, Encoding.ASCII);
|
|
||||||
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
{
|
||||||
TarEntry tarEntry;
|
ExtractTarGzipFile(taskDialog, updateFile, UpdateDir);
|
||||||
|
}
|
||||||
if (!OperatingSystem.IsWindows())
|
else if (OperatingSystem.IsWindows())
|
||||||
{
|
|
||||||
while ((tarEntry = tarStream.GetNextEntry()) is not null)
|
|
||||||
{
|
|
||||||
if (tarEntry.IsDirectory) continue;
|
|
||||||
|
|
||||||
string outPath = Path.Combine(UpdateDir, tarEntry.Name);
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
|
|
||||||
|
|
||||||
using (FileStream outStream = File.OpenWrite(outPath))
|
|
||||||
{
|
|
||||||
tarStream.CopyEntryContents(outStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
File.SetUnixFileMode(outPath, (UnixFileMode)tarEntry.TarHeader.Mode);
|
|
||||||
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
|
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
|
||||||
{
|
|
||||||
taskDialog.SetProgressBarState(GetPercentage(tarEntry.Size, inStream.Length), TaskDialogProgressState.Normal);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
taskDialog.SetProgressBarState(100, TaskDialogProgressState.Normal);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using Stream inStream = File.OpenRead(updateFile);
|
|
||||||
using ZipFile zipFile = new(inStream);
|
|
||||||
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
{
|
||||||
double count = 0;
|
ExtractZipFile(taskDialog, updateFile, UpdateDir);
|
||||||
foreach (ZipEntry zipEntry in zipFile)
|
}
|
||||||
{
|
else
|
||||||
count++;
|
{
|
||||||
if (zipEntry.IsDirectory) continue;
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
string outPath = Path.Combine(UpdateDir, zipEntry.Name);
|
});
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
|
|
||||||
|
|
||||||
using (Stream zipStream = zipFile.GetInputStream(zipEntry))
|
|
||||||
using (FileStream outStream = File.OpenWrite(outPath))
|
|
||||||
{
|
|
||||||
zipStream.CopyTo(outStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc));
|
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
|
||||||
{
|
|
||||||
taskDialog.SetProgressBarState(GetPercentage(count, zipFile.Count), TaskDialogProgressState.Normal);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete downloaded zip
|
// Delete downloaded zip
|
||||||
File.Delete(updateFile);
|
File.Delete(updateFile);
|
||||||
@@ -555,38 +599,42 @@ namespace Ryujinx.Modules
|
|||||||
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterRenaming];
|
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterRenaming];
|
||||||
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||||
|
|
||||||
// Replace old files
|
// NOTE: On macOS, replacement is delayed to the restart phase.
|
||||||
await Task.Run(() =>
|
if (!OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
double count = 0;
|
// Replace old files
|
||||||
foreach (string file in allFiles)
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
count++;
|
double count = 0;
|
||||||
try
|
foreach (string file in allFiles)
|
||||||
{
|
{
|
||||||
File.Move(file, file + ".ryuold");
|
count++;
|
||||||
|
try
|
||||||
Dispatcher.UIThread.Post(() =>
|
|
||||||
{
|
{
|
||||||
taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
|
File.Move(file, file + ".ryuold");
|
||||||
});
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.UpdaterRenameFailed, file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterAddingFiles];
|
taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
|
||||||
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.UpdaterRenameFailed, file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterAddingFiles];
|
||||||
|
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||||
|
});
|
||||||
|
|
||||||
|
MoveAllFilesOver(UpdatePublishDir, HomeDir, taskDialog);
|
||||||
});
|
});
|
||||||
|
|
||||||
MoveAllFilesOver(UpdatePublishDir, HomeDir, taskDialog);
|
Directory.Delete(UpdateDir, true);
|
||||||
});
|
}
|
||||||
|
|
||||||
Directory.Delete(UpdateDir, true);
|
|
||||||
|
|
||||||
_updateSuccessful = true;
|
_updateSuccessful = true;
|
||||||
|
|
||||||
@@ -596,7 +644,7 @@ namespace Ryujinx.Modules
|
|||||||
public static bool CanUpdate(bool showWarnings)
|
public static bool CanUpdate(bool showWarnings)
|
||||||
{
|
{
|
||||||
#if !DISABLE_UPDATER
|
#if !DISABLE_UPDATER
|
||||||
if (RuntimeInformation.OSArchitecture != Architecture.X64)
|
if (RuntimeInformation.OSArchitecture != Architecture.X64 && !OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
if (showWarnings)
|
if (showWarnings)
|
||||||
{
|
{
|
||||||
@@ -669,7 +717,7 @@ namespace Ryujinx.Modules
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This method should always reflect the latest build layout.s
|
// NOTE: This method should always reflect the latest build layout.
|
||||||
private static IEnumerable<string> EnumerateFilesToDelete()
|
private static IEnumerable<string> EnumerateFilesToDelete()
|
||||||
{
|
{
|
||||||
var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir.
|
var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir.
|
||||||
|
@@ -105,13 +105,13 @@ public class TitleUpdateViewModel : BaseModel
|
|||||||
AddUpdate(path);
|
AddUpdate(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Save the list again to remove leftovers.
|
|
||||||
Save();
|
|
||||||
|
|
||||||
TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == _titleUpdateWindowData.Selected, null);
|
TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == _titleUpdateWindowData.Selected, null);
|
||||||
|
|
||||||
SelectedUpdate = selected;
|
SelectedUpdate = selected;
|
||||||
|
|
||||||
|
// NOTE: Save the list again to remove leftovers.
|
||||||
|
Save();
|
||||||
|
|
||||||
SortUpdates();
|
SortUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
public readonly bool SupportsBlendEquationAdvanced;
|
public readonly bool SupportsBlendEquationAdvanced;
|
||||||
public readonly bool SupportsFragmentShaderInterlock;
|
public readonly bool SupportsFragmentShaderInterlock;
|
||||||
public readonly bool SupportsFragmentShaderOrderingIntel;
|
public readonly bool SupportsFragmentShaderOrderingIntel;
|
||||||
|
public readonly bool SupportsGeometryShader;
|
||||||
public readonly bool SupportsGeometryShaderPassthrough;
|
public readonly bool SupportsGeometryShaderPassthrough;
|
||||||
public readonly bool SupportsImageLoadFormatted;
|
public readonly bool SupportsImageLoadFormatted;
|
||||||
public readonly bool SupportsLayerVertexTessellation;
|
public readonly bool SupportsLayerVertexTessellation;
|
||||||
@@ -68,6 +69,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
bool supportsBlendEquationAdvanced,
|
bool supportsBlendEquationAdvanced,
|
||||||
bool supportsFragmentShaderInterlock,
|
bool supportsFragmentShaderInterlock,
|
||||||
bool supportsFragmentShaderOrderingIntel,
|
bool supportsFragmentShaderOrderingIntel,
|
||||||
|
bool supportsGeometryShader,
|
||||||
bool supportsGeometryShaderPassthrough,
|
bool supportsGeometryShaderPassthrough,
|
||||||
bool supportsImageLoadFormatted,
|
bool supportsImageLoadFormatted,
|
||||||
bool supportsLayerVertexTessellation,
|
bool supportsLayerVertexTessellation,
|
||||||
@@ -107,6 +109,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
SupportsBlendEquationAdvanced = supportsBlendEquationAdvanced;
|
SupportsBlendEquationAdvanced = supportsBlendEquationAdvanced;
|
||||||
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
||||||
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
||||||
|
SupportsGeometryShader = supportsGeometryShader;
|
||||||
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
||||||
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
||||||
SupportsLayerVertexTessellation = supportsLayerVertexTessellation;
|
SupportsLayerVertexTessellation = supportsLayerVertexTessellation;
|
||||||
|
@@ -439,7 +439,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
int samplesInY = msaaMode.SamplesInY();
|
int samplesInY = msaaMode.SamplesInY();
|
||||||
|
|
||||||
var scissor = _state.State.ScreenScissorState;
|
var scissor = _state.State.ScreenScissorState;
|
||||||
Size sizeHint = new Size(scissor.X + scissor.Width, scissor.Y + scissor.Height, 1);
|
Size sizeHint = new Size((scissor.X + scissor.Width) * samplesInX, (scissor.Y + scissor.Height) * samplesInY, 1);
|
||||||
|
|
||||||
int clipRegionWidth = int.MaxValue;
|
int clipRegionWidth = int.MaxValue;
|
||||||
int clipRegionHeight = int.MaxValue;
|
int clipRegionHeight = int.MaxValue;
|
||||||
|
@@ -214,41 +214,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if two formats are compatible, according to the host API copy format compatibility rules.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lhsFormat">First comparand</param>
|
|
||||||
/// <param name="rhsFormat">Second comparand</param>
|
|
||||||
/// <param name="caps">Host GPU capabilities</param>
|
|
||||||
/// <returns>True if the formats are compatible, false otherwise</returns>
|
|
||||||
public static bool FormatCompatible(TextureInfo lhs, TextureInfo rhs, Capabilities caps)
|
|
||||||
{
|
|
||||||
FormatInfo lhsFormat = lhs.FormatInfo;
|
|
||||||
FormatInfo rhsFormat = rhs.FormatInfo;
|
|
||||||
|
|
||||||
if (lhsFormat.Format.IsDepthOrStencil() || rhsFormat.Format.IsDepthOrStencil())
|
|
||||||
{
|
|
||||||
return lhsFormat.Format == rhsFormat.Format;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsFormatHostIncompatible(lhs, caps) || IsFormatHostIncompatible(rhs, caps))
|
|
||||||
{
|
|
||||||
return lhsFormat.Format == rhsFormat.Format;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lhsFormat.IsCompressed && rhsFormat.IsCompressed)
|
|
||||||
{
|
|
||||||
FormatClass lhsClass = GetFormatClass(lhsFormat.Format);
|
|
||||||
FormatClass rhsClass = GetFormatClass(rhsFormat.Format);
|
|
||||||
|
|
||||||
return lhsClass == rhsClass;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return lhsFormat.BytesPerPixel == rhsFormat.BytesPerPixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the texture format matches with the specified texture information.
|
/// Checks if the texture format matches with the specified texture information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -391,6 +356,13 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
Size lhsSize = GetSizeInBlocks(lhs, level);
|
Size lhsSize = GetSizeInBlocks(lhs, level);
|
||||||
Size rhsSize = GetSizeInBlocks(rhs);
|
Size rhsSize = GetSizeInBlocks(rhs);
|
||||||
|
|
||||||
|
bool alignedWidthMatches = lhsAlignedSize.Width == rhsAlignedSize.Width;
|
||||||
|
|
||||||
|
if (lhs.FormatInfo.BytesPerPixel != rhs.FormatInfo.BytesPerPixel && IsIncompatibleFormatAliasingAllowed(lhs.FormatInfo, rhs.FormatInfo))
|
||||||
|
{
|
||||||
|
alignedWidthMatches = lhsSize.Width * lhs.FormatInfo.BytesPerPixel == rhsSize.Width * rhs.FormatInfo.BytesPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
||||||
|
|
||||||
// For copies, we can copy a subset of the 3D texture slices,
|
// For copies, we can copy a subset of the 3D texture slices,
|
||||||
@@ -404,7 +376,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
// so the width may not match in this case for different uses of the same texture.
|
// so the width may not match in this case for different uses of the same texture.
|
||||||
// To account for this, we compare the aligned width here.
|
// To account for this, we compare the aligned width here.
|
||||||
// We expect height to always match exactly, if the texture is the same.
|
// We expect height to always match exactly, if the texture is the same.
|
||||||
if (lhsAlignedSize.Width == rhsAlignedSize.Width && lhsSize.Height == rhsSize.Height)
|
if (alignedWidthMatches && lhsSize.Height == rhsSize.Height)
|
||||||
{
|
{
|
||||||
return (exact && lhsSize.Width != rhsSize.Width) || lhsSize.Width < rhsSize.Width
|
return (exact && lhsSize.Width != rhsSize.Width) || lhsSize.Width < rhsSize.Width
|
||||||
? TextureViewCompatibility.CopyOnly
|
? TextureViewCompatibility.CopyOnly
|
||||||
@@ -659,21 +631,62 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <returns>The view compatibility level of the texture formats</returns>
|
/// <returns>The view compatibility level of the texture formats</returns>
|
||||||
public static TextureViewCompatibility ViewFormatCompatible(TextureInfo lhs, TextureInfo rhs, Capabilities caps)
|
public static TextureViewCompatibility ViewFormatCompatible(TextureInfo lhs, TextureInfo rhs, Capabilities caps)
|
||||||
{
|
{
|
||||||
if (FormatCompatible(lhs, rhs, caps))
|
FormatInfo lhsFormat = lhs.FormatInfo;
|
||||||
|
FormatInfo rhsFormat = rhs.FormatInfo;
|
||||||
|
|
||||||
|
if (lhsFormat.Format.IsDepthOrStencil() || rhsFormat.Format.IsDepthOrStencil())
|
||||||
{
|
{
|
||||||
if (lhs.FormatInfo.IsCompressed != rhs.FormatInfo.IsCompressed)
|
return lhsFormat.Format == rhsFormat.Format ? TextureViewCompatibility.Full : TextureViewCompatibility.Incompatible;
|
||||||
{
|
}
|
||||||
return TextureViewCompatibility.CopyOnly;
|
|
||||||
}
|
if (IsFormatHostIncompatible(lhs, caps) || IsFormatHostIncompatible(rhs, caps))
|
||||||
else
|
{
|
||||||
{
|
return lhsFormat.Format == rhsFormat.Format ? TextureViewCompatibility.Full : TextureViewCompatibility.Incompatible;
|
||||||
return TextureViewCompatibility.Full;
|
}
|
||||||
}
|
|
||||||
|
if (lhsFormat.IsCompressed && rhsFormat.IsCompressed)
|
||||||
|
{
|
||||||
|
FormatClass lhsClass = GetFormatClass(lhsFormat.Format);
|
||||||
|
FormatClass rhsClass = GetFormatClass(rhsFormat.Format);
|
||||||
|
|
||||||
|
return lhsClass == rhsClass ? TextureViewCompatibility.Full : TextureViewCompatibility.Incompatible;
|
||||||
|
}
|
||||||
|
else if (lhsFormat.BytesPerPixel == rhsFormat.BytesPerPixel)
|
||||||
|
{
|
||||||
|
return lhs.FormatInfo.IsCompressed == rhs.FormatInfo.IsCompressed
|
||||||
|
? TextureViewCompatibility.Full
|
||||||
|
: TextureViewCompatibility.CopyOnly;
|
||||||
|
}
|
||||||
|
else if (IsIncompatibleFormatAliasingAllowed(lhsFormat, rhsFormat))
|
||||||
|
{
|
||||||
|
return TextureViewCompatibility.CopyOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TextureViewCompatibility.Incompatible;
|
return TextureViewCompatibility.Incompatible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if aliasing of two formats that would normally be considered incompatible be allowed,
|
||||||
|
/// using copy dependencies.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhsFormat">Format information of the first texture</param
|
||||||
|
/// <param name="rhsFormat">Format information of the second texture</param>
|
||||||
|
/// <returns>True if aliasing should be allowed, false otherwise</returns>
|
||||||
|
private static bool IsIncompatibleFormatAliasingAllowed(FormatInfo lhsFormat, FormatInfo rhsFormat)
|
||||||
|
{
|
||||||
|
// Some games will try to alias textures with incompatible foramts, with different BPP (bytes per pixel).
|
||||||
|
// We allow that in some cases as long Width * BPP is equal on both textures.
|
||||||
|
// This is very conservative right now as we want to avoid copies as much as possible,
|
||||||
|
// so we only consider the formats we have seen being aliased.
|
||||||
|
|
||||||
|
if (rhsFormat.BytesPerPixel < lhsFormat.BytesPerPixel)
|
||||||
|
{
|
||||||
|
(lhsFormat, rhsFormat) = (rhsFormat, lhsFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if the target of the first texture view information is compatible with the target of the second texture view information.
|
/// Check if the target of the first texture view information is compatible with the target of the second texture view information.
|
||||||
/// This follows the host API target compatibility rules.
|
/// This follows the host API target compatibility rules.
|
||||||
|
@@ -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 = 4369;
|
private const uint CodeGenVersion = 4368;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
@@ -774,6 +774,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
sBuffers,
|
sBuffers,
|
||||||
textures,
|
textures,
|
||||||
images,
|
images,
|
||||||
|
ShaderIdentification.None,
|
||||||
|
0,
|
||||||
dataInfo.Stage,
|
dataInfo.Stage,
|
||||||
dataInfo.UsesInstanceId,
|
dataInfo.UsesInstanceId,
|
||||||
dataInfo.UsesDrawParameters,
|
dataInfo.UsesDrawParameters,
|
||||||
|
@@ -633,6 +633,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_context.Capabilities.SupportsGeometryShader)
|
||||||
|
{
|
||||||
|
ShaderCache.TryRemoveGeometryStage(translatorContexts);
|
||||||
|
}
|
||||||
|
|
||||||
CachedShaderStage[] shaders = new CachedShaderStage[guestShaders.Length];
|
CachedShaderStage[] shaders = new CachedShaderStage[guestShaders.Length];
|
||||||
List<ShaderProgram> translatedStages = new List<ShaderProgram>();
|
List<ShaderProgram> translatedStages = new List<ShaderProgram>();
|
||||||
|
|
||||||
|
@@ -126,6 +126,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
||||||
|
|
||||||
|
public bool QueryHostSupportsGeometryShader() => _context.Capabilities.SupportsGeometryShader;
|
||||||
|
|
||||||
public bool QueryHostSupportsGeometryShaderPassthrough() => _context.Capabilities.SupportsGeometryShaderPassthrough;
|
public bool QueryHostSupportsGeometryShaderPassthrough() => _context.Capabilities.SupportsGeometryShaderPassthrough;
|
||||||
|
|
||||||
public bool QueryHostSupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted;
|
public bool QueryHostSupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted;
|
||||||
|
@@ -353,6 +353,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_context.Capabilities.SupportsGeometryShader)
|
||||||
|
{
|
||||||
|
TryRemoveGeometryStage(translatorContexts);
|
||||||
|
}
|
||||||
|
|
||||||
CachedShaderStage[] shaders = new CachedShaderStage[Constants.ShaderStages + 1];
|
CachedShaderStage[] shaders = new CachedShaderStage[Constants.ShaderStages + 1];
|
||||||
List<ShaderSource> shaderSources = new List<ShaderSource>();
|
List<ShaderSource> shaderSources = new List<ShaderSource>();
|
||||||
|
|
||||||
@@ -421,6 +426,39 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
return gpShaders;
|
return gpShaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to eliminate the geometry stage from the array of translator contexts.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="translatorContexts">Array of translator contexts</param>
|
||||||
|
public static void TryRemoveGeometryStage(TranslatorContext[] translatorContexts)
|
||||||
|
{
|
||||||
|
if (translatorContexts[4] != null)
|
||||||
|
{
|
||||||
|
// We have a geometry shader, but geometry shaders are not supported.
|
||||||
|
// Try to eliminate the geometry shader.
|
||||||
|
|
||||||
|
ShaderProgramInfo info = translatorContexts[4].Translate().Info;
|
||||||
|
|
||||||
|
if (info.Identification == ShaderIdentification.GeometryLayerPassthrough)
|
||||||
|
{
|
||||||
|
// We managed to identify that this geometry shader is only used to set the output Layer value,
|
||||||
|
// we can set the Layer on the previous stage instead (usually the vertex stage) and eliminate it.
|
||||||
|
|
||||||
|
for (int i = 3; i >= 1; i--)
|
||||||
|
{
|
||||||
|
if (translatorContexts[i] != null)
|
||||||
|
{
|
||||||
|
translatorContexts[i].SetGeometryShaderLayerInputAttribute(info.GpLayerInputAttribute);
|
||||||
|
translatorContexts[i].SetLastInVertexPipeline(translatorContexts[5] != null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
translatorContexts[4] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a shader source for use with the backend from a translated shader program.
|
/// Creates a shader source for use with the backend from a translated shader program.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
252
Ryujinx.Graphics.OpenGL/Image/TextureCopyIncompatible.cs
Normal file
252
Ryujinx.Graphics.OpenGL/Image/TextureCopyIncompatible.cs
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
|
{
|
||||||
|
class TextureCopyIncompatible
|
||||||
|
{
|
||||||
|
private const string ComputeShaderShortening = @"#version 450 core
|
||||||
|
|
||||||
|
layout (binding = 0, $SRC_FORMAT$) uniform uimage2D src;
|
||||||
|
layout (binding = 1, $DST_FORMAT$) uniform uimage2D dst;
|
||||||
|
|
||||||
|
layout (local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uvec2 coords = gl_GlobalInvocationID.xy;
|
||||||
|
ivec2 imageSz = imageSize(src);
|
||||||
|
|
||||||
|
if (int(coords.x) >= imageSz.x || int(coords.y) >= imageSz.y)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint coordsShifted = coords.x << $RATIO_LOG2$;
|
||||||
|
|
||||||
|
uvec2 dstCoords0 = uvec2(coordsShifted, coords.y);
|
||||||
|
uvec2 dstCoords1 = uvec2(coordsShifted + 1, coords.y);
|
||||||
|
uvec2 dstCoords2 = uvec2(coordsShifted + 2, coords.y);
|
||||||
|
uvec2 dstCoords3 = uvec2(coordsShifted + 3, coords.y);
|
||||||
|
|
||||||
|
uvec4 rgba = imageLoad(src, ivec2(coords));
|
||||||
|
|
||||||
|
imageStore(dst, ivec2(dstCoords0), rgba.rrrr);
|
||||||
|
imageStore(dst, ivec2(dstCoords1), rgba.gggg);
|
||||||
|
imageStore(dst, ivec2(dstCoords2), rgba.bbbb);
|
||||||
|
imageStore(dst, ivec2(dstCoords3), rgba.aaaa);
|
||||||
|
}";
|
||||||
|
|
||||||
|
private const string ComputeShaderWidening = @"#version 450 core
|
||||||
|
|
||||||
|
layout (binding = 0, $SRC_FORMAT$) uniform uimage2D src;
|
||||||
|
layout (binding = 1, $DST_FORMAT$) uniform uimage2D dst;
|
||||||
|
|
||||||
|
layout (local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uvec2 coords = gl_GlobalInvocationID.xy;
|
||||||
|
ivec2 imageSz = imageSize(dst);
|
||||||
|
|
||||||
|
if (int(coords.x) >= imageSz.x || int(coords.y) >= imageSz.y)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uvec2 srcCoords = uvec2(coords.x << $RATIO_LOG2$, coords.y);
|
||||||
|
|
||||||
|
uint r = imageLoad(src, ivec2(srcCoords) + ivec2(0, 0)).r;
|
||||||
|
uint g = imageLoad(src, ivec2(srcCoords) + ivec2(1, 0)).r;
|
||||||
|
uint b = imageLoad(src, ivec2(srcCoords) + ivec2(2, 0)).r;
|
||||||
|
uint a = imageLoad(src, ivec2(srcCoords) + ivec2(3, 0)).r;
|
||||||
|
|
||||||
|
imageStore(dst, ivec2(coords), uvec4(r, g, b, a));
|
||||||
|
}";
|
||||||
|
|
||||||
|
private readonly OpenGLRenderer _renderer;
|
||||||
|
private readonly Dictionary<int, int> _shorteningProgramHandles;
|
||||||
|
private readonly Dictionary<int, int> _wideningProgramHandles;
|
||||||
|
|
||||||
|
public TextureCopyIncompatible(OpenGLRenderer renderer)
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
_shorteningProgramHandles = new Dictionary<int, int>();
|
||||||
|
_wideningProgramHandles = new Dictionary<int, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyIncompatibleFormats(ITextureInfo src, ITextureInfo dst, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int depth, int levels)
|
||||||
|
{
|
||||||
|
TextureCreateInfo srcInfo = src.Info;
|
||||||
|
TextureCreateInfo dstInfo = dst.Info;
|
||||||
|
|
||||||
|
int srcBpp = src.Info.BytesPerPixel;
|
||||||
|
int dstBpp = dst.Info.BytesPerPixel;
|
||||||
|
|
||||||
|
// Calculate ideal component size, given our constraints:
|
||||||
|
// - Component size must not exceed bytes per pixel of source and destination image formats.
|
||||||
|
// - Maximum component size is 4 (R32).
|
||||||
|
int componentSize = Math.Min(Math.Min(srcBpp, dstBpp), 4);
|
||||||
|
|
||||||
|
int srcComponentsCount = srcBpp / componentSize;
|
||||||
|
int dstComponentsCount = dstBpp / componentSize;
|
||||||
|
|
||||||
|
var srcFormat = GetFormat(componentSize, srcComponentsCount);
|
||||||
|
var dstFormat = GetFormat(componentSize, dstComponentsCount);
|
||||||
|
|
||||||
|
GL.UseProgram(srcBpp < dstBpp
|
||||||
|
? GetWideningShader(componentSize, srcComponentsCount, dstComponentsCount)
|
||||||
|
: GetShorteningShader(componentSize, srcComponentsCount, dstComponentsCount));
|
||||||
|
|
||||||
|
for (int l = 0; l < levels; l++)
|
||||||
|
{
|
||||||
|
int srcWidth = Math.Max(1, src.Info.Width >> l);
|
||||||
|
int srcHeight = Math.Max(1, src.Info.Height >> l);
|
||||||
|
|
||||||
|
int dstWidth = Math.Max(1, dst.Info.Width >> l);
|
||||||
|
int dstHeight = Math.Max(1, dst.Info.Height >> l);
|
||||||
|
|
||||||
|
int width = Math.Min(srcWidth, dstWidth);
|
||||||
|
int height = Math.Min(srcHeight, dstHeight);
|
||||||
|
|
||||||
|
for (int z = 0; z < depth; z++)
|
||||||
|
{
|
||||||
|
GL.BindImageTexture(0, src.Handle, srcLevel + l, false, srcLayer + z, TextureAccess.ReadOnly, srcFormat);
|
||||||
|
GL.BindImageTexture(1, dst.Handle, dstLevel + l, false, dstLayer + z, TextureAccess.WriteOnly, dstFormat);
|
||||||
|
|
||||||
|
GL.DispatchCompute((width + 31) / 32, (height + 31) / 32, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pipeline pipeline = (Pipeline)_renderer.Pipeline;
|
||||||
|
|
||||||
|
pipeline.RestoreProgram();
|
||||||
|
pipeline.RestoreImages1And2();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SizedInternalFormat GetFormat(int componentSize, int componentsCount)
|
||||||
|
{
|
||||||
|
if (componentSize == 1)
|
||||||
|
{
|
||||||
|
return componentsCount switch
|
||||||
|
{
|
||||||
|
1 => SizedInternalFormat.R8ui,
|
||||||
|
2 => SizedInternalFormat.Rg8ui,
|
||||||
|
4 => SizedInternalFormat.Rgba8ui,
|
||||||
|
_ => throw new ArgumentException($"Invalid components count {componentsCount}.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (componentSize == 2)
|
||||||
|
{
|
||||||
|
return componentsCount switch
|
||||||
|
{
|
||||||
|
1 => SizedInternalFormat.R16ui,
|
||||||
|
2 => SizedInternalFormat.Rg16ui,
|
||||||
|
4 => SizedInternalFormat.Rgba16ui,
|
||||||
|
_ => throw new ArgumentException($"Invalid components count {componentsCount}.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (componentSize == 4)
|
||||||
|
{
|
||||||
|
return componentsCount switch
|
||||||
|
{
|
||||||
|
1 => SizedInternalFormat.R32ui,
|
||||||
|
2 => SizedInternalFormat.Rg32ui,
|
||||||
|
4 => SizedInternalFormat.Rgba32ui,
|
||||||
|
_ => throw new ArgumentException($"Invalid components count {componentsCount}.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Invalid component size {componentSize}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetShorteningShader(int componentSize, int srcComponentsCount, int dstComponentsCount)
|
||||||
|
{
|
||||||
|
return GetShader(ComputeShaderShortening, _shorteningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetWideningShader(int componentSize, int srcComponentsCount, int dstComponentsCount)
|
||||||
|
{
|
||||||
|
return GetShader(ComputeShaderWidening, _wideningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetShader(
|
||||||
|
string code,
|
||||||
|
Dictionary<int, int> programHandles,
|
||||||
|
int componentSize,
|
||||||
|
int srcComponentsCount,
|
||||||
|
int dstComponentsCount)
|
||||||
|
{
|
||||||
|
int componentSizeLog2 = BitOperations.Log2((uint)componentSize);
|
||||||
|
|
||||||
|
int srcIndex = componentSizeLog2 + BitOperations.Log2((uint)srcComponentsCount) * 3;
|
||||||
|
int dstIndex = componentSizeLog2 + BitOperations.Log2((uint)dstComponentsCount) * 3;
|
||||||
|
|
||||||
|
int key = srcIndex | (dstIndex << 8);
|
||||||
|
|
||||||
|
if (!programHandles.TryGetValue(key, out int programHandle))
|
||||||
|
{
|
||||||
|
int csHandle = GL.CreateShader(ShaderType.ComputeShader);
|
||||||
|
|
||||||
|
string[] formatTable = new[] { "r8ui", "r16ui", "r32ui", "rg8ui", "rg16ui", "rg32ui", "rgba8ui", "rgba16ui", "rgba32ui" };
|
||||||
|
|
||||||
|
string srcFormat = formatTable[srcIndex];
|
||||||
|
string dstFormat = formatTable[dstIndex];
|
||||||
|
|
||||||
|
int srcBpp = srcComponentsCount * componentSize;
|
||||||
|
int dstBpp = dstComponentsCount * componentSize;
|
||||||
|
|
||||||
|
int ratio = srcBpp < dstBpp ? dstBpp / srcBpp : srcBpp / dstBpp;
|
||||||
|
int ratioLog2 = BitOperations.Log2((uint)ratio);
|
||||||
|
|
||||||
|
GL.ShaderSource(csHandle, code
|
||||||
|
.Replace("$SRC_FORMAT$", srcFormat)
|
||||||
|
.Replace("$DST_FORMAT$", dstFormat)
|
||||||
|
.Replace("$RATIO_LOG2$", ratioLog2.ToString(CultureInfo.InvariantCulture)));
|
||||||
|
|
||||||
|
GL.CompileShader(csHandle);
|
||||||
|
|
||||||
|
programHandle = GL.CreateProgram();
|
||||||
|
|
||||||
|
GL.AttachShader(programHandle, csHandle);
|
||||||
|
GL.LinkProgram(programHandle);
|
||||||
|
GL.DetachShader(programHandle, csHandle);
|
||||||
|
GL.DeleteShader(csHandle);
|
||||||
|
|
||||||
|
GL.GetProgram(programHandle, GetProgramParameterName.LinkStatus, out int status);
|
||||||
|
|
||||||
|
if (status == 0)
|
||||||
|
{
|
||||||
|
throw new Exception(GL.GetProgramInfoLog(programHandle));
|
||||||
|
}
|
||||||
|
|
||||||
|
programHandles.Add(key, programHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return programHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (int handle in _shorteningProgramHandles.Values)
|
||||||
|
{
|
||||||
|
GL.DeleteProgram(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
_shorteningProgramHandles.Clear();
|
||||||
|
|
||||||
|
foreach (int handle in _wideningProgramHandles.Values)
|
||||||
|
{
|
||||||
|
GL.DeleteProgram(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
_wideningProgramHandles.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -127,6 +127,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||||
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, layers);
|
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, layers);
|
||||||
}
|
}
|
||||||
|
else if (destinationView.Info.BytesPerPixel != Info.BytesPerPixel)
|
||||||
|
{
|
||||||
|
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||||
|
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
|
||||||
|
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_renderer.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
|
_renderer.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
|
||||||
@@ -145,6 +151,10 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
{
|
{
|
||||||
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, srcLayer, dstLayer, 1);
|
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, srcLayer, dstLayer, 1);
|
||||||
}
|
}
|
||||||
|
else if (destinationView.Info.BytesPerPixel != Info.BytesPerPixel)
|
||||||
|
{
|
||||||
|
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_renderer.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
_renderer.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||||
|
@@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
private TextureCopy _textureCopy;
|
private TextureCopy _textureCopy;
|
||||||
private TextureCopy _backgroundTextureCopy;
|
private TextureCopy _backgroundTextureCopy;
|
||||||
internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy;
|
internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy;
|
||||||
|
internal TextureCopyIncompatible TextureCopyIncompatible { get; }
|
||||||
internal TextureCopyMS TextureCopyMS { get; }
|
internal TextureCopyMS TextureCopyMS { get; }
|
||||||
|
|
||||||
private Sync _sync;
|
private Sync _sync;
|
||||||
@@ -49,6 +50,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_window = new Window(this);
|
_window = new Window(this);
|
||||||
_textureCopy = new TextureCopy(this);
|
_textureCopy = new TextureCopy(this);
|
||||||
_backgroundTextureCopy = new TextureCopy(this);
|
_backgroundTextureCopy = new TextureCopy(this);
|
||||||
|
TextureCopyIncompatible = new TextureCopyIncompatible(this);
|
||||||
TextureCopyMS = new TextureCopyMS(this);
|
TextureCopyMS = new TextureCopyMS(this);
|
||||||
_sync = new Sync();
|
_sync = new Sync();
|
||||||
PersistentBuffers = new PersistentBuffers();
|
PersistentBuffers = new PersistentBuffers();
|
||||||
@@ -122,6 +124,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
supportsBlendEquationAdvanced: HwCapabilities.SupportsBlendEquationAdvanced,
|
supportsBlendEquationAdvanced: HwCapabilities.SupportsBlendEquationAdvanced,
|
||||||
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
|
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
|
||||||
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
|
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
|
||||||
|
supportsGeometryShader: true,
|
||||||
supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough,
|
supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough,
|
||||||
supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
|
supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
|
||||||
supportsLayerVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
|
supportsLayerVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
|
||||||
|
@@ -259,6 +259,15 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries host GPU geometry shader support.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the GPU and driver supports geometry shaders, false otherwise</returns>
|
||||||
|
bool QueryHostSupportsGeometryShader()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries host GPU geometry shader passthrough support.
|
/// Queries host GPU geometry shader passthrough support.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
8
Ryujinx.Graphics.Shader/ShaderIdentification.cs
Normal file
8
Ryujinx.Graphics.Shader/ShaderIdentification.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ryujinx.Graphics.Shader
|
||||||
|
{
|
||||||
|
public enum ShaderIdentification
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
GeometryLayerPassthrough
|
||||||
|
}
|
||||||
|
}
|
@@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
public ReadOnlyCollection<TextureDescriptor> Textures { get; }
|
public ReadOnlyCollection<TextureDescriptor> Textures { get; }
|
||||||
public ReadOnlyCollection<TextureDescriptor> Images { get; }
|
public ReadOnlyCollection<TextureDescriptor> Images { get; }
|
||||||
|
|
||||||
|
public ShaderIdentification Identification { get; }
|
||||||
|
public int GpLayerInputAttribute { get; }
|
||||||
public ShaderStage Stage { get; }
|
public ShaderStage Stage { get; }
|
||||||
public bool UsesInstanceId { get; }
|
public bool UsesInstanceId { get; }
|
||||||
public bool UsesDrawParameters { get; }
|
public bool UsesDrawParameters { get; }
|
||||||
@@ -22,6 +24,8 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
BufferDescriptor[] sBuffers,
|
BufferDescriptor[] sBuffers,
|
||||||
TextureDescriptor[] textures,
|
TextureDescriptor[] textures,
|
||||||
TextureDescriptor[] images,
|
TextureDescriptor[] images,
|
||||||
|
ShaderIdentification identification,
|
||||||
|
int gpLayerInputAttribute,
|
||||||
ShaderStage stage,
|
ShaderStage stage,
|
||||||
bool usesInstanceId,
|
bool usesInstanceId,
|
||||||
bool usesDrawParameters,
|
bool usesDrawParameters,
|
||||||
@@ -34,6 +38,8 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
Textures = Array.AsReadOnly(textures);
|
Textures = Array.AsReadOnly(textures);
|
||||||
Images = Array.AsReadOnly(images);
|
Images = Array.AsReadOnly(images);
|
||||||
|
|
||||||
|
Identification = identification;
|
||||||
|
GpLayerInputAttribute = gpLayerInputAttribute;
|
||||||
Stage = stage;
|
Stage = stage;
|
||||||
UsesInstanceId = usesInstanceId;
|
UsesInstanceId = usesInstanceId;
|
||||||
UsesDrawParameters = usesDrawParameters;
|
UsesDrawParameters = usesDrawParameters;
|
||||||
|
@@ -241,6 +241,13 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
this.Copy(Attribute(AttributeConsts.PositionZ), this.FPFusedMultiplyAdd(z, ConstF(0.5f), halfW));
|
this.Copy(Attribute(AttributeConsts.PositionZ), this.FPFusedMultiplyAdd(z, ConstF(0.5f), halfW));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.Stage != ShaderStage.Geometry && Config.HasLayerInputAttribute)
|
||||||
|
{
|
||||||
|
Config.SetUsedFeature(FeatureFlags.RtLayer);
|
||||||
|
|
||||||
|
this.Copy(Attribute(AttributeConsts.Layer), Attribute(Config.GpLayerInputAttribute | AttributeConsts.LoadOutputMask));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrepareForVertexReturn(out Operand oldXLocal, out Operand oldYLocal, out Operand oldZLocal)
|
public void PrepareForVertexReturn(out Operand oldXLocal, out Operand oldYLocal, out Operand oldZLocal)
|
||||||
|
@@ -20,6 +20,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
public bool LastInPipeline { get; private set; }
|
public bool LastInPipeline { get; private set; }
|
||||||
public bool LastInVertexPipeline { get; private set; }
|
public bool LastInVertexPipeline { get; private set; }
|
||||||
|
|
||||||
|
public bool HasLayerInputAttribute { get; private set; }
|
||||||
|
public int GpLayerInputAttribute { get; private set; }
|
||||||
public int ThreadsPerInputPrimitive { get; }
|
public int ThreadsPerInputPrimitive { get; }
|
||||||
|
|
||||||
public OutputTopology OutputTopology { get; }
|
public OutputTopology OutputTopology { get; }
|
||||||
@@ -245,6 +247,22 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
LayerOutputAttribute = attr;
|
LayerOutputAttribute = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetGeometryShaderLayerInputAttribute(int attr)
|
||||||
|
{
|
||||||
|
HasLayerInputAttribute = true;
|
||||||
|
GpLayerInputAttribute = attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLastInVertexPipeline(bool hasFragment)
|
||||||
|
{
|
||||||
|
if (!hasFragment)
|
||||||
|
{
|
||||||
|
LastInPipeline = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastInVertexPipeline = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetInputUserAttributeFixedFunc(int index)
|
public void SetInputUserAttributeFixedFunc(int index)
|
||||||
{
|
{
|
||||||
UsedInputAttributes |= 1 << index;
|
UsedInputAttributes |= 1 << index;
|
||||||
@@ -706,13 +724,15 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
return FindDescriptorIndex(GetImageDescriptors(), texOp);
|
return FindDescriptorIndex(GetImageDescriptors(), texOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShaderProgramInfo CreateProgramInfo()
|
public ShaderProgramInfo CreateProgramInfo(ShaderIdentification identification = ShaderIdentification.None)
|
||||||
{
|
{
|
||||||
return new ShaderProgramInfo(
|
return new ShaderProgramInfo(
|
||||||
GetConstantBufferDescriptors(),
|
GetConstantBufferDescriptors(),
|
||||||
GetStorageBufferDescriptors(),
|
GetStorageBufferDescriptors(),
|
||||||
GetTextureDescriptors(),
|
GetTextureDescriptors(),
|
||||||
GetImageDescriptors(),
|
GetImageDescriptors(),
|
||||||
|
identification,
|
||||||
|
GpLayerInputAttribute,
|
||||||
Stage,
|
Stage,
|
||||||
UsedFeatures.HasFlag(FeatureFlags.InstanceId),
|
UsedFeatures.HasFlag(FeatureFlags.InstanceId),
|
||||||
UsedFeatures.HasFlag(FeatureFlags.DrawParameters),
|
UsedFeatures.HasFlag(FeatureFlags.DrawParameters),
|
||||||
|
145
Ryujinx.Graphics.Shader/Translation/ShaderIdentifier.cs
Normal file
145
Ryujinx.Graphics.Shader/Translation/ShaderIdentifier.cs
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Shader.Translation
|
||||||
|
{
|
||||||
|
static class ShaderIdentifier
|
||||||
|
{
|
||||||
|
public static ShaderIdentification Identify(Function[] functions, ShaderConfig config)
|
||||||
|
{
|
||||||
|
if (config.Stage == ShaderStage.Geometry &&
|
||||||
|
config.GpuAccessor.QueryPrimitiveTopology() == InputTopology.Triangles &&
|
||||||
|
!config.GpuAccessor.QueryHostSupportsGeometryShader() &&
|
||||||
|
IsLayerPassthroughGeometryShader(functions, out int layerInputAttr))
|
||||||
|
{
|
||||||
|
config.SetGeometryShaderLayerInputAttribute(layerInputAttr);
|
||||||
|
|
||||||
|
return ShaderIdentification.GeometryLayerPassthrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ShaderIdentification.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsLayerPassthroughGeometryShader(Function[] functions, out int layerInputAttr)
|
||||||
|
{
|
||||||
|
bool writesLayer = false;
|
||||||
|
layerInputAttr = 0;
|
||||||
|
|
||||||
|
if (functions.Length != 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verticesCount = 0;
|
||||||
|
int totalVerticesCount = 0;
|
||||||
|
|
||||||
|
foreach (BasicBlock block in functions[0].Blocks)
|
||||||
|
{
|
||||||
|
// We are not expecting loops or any complex control flow here, so fail in those cases.
|
||||||
|
if (block.Branch != null && block.Branch.Index <= block.Index)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (INode node in block.Operations)
|
||||||
|
{
|
||||||
|
if (!(node is Operation operation))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsResourceWrite(operation.Inst))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation.Inst == Instruction.StoreAttribute)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation.Inst == Instruction.Copy && operation.Dest.Type == OperandType.Attribute)
|
||||||
|
{
|
||||||
|
Operand src = operation.GetSource(0);
|
||||||
|
|
||||||
|
if (src.Type == OperandType.LocalVariable && src.AsgOp is Operation asgOp && asgOp.Inst == Instruction.LoadAttribute)
|
||||||
|
{
|
||||||
|
src = Attribute(asgOp.GetSource(0).Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src.Type == OperandType.Attribute)
|
||||||
|
{
|
||||||
|
if (operation.Dest.Value == AttributeConsts.Layer)
|
||||||
|
{
|
||||||
|
if ((src.Value & AttributeConsts.LoadOutputMask) != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writesLayer = true;
|
||||||
|
layerInputAttr = src.Value;
|
||||||
|
}
|
||||||
|
else if (src.Value != operation.Dest.Value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (src.Type == OperandType.Constant)
|
||||||
|
{
|
||||||
|
int dstComponent = (operation.Dest.Value >> 2) & 3;
|
||||||
|
float expectedValue = dstComponent == 3 ? 1f : 0f;
|
||||||
|
|
||||||
|
if (src.AsFloat() != expectedValue)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (operation.Inst == Instruction.EmitVertex)
|
||||||
|
{
|
||||||
|
verticesCount++;
|
||||||
|
}
|
||||||
|
else if (operation.Inst == Instruction.EndPrimitive)
|
||||||
|
{
|
||||||
|
totalVerticesCount += verticesCount;
|
||||||
|
verticesCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalVerticesCount + verticesCount == 3 && writesLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsResourceWrite(Instruction inst)
|
||||||
|
{
|
||||||
|
switch (inst)
|
||||||
|
{
|
||||||
|
case Instruction.AtomicAdd:
|
||||||
|
case Instruction.AtomicAnd:
|
||||||
|
case Instruction.AtomicCompareAndSwap:
|
||||||
|
case Instruction.AtomicMaxS32:
|
||||||
|
case Instruction.AtomicMaxU32:
|
||||||
|
case Instruction.AtomicMinS32:
|
||||||
|
case Instruction.AtomicMinU32:
|
||||||
|
case Instruction.AtomicOr:
|
||||||
|
case Instruction.AtomicSwap:
|
||||||
|
case Instruction.AtomicXor:
|
||||||
|
case Instruction.ImageAtomic:
|
||||||
|
case Instruction.ImageStore:
|
||||||
|
case Instruction.StoreGlobal:
|
||||||
|
case Instruction.StoreGlobal16:
|
||||||
|
case Instruction.StoreGlobal8:
|
||||||
|
case Instruction.StoreStorage:
|
||||||
|
case Instruction.StoreStorage16:
|
||||||
|
case Instruction.StoreStorage8:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -77,9 +77,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
funcs[i] = new Function(cfg.Blocks, $"fun{i}", false, inArgumentsCount, outArgumentsCount);
|
funcs[i] = new Function(cfg.Blocks, $"fun{i}", false, inArgumentsCount, outArgumentsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var identification = ShaderIdentifier.Identify(funcs, config);
|
||||||
|
|
||||||
var sInfo = StructuredProgram.MakeStructuredProgram(funcs, config);
|
var sInfo = StructuredProgram.MakeStructuredProgram(funcs, config);
|
||||||
|
|
||||||
var info = config.CreateProgramInfo();
|
var info = config.CreateProgramInfo(identification);
|
||||||
|
|
||||||
return config.Options.TargetLanguage switch
|
return config.Options.TargetLanguage switch
|
||||||
{
|
{
|
||||||
|
@@ -138,6 +138,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
_config.MergeFromtNextStage(nextStage._config);
|
_config.MergeFromtNextStage(nextStage._config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetGeometryShaderLayerInputAttribute(int attr)
|
||||||
|
{
|
||||||
|
_config.SetGeometryShaderLayerInputAttribute(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLastInVertexPipeline(bool hasFragment)
|
||||||
|
{
|
||||||
|
_config.SetLastInVertexPipeline(hasFragment);
|
||||||
|
}
|
||||||
|
|
||||||
public ShaderProgram Translate(TranslatorContext other = null)
|
public ShaderProgram Translate(TranslatorContext other = null)
|
||||||
{
|
{
|
||||||
FunctionCode[] code = EmitShader(_program, _config, initializeOutputs: other == null, out _);
|
FunctionCode[] code = EmitShader(_program, _config, initializeOutputs: other == null, out _);
|
||||||
|
@@ -5,6 +5,7 @@ using Ryujinx.Graphics.Vulkan.Shaders;
|
|||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
using VkFormat = Silk.NET.Vulkan.Format;
|
using VkFormat = Silk.NET.Vulkan.Format;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
@@ -32,7 +33,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly IProgram _programStrideChange;
|
private readonly IProgram _programStrideChange;
|
||||||
private readonly IProgram _programConvertIndexBuffer;
|
private readonly IProgram _programConvertIndexBuffer;
|
||||||
private readonly IProgram _programConvertIndirectData;
|
private readonly IProgram _programConvertIndirectData;
|
||||||
|
private readonly IProgram _programColorCopyShortening;
|
||||||
private readonly IProgram _programColorCopyToNonMs;
|
private readonly IProgram _programColorCopyToNonMs;
|
||||||
|
private readonly IProgram _programColorCopyWidening;
|
||||||
private readonly IProgram _programColorDrawToMs;
|
private readonly IProgram _programColorDrawToMs;
|
||||||
private readonly IProgram _programDepthBlit;
|
private readonly IProgram _programDepthBlit;
|
||||||
private readonly IProgram _programDepthBlitMs;
|
private readonly IProgram _programDepthBlitMs;
|
||||||
@@ -112,15 +115,25 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
new ShaderSource(ShaderBinaries.ChangeBufferStrideShaderSource, strideChangeBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ChangeBufferStrideShaderSource, strideChangeBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
var colorCopyToNonMsBindings = new ShaderBindings(
|
var colorCopyBindings = new ShaderBindings(
|
||||||
new[] { 0 },
|
new[] { 0 },
|
||||||
Array.Empty<int>(),
|
Array.Empty<int>(),
|
||||||
new[] { 0 },
|
new[] { 0 },
|
||||||
new[] { 0 });
|
new[] { 0 });
|
||||||
|
|
||||||
|
_programColorCopyShortening = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ColorCopyShorteningComputeShaderSource, colorCopyBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
|
||||||
_programColorCopyToNonMs = gd.CreateProgramWithMinimalLayout(new[]
|
_programColorCopyToNonMs = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
{
|
{
|
||||||
new ShaderSource(ShaderBinaries.ColorCopyToNonMsComputeShaderSource, colorCopyToNonMsBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
new ShaderSource(ShaderBinaries.ColorCopyToNonMsComputeShaderSource, colorCopyBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||||
|
});
|
||||||
|
|
||||||
|
_programColorCopyWidening = gd.CreateProgramWithMinimalLayout(new[]
|
||||||
|
{
|
||||||
|
new ShaderSource(ShaderBinaries.ColorCopyWideningComputeShaderSource, colorCopyBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||||
});
|
});
|
||||||
|
|
||||||
var colorDrawToMsVertexBindings = new ShaderBindings(
|
var colorDrawToMsVertexBindings = new ShaderBindings(
|
||||||
@@ -922,6 +935,107 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
convertedCount * outputIndexSize);
|
convertedCount * outputIndexSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyIncompatibleFormats(
|
||||||
|
VulkanRenderer gd,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
TextureView src,
|
||||||
|
TextureView dst,
|
||||||
|
int srcLayer,
|
||||||
|
int dstLayer,
|
||||||
|
int srcLevel,
|
||||||
|
int dstLevel,
|
||||||
|
int depth,
|
||||||
|
int levels)
|
||||||
|
{
|
||||||
|
const int ParamsBufferSize = 4;
|
||||||
|
|
||||||
|
Span<int> shaderParams = stackalloc int[sizeof(int)];
|
||||||
|
|
||||||
|
int srcBpp = src.Info.BytesPerPixel;
|
||||||
|
int dstBpp = dst.Info.BytesPerPixel;
|
||||||
|
|
||||||
|
int ratio = srcBpp < dstBpp ? dstBpp / srcBpp : srcBpp / dstBpp;
|
||||||
|
|
||||||
|
shaderParams[0] = BitOperations.Log2((uint)ratio);
|
||||||
|
|
||||||
|
var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize, false);
|
||||||
|
|
||||||
|
gd.BufferManager.SetData<int>(bufferHandle, 0, shaderParams);
|
||||||
|
|
||||||
|
TextureView.InsertImageBarrier(
|
||||||
|
gd.Api,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
src.GetImage().Get(cbs).Value,
|
||||||
|
TextureStorage.DefaultAccessMask,
|
||||||
|
AccessFlags.ShaderReadBit,
|
||||||
|
PipelineStageFlags.AllCommandsBit,
|
||||||
|
PipelineStageFlags.ComputeShaderBit,
|
||||||
|
ImageAspectFlags.ColorBit,
|
||||||
|
src.FirstLayer + srcLayer,
|
||||||
|
src.FirstLevel + srcLevel,
|
||||||
|
depth,
|
||||||
|
levels);
|
||||||
|
|
||||||
|
_pipeline.SetCommandBuffer(cbs);
|
||||||
|
|
||||||
|
_pipeline.SetProgram(srcBpp < dstBpp ? _programColorCopyWidening : _programColorCopyShortening);
|
||||||
|
|
||||||
|
// Calculate ideal component size, given our constraints:
|
||||||
|
// - Component size must not exceed bytes per pixel of source and destination image formats.
|
||||||
|
// - Maximum component size is 4 (R32).
|
||||||
|
int componentSize = Math.Min(Math.Min(srcBpp, dstBpp), 4);
|
||||||
|
|
||||||
|
var srcFormat = GetFormat(componentSize, srcBpp / componentSize);
|
||||||
|
var dstFormat = GetFormat(componentSize, dstBpp / componentSize);
|
||||||
|
|
||||||
|
_pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) });
|
||||||
|
|
||||||
|
for (int l = 0; l < levels; l++)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < depth; z++)
|
||||||
|
{
|
||||||
|
var srcView = Create2DLayerView(src, srcLayer + z, srcLevel + l, srcFormat);
|
||||||
|
var dstView = Create2DLayerView(dst, dstLayer + z, dstLevel + l);
|
||||||
|
|
||||||
|
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
||||||
|
_pipeline.SetImage(0, dstView, dstFormat);
|
||||||
|
|
||||||
|
int dispatchX = (Math.Min(srcView.Info.Width, dstView.Info.Width) + 31) / 32;
|
||||||
|
int dispatchY = (Math.Min(srcView.Info.Height, dstView.Info.Height) + 31) / 32;
|
||||||
|
|
||||||
|
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
||||||
|
|
||||||
|
if (srcView != src)
|
||||||
|
{
|
||||||
|
srcView.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstView != dst)
|
||||||
|
{
|
||||||
|
dstView.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gd.BufferManager.Delete(bufferHandle);
|
||||||
|
|
||||||
|
_pipeline.Finish(gd, cbs);
|
||||||
|
|
||||||
|
TextureView.InsertImageBarrier(
|
||||||
|
gd.Api,
|
||||||
|
cbs.CommandBuffer,
|
||||||
|
dst.GetImage().Get(cbs).Value,
|
||||||
|
AccessFlags.ShaderWriteBit,
|
||||||
|
TextureStorage.DefaultAccessMask,
|
||||||
|
PipelineStageFlags.ComputeShaderBit,
|
||||||
|
PipelineStageFlags.AllCommandsBit,
|
||||||
|
ImageAspectFlags.ColorBit,
|
||||||
|
dst.FirstLayer + dstLayer,
|
||||||
|
dst.FirstLevel + dstLevel,
|
||||||
|
depth,
|
||||||
|
levels);
|
||||||
|
}
|
||||||
|
|
||||||
public void CopyMSToNonMS(VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, TextureView dst, int srcLayer, int dstLayer, int depth)
|
public void CopyMSToNonMS(VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, TextureView dst, int srcLayer, int dstLayer, int depth)
|
||||||
{
|
{
|
||||||
const int ParamsBufferSize = 16;
|
const int ParamsBufferSize = 16;
|
||||||
@@ -1196,6 +1310,44 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static GAL.Format GetFormat(int componentSize, int componentsCount)
|
||||||
|
{
|
||||||
|
if (componentSize == 1)
|
||||||
|
{
|
||||||
|
return componentsCount switch
|
||||||
|
{
|
||||||
|
1 => GAL.Format.R8Uint,
|
||||||
|
2 => GAL.Format.R8G8Uint,
|
||||||
|
4 => GAL.Format.R8G8B8A8Uint,
|
||||||
|
_ => throw new ArgumentException($"Invalid components count {componentsCount}.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (componentSize == 2)
|
||||||
|
{
|
||||||
|
return componentsCount switch
|
||||||
|
{
|
||||||
|
1 => GAL.Format.R16Uint,
|
||||||
|
2 => GAL.Format.R16G16Uint,
|
||||||
|
4 => GAL.Format.R16G16B16A16Uint,
|
||||||
|
_ => throw new ArgumentException($"Invalid components count {componentsCount}.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (componentSize == 4)
|
||||||
|
{
|
||||||
|
return componentsCount switch
|
||||||
|
{
|
||||||
|
1 => GAL.Format.R32Uint,
|
||||||
|
2 => GAL.Format.R32G32Uint,
|
||||||
|
4 => GAL.Format.R32G32B32A32Uint,
|
||||||
|
_ => throw new ArgumentException($"Invalid components count {componentsCount}.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Invalid component size {componentSize}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ConvertIndexBufferIndirect(
|
public void ConvertIndexBufferIndirect(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
CommandBufferScoped cbs,
|
CommandBufferScoped cbs,
|
||||||
@@ -1336,7 +1488,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_programStrideChange.Dispose();
|
_programStrideChange.Dispose();
|
||||||
_programConvertIndexBuffer.Dispose();
|
_programConvertIndexBuffer.Dispose();
|
||||||
_programConvertIndirectData.Dispose();
|
_programConvertIndirectData.Dispose();
|
||||||
|
_programColorCopyShortening.Dispose();
|
||||||
_programColorCopyToNonMs.Dispose();
|
_programColorCopyToNonMs.Dispose();
|
||||||
|
_programColorCopyWidening.Dispose();
|
||||||
_programColorDrawToMs.Dispose();
|
_programColorDrawToMs.Dispose();
|
||||||
_programDepthBlit.Dispose();
|
_programDepthBlit.Dispose();
|
||||||
_programDepthBlitMs.Dispose();
|
_programDepthBlitMs.Dispose();
|
||||||
|
@@ -80,8 +80,16 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
value = _list[id];
|
if ((uint)id < (uint)_list.Count)
|
||||||
return value != null;
|
{
|
||||||
|
value = _list[id];
|
||||||
|
return value != null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ArgumentOutOfRangeException)
|
catch (ArgumentOutOfRangeException)
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,36 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout (std140, binding = 0) uniform ratio_in
|
||||||
|
{
|
||||||
|
int ratio;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (set = 2, binding = 0) uniform usampler2D src;
|
||||||
|
layout (set = 3, binding = 0) writeonly uniform uimage2D dst;
|
||||||
|
|
||||||
|
layout (local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uvec2 coords = gl_GlobalInvocationID.xy;
|
||||||
|
ivec2 textureSz = textureSize(src, 0);
|
||||||
|
|
||||||
|
if (int(coords.x) >= textureSz.x || int(coords.y) >= textureSz.y)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint coordsShifted = coords.x << ratio;
|
||||||
|
|
||||||
|
uvec2 dstCoords0 = uvec2(coordsShifted, coords.y);
|
||||||
|
uvec2 dstCoords1 = uvec2(coordsShifted + 1, coords.y);
|
||||||
|
uvec2 dstCoords2 = uvec2(coordsShifted + 2, coords.y);
|
||||||
|
uvec2 dstCoords3 = uvec2(coordsShifted + 3, coords.y);
|
||||||
|
|
||||||
|
uvec4 rgba = texelFetch(src, ivec2(coords), 0);
|
||||||
|
|
||||||
|
imageStore(dst, ivec2(dstCoords0), rgba.rrrr);
|
||||||
|
imageStore(dst, ivec2(dstCoords1), rgba.gggg);
|
||||||
|
imageStore(dst, ivec2(dstCoords2), rgba.bbbb);
|
||||||
|
imageStore(dst, ivec2(dstCoords3), rgba.aaaa);
|
||||||
|
}
|
@@ -0,0 +1,31 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout (std140, binding = 0) uniform ratio_in
|
||||||
|
{
|
||||||
|
int ratio;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (set = 2, binding = 0) uniform usampler2D src;
|
||||||
|
layout (set = 3, binding = 0) writeonly uniform uimage2D dst;
|
||||||
|
|
||||||
|
layout (local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uvec2 coords = gl_GlobalInvocationID.xy;
|
||||||
|
ivec2 imageSz = imageSize(dst);
|
||||||
|
|
||||||
|
if (int(coords.x) >= imageSz.x || int(coords.y) >= imageSz.y)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uvec2 srcCoords = uvec2(coords.x << ratio, coords.y);
|
||||||
|
|
||||||
|
uint r = texelFetchOffset(src, ivec2(srcCoords), 0, ivec2(0, 0)).r;
|
||||||
|
uint g = texelFetchOffset(src, ivec2(srcCoords), 0, ivec2(1, 0)).r;
|
||||||
|
uint b = texelFetchOffset(src, ivec2(srcCoords), 0, ivec2(2, 0)).r;
|
||||||
|
uint a = texelFetchOffset(src, ivec2(srcCoords), 0, ivec2(3, 0)).r;
|
||||||
|
|
||||||
|
imageStore(dst, ivec2(coords), uvec4(r, g, b, a));
|
||||||
|
}
|
@@ -669,6 +669,138 @@ namespace Ryujinx.Graphics.Vulkan.Shaders
|
|||||||
0x35, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
0x35, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] ColorCopyShorteningComputeShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x05, 0x01, 0x00, 0x0B, 0x00, 0x08, 0x00, 0x79, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x32, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x38, 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, 0x09, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
|
||||||
|
0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 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, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x73, 0x72, 0x63, 0x00, 0x05, 0x00, 0x05, 0x00, 0x36, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x69,
|
||||||
|
0x6F, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x36, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
|
||||||
|
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0x73, 0x74, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x36, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x60, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x76, 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,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 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, 0x15, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00,
|
||||||
|
0x36, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00,
|
||||||
|
0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x4A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x5E, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00,
|
||||||
|
0x0A, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00,
|
||||||
|
0x28, 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, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x03, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x78, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x4F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x14, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x67, 0x00, 0x05, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||||
|
0x1F, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x04, 0x00,
|
||||||
|
0x1B, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00,
|
||||||
|
0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00,
|
||||||
|
0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x26, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
|
||||||
|
0x2A, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00,
|
||||||
|
0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
0x2E, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||||
|
0x27, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x27, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00,
|
||||||
|
0x1B, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
|
||||||
|
0x2E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
|
||||||
|
0x31, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||||
|
0x77, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x31, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||||
|
0x39, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00,
|
||||||
|
0xC4, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x41, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
|
||||||
|
0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00,
|
||||||
|
0x3C, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x4E, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
|
||||||
|
0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x56, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00,
|
||||||
|
0x5C, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||||
|
0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
|
||||||
|
0x4F, 0x00, 0x09, 0x00, 0x56, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00,
|
||||||
|
0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
|
||||||
|
0x65, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x5E, 0x00, 0x00, 0x00,
|
||||||
|
0x66, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x68, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0x56, 0x00, 0x00, 0x00,
|
||||||
|
0x6A, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x00, 0x05, 0x00,
|
||||||
|
0x66, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||||
|
0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00,
|
||||||
|
0x4F, 0x00, 0x09, 0x00, 0x56, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00,
|
||||||
|
0x5D, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x63, 0x00, 0x05, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00,
|
||||||
|
0x6F, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x5E, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x72, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0x56, 0x00, 0x00, 0x00,
|
||||||
|
0x74, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x63, 0x00, 0x05, 0x00,
|
||||||
|
0x70, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
|
||||||
|
0xF9, 0x00, 0x02, 0x00, 0x77, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x77, 0x00, 0x00, 0x00,
|
||||||
|
0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
public static readonly byte[] ColorCopyToNonMsComputeShaderSource = new byte[]
|
public static readonly byte[] ColorCopyToNonMsComputeShaderSource = new byte[]
|
||||||
{
|
{
|
||||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x86, 0x00, 0x00, 0x00,
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x86, 0x00, 0x00, 0x00,
|
||||||
@@ -801,6 +933,133 @@ namespace Ryujinx.Graphics.Vulkan.Shaders
|
|||||||
0x84, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
0x84, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly byte[] ColorCopyWideningComputeShaderSource = new byte[]
|
||||||
|
{
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x05, 0x01, 0x00, 0x0B, 0x00, 0x08, 0x00, 0x72, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x32, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x38, 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, 0x09, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
|
||||||
|
0x42, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 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, 0x03, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0x73, 0x74, 0x00, 0x05, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x69,
|
||||||
|
0x6F, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
|
||||||
|
0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x42, 0x00, 0x00, 0x00,
|
||||||
|
0x73, 0x72, 0x63, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x35, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x35, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x42, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x42, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x6F, 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,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 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, 0x15, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x34, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x37, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
|
||||||
|
0x3F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x1B, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x04, 0x00, 0x48, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x2C, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
|
||||||
|
0x58, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x61, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00,
|
||||||
|
0x0A, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00,
|
||||||
|
0x25, 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, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x03, 0x00,
|
||||||
|
0x19, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x71, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x4F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x7C, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x1D, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x24, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x23, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x7C, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
|
||||||
|
0x28, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x2C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFA, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x2D, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x70, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x37, 0x00, 0x00, 0x00,
|
||||||
|
0x38, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||||
|
0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||||
|
0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x45, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3F, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, 0x00,
|
||||||
|
0x49, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x00, 0x00,
|
||||||
|
0x36, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x4A, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||||
|
0x3F, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x08, 0x00,
|
||||||
|
0x48, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
|
||||||
|
0x0A, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0x00, 0x04, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
|
||||||
|
0x5F, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00,
|
||||||
|
0x45, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
|
||||||
|
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
|
||||||
|
0x43, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
|
||||||
|
0x63, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
|
||||||
|
0x62, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
|
||||||
|
0x66, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x68, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x48, 0x00, 0x00, 0x00,
|
||||||
|
0x6D, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00,
|
||||||
|
0x65, 0x00, 0x00, 0x00, 0x63, 0x00, 0x05, 0x00, 0x66, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
|
||||||
|
0x6D, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x70, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x70, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
public static readonly byte[] ColorDrawToMsVertexShaderSource = new byte[]
|
public static readonly byte[] ColorDrawToMsVertexShaderSource = new byte[]
|
||||||
{
|
{
|
||||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x2E, 0x00, 0x00, 0x00,
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x2E, 0x00, 0x00, 0x00,
|
||||||
|
@@ -199,6 +199,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
|
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
|
||||||
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, 0, firstLayer, layers);
|
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, 0, firstLayer, layers);
|
||||||
}
|
}
|
||||||
|
else if (dst.Info.BytesPerPixel != Info.BytesPerPixel)
|
||||||
|
{
|
||||||
|
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
|
||||||
|
int levels = Math.Min(Info.Levels, dst.Info.Levels - firstLevel);
|
||||||
|
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, 0, firstLayer, 0, firstLevel, layers, levels);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TextureCopy.Copy(
|
TextureCopy.Copy(
|
||||||
@@ -244,6 +250,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1);
|
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1);
|
||||||
}
|
}
|
||||||
|
else if (dst.Info.BytesPerPixel != Info.BytesPerPixel)
|
||||||
|
{
|
||||||
|
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TextureCopy.Copy(
|
TextureCopy.Copy(
|
||||||
|
@@ -546,6 +546,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
supportsBlendEquationAdvanced: Capabilities.SupportsBlendEquationAdvanced,
|
supportsBlendEquationAdvanced: Capabilities.SupportsBlendEquationAdvanced,
|
||||||
supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock,
|
supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock,
|
||||||
supportsFragmentShaderOrderingIntel: false,
|
supportsFragmentShaderOrderingIntel: false,
|
||||||
|
supportsGeometryShader: Capabilities.SupportsGeometryShader,
|
||||||
supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough,
|
supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough,
|
||||||
supportsImageLoadFormatted: features2.Features.ShaderStorageImageReadWithoutFormat,
|
supportsImageLoadFormatted: features2.Features.ShaderStorageImageReadWithoutFormat,
|
||||||
supportsLayerVertexTessellation: featuresVk12.ShaderOutputLayer,
|
supportsLayerVertexTessellation: featuresVk12.ShaderOutputLayer,
|
||||||
|
@@ -24,6 +24,7 @@ cp $PUBLISH_DIRECTORY/*.dylib $APP_BUNDLE_DIRECTORY/Contents/Frameworks
|
|||||||
# Then resources
|
# Then resources
|
||||||
cp Info.plist $APP_BUNDLE_DIRECTORY/Contents
|
cp Info.plist $APP_BUNDLE_DIRECTORY/Contents
|
||||||
cp Ryujinx.icns $APP_BUNDLE_DIRECTORY/Contents/Resources/Ryujinx.icns
|
cp Ryujinx.icns $APP_BUNDLE_DIRECTORY/Contents/Resources/Ryujinx.icns
|
||||||
|
cp updater.sh $APP_BUNDLE_DIRECTORY/Contents/Resources/updater.sh
|
||||||
cp -r $PUBLISH_DIRECTORY/THIRDPARTY.md $APP_BUNDLE_DIRECTORY/Contents/Resources
|
cp -r $PUBLISH_DIRECTORY/THIRDPARTY.md $APP_BUNDLE_DIRECTORY/Contents/Resources
|
||||||
|
|
||||||
echo -n "APPL????" > $APP_BUNDLE_DIRECTORY/Contents/PkgInfo
|
echo -n "APPL????" > $APP_BUNDLE_DIRECTORY/Contents/PkgInfo
|
||||||
|
@@ -27,7 +27,7 @@ EXECUTABLE_SUB_PATH=Contents/MacOS/Ryujinx
|
|||||||
rm -rf $TEMP_DIRECTORY
|
rm -rf $TEMP_DIRECTORY
|
||||||
mkdir -p $TEMP_DIRECTORY
|
mkdir -p $TEMP_DIRECTORY
|
||||||
|
|
||||||
DOTNET_COMMON_ARGS="-p:DebugType=embedded -p:Version=$VERSION -p:SourceRevisionId=$SOURCE_REVISION_ID -p:ExtraDefineConstants=DISABLE_UPDATER --self-contained true"
|
DOTNET_COMMON_ARGS="-p:DebugType=embedded -p:Version=$VERSION -p:SourceRevisionId=$SOURCE_REVISION_ID --self-contained true"
|
||||||
|
|
||||||
dotnet restore
|
dotnet restore
|
||||||
dotnet build -c Release Ryujinx.Ava
|
dotnet build -c Release Ryujinx.Ava
|
||||||
|
39
distribution/macos/updater.sh
Executable file
39
distribution/macos/updater.sh
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
INSTALL_DIRECTORY=$1
|
||||||
|
NEW_APP_DIRECTORY=$2
|
||||||
|
APP_PID=$3
|
||||||
|
APP_ARGUMENTS="${@:4}"
|
||||||
|
|
||||||
|
error_handler() {
|
||||||
|
local lineno="$1"
|
||||||
|
|
||||||
|
script="""
|
||||||
|
set alertTitle to \"Ryujinx - Updater error\"
|
||||||
|
set alertMessage to \"An error occurred during Ryujinx update (updater.sh:$lineno)\n\nPlease download the update manually from our website if the problem persists.\"
|
||||||
|
display dialog alertMessage with icon caution with title alertTitle buttons {\"Open Download Page\", \"Exit\"}
|
||||||
|
set the button_pressed to the button returned of the result
|
||||||
|
|
||||||
|
if the button_pressed is \"Open Download Page\" then
|
||||||
|
open location \"https://ryujinx.org/download\"
|
||||||
|
end if
|
||||||
|
"""
|
||||||
|
|
||||||
|
osascript -e "$script"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'error_handler ${LINENO}' ERR
|
||||||
|
|
||||||
|
# Wait for Ryujinx to exit
|
||||||
|
# NOTE: in case no fds are open, lsof could be returning with a process still living.
|
||||||
|
# We wait 1s and assume the process stopped after that
|
||||||
|
lsof -p $APP_PID +r 1 &>/dev/null
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Now replace and reopen.
|
||||||
|
rm -rf "$INSTALL_DIRECTORY"
|
||||||
|
mv "$NEW_APP_DIRECTORY" "$INSTALL_DIRECTORY"
|
||||||
|
open -a "$INSTALL_DIRECTORY" --args "$APP_ARGUMENTS"
|
Reference in New Issue
Block a user