BuiltInFunctionEmulatorHLSL.cpp (7167B)
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 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 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