using Ryujinx.Common; using Ryujinx.Graphics.GAL; using System; using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Gpu.Engine.MME { /// /// Table with information about High-level implementations of GPU Macro code. /// static class MacroHLETable { /// /// Macroo High-level implementation table entry. /// readonly struct TableEntry { /// /// Name of the Macro function. /// public MacroHLEFunctionName Name { get; } /// /// Hash of the original binary Macro function code. /// public Hash128 Hash { get; } /// /// Size (in bytes) of the original binary Macro function code. /// public int Length { get; } /// /// Creates a new table entry. /// /// Name of the Macro function /// Hash of the original binary Macro function code /// Size (in bytes) of the original binary Macro function code 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) }; /// /// Checks if the host supports all features required by the HLE macro. /// /// Host capabilities /// Name of the HLE macro to be checked /// True if the host supports the HLE macro, false otherwise 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; } /// /// Checks if there's a fast, High-level implementation of the specified Macro code available. /// /// Macro code to be checked /// Renderer capabilities to check for this macro HLE support /// Name of the function if a implementation is available and supported, otherwise /// True if there is a implementation available and supported, false otherwise public static bool TryGetMacroHLEFunction(ReadOnlySpan code, Capabilities caps, out MacroHLEFunctionName name) { var mc = MemoryMarshal.Cast(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; } } }