Move the OpActivator to OpCodeTable class for improve performance (#1001)
* Move the OpActivator to OpCodeTable class, for reduce the use of ConcurrentDictionary * Modify code style.
This commit is contained in:
parent
2816b2bf17
commit
7ad8b3ef75
2 changed files with 35 additions and 47 deletions
|
@ -1,10 +1,8 @@
|
||||||
using Ryujinx.Graphics.Shader.Instructions;
|
using Ryujinx.Graphics.Shader.Instructions;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection.Emit;
|
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
|
@ -12,15 +10,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
{
|
{
|
||||||
static class Decoder
|
static class Decoder
|
||||||
{
|
{
|
||||||
private delegate object OpActivator(InstEmitter emitter, ulong address, long opCode);
|
|
||||||
|
|
||||||
private static ConcurrentDictionary<Type, OpActivator> _opActivators;
|
|
||||||
|
|
||||||
static Decoder()
|
|
||||||
{
|
|
||||||
_opActivators = new ConcurrentDictionary<Type, OpActivator>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Block[] Decode(ReadOnlySpan<byte> code, ulong headerSize)
|
public static Block[] Decode(ReadOnlySpan<byte> code, ulong headerSize)
|
||||||
{
|
{
|
||||||
List<Block> blocks = new List<Block>();
|
List<Block> blocks = new List<Block>();
|
||||||
|
@ -245,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
|
|
||||||
long opCode = word0 | (long)word1 << 32;
|
long opCode = word0 | (long)word1 << 32;
|
||||||
|
|
||||||
(InstEmitter emitter, Type opCodeType) = OpCodeTable.GetEmitter(opCode);
|
(InstEmitter emitter, OpCodeTable.OpActivator opActivator) = OpCodeTable.GetEmitter(opCode);
|
||||||
|
|
||||||
if (emitter == null)
|
if (emitter == null)
|
||||||
{
|
{
|
||||||
|
@ -256,7 +245,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpCode op = MakeOpCode(opCodeType, emitter, opAddress, opCode);
|
if (opActivator == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(opActivator));
|
||||||
|
}
|
||||||
|
|
||||||
|
OpCode op = (OpCode)opActivator(emitter, opAddress, opCode);
|
||||||
|
|
||||||
block.OpCodes.Add(op);
|
block.OpCodes.Add(op);
|
||||||
}
|
}
|
||||||
|
@ -295,35 +289,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
return opCode is OpCodeExit;
|
return opCode is OpCodeExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OpCode MakeOpCode(Type type, InstEmitter emitter, ulong address, long opCode)
|
|
||||||
{
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
OpActivator createInstance = _opActivators.GetOrAdd(type, CacheOpActivator);
|
|
||||||
|
|
||||||
return (OpCode)createInstance(emitter, address, opCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static OpActivator CacheOpActivator(Type type)
|
|
||||||
{
|
|
||||||
Type[] argTypes = new Type[] { typeof(InstEmitter), typeof(ulong), typeof(long) };
|
|
||||||
|
|
||||||
DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes);
|
|
||||||
|
|
||||||
ILGenerator generator = mthd.GetILGenerator();
|
|
||||||
|
|
||||||
generator.Emit(OpCodes.Ldarg_0);
|
|
||||||
generator.Emit(OpCodes.Ldarg_1);
|
|
||||||
generator.Emit(OpCodes.Ldarg_2);
|
|
||||||
generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes));
|
|
||||||
generator.Emit(OpCodes.Ret);
|
|
||||||
|
|
||||||
return (OpActivator)mthd.CreateDelegate(typeof(OpActivator));
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct PathBlockState
|
private struct PathBlockState
|
||||||
{
|
{
|
||||||
public Block Block { get; }
|
public Block Block { get; }
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using Ryujinx.Graphics.Shader.Instructions;
|
using Ryujinx.Graphics.Shader.Instructions;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Decoders
|
namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
{
|
{
|
||||||
static class OpCodeTable
|
static class OpCodeTable
|
||||||
{
|
{
|
||||||
|
public delegate object OpActivator(InstEmitter emitter, ulong address, long opCode);
|
||||||
|
|
||||||
private const int EncodingBits = 14;
|
private const int EncodingBits = 14;
|
||||||
|
|
||||||
private class TableEntry
|
private class TableEntry
|
||||||
|
@ -15,11 +18,31 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
|
|
||||||
public int XBits { get; }
|
public int XBits { get; }
|
||||||
|
|
||||||
|
public OpActivator OpActivator { get; }
|
||||||
|
|
||||||
public TableEntry(InstEmitter emitter, Type opCodeType, int xBits)
|
public TableEntry(InstEmitter emitter, Type opCodeType, int xBits)
|
||||||
{
|
{
|
||||||
Emitter = emitter;
|
Emitter = emitter;
|
||||||
OpCodeType = opCodeType;
|
OpCodeType = opCodeType;
|
||||||
XBits = xBits;
|
XBits = xBits;
|
||||||
|
OpActivator = CacheOpActivator(opCodeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OpActivator CacheOpActivator(Type type)
|
||||||
|
{
|
||||||
|
Type[] argTypes = new Type[] { typeof(InstEmitter), typeof(ulong), typeof(long) };
|
||||||
|
|
||||||
|
DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes);
|
||||||
|
|
||||||
|
ILGenerator generator = mthd.GetILGenerator();
|
||||||
|
|
||||||
|
generator.Emit(OpCodes.Ldarg_0);
|
||||||
|
generator.Emit(OpCodes.Ldarg_1);
|
||||||
|
generator.Emit(OpCodes.Ldarg_2);
|
||||||
|
generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes));
|
||||||
|
generator.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
return (OpActivator)mthd.CreateDelegate(typeof(OpActivator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,13 +289,13 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (InstEmitter emitter, Type opCodeType) GetEmitter(long opCode)
|
public static (InstEmitter emitter, OpActivator opActivator) GetEmitter(long opCode)
|
||||||
{
|
{
|
||||||
TableEntry entry = _opCodes[(ulong)opCode >> (64 - EncodingBits)];
|
TableEntry entry = _opCodes[(ulong)opCode >> (64 - EncodingBits)];
|
||||||
|
|
||||||
if (entry != null)
|
if (entry != null)
|
||||||
{
|
{
|
||||||
return (entry.Emitter, entry.OpCodeType);
|
return (entry.Emitter, entry.OpActivator);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|
Loading…
Reference in a new issue