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