1 //
2 // Copyright (c) 2014 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/BuiltInFunctionEmulatorHLSL.h"
10 #include "compiler/translator/SymbolTable.h"
11 #include "compiler/translator/VersionGLSL.h"
12
13 namespace sh
14 {
15
16 // Defined in emulated_builtin_functions_hlsl_autogen.cpp.
17 const char *FindHLSLFunction(const FunctionId &functionID);
18
InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator * emu,int targetGLSLVersion)19 void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
20 int targetGLSLVersion)
21 {
22 if (targetGLSLVersion < GLSL_VERSION_130)
23 return;
24
25 TType *float1 = new TType(EbtFloat);
26 TType *float2 = new TType(EbtFloat, 2);
27 TType *float3 = new TType(EbtFloat, 3);
28 TType *float4 = new TType(EbtFloat, 4);
29
30 emu->addEmulatedFunction(EOpIsNan, float1,
31 "bool isnan_emu(float x)\n"
32 "{\n"
33 " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
34 "}\n"
35 "\n");
36
37 emu->addEmulatedFunction(
38 EOpIsNan, float2,
39 "bool2 isnan_emu(float2 x)\n"
40 "{\n"
41 " bool2 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
49 emu->addEmulatedFunction(
50 EOpIsNan, float3,
51 "bool3 isnan_emu(float3 x)\n"
52 "{\n"
53 " bool3 isnan;\n"
54 " for (int i = 0; i < 3; i++)\n"
55 " {\n"
56 " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
57 " }\n"
58 " return isnan;\n"
59 "}\n");
60
61 emu->addEmulatedFunction(
62 EOpIsNan, float4,
63 "bool4 isnan_emu(float4 x)\n"
64 "{\n"
65 " bool4 isnan;\n"
66 " for (int i = 0; i < 4; i++)\n"
67 " {\n"
68 " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
69 " }\n"
70 " return isnan;\n"
71 "}\n");
72 }
73
InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator * emu)74 void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
75 {
76 TType *int1 = new TType(EbtInt);
77 TType *int2 = new TType(EbtInt, 2);
78 TType *int3 = new TType(EbtInt, 3);
79 TType *int4 = new TType(EbtInt, 4);
80 TType *uint1 = new TType(EbtUInt);
81 TType *uint2 = new TType(EbtUInt, 2);
82 TType *uint3 = new TType(EbtUInt, 3);
83 TType *uint4 = new TType(EbtUInt, 4);
84
85 emu->addFunctionMap(FindHLSLFunction);
86
87 // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
88 // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
89 // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
90 FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
91 EOpUmulExtended, uint1, uint1, uint1, uint1,
92 "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
93 "{\n"
94 " lsb = x * y;\n"
95 " uint a = (x & 0xffffu);\n"
96 " uint b = (x >> 16);\n"
97 " uint c = (y & 0xffffu);\n"
98 " uint d = (y >> 16);\n"
99 " uint ad = a * d + ((a * c) >> 16);\n"
100 " uint bc = b * c;\n"
101 " uint carry = uint(ad > (0xffffffffu - bc));\n"
102 " msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
103 "}\n");
104 emu->addEmulatedFunctionWithDependency(
105 umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
106 "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
107 "{\n"
108 " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
109 " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
110 "}\n");
111 emu->addEmulatedFunctionWithDependency(
112 umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
113 "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
114 "{\n"
115 " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
116 " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
117 " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
118 "}\n");
119 emu->addEmulatedFunctionWithDependency(
120 umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
121 "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
122 "{\n"
123 " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
124 " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
125 " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
126 " umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
127 "}\n");
128
129 // The imul emulation does two's complement negation on the lsb and msb manually in case the
130 // result needs to be negative.
131 // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
132 // -2^31. abs(-2^31) is undefined.
133 FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
134 umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
135 "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
136 "{\n"
137 " uint unsignedMsb;\n"
138 " uint unsignedLsb;\n"
139 " bool negative = (x < 0) != (y < 0);\n"
140 " umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n"
141 " lsb = asint(unsignedLsb);\n"
142 " msb = asint(unsignedMsb);\n"
143 " if (negative)\n"
144 " {\n"
145 " lsb = ~lsb;\n"
146 " msb = ~msb;\n"
147 " if (lsb == 0xffffffff)\n"
148 " {\n"
149 " lsb = 0;\n"
150 " msb += 1;\n"
151 " }\n"
152 " else\n"
153 " {\n"
154 " lsb += 1;\n"
155 " }\n"
156 " }\n"
157 "}\n");
158 emu->addEmulatedFunctionWithDependency(
159 imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
160 "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
161 "{\n"
162 " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
163 " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
164 "}\n");
165 emu->addEmulatedFunctionWithDependency(
166 imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
167 "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
168 "{\n"
169 " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
170 " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
171 " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
172 "}\n");
173 emu->addEmulatedFunctionWithDependency(
174 imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
175 "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
176 "{\n"
177 " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
178 " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
179 " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
180 " imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
181 "}\n");
182 }
183
184 } // namespace sh
185