| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- using Ryujinx.Graphics.Shader.Decoders;
- using Ryujinx.Graphics.Shader.IntermediateRepresentation;
- using System;
- using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
- namespace Ryujinx.Graphics.Shader.Translation.Optimizations
- {
- static class ConstantFolding
- {
- public static void RunPass(Operation operation)
- {
- if (!AreAllSourcesConstant(operation))
- {
- return;
- }
- switch (operation.Inst)
- {
- case Instruction.Add:
- EvaluateBinary(operation, (x, y) => x + y);
- break;
- case Instruction.BitCount:
- EvaluateUnary(operation, (x) => BitCount(x));
- break;
- case Instruction.BitwiseAnd:
- EvaluateBinary(operation, (x, y) => x & y);
- break;
- case Instruction.BitwiseExclusiveOr:
- EvaluateBinary(operation, (x, y) => x ^ y);
- break;
- case Instruction.BitwiseNot:
- EvaluateUnary(operation, (x) => ~x);
- break;
- case Instruction.BitwiseOr:
- EvaluateBinary(operation, (x, y) => x | y);
- break;
- case Instruction.BitfieldExtractS32:
- BitfieldExtractS32(operation);
- break;
- case Instruction.BitfieldExtractU32:
- BitfieldExtractU32(operation);
- break;
- case Instruction.Clamp:
- EvaluateTernary(operation, (x, y, z) => Math.Clamp(x, y, z));
- break;
- case Instruction.ClampU32:
- EvaluateTernary(operation, (x, y, z) => (int)Math.Clamp((uint)x, (uint)y, (uint)z));
- break;
- case Instruction.CompareEqual:
- EvaluateBinary(operation, (x, y) => x == y);
- break;
- case Instruction.CompareGreater:
- EvaluateBinary(operation, (x, y) => x > y);
- break;
- case Instruction.CompareGreaterOrEqual:
- EvaluateBinary(operation, (x, y) => x >= y);
- break;
- case Instruction.CompareGreaterOrEqualU32:
- EvaluateBinary(operation, (x, y) => (uint)x >= (uint)y);
- break;
- case Instruction.CompareGreaterU32:
- EvaluateBinary(operation, (x, y) => (uint)x > (uint)y);
- break;
- case Instruction.CompareLess:
- EvaluateBinary(operation, (x, y) => x < y);
- break;
- case Instruction.CompareLessOrEqual:
- EvaluateBinary(operation, (x, y) => x <= y);
- break;
- case Instruction.CompareLessOrEqualU32:
- EvaluateBinary(operation, (x, y) => (uint)x <= (uint)y);
- break;
- case Instruction.CompareLessU32:
- EvaluateBinary(operation, (x, y) => (uint)x < (uint)y);
- break;
- case Instruction.CompareNotEqual:
- EvaluateBinary(operation, (x, y) => x != y);
- break;
- case Instruction.Divide:
- EvaluateBinary(operation, (x, y) => y != 0 ? x / y : 0);
- break;
- case Instruction.FP32 | Instruction.Add:
- EvaluateFPBinary(operation, (x, y) => x + y);
- break;
- case Instruction.FP32 | Instruction.Clamp:
- EvaluateFPTernary(operation, (x, y, z) => Math.Clamp(x, y, z));
- break;
- case Instruction.FP32 | Instruction.CompareEqual:
- EvaluateFPBinary(operation, (x, y) => x == y);
- break;
- case Instruction.FP32 | Instruction.CompareGreater:
- EvaluateFPBinary(operation, (x, y) => x > y);
- break;
- case Instruction.FP32 | Instruction.CompareGreaterOrEqual:
- EvaluateFPBinary(operation, (x, y) => x >= y);
- break;
- case Instruction.FP32 | Instruction.CompareLess:
- EvaluateFPBinary(operation, (x, y) => x < y);
- break;
- case Instruction.FP32 | Instruction.CompareLessOrEqual:
- EvaluateFPBinary(operation, (x, y) => x <= y);
- break;
- case Instruction.FP32 | Instruction.CompareNotEqual:
- EvaluateFPBinary(operation, (x, y) => x != y);
- break;
- case Instruction.FP32 | Instruction.Divide:
- EvaluateFPBinary(operation, (x, y) => x / y);
- break;
- case Instruction.FP32 | Instruction.Multiply:
- EvaluateFPBinary(operation, (x, y) => x * y);
- break;
- case Instruction.FP32 | Instruction.Negate:
- EvaluateFPUnary(operation, (x) => -x);
- break;
- case Instruction.FP32 | Instruction.Subtract:
- EvaluateFPBinary(operation, (x, y) => x - y);
- break;
- case Instruction.IsNan:
- EvaluateFPUnary(operation, (x) => float.IsNaN(x));
- break;
- case Instruction.LoadConstant:
- operation.TurnIntoCopy(Cbuf(operation.GetSource(0).Value, operation.GetSource(1).Value));
- break;
- case Instruction.Maximum:
- EvaluateBinary(operation, (x, y) => Math.Max(x, y));
- break;
- case Instruction.MaximumU32:
- EvaluateBinary(operation, (x, y) => (int)Math.Max((uint)x, (uint)y));
- break;
- case Instruction.Minimum:
- EvaluateBinary(operation, (x, y) => Math.Min(x, y));
- break;
- case Instruction.MinimumU32:
- EvaluateBinary(operation, (x, y) => (int)Math.Min((uint)x, (uint)y));
- break;
- case Instruction.Multiply:
- EvaluateBinary(operation, (x, y) => x * y);
- break;
- case Instruction.Negate:
- EvaluateUnary(operation, (x) => -x);
- break;
- case Instruction.ShiftLeft:
- EvaluateBinary(operation, (x, y) => x << y);
- break;
- case Instruction.ShiftRightS32:
- EvaluateBinary(operation, (x, y) => x >> y);
- break;
- case Instruction.ShiftRightU32:
- EvaluateBinary(operation, (x, y) => (int)((uint)x >> y));
- break;
- case Instruction.Subtract:
- EvaluateBinary(operation, (x, y) => x - y);
- break;
- case Instruction.UnpackHalf2x16:
- UnpackHalf2x16(operation);
- break;
- }
- }
- private static bool AreAllSourcesConstant(Operation operation)
- {
- for (int index = 0; index < operation.SourcesCount; index++)
- {
- if (operation.GetSource(index).Type != OperandType.Constant)
- {
- return false;
- }
- }
- return true;
- }
- private static int BitCount(int value)
- {
- int count = 0;
- for (int bit = 0; bit < 32; bit++)
- {
- if (value.Extract(bit))
- {
- count++;
- }
- }
- return count;
- }
- private static void BitfieldExtractS32(Operation operation)
- {
- int value = GetBitfieldExtractValue(operation);
- int shift = 32 - operation.GetSource(2).Value;
- value = (value << shift) >> shift;
- operation.TurnIntoCopy(Const(value));
- }
- private static void BitfieldExtractU32(Operation operation)
- {
- operation.TurnIntoCopy(Const(GetBitfieldExtractValue(operation)));
- }
- private static int GetBitfieldExtractValue(Operation operation)
- {
- int value = operation.GetSource(0).Value;
- int lsb = operation.GetSource(1).Value;
- int length = operation.GetSource(2).Value;
- return value.Extract(lsb, length);
- }
- private static void UnpackHalf2x16(Operation operation)
- {
- int value = operation.GetSource(0).Value;
- value = (value >> operation.Index * 16) & 0xffff;
- operation.TurnIntoCopy(ConstF((float)BitConverter.UInt16BitsToHalf((ushort)value)));
- }
- private static void FPNegate(Operation operation)
- {
- float value = operation.GetSource(0).AsFloat();
- operation.TurnIntoCopy(ConstF(-value));
- }
- private static void EvaluateUnary(Operation operation, Func<int, int> op)
- {
- int x = operation.GetSource(0).Value;
- operation.TurnIntoCopy(Const(op(x)));
- }
- private static void EvaluateFPUnary(Operation operation, Func<float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
- operation.TurnIntoCopy(ConstF(op(x)));
- }
- private static void EvaluateFPUnary(Operation operation, Func<float, bool> op)
- {
- float x = operation.GetSource(0).AsFloat();
- operation.TurnIntoCopy(Const(op(x) ? IrConsts.True : IrConsts.False));
- }
- private static void EvaluateBinary(Operation operation, Func<int, int, int> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
- operation.TurnIntoCopy(Const(op(x, y)));
- }
- private static void EvaluateBinary(Operation operation, Func<int, int, bool> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
- operation.TurnIntoCopy(Const(op(x, y) ? IrConsts.True : IrConsts.False));
- }
- private static void EvaluateFPBinary(Operation operation, Func<float, float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
- operation.TurnIntoCopy(ConstF(op(x, y)));
- }
- private static void EvaluateFPBinary(Operation operation, Func<float, float, bool> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
- operation.TurnIntoCopy(Const(op(x, y) ? IrConsts.True : IrConsts.False));
- }
- private static void EvaluateTernary(Operation operation, Func<int, int, int, int> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
- int z = operation.GetSource(2).Value;
- operation.TurnIntoCopy(Const(op(x, y, z)));
- }
- private static void EvaluateFPTernary(Operation operation, Func<float, float, float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
- float z = operation.GetSource(2).AsFloat();
- operation.TurnIntoCopy(ConstF(op(x, y, z)));
- }
- }
- }
|