diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs new file mode 100644 index 00000000..719e170f --- /dev/null +++ b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs @@ -0,0 +1,113 @@ +using Ryujinx.Common; +using Ryujinx.Graphics.GAL; +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.Gpu.Engine.MME +{ + /// <summary> + /// Table with information about High-level implementations of GPU Macro code. + /// </summary> + static class MacroHLETable + { + /// <summary> + /// Macroo High-level implementation table entry. + /// </summary> + readonly struct TableEntry + { + /// <summary> + /// Name of the Macro function. + /// </summary> + public MacroHLEFunctionName Name { get; } + + /// <summary> + /// Hash of the original binary Macro function code. + /// </summary> + public Hash128 Hash { get; } + + /// <summary> + /// Size (in bytes) of the original binary Macro function code. + /// </summary> + public int Length { get; } + + /// <summary> + /// Creates a new table entry. + /// </summary> + /// <param name="name">Name of the Macro function</param> + /// <param name="hash">Hash of the original binary Macro function code</param> + /// <param name="length">Size (in bytes) of the original binary Macro function code</param> + public TableEntry(MacroHLEFunctionName name, Hash128 hash, int length) + { + Name = name; + Hash = hash; + Length = length; + } + } + + private static readonly TableEntry[] _table = new TableEntry[] + { + new TableEntry(MacroHLEFunctionName.ClearColor, new Hash128(0xA9FB28D1DC43645A, 0xB177E5D2EAE67FB0), 0x28), + new TableEntry(MacroHLEFunctionName.ClearDepthStencil, new Hash128(0x1B96CB77D4879F4F, 0x8557032FE0C965FB), 0x24), + new TableEntry(MacroHLEFunctionName.DrawArraysInstanced, new Hash128(0x197FB416269DBC26, 0x34288C01DDA82202), 0x48), + new TableEntry(MacroHLEFunctionName.DrawElementsInstanced, new Hash128(0x1A501FD3D54EC8E0, 0x6CF570CF79DA74D6), 0x5c), + new TableEntry(MacroHLEFunctionName.DrawElementsIndirect, new Hash128(0x86A3E8E903AF8F45, 0xD35BBA07C23860A4), 0x7c), + new TableEntry(MacroHLEFunctionName.MultiDrawElementsIndirectCount, new Hash128(0x890AF57ED3FB1C37, 0x35D0C95C61F5386F), 0x19C) + }; + + /// <summary> + /// Checks if the host supports all features required by the HLE macro. + /// </summary> + /// <param name="caps">Host capabilities</param> + /// <param name="name">Name of the HLE macro to be checked</param> + /// <returns>True if the host supports the HLE macro, false otherwise</returns> + private static bool IsMacroHLESupported(Capabilities caps, MacroHLEFunctionName name) + { + if (name == MacroHLEFunctionName.ClearColor || + name == MacroHLEFunctionName.ClearDepthStencil || + name == MacroHLEFunctionName.DrawArraysInstanced || + name == MacroHLEFunctionName.DrawElementsInstanced || + name == MacroHLEFunctionName.DrawElementsIndirect) + { + return true; + } + else if (name == MacroHLEFunctionName.MultiDrawElementsIndirectCount) + { + return caps.SupportsIndirectParameters; + } + + return false; + } + + /// <summary> + /// Checks if there's a fast, High-level implementation of the specified Macro code available. + /// </summary> + /// <param name="code">Macro code to be checked</param> + /// <param name="caps">Renderer capabilities to check for this macro HLE support</param> + /// <param name="name">Name of the function if a implementation is available and supported, otherwise <see cref="MacroHLEFunctionName.None"/></param> + /// <returns>True if there is a implementation available and supported, false otherwise</returns> + public static bool TryGetMacroHLEFunction(ReadOnlySpan<int> code, Capabilities caps, out MacroHLEFunctionName name) + { + var mc = MemoryMarshal.Cast<int, byte>(code); + + for (int i = 0; i < _table.Length; i++) + { + ref var entry = ref _table[i]; + + var hash = XXHash128.ComputeHash(mc.Slice(0, entry.Length)); + if (hash == entry.Hash) + { + if (IsMacroHLESupported(caps, entry.Name)) + { + name = entry.Name; + return true; + } + + break; + } + } + + name = MacroHLEFunctionName.None; + return false; + } + } +} |