Line data Source code
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 :
17 0 : void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
18 : sh::GLenum shaderType)
19 : {
20 0 : if (shaderType == GL_VERTEX_SHADER)
21 : {
22 0 : const TType *int1 = TCache::getType(EbtInt);
23 0 : emu->addEmulatedFunction(EOpAbs, int1, "int webgl_abs_emu(int x) { return x * sign(x); }");
24 : }
25 0 : }
26 :
27 0 : void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
28 : int targetGLSLVersion)
29 : {
30 : // isnan() is supported since GLSL 1.3.
31 0 : if (targetGLSLVersion < GLSL_VERSION_130)
32 0 : return;
33 :
34 0 : const TType *float1 = TCache::getType(EbtFloat);
35 0 : const TType *float2 = TCache::getType(EbtFloat, 2);
36 0 : const TType *float3 = TCache::getType(EbtFloat, 3);
37 0 : 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 0 : "bool webgl_isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
43 : emu->addEmulatedFunction(
44 : EOpIsNan, float2,
45 : "bvec2 webgl_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 0 : "}\n");
54 : emu->addEmulatedFunction(
55 : EOpIsNan, float3,
56 : "bvec3 webgl_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 0 : "}\n");
65 : emu->addEmulatedFunction(
66 : EOpIsNan, float4,
67 : "bvec4 webgl_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 0 : "}\n");
76 0 : emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1, "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))");
77 :
78 : }
79 :
80 : // Emulate built-in functions missing from GLSL 1.30 and higher
81 0 : void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, sh::GLenum shaderType,
82 : int targetGLSLVersion)
83 : {
84 : // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
85 0 : if (targetGLSLVersion < GLSL_VERSION_410)
86 : {
87 0 : const TType *float2 = TCache::getType(EbtFloat, 2);
88 0 : const TType *uint1 = TCache::getType(EbtUInt);
89 :
90 : // clang-format off
91 : emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
92 : "uint webgl_packUnorm2x16_emu(vec2 v)\n"
93 : "{\n"
94 : " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
95 : " int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
96 : " return uint((y << 16) | (x & 0xFFFF));\n"
97 0 : "}\n");
98 :
99 : emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
100 : "vec2 webgl_unpackUnorm2x16_emu(uint u)\n"
101 : "{\n"
102 : " float x = float(u & 0xFFFFu) / 65535.0;\n"
103 : " float y = float(u >> 16) / 65535.0;\n"
104 : " return vec2(x, y);\n"
105 0 : "}\n");
106 : // clang-format on
107 : }
108 :
109 : // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
110 : // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
111 0 : if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
112 : {
113 0 : const TType *float2 = TCache::getType(EbtFloat, 2);
114 0 : const TType *uint1 = TCache::getType(EbtUInt);
115 :
116 : // clang-format off
117 : emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
118 : "uint webgl_packSnorm2x16_emu(vec2 v)\n"
119 : "{\n"
120 : " #if defined(GL_ARB_shading_language_packing)\n"
121 : " return packSnorm2x16(v);\n"
122 : " #else\n"
123 : " int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
124 : " int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
125 : " return uint((y << 16) | (x & 0xFFFF));\n"
126 : " #endif\n"
127 0 : "}\n");
128 : emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
129 : "#if !defined(GL_ARB_shading_language_packing)\n"
130 : " float webgl_fromSnorm(uint x)\n"
131 : " {\n"
132 : " int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
133 : " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
134 : " }\n"
135 : "#endif\n"
136 : "\n"
137 : "vec2 webgl_unpackSnorm2x16_emu(uint u)\n"
138 : "{\n"
139 : " #if defined(GL_ARB_shading_language_packing)\n"
140 : " return unpackSnorm2x16(u);\n"
141 : " #else\n"
142 : " uint y = (u >> 16);\n"
143 : " uint x = u;\n"
144 : " return vec2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
145 : " #endif\n"
146 0 : "}\n");
147 : // Functions uint webgl_f32tof16(float val) and float webgl_f16tof32(uint val) are
148 : // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
149 : emu->addEmulatedFunction(EOpPackHalf2x16, float2,
150 : "#if !defined(GL_ARB_shading_language_packing)\n"
151 : " uint webgl_f32tof16(float val)\n"
152 : " {\n"
153 : " uint f32 = floatBitsToUint(val);\n"
154 : " uint f16 = 0u;\n"
155 : " uint sign = (f32 >> 16) & 0x8000u;\n"
156 : " int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
157 : " uint mantissa = f32 & 0x007FFFFFu;\n"
158 : " if (exponent == 128)\n"
159 : " {\n"
160 : " // Infinity or NaN\n"
161 : " // NaN bits that are masked out by 0x3FF get discarded.\n"
162 : " // This can turn some NaNs to infinity, but this is allowed by the spec.\n"
163 : " f16 = sign | (0x1Fu << 10);\n"
164 : " f16 |= (mantissa & 0x3FFu);\n"
165 : " }\n"
166 : " else if (exponent > 15)\n"
167 : " {\n"
168 : " // Overflow - flush to Infinity\n"
169 : " f16 = sign | (0x1Fu << 10);\n"
170 : " }\n"
171 : " else if (exponent > -15)\n"
172 : " {\n"
173 : " // Representable value\n"
174 : " exponent += 15;\n"
175 : " mantissa >>= 13;\n"
176 : " f16 = sign | uint(exponent << 10) | mantissa;\n"
177 : " }\n"
178 : " else\n"
179 : " {\n"
180 : " f16 = sign;\n"
181 : " }\n"
182 : " return f16;\n"
183 : " }\n"
184 : "#endif\n"
185 : "\n"
186 : "uint webgl_packHalf2x16_emu(vec2 v)\n"
187 : "{\n"
188 : " #if defined(GL_ARB_shading_language_packing)\n"
189 : " return packHalf2x16(v);\n"
190 : " #else\n"
191 : " uint x = webgl_f32tof16(v.x);\n"
192 : " uint y = webgl_f32tof16(v.y);\n"
193 : " return (y << 16) | x;\n"
194 : " #endif\n"
195 0 : "}\n");
196 : emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
197 : "#if !defined(GL_ARB_shading_language_packing)\n"
198 : " float webgl_f16tof32(uint val)\n"
199 : " {\n"
200 : " uint sign = (val & 0x8000u) << 16;\n"
201 : " int exponent = int((val & 0x7C00u) >> 10);\n"
202 : " uint mantissa = val & 0x03FFu;\n"
203 : " float f32 = 0.0;\n"
204 : " if(exponent == 0)\n"
205 : " {\n"
206 : " if (mantissa != 0u)\n"
207 : " {\n"
208 : " const float scale = 1.0 / (1 << 24);\n"
209 : " f32 = scale * mantissa;\n"
210 : " }\n"
211 : " }\n"
212 : " else if (exponent == 31)\n"
213 : " {\n"
214 : " return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n"
215 : " }\n"
216 : " else\n"
217 : " {\n"
218 : " exponent -= 15;\n"
219 : " float scale;\n"
220 : " if(exponent < 0)\n"
221 : " {\n"
222 : " // The negative unary operator is buggy on OSX.\n"
223 : " // Work around this by using abs instead.\n"
224 : " scale = 1.0 / (1 << abs(exponent));\n"
225 : " }\n"
226 : " else\n"
227 : " {\n"
228 : " scale = 1 << exponent;\n"
229 : " }\n"
230 : " float decimal = 1.0 + float(mantissa) / float(1 << 10);\n"
231 : " f32 = scale * decimal;\n"
232 : " }\n"
233 : "\n"
234 : " if (sign != 0u)\n"
235 : " {\n"
236 : " f32 = -f32;\n"
237 : " }\n"
238 : "\n"
239 : " return f32;\n"
240 : " }\n"
241 : "#endif\n"
242 : "\n"
243 : "vec2 webgl_unpackHalf2x16_emu(uint u)\n"
244 : "{\n"
245 : " #if defined(GL_ARB_shading_language_packing)\n"
246 : " return unpackHalf2x16(u);\n"
247 : " #else\n"
248 : " uint y = (u >> 16);\n"
249 : " uint x = u & 0xFFFFu;\n"
250 : " return vec2(webgl_f16tof32(x), webgl_f16tof32(y));\n"
251 : " #endif\n"
252 0 : "}\n");
253 : // clang-format on
254 : }
255 0 : }
256 :
257 : } // namespace sh
|