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