|
1 From: Jeff Gilbert <jgilbert@mozilla.com> |
|
2 Bug 771406 - Add emulation for GLSL faceforward() to ANGLE - r=bjacob |
|
3 |
|
4 diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp |
|
5 --- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp |
|
6 +++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp |
|
7 @@ -26,16 +26,22 @@ const char* kFunctionEmulationVertexSour |
|
8 "#error no emulation for distance(vec3, vec3)", |
|
9 "#error no emulation for distance(vec4, vec4)", |
|
10 |
|
11 "#define webgl_dot_emu(x, y) ((x) * (y))", |
|
12 "#error no emulation for dot(vec2, vec2)", |
|
13 "#error no emulation for dot(vec3, vec3)", |
|
14 "#error no emulation for dot(vec4, vec4)", |
|
15 |
|
16 + // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| |
|
17 + "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", |
|
18 + "#error no emulation for faceforward(vec2, vec2, vec2)", |
|
19 + "#error no emulation for faceforward(vec3, vec3, vec3)", |
|
20 + "#error no emulation for faceforward(vec4, vec4, vec4)", |
|
21 + |
|
22 "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", |
|
23 "#error no emulation for length(vec2)", |
|
24 "#error no emulation for length(vec3)", |
|
25 "#error no emulation for length(vec4)", |
|
26 |
|
27 "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", |
|
28 "#error no emulation for normalize(vec2)", |
|
29 "#error no emulation for normalize(vec3)", |
|
30 @@ -58,16 +64,22 @@ const char* kFunctionEmulationFragmentSo |
|
31 "#error no emulation for distance(vec3, vec3)", |
|
32 "#error no emulation for distance(vec4, vec4)", |
|
33 |
|
34 "#define webgl_dot_emu(x, y) ((x) * (y))", |
|
35 "#error no emulation for dot(vec2, vec2)", |
|
36 "#error no emulation for dot(vec3, vec3)", |
|
37 "#error no emulation for dot(vec4, vec4)", |
|
38 |
|
39 + // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| |
|
40 + "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", |
|
41 + "#error no emulation for faceforward(vec2, vec2, vec2)", |
|
42 + "#error no emulation for faceforward(vec3, vec3, vec3)", |
|
43 + "#error no emulation for faceforward(vec4, vec4, vec4)", |
|
44 + |
|
45 "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", |
|
46 "#error no emulation for length(vec2)", |
|
47 "#error no emulation for length(vec3)", |
|
48 "#error no emulation for length(vec4)", |
|
49 |
|
50 "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", |
|
51 "#error no emulation for normalize(vec2)", |
|
52 "#error no emulation for normalize(vec3)", |
|
53 @@ -89,16 +101,20 @@ const bool kFunctionEmulationVertexMask[ |
|
54 true, // TFunctionDistance1_1 |
|
55 false, // TFunctionDistance2_2 |
|
56 false, // TFunctionDistance3_3 |
|
57 false, // TFunctionDistance4_4 |
|
58 true, // TFunctionDot1_1 |
|
59 false, // TFunctionDot2_2 |
|
60 false, // TFunctionDot3_3 |
|
61 false, // TFunctionDot4_4 |
|
62 + true, // TFunctionFaceForward1_1_1 |
|
63 + false, // TFunctionFaceForward2_2_2 |
|
64 + false, // TFunctionFaceForward3_3_3 |
|
65 + false, // TFunctionFaceForward4_4_4 |
|
66 true, // TFunctionLength1 |
|
67 false, // TFunctionLength2 |
|
68 false, // TFunctionLength3 |
|
69 false, // TFunctionLength4 |
|
70 true, // TFunctionNormalize1 |
|
71 false, // TFunctionNormalize2 |
|
72 false, // TFunctionNormalize3 |
|
73 false, // TFunctionNormalize4 |
|
74 @@ -115,16 +131,20 @@ const bool kFunctionEmulationVertexMask[ |
|
75 false, // TFunctionDistance1_1 |
|
76 false, // TFunctionDistance2_2 |
|
77 false, // TFunctionDistance3_3 |
|
78 false, // TFunctionDistance4_4 |
|
79 false, // TFunctionDot1_1 |
|
80 false, // TFunctionDot2_2 |
|
81 false, // TFunctionDot3_3 |
|
82 false, // TFunctionDot4_4 |
|
83 + false, // TFunctionFaceForward1_1_1 |
|
84 + false, // TFunctionFaceForward2_2_2 |
|
85 + false, // TFunctionFaceForward3_3_3 |
|
86 + false, // TFunctionFaceForward4_4_4 |
|
87 false, // TFunctionLength1 |
|
88 false, // TFunctionLength2 |
|
89 false, // TFunctionLength3 |
|
90 false, // TFunctionLength4 |
|
91 false, // TFunctionNormalize1 |
|
92 false, // TFunctionNormalize2 |
|
93 false, // TFunctionNormalize3 |
|
94 false, // TFunctionNormalize4 |
|
95 @@ -146,16 +166,20 @@ const bool kFunctionEmulationFragmentMas |
|
96 true, // TFunctionDistance1_1 |
|
97 false, // TFunctionDistance2_2 |
|
98 false, // TFunctionDistance3_3 |
|
99 false, // TFunctionDistance4_4 |
|
100 true, // TFunctionDot1_1 |
|
101 false, // TFunctionDot2_2 |
|
102 false, // TFunctionDot3_3 |
|
103 false, // TFunctionDot4_4 |
|
104 + true, // TFunctionFaceForward1_1_1 |
|
105 + false, // TFunctionFaceForward2_2_2 |
|
106 + false, // TFunctionFaceForward3_3_3 |
|
107 + false, // TFunctionFaceForward4_4_4 |
|
108 true, // TFunctionLength1 |
|
109 false, // TFunctionLength2 |
|
110 false, // TFunctionLength3 |
|
111 false, // TFunctionLength4 |
|
112 true, // TFunctionNormalize1 |
|
113 false, // TFunctionNormalize2 |
|
114 false, // TFunctionNormalize3 |
|
115 false, // TFunctionNormalize4 |
|
116 @@ -172,16 +196,20 @@ const bool kFunctionEmulationFragmentMas |
|
117 false, // TFunctionDistance1_1 |
|
118 false, // TFunctionDistance2_2 |
|
119 false, // TFunctionDistance3_3 |
|
120 false, // TFunctionDistance4_4 |
|
121 false, // TFunctionDot1_1 |
|
122 false, // TFunctionDot2_2 |
|
123 false, // TFunctionDot3_3 |
|
124 false, // TFunctionDot4_4 |
|
125 + false, // TFunctionFaceForward1_1_1 |
|
126 + false, // TFunctionFaceForward2_2_2 |
|
127 + false, // TFunctionFaceForward3_3_3 |
|
128 + false, // TFunctionFaceForward4_4_4 |
|
129 false, // TFunctionLength1 |
|
130 false, // TFunctionLength2 |
|
131 false, // TFunctionLength3 |
|
132 false, // TFunctionLength4 |
|
133 false, // TFunctionNormalize1 |
|
134 false, // TFunctionNormalize2 |
|
135 false, // TFunctionNormalize3 |
|
136 false, // TFunctionNormalize4 |
|
137 @@ -239,25 +267,37 @@ public: |
|
138 case EOpReflect: |
|
139 case EOpRefract: |
|
140 case EOpMul: |
|
141 break; |
|
142 default: |
|
143 return true; |
|
144 }; |
|
145 const TIntermSequence& sequence = node->getSequence(); |
|
146 - // Right now we only handle built-in functions with two parameters. |
|
147 - if (sequence.size() != 2) |
|
148 + bool needToEmulate = false; |
|
149 + |
|
150 + if (sequence.size() == 2) { |
|
151 + TIntermTyped* param1 = sequence[0]->getAsTyped(); |
|
152 + TIntermTyped* param2 = sequence[1]->getAsTyped(); |
|
153 + if (!param1 || !param2) |
|
154 + return true; |
|
155 + needToEmulate = mEmulator.SetFunctionCalled( |
|
156 + node->getOp(), param1->getType(), param2->getType()); |
|
157 + } else if (sequence.size() == 3) { |
|
158 + TIntermTyped* param1 = sequence[0]->getAsTyped(); |
|
159 + TIntermTyped* param2 = sequence[1]->getAsTyped(); |
|
160 + TIntermTyped* param3 = sequence[2]->getAsTyped(); |
|
161 + if (!param1 || !param2 || !param3) |
|
162 + return true; |
|
163 + needToEmulate = mEmulator.SetFunctionCalled( |
|
164 + node->getOp(), param1->getType(), param2->getType(), param3->getType()); |
|
165 + } else { |
|
166 return true; |
|
167 - TIntermTyped* param1 = sequence[0]->getAsTyped(); |
|
168 - TIntermTyped* param2 = sequence[1]->getAsTyped(); |
|
169 - if (!param1 || !param2) |
|
170 - return true; |
|
171 - bool needToEmulate = mEmulator.SetFunctionCalled( |
|
172 - node->getOp(), param1->getType(), param2->getType()); |
|
173 + } |
|
174 + |
|
175 if (needToEmulate) |
|
176 node->setUseEmulatedFunction(); |
|
177 } |
|
178 return true; |
|
179 } |
|
180 |
|
181 private: |
|
182 BuiltInFunctionEmulator& mEmulator; |
|
183 @@ -286,16 +326,23 @@ bool BuiltInFunctionEmulator::SetFunctio |
|
184 bool BuiltInFunctionEmulator::SetFunctionCalled( |
|
185 TOperator op, const TType& param1, const TType& param2) |
|
186 { |
|
187 TBuiltInFunction function = IdentifyFunction(op, param1, param2); |
|
188 return SetFunctionCalled(function); |
|
189 } |
|
190 |
|
191 bool BuiltInFunctionEmulator::SetFunctionCalled( |
|
192 + TOperator op, const TType& param1, const TType& param2, const TType& param3) |
|
193 +{ |
|
194 + TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3); |
|
195 + return SetFunctionCalled(function); |
|
196 +} |
|
197 + |
|
198 +bool BuiltInFunctionEmulator::SetFunctionCalled( |
|
199 BuiltInFunctionEmulator::TBuiltInFunction function) { |
|
200 if (function == TFunctionUnknown || mFunctionMask[function] == false) |
|
201 return false; |
|
202 for (size_t i = 0; i < mFunctions.size(); ++i) { |
|
203 if (mFunctions[i] == function) |
|
204 return true; |
|
205 } |
|
206 mFunctions.push_back(function); |
|
207 @@ -377,16 +424,44 @@ BuiltInFunctionEmulator::IdentifyFunctio |
|
208 } |
|
209 if (function == TFunctionUnknown) |
|
210 return TFunctionUnknown; |
|
211 if (param1.isVector()) |
|
212 function += param1.getNominalSize() - 1; |
|
213 return static_cast<TBuiltInFunction>(function); |
|
214 } |
|
215 |
|
216 +BuiltInFunctionEmulator::TBuiltInFunction |
|
217 +BuiltInFunctionEmulator::IdentifyFunction( |
|
218 + TOperator op, const TType& param1, const TType& param2, const TType& param3) |
|
219 +{ |
|
220 + // Check that all params have the same type, length, |
|
221 + // and that they're not too large. |
|
222 + if (param1.isVector() != param2.isVector() || |
|
223 + param2.isVector() != param3.isVector() || |
|
224 + param1.getNominalSize() != param2.getNominalSize() || |
|
225 + param2.getNominalSize() != param3.getNominalSize() || |
|
226 + param1.getNominalSize() > 4) |
|
227 + return TFunctionUnknown; |
|
228 + |
|
229 + unsigned int function = TFunctionUnknown; |
|
230 + switch (op) { |
|
231 + case EOpFaceForward: |
|
232 + function = TFunctionFaceForward1_1_1; |
|
233 + break; |
|
234 + default: |
|
235 + break; |
|
236 + } |
|
237 + if (function == TFunctionUnknown) |
|
238 + return TFunctionUnknown; |
|
239 + if (param1.isVector()) |
|
240 + function += param1.getNominalSize() - 1; |
|
241 + return static_cast<TBuiltInFunction>(function); |
|
242 +} |
|
243 + |
|
244 void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( |
|
245 TIntermNode* root) |
|
246 { |
|
247 ASSERT(root); |
|
248 |
|
249 BuiltInFunctionEmulationMarker marker(*this); |
|
250 root->traverse(&marker); |
|
251 } |
|
252 diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h |
|
253 --- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h |
|
254 +++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h |
|
255 @@ -23,16 +23,18 @@ public: |
|
256 // Records that a function is called by the shader and might needs to be |
|
257 // emulated. If the function's group is not in mFunctionGroupFilter, this |
|
258 // becomes an no-op. |
|
259 // Returns true if the function call needs to be replaced with an emulated |
|
260 // one. |
|
261 bool SetFunctionCalled(TOperator op, const TType& param); |
|
262 bool SetFunctionCalled( |
|
263 TOperator op, const TType& param1, const TType& param2); |
|
264 + bool SetFunctionCalled( |
|
265 + TOperator op, const TType& param1, const TType& param2, const TType& param3); |
|
266 |
|
267 // Output function emulation definition. This should be before any other |
|
268 // shader source. |
|
269 void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const; |
|
270 |
|
271 void MarkBuiltInFunctionsForEmulation(TIntermNode* root); |
|
272 |
|
273 void Cleanup(); |
|
274 @@ -55,16 +57,21 @@ private: |
|
275 TFunctionDistance3_3, // vec3 distance(vec3, vec3); |
|
276 TFunctionDistance4_4, // vec4 distance(vec4, vec4); |
|
277 |
|
278 TFunctionDot1_1, // float dot(float, float); |
|
279 TFunctionDot2_2, // vec2 dot(vec2, vec2); |
|
280 TFunctionDot3_3, // vec3 dot(vec3, vec3); |
|
281 TFunctionDot4_4, // vec4 dot(vec4, vec4); |
|
282 |
|
283 + TFunctionFaceForward1_1_1, // float faceforward(float, float, float); |
|
284 + TFunctionFaceForward2_2_2, // vec2 faceforward(vec2, vec2, vec2); |
|
285 + TFunctionFaceForward3_3_3, // vec3 faceforward(vec3, vec3, vec3); |
|
286 + TFunctionFaceForward4_4_4, // vec4 faceforward(vec4, vec4, vec4); |
|
287 + |
|
288 TFunctionLength1, // float length(float); |
|
289 TFunctionLength2, // float length(vec2); |
|
290 TFunctionLength3, // float length(vec3); |
|
291 TFunctionLength4, // float length(vec4); |
|
292 |
|
293 TFunctionNormalize1, // float normalize(float); |
|
294 TFunctionNormalize2, // vec2 normalize(vec2); |
|
295 TFunctionNormalize3, // vec3 normalize(vec3); |
|
296 @@ -76,16 +83,18 @@ private: |
|
297 TFunctionReflect4_4, // vec4 reflect(vec4, vec4); |
|
298 |
|
299 TFunctionUnknown |
|
300 }; |
|
301 |
|
302 TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); |
|
303 TBuiltInFunction IdentifyFunction( |
|
304 TOperator op, const TType& param1, const TType& param2); |
|
305 + TBuiltInFunction IdentifyFunction( |
|
306 + TOperator op, const TType& param1, const TType& param2, const TType& param3); |
|
307 |
|
308 bool SetFunctionCalled(TBuiltInFunction function); |
|
309 |
|
310 std::vector<TBuiltInFunction> mFunctions; |
|
311 |
|
312 const bool* mFunctionMask; // a boolean flag for each function. |
|
313 const char** mFunctionSource; |
|
314 }; |