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