aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs
blob: 8eccef237546b602e58a28f41389a66514e8ef14 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation;
using System;

namespace Ryujinx.Graphics.Shader.StructuredIr
{
    static class InstructionInfo
    {
        private readonly struct InstInfo
        {
            public AggregateType DestType { get; }

            public AggregateType[] SrcTypes { get; }

            public InstInfo(AggregateType destType, params AggregateType[] srcTypes)
            {
                DestType = destType;
                SrcTypes = srcTypes;
            }
        }

        private static InstInfo[] _infoTbl;

        static InstructionInfo()
        {
            _infoTbl = new InstInfo[(int)Instruction.Count];

            //  Inst                                  Destination type      Source 1 type          Source 2 type          Source 3 type          Source 4 type
            Add(Instruction.AtomicAdd,                AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.AtomicAnd,                AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.AtomicCompareAndSwap,     AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32,     AggregateType.U32);
            Add(Instruction.AtomicMaxS32,             AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
            Add(Instruction.AtomicMaxU32,             AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.AtomicMinS32,             AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
            Add(Instruction.AtomicMinU32,             AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.AtomicOr,                 AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.AtomicSwap,               AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.AtomicXor,                AggregateType.U32,    AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.Absolute,                 AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.Add,                      AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.Ballot,                   AggregateType.U32,    AggregateType.Bool);
            Add(Instruction.BitCount,                 AggregateType.S32,    AggregateType.S32);
            Add(Instruction.BitfieldExtractS32,       AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
            Add(Instruction.BitfieldExtractU32,       AggregateType.U32,    AggregateType.U32,     AggregateType.S32,     AggregateType.S32);
            Add(Instruction.BitfieldInsert,           AggregateType.S32,    AggregateType.S32,     AggregateType.S32,     AggregateType.S32,     AggregateType.S32);
            Add(Instruction.BitfieldReverse,          AggregateType.S32,    AggregateType.S32);
            Add(Instruction.BitwiseAnd,               AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.BitwiseExclusiveOr,       AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.BitwiseNot,               AggregateType.S32,    AggregateType.S32);
            Add(Instruction.BitwiseOr,                AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.BranchIfTrue,             AggregateType.Void,   AggregateType.Bool);
            Add(Instruction.BranchIfFalse,            AggregateType.Void,   AggregateType.Bool);
            Add(Instruction.Call,                     AggregateType.Scalar);
            Add(Instruction.Ceiling,                  AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.Clamp,                    AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.ClampU32,                 AggregateType.U32,    AggregateType.U32,     AggregateType.U32,     AggregateType.U32);
            Add(Instruction.CompareEqual,             AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.CompareGreater,           AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.CompareGreaterOrEqual,    AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.CompareGreaterOrEqualU32, AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
            Add(Instruction.CompareGreaterU32,        AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
            Add(Instruction.CompareLess,              AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.CompareLessOrEqual,       AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.CompareLessOrEqualU32,    AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
            Add(Instruction.CompareLessU32,           AggregateType.Bool,   AggregateType.U32,     AggregateType.U32);
            Add(Instruction.CompareNotEqual,          AggregateType.Bool,   AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.ConditionalSelect,        AggregateType.Scalar, AggregateType.Bool,    AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.ConvertFP32ToFP64,        AggregateType.FP64,   AggregateType.FP32);
            Add(Instruction.ConvertFP64ToFP32,        AggregateType.FP32,   AggregateType.FP64);
            Add(Instruction.ConvertFP32ToS32,         AggregateType.S32,    AggregateType.FP32);
            Add(Instruction.ConvertFP32ToU32,         AggregateType.U32,    AggregateType.FP32);
            Add(Instruction.ConvertFP64ToS32,         AggregateType.S32,    AggregateType.FP64);
            Add(Instruction.ConvertFP64ToU32,         AggregateType.U32,    AggregateType.FP64);
            Add(Instruction.ConvertS32ToFP32,         AggregateType.FP32,   AggregateType.S32);
            Add(Instruction.ConvertS32ToFP64,         AggregateType.FP64,   AggregateType.S32);
            Add(Instruction.ConvertU32ToFP32,         AggregateType.FP32,   AggregateType.U32);
            Add(Instruction.ConvertU32ToFP64,         AggregateType.FP64,   AggregateType.U32);
            Add(Instruction.Cosine,                   AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.Ddx,                      AggregateType.FP32,   AggregateType.FP32);
            Add(Instruction.Ddy,                      AggregateType.FP32,   AggregateType.FP32);
            Add(Instruction.Divide,                   AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.ExponentB2,               AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.FindLSB,                  AggregateType.S32,    AggregateType.S32);
            Add(Instruction.FindMSBS32,               AggregateType.S32,    AggregateType.S32);
            Add(Instruction.FindMSBU32,               AggregateType.S32,    AggregateType.U32);
            Add(Instruction.Floor,                    AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.FusedMultiplyAdd,         AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.ImageLoad,                AggregateType.FP32);
            Add(Instruction.ImageStore,               AggregateType.Void);
            Add(Instruction.ImageAtomic,              AggregateType.S32);
            Add(Instruction.IsNan,                    AggregateType.Bool,   AggregateType.Scalar);
            Add(Instruction.Load,                     AggregateType.FP32);
            Add(Instruction.LoadConstant,             AggregateType.FP32,   AggregateType.S32,     AggregateType.S32);
            Add(Instruction.LoadGlobal,               AggregateType.U32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.LoadLocal,                AggregateType.U32,    AggregateType.S32);
            Add(Instruction.LoadShared,               AggregateType.U32,    AggregateType.S32);
            Add(Instruction.LoadStorage,              AggregateType.U32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.Lod,                      AggregateType.FP32);
            Add(Instruction.LogarithmB2,              AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.LogicalAnd,               AggregateType.Bool,   AggregateType.Bool,    AggregateType.Bool);
            Add(Instruction.LogicalExclusiveOr,       AggregateType.Bool,   AggregateType.Bool,    AggregateType.Bool);
            Add(Instruction.LogicalNot,               AggregateType.Bool,   AggregateType.Bool);
            Add(Instruction.LogicalOr,                AggregateType.Bool,   AggregateType.Bool,    AggregateType.Bool);
            Add(Instruction.Maximum,                  AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.MaximumU32,               AggregateType.U32,    AggregateType.U32,     AggregateType.U32);
            Add(Instruction.Minimum,                  AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.MinimumU32,               AggregateType.U32,    AggregateType.U32,     AggregateType.U32);
            Add(Instruction.Multiply,                 AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.MultiplyHighS32,          AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.MultiplyHighU32,          AggregateType.U32,    AggregateType.U32,     AggregateType.U32);
            Add(Instruction.Negate,                   AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.PackDouble2x32,           AggregateType.FP64,   AggregateType.U32,     AggregateType.U32);
            Add(Instruction.PackHalf2x16,             AggregateType.U32,    AggregateType.FP32,    AggregateType.FP32);
            Add(Instruction.ReciprocalSquareRoot,     AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.Round,                    AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.ShiftLeft,                AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.ShiftRightS32,            AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.ShiftRightU32,            AggregateType.U32,    AggregateType.U32,     AggregateType.S32);
            Add(Instruction.Shuffle,                  AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32,     AggregateType.U32,     AggregateType.Bool);
            Add(Instruction.ShuffleDown,              AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32,     AggregateType.U32,     AggregateType.Bool);
            Add(Instruction.ShuffleUp,                AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32,     AggregateType.U32,     AggregateType.Bool);
            Add(Instruction.ShuffleXor,               AggregateType.FP32,   AggregateType.FP32,    AggregateType.U32,     AggregateType.U32,     AggregateType.Bool);
            Add(Instruction.Sine,                     AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.SquareRoot,               AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.Store,                    AggregateType.Void);
            Add(Instruction.StoreGlobal,              AggregateType.Void,   AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.StoreLocal,               AggregateType.Void,   AggregateType.S32,     AggregateType.U32);
            Add(Instruction.StoreShared,              AggregateType.Void,   AggregateType.S32,     AggregateType.U32);
            Add(Instruction.StoreShared16,            AggregateType.Void,   AggregateType.S32,     AggregateType.U32);
            Add(Instruction.StoreShared8,             AggregateType.Void,   AggregateType.S32,     AggregateType.U32);
            Add(Instruction.StoreStorage,             AggregateType.Void,   AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.StoreStorage16,           AggregateType.Void,   AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.StoreStorage8,            AggregateType.Void,   AggregateType.S32,     AggregateType.S32,     AggregateType.U32);
            Add(Instruction.Subtract,                 AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
            Add(Instruction.SwizzleAdd,               AggregateType.FP32,   AggregateType.FP32,    AggregateType.FP32,    AggregateType.S32);
            Add(Instruction.TextureSample,            AggregateType.FP32);
            Add(Instruction.TextureSize,              AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
            Add(Instruction.Truncate,                 AggregateType.Scalar, AggregateType.Scalar);
            Add(Instruction.UnpackDouble2x32,         AggregateType.U32,    AggregateType.FP64);
            Add(Instruction.UnpackHalf2x16,           AggregateType.FP32,   AggregateType.U32);
            Add(Instruction.VectorExtract,            AggregateType.Scalar, AggregateType.Vector4, AggregateType.S32);
            Add(Instruction.VoteAll,                  AggregateType.Bool,   AggregateType.Bool);
            Add(Instruction.VoteAllEqual,             AggregateType.Bool,   AggregateType.Bool);
            Add(Instruction.VoteAny,                  AggregateType.Bool,   AggregateType.Bool);
        }

        private static void Add(Instruction inst, AggregateType destType, params AggregateType[] srcTypes)
        {
            _infoTbl[(int)inst] = new InstInfo(destType, srcTypes);
        }

        public static AggregateType GetDestVarType(Instruction inst)
        {
            return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].DestType, inst);
        }

        public static AggregateType GetSrcVarType(Instruction inst, int index)
        {
            // TODO: Return correct type depending on source index,
            // that can improve the decompiler output.
            if (inst == Instruction.ImageLoad ||
                inst == Instruction.ImageStore ||
                inst == Instruction.ImageAtomic ||
                inst == Instruction.Lod ||
                inst == Instruction.TextureSample)
            {
                return AggregateType.FP32;
            }
            else if (inst == Instruction.Call || inst == Instruction.Load || inst == Instruction.Store)
            {
                return AggregateType.S32;
            }

            return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].SrcTypes[index], inst);
        }

        private static AggregateType GetFinalVarType(AggregateType type, Instruction inst)
        {
            if (type == AggregateType.Scalar)
            {
                if ((inst & Instruction.FP32) != 0)
                {
                    return AggregateType.FP32;
                }
                else if ((inst & Instruction.FP64) != 0)
                {
                    return AggregateType.FP64;
                }
                else
                {
                    return AggregateType.S32;
                }
            }
            else if (type == AggregateType.Void)
            {
                throw new ArgumentException($"Invalid operand for instruction \"{inst}\".");
            }

            return type;
        }

        public static bool IsUnary(Instruction inst)
        {
            if (inst == Instruction.Copy)
            {
                return true;
            }
            else if (inst == Instruction.TextureSample)
            {
                return false;
            }

            return _infoTbl[(int)(inst & Instruction.Mask)].SrcTypes.Length == 1;
        }
    }
}