BuiltInFunctionEmulatorGLSL.cpp (11439B)
1 // 2 // Copyright 2002 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/BuiltInFunctionEmulatorGLSL.h" 8 9 #include "angle_gl.h" 10 #include "compiler/translator/BuiltInFunctionEmulator.h" 11 #include "compiler/translator/VersionGLSL.h" 12 #include "compiler/translator/tree_util/BuiltIn.h" 13 14 namespace sh 15 { 16 17 void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, 18 sh::GLenum shaderType) 19 { 20 if (shaderType == GL_VERTEX_SHADER) 21 { 22 emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }"); 23 } 24 } 25 26 void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, 27 int targetGLSLVersion) 28 { 29 // isnan() is supported since GLSL 1.3. 30 if (targetGLSLVersion < GLSL_VERSION_130) 31 return; 32 33 // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. 34 emu->addEmulatedFunction( 35 BuiltInId::isnan_Float1, 36 "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); 37 emu->addEmulatedFunction( 38 BuiltInId::isnan_Float2, 39 "bvec2 isnan_emu(vec2 x)\n" 40 "{\n" 41 " bvec2 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 emu->addEmulatedFunction( 49 BuiltInId::isnan_Float3, 50 "bvec3 isnan_emu(vec3 x)\n" 51 "{\n" 52 " bvec3 isnan;\n" 53 " for (int i = 0; i < 3; i++)\n" 54 " {\n" 55 " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" 56 " }\n" 57 " return isnan;\n" 58 "}\n"); 59 emu->addEmulatedFunction( 60 BuiltInId::isnan_Float4, 61 "bvec4 isnan_emu(vec4 x)\n" 62 "{\n" 63 " bvec4 isnan;\n" 64 " for (int i = 0; i < 4; i++)\n" 65 " {\n" 66 " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" 67 " }\n" 68 " return isnan;\n" 69 "}\n"); 70 } 71 72 void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu) 73 { 74 emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1, 75 "emu_precision float atan_emu(emu_precision float y, emu_precision " 76 "float x)\n" 77 "{\n" 78 " if (x > 0.0) return atan(y / x);\n" 79 " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n" 80 " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n" 81 " else return 1.57079632 * sign(y);\n" 82 "}\n"); 83 static const std::array<TSymbolUniqueId, 4> ids = { 84 BuiltInId::atan_Float1_Float1, 85 BuiltInId::atan_Float2_Float2, 86 BuiltInId::atan_Float3_Float3, 87 BuiltInId::atan_Float4_Float4, 88 }; 89 for (int dim = 2; dim <= 4; ++dim) 90 { 91 std::stringstream ss = sh::InitializeStream<std::stringstream>(); 92 ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim 93 << " y, emu_precision vec" << dim << " x)\n" 94 << "{\n" 95 " return vec" 96 << dim << "("; 97 for (int i = 0; i < dim; ++i) 98 { 99 ss << "atan_emu(y[" << i << "], x[" << i << "])"; 100 if (i < dim - 1) 101 { 102 ss << ", "; 103 } 104 } 105 ss << ");\n" 106 "}\n"; 107 emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1], 108 ss.str().c_str()); 109 } 110 } 111 112 // Emulate built-in functions missing from GLSL 1.30 and higher 113 void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, 114 sh::GLenum shaderType, 115 int targetGLSLVersion) 116 { 117 // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10) 118 if (targetGLSLVersion < GLSL_VERSION_410) 119 { 120 // clang-format off 121 emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2, 122 "uint packUnorm2x16_emu(vec2 v)\n" 123 "{\n" 124 " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n" 125 " int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n" 126 " return uint((y << 16) | (x & 0xFFFF));\n" 127 "}\n"); 128 129 emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1, 130 "vec2 unpackUnorm2x16_emu(uint u)\n" 131 "{\n" 132 " float x = float(u & 0xFFFFu) / 65535.0;\n" 133 " float y = float(u >> 16) / 65535.0;\n" 134 " return vec2(x, y);\n" 135 "}\n"); 136 // clang-format on 137 } 138 139 // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20) 140 // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30). 141 if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420) 142 { 143 // clang-format off 144 emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2, 145 "uint packSnorm2x16_emu(vec2 v)\n" 146 "{\n" 147 " #if defined(GL_ARB_shading_language_packing)\n" 148 " return packSnorm2x16(v);\n" 149 " #else\n" 150 " int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n" 151 " int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n" 152 " return uint((y << 16) | (x & 0xFFFF));\n" 153 " #endif\n" 154 "}\n"); 155 emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1, 156 "#if !defined(GL_ARB_shading_language_packing)\n" 157 " float fromSnorm(uint x)\n" 158 " {\n" 159 " int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n" 160 " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" 161 " }\n" 162 "#endif\n" 163 "\n" 164 "vec2 unpackSnorm2x16_emu(uint u)\n" 165 "{\n" 166 " #if defined(GL_ARB_shading_language_packing)\n" 167 " return unpackSnorm2x16(u);\n" 168 " #else\n" 169 " uint y = (u >> 16);\n" 170 " uint x = u;\n" 171 " return vec2(fromSnorm(x), fromSnorm(y));\n" 172 " #endif\n" 173 "}\n"); 174 // Functions uint f32tof16(float val) and float f16tof32(uint val) are 175 // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL". 176 emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2, 177 "#if !defined(GL_ARB_shading_language_packing)\n" 178 " uint f32tof16(float val)\n" 179 " {\n" 180 " uint f32 = floatBitsToUint(val);\n" 181 " uint f16 = 0u;\n" 182 " uint sign = (f32 >> 16) & 0x8000u;\n" 183 " int exponent = int((f32 >> 23) & 0xFFu) - 127;\n" 184 " uint mantissa = f32 & 0x007FFFFFu;\n" 185 " if (exponent == 128)\n" 186 " {\n" 187 " // Infinity or NaN\n" 188 " // NaN bits that are masked out by 0x3FF get discarded.\n" 189 " // This can turn some NaNs to infinity, but this is allowed by the spec.\n" 190 " f16 = sign | (0x1Fu << 10);\n" 191 " f16 |= (mantissa & 0x3FFu);\n" 192 " }\n" 193 " else if (exponent > 15)\n" 194 " {\n" 195 " // Overflow - flush to Infinity\n" 196 " f16 = sign | (0x1Fu << 10);\n" 197 " }\n" 198 " else if (exponent > -15)\n" 199 " {\n" 200 " // Representable value\n" 201 " exponent += 15;\n" 202 " mantissa >>= 13;\n" 203 " f16 = sign | uint(exponent << 10) | mantissa;\n" 204 " }\n" 205 " else\n" 206 " {\n" 207 " f16 = sign;\n" 208 " }\n" 209 " return f16;\n" 210 " }\n" 211 "#endif\n" 212 "\n" 213 "uint packHalf2x16_emu(vec2 v)\n" 214 "{\n" 215 " #if defined(GL_ARB_shading_language_packing)\n" 216 " return packHalf2x16(v);\n" 217 " #else\n" 218 " uint x = f32tof16(v.x);\n" 219 " uint y = f32tof16(v.y);\n" 220 " return (y << 16) | x;\n" 221 " #endif\n" 222 "}\n"); 223 emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1, 224 "#if !defined(GL_ARB_shading_language_packing)\n" 225 " float f16tof32(uint val)\n" 226 " {\n" 227 " uint sign = (val & 0x8000u) << 16;\n" 228 " int exponent = int((val & 0x7C00u) >> 10);\n" 229 " uint mantissa = val & 0x03FFu;\n" 230 " float f32 = 0.0;\n" 231 " if(exponent == 0)\n" 232 " {\n" 233 " if (mantissa != 0u)\n" 234 " {\n" 235 " const float scale = 1.0 / (1 << 24);\n" 236 " f32 = scale * mantissa;\n" 237 " }\n" 238 " }\n" 239 " else if (exponent == 31)\n" 240 " {\n" 241 " return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n" 242 " }\n" 243 " else\n" 244 " {\n" 245 " exponent -= 15;\n" 246 " float scale;\n" 247 " if(exponent < 0)\n" 248 " {\n" 249 " // The negative unary operator is buggy on OSX.\n" 250 " // Work around this by using abs instead.\n" 251 " scale = 1.0 / (1 << abs(exponent));\n" 252 " }\n" 253 " else\n" 254 " {\n" 255 " scale = 1 << exponent;\n" 256 " }\n" 257 " float decimal = 1.0 + float(mantissa) / float(1 << 10);\n" 258 " f32 = scale * decimal;\n" 259 " }\n" 260 "\n" 261 " if (sign != 0u)\n" 262 " {\n" 263 " f32 = -f32;\n" 264 " }\n" 265 "\n" 266 " return f32;\n" 267 " }\n" 268 "#endif\n" 269 "\n" 270 "vec2 unpackHalf2x16_emu(uint u)\n" 271 "{\n" 272 " #if defined(GL_ARB_shading_language_packing)\n" 273 " return unpackHalf2x16(u);\n" 274 " #else\n" 275 " uint y = (u >> 16);\n" 276 " uint x = u & 0xFFFFu;\n" 277 " return vec2(f16tof32(x), f16tof32(y));\n" 278 " #endif\n" 279 "}\n"); 280 // clang-format on 281 } 282 } 283 284 } // namespace sh