1 //
2 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "angle_gl.h"
8 #include "compiler/translator/BuiltInFunctionEmulator.h"
9 #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
10 #include "compiler/translator/Cache.h"
11 #include "compiler/translator/SymbolTable.h"
12 #include "compiler/translator/VersionGLSL.h"
13
14 namespace sh
15 {
16
InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator * emu,sh::GLenum shaderType)17 void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
18 sh::GLenum shaderType)
19 {
20 if (shaderType == GL_VERTEX_SHADER)
21 {
22 const TType *int1 = TCache::getType(EbtInt);
23 emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
24 }
25 }
26
InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator * emu,int targetGLSLVersion)27 void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
28 int targetGLSLVersion)
29 {
30 // isnan() is supported since GLSL 1.3.
31 if (targetGLSLVersion < GLSL_VERSION_130)
32 return;
33
34 const TType *float1 = TCache::getType(EbtFloat);
35 const TType *float2 = TCache::getType(EbtFloat, 2);
36 const TType *float3 = TCache::getType(EbtFloat, 3);
37 const TType *float4 = TCache::getType(EbtFloat, 4);
38
39 // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
40 emu->addEmulatedFunction(
41 EOpIsNan, float1,
42 "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
43 emu->addEmulatedFunction(
44 EOpIsNan, float2,
45 "bvec2 isnan_emu(vec2 x)\n"
46 "{\n"
47 " bvec2 isnan;\n"
48 " for (int i = 0; i < 2; i++)\n"
49 " {\n"
50 " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
51 " }\n"
52 " return isnan;\n"
53 "}\n");
54 emu->addEmulatedFunction(
55 EOpIsNan, float3,
56 "bvec3 isnan_emu(vec3 x)\n"
57 "{\n"
58 " bvec3 isnan;\n"
59 " for (int i = 0; i < 3; i++)\n"
60 " {\n"
61 " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
62 " }\n"
63 " return isnan;\n"
64 "}\n");
65 emu->addEmulatedFunction(
66 EOpIsNan, float4,
67 "bvec4 isnan_emu(vec4 x)\n"
68 "{\n"
69 " bvec4 isnan;\n"
70 " for (int i = 0; i < 4; i++)\n"
71 " {\n"
72 " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
73 " }\n"
74 " return isnan;\n"
75 "}\n");
76 }
77
InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator * emu)78 void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
79 {
80 const TType *float1 = TCache::getType(EbtFloat);
81 auto floatFuncId = emu->addEmulatedFunction(
82 EOpAtan, float1, float1,
83 "emu_precision float atan_emu(emu_precision float y, emu_precision "
84 "float x)\n"
85 "{\n"
86 " if (x > 0.0) return atan(y / x);\n"
87 " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
88 " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
89 " else return 1.57079632 * sign(y);\n"
90 "}\n");
91 for (int dim = 2; dim <= 4; ++dim)
92 {
93 const TType *floatVec = TCache::getType(EbtFloat, static_cast<unsigned char>(dim));
94 std::stringstream ss;
95 ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
96 << " y, emu_precision vec" << dim << " x)\n"
97 << "{\n"
98 " return vec"
99 << dim << "(";
100 for (int i = 0; i < dim; ++i)
101 {
102 ss << "atan_emu(y[" << i << "], x[" << i << "])";
103 if (i < dim - 1)
104 {
105 ss << ", ";
106 }
107 }
108 ss << ");\n"
109 "}\n";
110 emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
111 ss.str().c_str());
112 }
113 }
114
115 // Emulate built-in functions missing from GLSL 1.30 and higher
InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator * emu,sh::GLenum shaderType,int targetGLSLVersion)116 void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
117 sh::GLenum shaderType,
118 int targetGLSLVersion)
119 {
120 // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
121 if (targetGLSLVersion < GLSL_VERSION_410)
122 {
123 const TType *float2 = TCache::getType(EbtFloat, 2);
124 const TType *uint1 = TCache::getType(EbtUInt);
125
126 // clang-format off
127 emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
128 "uint packUnorm2x16_emu(vec2 v)\n"
129 "{\n"
130 " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
131 " int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
132 " return uint((y << 16) | (x & 0xFFFF));\n"
133 "}\n");
134
135 emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
136 "vec2 unpackUnorm2x16_emu(uint u)\n"
137 "{\n"
138 " float x = float(u & 0xFFFFu) / 65535.0;\n"
139 " float y = float(u >> 16) / 65535.0;\n"
140 " return vec2(x, y);\n"
141 "}\n");
142 // clang-format on
143 }
144
145 // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
146 // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
147 if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
148 {
149 const TType *float2 = TCache::getType(EbtFloat, 2);
150 const TType *uint1 = TCache::getType(EbtUInt);
151
152 // clang-format off
153 emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
154 "uint packSnorm2x16_emu(vec2 v)\n"
155 "{\n"
156 " #if defined(GL_ARB_shading_language_packing)\n"
157 " return packSnorm2x16(v);\n"
158 " #else\n"
159 " int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
160 " int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
161 " return uint((y << 16) | (x & 0xFFFF));\n"
162 " #endif\n"
163 "}\n");
164 emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
165 "#if !defined(GL_ARB_shading_language_packing)\n"
166 " float fromSnorm(uint x)\n"
167 " {\n"
168 " int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
169 " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
170 " }\n"
171 "#endif\n"
172 "\n"
173 "vec2 unpackSnorm2x16_emu(uint u)\n"
174 "{\n"
175 " #if defined(GL_ARB_shading_language_packing)\n"
176 " return unpackSnorm2x16(u);\n"
177 " #else\n"
178 " uint y = (u >> 16);\n"
179 " uint x = u;\n"
180 " return vec2(fromSnorm(x), fromSnorm(y));\n"
181 " #endif\n"
182 "}\n");
183 // Functions uint f32tof16(float val) and float f16tof32(uint val) are
184 // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
185 emu->addEmulatedFunction(EOpPackHalf2x16, float2,
186 "#if !defined(GL_ARB_shading_language_packing)\n"
187 " uint f32tof16(float val)\n"
188 " {\n"
189 " uint f32 = floatBitsToUint(val);\n"
190 " uint f16 = 0u;\n"
191 " uint sign = (f32 >> 16) & 0x8000u;\n"
192 " int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
193 " uint mantissa = f32 & 0x007FFFFFu;\n"
194 " if (exponent == 128)\n"
195 " {\n"
196 " // Infinity or NaN\n"
197 " // NaN bits that are masked out by 0x3FF get discarded.\n"
198 " // This can turn some NaNs to infinity, but this is allowed by the spec.\n"
199 " f16 = sign | (0x1Fu << 10);\n"
200 " f16 |= (mantissa & 0x3FFu);\n"
201 " }\n"
202 " else if (exponent > 15)\n"
203 " {\n"
204 " // Overflow - flush to Infinity\n"
205 " f16 = sign | (0x1Fu << 10);\n"
206 " }\n"
207 " else if (exponent > -15)\n"
208 " {\n"
209 " // Representable value\n"
210 " exponent += 15;\n"
211 " mantissa >>= 13;\n"
212 " f16 = sign | uint(exponent << 10) | mantissa;\n"
213 " }\n"
214 " else\n"
215 " {\n"
216 " f16 = sign;\n"
217 " }\n"
218 " return f16;\n"
219 " }\n"
220 "#endif\n"
221 "\n"
222 "uint packHalf2x16_emu(vec2 v)\n"
223 "{\n"
224 " #if defined(GL_ARB_shading_language_packing)\n"
225 " return packHalf2x16(v);\n"
226 " #else\n"
227 " uint x = f32tof16(v.x);\n"
228 " uint y = f32tof16(v.y);\n"
229 " return (y << 16) | x;\n"
230 " #endif\n"
231 "}\n");
232 emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
233 "#if !defined(GL_ARB_shading_language_packing)\n"
234 " float f16tof32(uint val)\n"
235 " {\n"
236 " uint sign = (val & 0x8000u) << 16;\n"
237 " int exponent = int((val & 0x7C00u) >> 10);\n"
238 " uint mantissa = val & 0x03FFu;\n"
239 " float f32 = 0.0;\n"
240 " if(exponent == 0)\n"
241 " {\n"
242 " if (mantissa != 0u)\n"
243 " {\n"
244 " const float scale = 1.0 / (1 << 24);\n"
245 " f32 = scale * mantissa;\n"
246 " }\n"
247 " }\n"
248 " else if (exponent == 31)\n"
249 " {\n"
250 " return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n"
251 " }\n"
252 " else\n"
253 " {\n"
254 " exponent -= 15;\n"
255 " float scale;\n"
256 " if(exponent < 0)\n"
257 " {\n"
258 " // The negative unary operator is buggy on OSX.\n"
259 " // Work around this by using abs instead.\n"
260 " scale = 1.0 / (1 << abs(exponent));\n"
261 " }\n"
262 " else\n"
263 " {\n"
264 " scale = 1 << exponent;\n"
265 " }\n"
266 " float decimal = 1.0 + float(mantissa) / float(1 << 10);\n"
267 " f32 = scale * decimal;\n"
268 " }\n"
269 "\n"
270 " if (sign != 0u)\n"
271 " {\n"
272 " f32 = -f32;\n"
273 " }\n"
274 "\n"
275 " return f32;\n"
276 " }\n"
277 "#endif\n"
278 "\n"
279 "vec2 unpackHalf2x16_emu(uint u)\n"
280 "{\n"
281 " #if defined(GL_ARB_shading_language_packing)\n"
282 " return unpackHalf2x16(u);\n"
283 " #else\n"
284 " uint y = (u >> 16);\n"
285 " uint x = u & 0xFFFFu;\n"
286 " return vec2(f16tof32(x), f16tof32(y));\n"
287 " #endif\n"
288 "}\n");
289 // clang-format on
290 }
291 }
292
293 } // namespace sh
294