1 // GENERATED FILE - DO NOT EDIT.
2 // Generated by gen_emulated_builtin_function_tables.py using data from
3 // emulated_builtin_function_data_hlsl.json.
4 //
5 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file.
8 //
9 // emulated_builtin_functions_hlsl:
10 // HLSL code for emulating GLSL builtin functions not present in HLSL.
11
12 #include "compiler/translator/BuiltInFunctionEmulator.h"
13 #include "compiler/translator/tree_util/BuiltIn.h"
14
15 namespace sh
16 {
17
18 namespace
19 {
20
21 struct FunctionPair
22 {
FunctionPairsh::__anond786d8ad0111::FunctionPair23 constexpr FunctionPair(const TSymbolUniqueId &idIn, const char *bodyIn)
24 : id(idIn.get()), body(bodyIn)
25 {}
26
27 int id;
28 const char *body;
29 };
30
31 constexpr FunctionPair g_hlslFunctions[] = {
32 {BuiltInId::mod_Float1_Float1,
33 "float mod_emu(float x, float y)\n"
34 "{\n"
35 " return x - y * floor(x / y);\n"
36 "}\n"},
37 {BuiltInId::mod_Float2_Float2,
38 "float2 mod_emu(float2 x, float2 y)\n"
39 "{\n"
40 " return x - y * floor(x / y);\n"
41 "}\n"},
42 {BuiltInId::mod_Float2_Float1,
43 "float2 mod_emu(float2 x, float y)\n"
44 "{\n"
45 " return x - y * floor(x / y);\n"
46 "}\n"},
47 {BuiltInId::mod_Float3_Float3,
48 "float3 mod_emu(float3 x, float3 y)\n"
49 "{\n"
50 " return x - y * floor(x / y);\n"
51 "}\n"},
52 {BuiltInId::mod_Float3_Float1,
53 "float3 mod_emu(float3 x, float y)\n"
54 "{\n"
55 " return x - y * floor(x / y);\n"
56 "}\n"},
57 {BuiltInId::mod_Float4_Float4,
58 "float4 mod_emu(float4 x, float4 y)\n"
59 "{\n"
60 " return x - y * floor(x / y);\n"
61 "}\n"},
62 {BuiltInId::mod_Float4_Float1,
63 "float4 mod_emu(float4 x, float y)\n"
64 "{\n"
65 " return x - y * floor(x / y);\n"
66 "}\n"},
67 {BuiltInId::frexp_Float1_Int1,
68 "float frexp_emu(float x, out int exp)\n"
69 "{\n"
70 " float fexp;\n"
71 " float mantissa = frexp(abs(x), fexp) * sign(x);\n"
72 " exp = int(fexp);\n"
73 " return mantissa;\n"
74 "}\n"},
75 {BuiltInId::frexp_Float2_Int2,
76 "float2 frexp_emu(float2 x, out int2 exp)\n"
77 "{\n"
78 " float2 fexp;\n"
79 " float2 mantissa = frexp(abs(x), fexp) * sign(x);\n"
80 " exp = int2(fexp);\n"
81 " return mantissa;\n"
82 "}\n"},
83 {BuiltInId::frexp_Float3_Int3,
84 "float3 frexp_emu(float3 x, out int3 exp)\n"
85 "{\n"
86 " float3 fexp;\n"
87 " float3 mantissa = frexp(abs(x), fexp) * sign(x);\n"
88 " exp = int3(fexp);\n"
89 " return mantissa;\n"
90 "}\n"},
91 {BuiltInId::frexp_Float4_Int4,
92 "float4 frexp_emu(float4 x, out int4 exp)\n"
93 "{\n"
94 " float4 fexp;\n"
95 " float4 mantissa = frexp(abs(x), fexp) * sign(x);\n"
96 " exp = int4(fexp);\n"
97 " return mantissa;\n"
98 "}\n"},
99 {BuiltInId::ldexp_Float1_Int1,
100 "float ldexp_emu(float x, int exp)\n"
101 "{\n"
102 " return ldexp(x, float(exp));\n"
103 "}\n"},
104 {BuiltInId::ldexp_Float2_Int2,
105 "float2 ldexp_emu(float2 x, int2 exp)\n"
106 "{\n"
107 " return ldexp(x, float2(exp));\n"
108 "}\n"},
109 {BuiltInId::ldexp_Float3_Int3,
110 "float3 ldexp_emu(float3 x, int3 exp)\n"
111 "{\n"
112 " return ldexp(x, float3(exp));\n"
113 "}\n"},
114 {BuiltInId::ldexp_Float4_Int4,
115 "float4 ldexp_emu(float4 x, int4 exp)\n"
116 "{\n"
117 " return ldexp(x, float4(exp));\n"
118 "}\n"},
119 {BuiltInId::faceforward_Float1_Float1_Float1,
120 "float faceforward_emu(float N, float I, float Nref)\n"
121 "{\n"
122 " if(dot(Nref, I) >= 0)\n"
123 " {\n"
124 " return -N;\n"
125 " }\n"
126 " else\n"
127 " {\n"
128 " return N;\n"
129 " }\n"
130 "}\n"},
131 {BuiltInId::faceforward_Float2_Float2_Float2,
132 "float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n"
133 "{\n"
134 " if(dot(Nref, I) >= 0)\n"
135 " {\n"
136 " return -N;\n"
137 " }\n"
138 " else\n"
139 " {\n"
140 " return N;\n"
141 " }\n"
142 "}\n"},
143 {BuiltInId::faceforward_Float3_Float3_Float3,
144 "float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n"
145 "{\n"
146 " if(dot(Nref, I) >= 0)\n"
147 " {\n"
148 " return -N;\n"
149 " }\n"
150 " else\n"
151 " {\n"
152 " return N;\n"
153 " }\n"
154 "}\n"},
155 {BuiltInId::faceforward_Float4_Float4_Float4,
156 "float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n"
157 "{\n"
158 " if(dot(Nref, I) >= 0)\n"
159 " {\n"
160 " return -N;\n"
161 " }\n"
162 " else\n"
163 " {\n"
164 " return N;\n"
165 " }\n"
166 "}\n"},
167 {BuiltInId::atan_Float1_Float1,
168 "float atan_emu(float y, float x)\n"
169 "{\n"
170 " if(x == 0 && y == 0) x = 1;\n"
171 " return atan2(y, x);\n"
172 "}\n"},
173 {BuiltInId::atan_Float2_Float2,
174 "float2 atan_emu(float2 y, float2 x)\n"
175 "{\n"
176 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
177 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
178 " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
179 "}\n"},
180 {BuiltInId::atan_Float3_Float3,
181 "float3 atan_emu(float3 y, float3 x)\n"
182 "{\n"
183 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
184 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
185 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
186 " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
187 "}\n"},
188 {BuiltInId::atan_Float4_Float4,
189 "float4 atan_emu(float4 y, float4 x)\n"
190 "{\n"
191 " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
192 " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
193 " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
194 " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
195 " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n"
196 " x[2]), atan2(y[3], x[3]));\n"
197 "}\n"},
198 {BuiltInId::asinh_Float1,
199 "float asinh_emu(in float x)\n"
200 "{\n"
201 " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
202 "}\n"},
203 {BuiltInId::asinh_Float2,
204 "float2 asinh_emu(in float2 x)\n"
205 "{\n"
206 " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
207 "}\n"},
208 {BuiltInId::asinh_Float3,
209 "float3 asinh_emu(in float3 x)\n"
210 "{\n"
211 " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
212 "}\n"},
213 {BuiltInId::asinh_Float4,
214 "float4 asinh_emu(in float4 x)\n"
215 "{\n"
216 " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
217 "}\n"},
218 {BuiltInId::acosh_Float1,
219 "float acosh_emu(in float x)\n"
220 "{\n"
221 " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
222 "}\n"},
223 {BuiltInId::acosh_Float2,
224 "float2 acosh_emu(in float2 x)\n"
225 "{\n"
226 " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
227 "}\n"},
228 {BuiltInId::acosh_Float3,
229 "float3 acosh_emu(in float3 x)\n"
230 "{\n"
231 " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
232 "}\n"},
233 {BuiltInId::acosh_Float4,
234 "float4 acosh_emu(in float4 x)\n"
235 "{\n"
236 " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
237 "}\n"},
238 {BuiltInId::atanh_Float1,
239 "float atanh_emu(in float x)\n"
240 "{\n"
241 " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
242 "}\n"},
243 {BuiltInId::atanh_Float2,
244 "float2 atanh_emu(in float2 x)\n"
245 "{\n"
246 " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
247 "}\n"},
248 {BuiltInId::atanh_Float3,
249 "float3 atanh_emu(in float3 x)\n"
250 "{\n"
251 " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
252 "}\n"},
253 {BuiltInId::atanh_Float4,
254 "float4 atanh_emu(in float4 x)\n"
255 "{\n"
256 " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
257 "}\n"},
258 {BuiltInId::roundEven_Float1,
259 "float roundEven_emu(in float x)\n"
260 "{\n"
261 " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
262 "}\n"},
263 {BuiltInId::roundEven_Float2,
264 "float2 roundEven_emu(in float2 x)\n"
265 "{\n"
266 " float2 v;\n"
267 " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
268 " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
269 " return v;\n"
270 "}\n"},
271 {BuiltInId::roundEven_Float3,
272 "float3 roundEven_emu(in float3 x)\n"
273 "{\n"
274 " float3 v;\n"
275 " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
276 " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
277 " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
278 " return v;\n"
279 "}\n"},
280 {BuiltInId::roundEven_Float4,
281 "float4 roundEven_emu(in float4 x)\n"
282 "{\n"
283 " float4 v;\n"
284 " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
285 " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
286 " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
287 " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
288 " return v;\n"
289 "}\n"},
290 {BuiltInId::packSnorm2x16_Float2,
291 "int webgl_toSnorm16(in float x) {\n"
292 " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
293 "}\n"
294 "uint packSnorm2x16_emu(in float2 v)\n"
295 "{\n"
296 " int x = webgl_toSnorm16(v.x);\n"
297 " int y = webgl_toSnorm16(v.y);\n"
298 " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
299 "}\n"},
300 {BuiltInId::packUnorm2x16_Float2,
301 "uint webgl_toUnorm16(in float x) {\n"
302 " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
303 "}\n"
304 "uint packUnorm2x16_emu(in float2 v)\n"
305 "{\n"
306 " uint x = webgl_toUnorm16(v.x);\n"
307 " uint y = webgl_toUnorm16(v.y);\n"
308 " return (y << 16) | x;\n"
309 "}\n"},
310 {BuiltInId::packHalf2x16_Float2,
311 "uint packHalf2x16_emu(in float2 v)\n"
312 "{\n"
313 " uint x = f32tof16(v.x);\n"
314 " uint y = f32tof16(v.y);\n"
315 " return (y << 16) | x;\n"
316 "}\n"},
317 {BuiltInId::unpackSnorm2x16_UInt1,
318 "float webgl_fromSnorm16(in uint x) {\n"
319 " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
320 " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
321 "}\n"
322 "float2 unpackSnorm2x16_emu(in uint u)\n"
323 "{\n"
324 " uint y = (u >> 16);\n"
325 " uint x = u;\n"
326 " return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n"
327 "}\n"},
328 {BuiltInId::unpackUnorm2x16_UInt1,
329 "float webgl_fromUnorm16(in uint x) {\n"
330 " return float(x) / 65535.0;\n"
331 "}\n"
332 "float2 unpackUnorm2x16_emu(in uint u)\n"
333 "{\n"
334 " uint y = (u >> 16);\n"
335 " uint x = u & 0xffffu;\n"
336 " return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n"
337 "}\n"},
338 {BuiltInId::unpackHalf2x16_UInt1,
339 "float2 unpackHalf2x16_emu(in uint u)\n"
340 "{\n"
341 " uint y = (u >> 16);\n"
342 " uint x = u & 0xffffu;\n"
343 " return float2(f16tof32(x), f16tof32(y));\n"
344 "}\n"},
345 {BuiltInId::packSnorm4x8_Float4,
346 "int webgl_toSnorm8(in float x) {\n"
347 " return int(round(clamp(x, -1.0, 1.0) * 127.0));\n"
348 "}\n"
349 "uint packSnorm4x8_emu(in float4 v)\n"
350 "{\n"
351 " int x = webgl_toSnorm8(v.x);\n"
352 " int y = webgl_toSnorm8(v.y);\n"
353 " int z = webgl_toSnorm8(v.z);\n"
354 " int w = webgl_toSnorm8(v.w);\n"
355 " return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n"
356 " | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n"
357 "}\n"},
358 {BuiltInId::packUnorm4x8_Float4,
359 "uint webgl_toUnorm8(in float x) {\n"
360 " return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n"
361 "}\n"
362 "uint packUnorm4x8_emu(in float4 v)\n"
363 "{\n"
364 " uint x = webgl_toUnorm8(v.x);\n"
365 " uint y = webgl_toUnorm8(v.y);\n"
366 " uint z = webgl_toUnorm8(v.z);\n"
367 " uint w = webgl_toUnorm8(v.w);\n"
368 " return (w << 24) | (z << 16) | (y << 8) | x;\n"
369 "}\n"},
370 {BuiltInId::unpackSnorm4x8_UInt1,
371 "float webgl_fromSnorm8(in uint x) {\n"
372 " int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n"
373 " return clamp(float(xi) / 127.0, -1.0, 1.0);\n"
374 "}\n"
375 "float4 unpackSnorm4x8_emu(in uint u)\n"
376 "{\n"
377 " uint w = (u >> 24);\n"
378 " uint z = (u >> 16);\n"
379 " uint y = (u >> 8);\n"
380 " uint x = u;\n"
381 " return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n"
382 " webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n"
383 "}\n"},
384 {BuiltInId::unpackUnorm4x8_UInt1,
385 "float webgl_fromUnorm8(in uint x) {\n"
386 " return float(x) / 255.0;\n"
387 "}\n"
388 "float4 unpackUnorm4x8_emu(in uint u)\n"
389 "{\n"
390 " uint w = (u >> 24) & 0xffu;\n"
391 " uint z = (u >> 16) & 0xffu;\n"
392 " uint y = (u >> 8) & 0xffu;\n"
393 " uint x = u & 0xffu;\n"
394 " return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), \n"
395 " webgl_fromUnorm8(z), webgl_fromUnorm8(w));\n"
396 "}\n"},
397 // The matrix resulting from outer product needs to be transposed
398 // (matrices are stored as transposed to simplify element access in HLSL).
399 // So the function should return transpose(c * r) where c is a column vector
400 // and r is a row vector. This can be simplified by using the following
401 // formula:
402 // transpose(c * r) = transpose(r) * transpose(c)
403 // transpose(r) and transpose(c) are in a sense free, since to get the
404 // transpose of r, we simply can build a column matrix out of the original
405 // vector instead of a row matrix.
406 {BuiltInId::outerProduct_Float2_Float2,
407 "float2x2 outerProduct_emu(in float2 c, in float2 r)\n"
408 "{\n"
409 " return mul(float2x1(r), float1x2(c));\n"
410 "}\n"},
411 {BuiltInId::outerProduct_Float3_Float3,
412 "float3x3 outerProduct_emu(in float3 c, in float3 r)\n"
413 "{\n"
414 " return mul(float3x1(r), float1x3(c));\n"
415 "}\n"},
416 {BuiltInId::outerProduct_Float4_Float4,
417 "float4x4 outerProduct_emu(in float4 c, in float4 r)\n"
418 "{\n"
419 " return mul(float4x1(r), float1x4(c));\n"
420 "}\n"},
421 {BuiltInId::outerProduct_Float3_Float2,
422 "float2x3 outerProduct_emu(in float3 c, in float2 r)\n"
423 "{\n"
424 " return mul(float2x1(r), float1x3(c));\n"
425 "}\n"},
426 {BuiltInId::outerProduct_Float2_Float3,
427 "float3x2 outerProduct_emu(in float2 c, in float3 r)\n"
428 "{\n"
429 " return mul(float3x1(r), float1x2(c));\n"
430 "}\n"},
431 {BuiltInId::outerProduct_Float4_Float2,
432 "float2x4 outerProduct_emu(in float4 c, in float2 r)\n"
433 "{\n"
434 " return mul(float2x1(r), float1x4(c));\n"
435 "}\n"},
436 {BuiltInId::outerProduct_Float2_Float4,
437 "float4x2 outerProduct_emu(in float2 c, in float4 r)\n"
438 "{\n"
439 " return mul(float4x1(r), float1x2(c));\n"
440 "}\n"},
441 {BuiltInId::outerProduct_Float4_Float3,
442 "float3x4 outerProduct_emu(in float4 c, in float3 r)\n"
443 "{\n"
444 " return mul(float3x1(r), float1x4(c));\n"
445 "}\n"},
446 {BuiltInId::outerProduct_Float3_Float4,
447 "float4x3 outerProduct_emu(in float3 c, in float4 r)\n"
448 "{\n"
449 " return mul(float4x1(r), float1x3(c));\n"
450 "}\n"},
451 // Remember here that the parameter matrix is actually the transpose
452 // of the matrix that we're trying to invert, and the resulting matrix
453 // should also be the transpose of the inverse.
454 // When accessing the parameter matrix with m[a][b] it can be thought of so
455 // that a is the column and b is the row of the matrix that we're inverting.
456 // We calculate the inverse as the adjugate matrix divided by the
457 // determinant of the matrix being inverted. However, as the result needs
458 // to be transposed, we actually use of the transpose of the adjugate matrix
459 // which happens to be the cofactor matrix. That's stored in 'cof'.
460 // We don't need to care about divide-by-zero since results are undefined
461 // for singular or poorly-conditioned matrices.
462 {BuiltInId::inverse_Float2x2,
463 "float2x2 inverse_emu(in float2x2 m)\n"
464 "{\n"
465 " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
466 " return cof / determinant(transpose(m));\n"
467 "}\n"},
468 // cofAB is the cofactor for column A and row B.
469 {BuiltInId::inverse_Float3x3,
470 "float3x3 inverse_emu(in float3x3 m)\n"
471 "{\n"
472 " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
473 " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
474 " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
475 " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
476 " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
477 " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
478 " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
479 " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
480 " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
481 " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
482 " return cof / determinant(transpose(m));\n"
483 "}\n"},
484 {BuiltInId::inverse_Float4x4,
485 "float4x4 inverse_emu(in float4x4 m)\n"
486 "{\n"
487 " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n"
488 " m[1][2] * m[2][3]\n"
489 " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * \n"
490 " m[1][3];\n"
491 " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * \n"
492 " m[1][2] * m[2][3]\n"
493 " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * \n"
494 " m[1][3]);\n"
495 " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * \n"
496 " m[1][1] * m[2][3]\n"
497 " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * \n"
498 " m[1][3];\n"
499 " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * \n"
500 " m[1][1] * m[2][2]\n"
501 " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * \n"
502 " m[1][2]);\n"
503 " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * \n"
504 " m[0][2] * m[2][3]\n"
505 " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * \n"
506 " m[0][3]);\n"
507 " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * \n"
508 " m[0][2] * m[2][3]\n"
509 " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * \n"
510 " m[0][3];\n"
511 " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * \n"
512 " m[0][1] * m[2][3]\n"
513 " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * \n"
514 " m[0][3]);\n"
515 " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * \n"
516 " m[0][1] * m[2][2]\n"
517 " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * \n"
518 " m[0][2];\n"
519 " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * \n"
520 " m[0][2] * m[1][3]\n"
521 " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * \n"
522 " m[0][3];\n"
523 " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * \n"
524 " m[0][2] * m[1][3]\n"
525 " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * \n"
526 " m[0][3]);\n"
527 " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * \n"
528 " m[0][1] * m[1][3]\n"
529 " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * \n"
530 " m[0][3];\n"
531 " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * \n"
532 " m[0][1] * m[1][2]\n"
533 " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * \n"
534 " m[0][2]);\n"
535 " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * \n"
536 " m[0][2] * m[1][3]\n"
537 " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * \n"
538 " m[0][3]);\n"
539 " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * \n"
540 " m[0][2] * m[1][3]\n"
541 " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * \n"
542 " m[0][3];\n"
543 " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * \n"
544 " m[0][1] * m[1][3]\n"
545 " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * \n"
546 " m[0][3]);\n"
547 " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * \n"
548 " m[0][1] * m[1][2]\n"
549 " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * \n"
550 " m[0][2];\n"
551 " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,\n"
552 " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
553 " return cof / determinant(transpose(m));\n"
554 "}\n"},
555 // Emulate ESSL3 variant of mix that takes last argument as boolean vector.
556 // genType mix(genType x, genType y, genBType a): Selects which vector each returned component
557 // comes from. For a component of 'a' that is false, the corresponding component of 'x' is
558 // returned. For a component of 'a' that is true, the corresponding component of 'y' is
559 // returned.
560 {BuiltInId::mix_Float1_Float1_Bool1,
561 "float mix_emu(float x, float y, bool a)\n"
562 "{\n"
563 " return a ? y : x;\n"
564 "}\n"},
565 {BuiltInId::mix_Int1_Int1_Bool1,
566 "int mix_emu(int x, int y, bool a)\n"
567 "{\n"
568 " return a ? y : x;\n"
569 "}\n"},
570 {BuiltInId::mix_UInt1_UInt1_Bool1,
571 "uint mix_emu(uint x, uint y, bool a)\n"
572 "{\n"
573 " return a ? y : x;\n"
574 "}\n"},
575 {BuiltInId::mix_Float2_Float2_Bool2,
576 "float2 mix_emu(float2 x, float2 y, bool2 a)\n"
577 "{\n"
578 " return float2(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1]);\n"
579 "}\n"},
580 {BuiltInId::mix_Int2_Int2_Bool2,
581 "int2 mix_emu(int2 x, int2 y, bool2 a)\n"
582 "{\n"
583 " return int2(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1]);\n"
584 "}\n"},
585 {BuiltInId::mix_UInt2_UInt2_Bool2,
586 "uint2 mix_emu(uint2 x, uint2 y, bool2 a)\n"
587 "{\n"
588 " return uint2(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1]);\n"
589 "}\n"},
590 {BuiltInId::mix_Float3_Float3_Bool3,
591 "float3 mix_emu(float3 x, float3 y, bool3 a)\n"
592 "{\n"
593 " return float3(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1], a[2] ? y[2] : x[2]);\n"
594 "}\n"},
595 {BuiltInId::mix_Int3_Int3_Bool3,
596 "int3 mix_emu(int3 x, int3 y, bool3 a)\n"
597 "{\n"
598 " return int3(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1], a[2] ? y[2] : x[2]);\n"
599 "}\n"},
600 {BuiltInId::mix_UInt3_UInt3_Bool3,
601 "uint3 mix_emu(uint3 x, uint3 y, bool3 a)\n"
602 "{\n"
603 " return uint3(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1], a[2] ? y[2] : x[2]);\n"
604 "}\n"},
605 {BuiltInId::mix_Float4_Float4_Bool4,
606 "float4 mix_emu(float4 x, float4 y, bool4 a)\n"
607 "{\n"
608 " return float4(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1], a[2] ? y[2] : x[2], a[3] ? y[3] : "
609 "x[3]);\n"
610 "}\n"},
611 {BuiltInId::mix_Int4_Int4_Bool4,
612 "int4 mix_emu(int4 x, int4 y, bool4 a)\n"
613 "{\n"
614 " return int4(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1], a[2] ? y[2] : x[2], a[3] ? y[3] : "
615 "x[3]);\n"
616 "}\n"},
617 {BuiltInId::mix_UInt4_UInt4_Bool4,
618 "uint4 mix_emu(uint4 x, uint4 y, bool4 a)\n"
619 "{\n"
620 " return uint4(a[0] ? y[0] : x[0], a[1] ? y[1] : x[1], a[2] ? y[2] : x[2], a[3] ? y[3] : "
621 "x[3]);\n"
622 "}\n"},
623 {BuiltInId::bitfieldExtract_UInt1_Int1_Int1,
624 "uint bitfieldExtract_emu(uint value, int offset, int bits)\n"
625 "{\n"
626 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
627 " {\n"
628 " return 0u;\n"
629 " }\n"
630 " uint maskMsb = (1u << (bits - 1));\n"
631 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
632 " return (value & mask) >> offset;\n"
633 "}\n"},
634 {BuiltInId::bitfieldExtract_UInt2_Int1_Int1,
635 "uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
636 "{\n"
637 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
638 " {\n"
639 " return uint2(0u, 0u);\n"
640 " }\n"
641 " uint maskMsb = (1u << (bits - 1));\n"
642 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
643 " return (value & mask) >> offset;\n"
644 "}\n"},
645 {BuiltInId::bitfieldExtract_UInt3_Int1_Int1,
646 "uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
647 "{\n"
648 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
649 " {\n"
650 " return uint3(0u, 0u, 0u);\n"
651 " }\n"
652 " uint maskMsb = (1u << (bits - 1));\n"
653 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
654 " return (value & mask) >> offset;\n"
655 "}\n"},
656 {BuiltInId::bitfieldExtract_UInt4_Int1_Int1,
657 "uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
658 "{\n"
659 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
660 " {\n"
661 " return uint4(0u, 0u, 0u, 0u);\n"
662 " }\n"
663 " uint maskMsb = (1u << (bits - 1));\n"
664 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
665 " return (value & mask) >> offset;\n"
666 "}\n"},
667 {BuiltInId::bitfieldExtract_Int1_Int1_Int1,
668 "int bitfieldExtract_emu(int value, int offset, int bits)\n"
669 "{\n"
670 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
671 " {\n"
672 " return 0;\n"
673 " }\n"
674 " uint maskMsb = (1u << (bits - 1));\n"
675 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
676 " uint resultUnsigned = (asuint(value) & mask) >> offset;\n"
677 " if (bits != 32 && (resultUnsigned & maskMsb) != 0)\n"
678 " {\n"
679 " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
680 " resultUnsigned |= higherBitsMask;\n"
681 " }\n"
682 " return asint(resultUnsigned);\n"
683 "}\n"},
684 {BuiltInId::bitfieldExtract_Int2_Int1_Int1,
685 "int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n"
686 "{\n"
687 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
688 " {\n"
689 " return int2(0, 0);\n"
690 " }\n"
691 " uint maskMsb = (1u << (bits - 1));\n"
692 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
693 " uint2 resultUnsigned = (asuint(value) & mask) >> offset;\n"
694 " if (bits != 32)\n"
695 " {\n"
696 " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
697 " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
698 " }\n"
699 " return asint(resultUnsigned);\n"
700 "}\n"},
701 {BuiltInId::bitfieldExtract_Int3_Int1_Int1,
702 "int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n"
703 "{\n"
704 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
705 " {\n"
706 " return int3(0, 0, 0);\n"
707 " }\n"
708 " uint maskMsb = (1u << (bits - 1));\n"
709 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
710 " uint3 resultUnsigned = (asuint(value) & mask) >> offset;\n"
711 " if (bits != 32)\n"
712 " {\n"
713 " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
714 " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
715 " }\n"
716 " return asint(resultUnsigned);\n"
717 "}\n"},
718 {BuiltInId::bitfieldExtract_Int4_Int1_Int1,
719 "int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n"
720 "{\n"
721 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
722 " {\n"
723 " return int4(0, 0, 0, 0);\n"
724 " }\n"
725 " uint maskMsb = (1u << (bits - 1));\n"
726 " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
727 " uint4 resultUnsigned = (asuint(value) & mask) >> offset;\n"
728 " if (bits != 32)\n"
729 " {\n"
730 " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
731 " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
732 " }\n"
733 " return asint(resultUnsigned);\n"
734 "}\n"},
735 {BuiltInId::bitfieldInsert_UInt1_UInt1_Int1_Int1,
736 "uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n"
737 "{\n"
738 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
739 " {\n"
740 " return base;\n"
741 " }\n"
742 " uint maskMsb = (1u << (bits - 1));\n"
743 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
744 " uint baseMask = ~insertMask;\n"
745 " return (base & baseMask) | ((insert << offset) & insertMask);\n"
746 "}\n"},
747 {BuiltInId::bitfieldInsert_UInt2_UInt2_Int1_Int1,
748 "uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n"
749 "{\n"
750 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
751 " {\n"
752 " return base;\n"
753 " }\n"
754 " uint maskMsb = (1u << (bits - 1));\n"
755 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
756 " uint baseMask = ~insertMask;\n"
757 " return (base & baseMask) | ((insert << offset) & insertMask);\n"
758 "}\n"},
759 {BuiltInId::bitfieldInsert_UInt3_UInt3_Int1_Int1,
760 "uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n"
761 "{\n"
762 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
763 " {\n"
764 " return base;\n"
765 " }\n"
766 " uint maskMsb = (1u << (bits - 1));\n"
767 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
768 " uint baseMask = ~insertMask;\n"
769 " return (base & baseMask) | ((insert << offset) & insertMask);\n"
770 "}\n"},
771 {BuiltInId::bitfieldInsert_UInt4_UInt4_Int1_Int1,
772 "uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n"
773 "{\n"
774 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
775 " {\n"
776 " return base;\n"
777 " }\n"
778 " uint maskMsb = (1u << (bits - 1));\n"
779 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
780 " uint baseMask = ~insertMask;\n"
781 " return (base & baseMask) | ((insert << offset) & insertMask);\n"
782 "}\n"},
783 {BuiltInId::bitfieldInsert_Int1_Int1_Int1_Int1,
784 "int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n"
785 "{\n"
786 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
787 " {\n"
788 " return base;\n"
789 " }\n"
790 " uint maskMsb = (1u << (bits - 1));\n"
791 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
792 " uint baseMask = ~insertMask;\n"
793 " uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
794 " insertMask);\n"
795 " return asint(resultUnsigned);\n"
796 "}\n"},
797 {BuiltInId::bitfieldInsert_Int2_Int2_Int1_Int1,
798 "int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n"
799 "{\n"
800 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
801 " {\n"
802 " return base;\n"
803 " }\n"
804 " uint maskMsb = (1u << (bits - 1));\n"
805 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
806 " uint baseMask = ~insertMask;\n"
807 " uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
808 " insertMask);\n"
809 " return asint(resultUnsigned);\n"
810 "}\n"},
811 {BuiltInId::bitfieldInsert_Int3_Int3_Int1_Int1,
812 "int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n"
813 "{\n"
814 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
815 " {\n"
816 " return base;\n"
817 " }\n"
818 " uint maskMsb = (1u << (bits - 1));\n"
819 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
820 " uint baseMask = ~insertMask;\n"
821 " uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
822 " insertMask);\n"
823 " return asint(resultUnsigned);\n"
824 "}\n"},
825 {BuiltInId::bitfieldInsert_Int4_Int4_Int1_Int1,
826 "int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n"
827 "{\n"
828 " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
829 " {\n"
830 " return base;\n"
831 " }\n"
832 " uint maskMsb = (1u << (bits - 1));\n"
833 " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
834 " uint baseMask = ~insertMask;\n"
835 " uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
836 " insertMask);\n"
837 " return asint(resultUnsigned);\n"
838 "}\n"},
839 {BuiltInId::uaddCarry_UInt1_UInt1_UInt1,
840 "uint uaddCarry_emu(uint x, uint y, out uint carry)\n"
841 "{\n"
842 " carry = uint(x > (0xffffffffu - y));\n"
843 " return x + y;\n"
844 "}\n"},
845 {BuiltInId::uaddCarry_UInt2_UInt2_UInt2,
846 "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n"
847 "{\n"
848 " carry = uint2(x > (0xffffffffu - y));\n"
849 " return x + y;\n"
850 "}\n"},
851 {BuiltInId::uaddCarry_UInt3_UInt3_UInt3,
852 "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n"
853 "{\n"
854 " carry = uint3(x > (0xffffffffu - y));\n"
855 " return x + y;\n"
856 "}\n"},
857 {BuiltInId::uaddCarry_UInt4_UInt4_UInt4,
858 "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n"
859 "{\n"
860 " carry = uint4(x > (0xffffffffu - y));\n"
861 " return x + y;\n"
862 "}\n"},
863 {BuiltInId::usubBorrow_UInt1_UInt1_UInt1,
864 "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n"
865 "{\n"
866 " borrow = uint(x < y);\n"
867 " return x - y;\n"
868 "}\n"},
869 {BuiltInId::usubBorrow_UInt2_UInt2_UInt2,
870 "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n"
871 "{\n"
872 " borrow = uint2(x < y);\n"
873 " return x - y;\n"
874 "}\n"},
875 {BuiltInId::usubBorrow_UInt3_UInt3_UInt3,
876 "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n"
877 "{\n"
878 " borrow = uint3(x < y);\n"
879 " return x - y;\n"
880 "}\n"},
881 {BuiltInId::usubBorrow_UInt4_UInt4_UInt4,
882 "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n"
883 "{\n"
884 " borrow = uint4(x < y);\n"
885 " return x - y;\n"
886 "}\n"},
887 // We emulate tanh just to avoid overflow on large arguments.
888 {BuiltInId::tanh_Float1,
889 "float tanh_emu(float x)\n"
890 "{\n"
891 " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
892 "}\n"},
893 {BuiltInId::tanh_Float2,
894 "float2 tanh_emu(float2 x)\n"
895 "{\n"
896 " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
897 "}\n"},
898 {BuiltInId::tanh_Float3,
899 "float3 tanh_emu(float3 x)\n"
900 "{\n"
901 " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
902 "}\n"},
903 {BuiltInId::tanh_Float4,
904 "float4 tanh_emu(float4 x)\n"
905 "{\n"
906 " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
907 "}\n"},
908 };
909 } // anonymous namespace
910
FindHLSLFunction(int uniqueId)911 const char *FindHLSLFunction(int uniqueId)
912 {
913 for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
914 {
915 const auto &function = g_hlslFunctions[index];
916 if (function.id == uniqueId)
917 {
918 return function.body;
919 }
920 }
921
922 return nullptr;
923 }
924 } // namespace sh
925