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