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
|
using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation
{
class EmitterContext
{
public Block CurrBlock { get; set; }
public OpCode CurrOp { get; set; }
public ShaderConfig Config { get; }
public bool IsNonMain { get; }
private readonly IReadOnlyDictionary<ulong, int> _funcs;
private readonly List<Operation> _operations;
private readonly Dictionary<ulong, Operand> _labels;
public EmitterContext(ShaderConfig config, bool isNonMain, IReadOnlyDictionary<ulong, int> funcs)
{
Config = config;
IsNonMain = isNonMain;
_funcs = funcs;
_operations = new List<Operation>();
_labels = new Dictionary<ulong, Operand>();
}
public Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
{
Operation operation = new Operation(inst, dest, sources);
Add(operation);
return dest;
}
public void Add(Operation operation)
{
_operations.Add(operation);
}
public void FlagAttributeRead(int attribute)
{
if (Config.Stage == ShaderStage.Fragment)
{
switch (attribute)
{
case AttributeConsts.PositionX:
case AttributeConsts.PositionY:
Config.SetUsedFeature(FeatureFlags.FragCoordXY);
break;
}
}
}
public void MarkLabel(Operand label)
{
Add(Instruction.MarkLabel, label);
}
public Operand GetLabel(ulong address)
{
if (!_labels.TryGetValue(address, out Operand label))
{
label = Label();
_labels.Add(address, label);
}
return label;
}
public int GetFunctionId(ulong address)
{
return _funcs[address];
}
public void PrepareForReturn()
{
if (Config.Stage == ShaderStage.Fragment)
{
if (Config.OmapDepth)
{
Operand dest = Attribute(AttributeConsts.FragmentOutputDepth);
Operand src = Register(Config.GetDepthRegister(), RegisterType.Gpr);
this.Copy(dest, src);
}
int regIndexBase = 0;
for (int rtIndex = 0; rtIndex < 8; rtIndex++)
{
OmapTarget target = Config.OmapTargets[rtIndex];
for (int component = 0; component < 4; component++)
{
if (!target.ComponentEnabled(component))
{
continue;
}
int fragmentOutputColorAttr = AttributeConsts.FragmentOutputColorBase + rtIndex * 16;
Operand src = Register(regIndexBase + component, RegisterType.Gpr);
// Perform B <-> R swap if needed, for BGRA formats (not supported on OpenGL).
if (component == 0 || component == 2)
{
Operand isBgra = Attribute(AttributeConsts.FragmentOutputIsBgraBase + rtIndex * 4);
Operand lblIsBgra = Label();
Operand lblEnd = Label();
this.BranchIfTrue(lblIsBgra, isBgra);
this.Copy(Attribute(fragmentOutputColorAttr + component * 4), src);
this.Branch(lblEnd);
MarkLabel(lblIsBgra);
this.Copy(Attribute(fragmentOutputColorAttr + (2 - component) * 4), src);
MarkLabel(lblEnd);
}
else
{
this.Copy(Attribute(fragmentOutputColorAttr + component * 4), src);
}
}
if (target.Enabled)
{
regIndexBase += 4;
}
}
}
}
public Operation[] GetOperations()
{
return _operations.ToArray();
}
}
}
|