diff options
Diffstat (limited to 'gfx/angle/src/compiler/translator/util.cpp')
-rwxr-xr-x | gfx/angle/src/compiler/translator/util.cpp | 620 |
1 files changed, 620 insertions, 0 deletions
diff --git a/gfx/angle/src/compiler/translator/util.cpp b/gfx/angle/src/compiler/translator/util.cpp new file mode 100755 index 000000000..89f237ceb --- /dev/null +++ b/gfx/angle/src/compiler/translator/util.cpp @@ -0,0 +1,620 @@ +// +// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/util.h" + +#include <limits> + +#include "compiler/preprocessor/numeric_lex.h" +#include "compiler/translator/SymbolTable.h" +#include "common/utilities.h" + +bool strtof_clamp(const std::string &str, float *value) +{ + bool success = pp::numeric_lex_float(str, value); + if (!success) + *value = std::numeric_limits<float>::max(); + return success; +} + +bool atoi_clamp(const char *str, unsigned int *value) +{ + bool success = pp::numeric_lex_int(str, value); + if (!success) + *value = std::numeric_limits<unsigned int>::max(); + return success; +} + +namespace sh +{ + +GLenum GLVariableType(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + if (type.isScalar()) + { + return GL_FLOAT; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_FLOAT_VEC2; + case 3: return GL_FLOAT_VEC3; + case 4: return GL_FLOAT_VEC4; + default: UNREACHABLE(); + } + } + else if (type.isMatrix()) + { + switch (type.getCols()) + { + case 2: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT2; + case 3: return GL_FLOAT_MAT2x3; + case 4: return GL_FLOAT_MAT2x4; + default: UNREACHABLE(); + } + + case 3: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT3x2; + case 3: return GL_FLOAT_MAT3; + case 4: return GL_FLOAT_MAT3x4; + default: UNREACHABLE(); + } + + case 4: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT4x2; + case 3: return GL_FLOAT_MAT4x3; + case 4: return GL_FLOAT_MAT4; + default: UNREACHABLE(); + } + + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtInt) + { + if (type.isScalar()) + { + return GL_INT; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_INT_VEC2; + case 3: return GL_INT_VEC3; + case 4: return GL_INT_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtUInt) + { + if (type.isScalar()) + { + return GL_UNSIGNED_INT; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_UNSIGNED_INT_VEC2; + case 3: return GL_UNSIGNED_INT_VEC3; + case 4: return GL_UNSIGNED_INT_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtBool) + { + if (type.isScalar()) + { + return GL_BOOL; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_BOOL_VEC2; + case 3: return GL_BOOL_VEC3; + case 4: return GL_BOOL_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + + switch (type.getBasicType()) + { + case EbtSampler2D: return GL_SAMPLER_2D; + case EbtSampler3D: return GL_SAMPLER_3D; + case EbtSamplerCube: return GL_SAMPLER_CUBE; + case EbtSamplerExternalOES: return GL_SAMPLER_EXTERNAL_OES; + case EbtSampler2DRect: return GL_SAMPLER_2D_RECT_ARB; + case EbtSampler2DArray: return GL_SAMPLER_2D_ARRAY; + case EbtISampler2D: return GL_INT_SAMPLER_2D; + case EbtISampler3D: return GL_INT_SAMPLER_3D; + case EbtISamplerCube: return GL_INT_SAMPLER_CUBE; + case EbtISampler2DArray: return GL_INT_SAMPLER_2D_ARRAY; + case EbtUSampler2D: return GL_UNSIGNED_INT_SAMPLER_2D; + case EbtUSampler3D: return GL_UNSIGNED_INT_SAMPLER_3D; + case EbtUSamplerCube: return GL_UNSIGNED_INT_SAMPLER_CUBE; + case EbtUSampler2DArray: return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; + case EbtSampler2DShadow: return GL_SAMPLER_2D_SHADOW; + case EbtSamplerCubeShadow: return GL_SAMPLER_CUBE_SHADOW; + case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW; + case EbtImage2D: + return GL_IMAGE_2D; + case EbtIImage2D: + return GL_INT_IMAGE_2D; + case EbtUImage2D: + return GL_UNSIGNED_INT_IMAGE_2D; + case EbtImage2DArray: + return GL_IMAGE_2D_ARRAY; + case EbtIImage2DArray: + return GL_INT_IMAGE_2D_ARRAY; + case EbtUImage2DArray: + return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; + case EbtImage3D: + return GL_IMAGE_3D; + case EbtIImage3D: + return GL_INT_IMAGE_3D; + case EbtUImage3D: + return GL_UNSIGNED_INT_IMAGE_3D; + case EbtImageCube: + return GL_IMAGE_CUBE; + case EbtIImageCube: + return GL_INT_IMAGE_CUBE; + case EbtUImageCube: + return GL_UNSIGNED_INT_IMAGE_CUBE; + default: UNREACHABLE(); + } + + return GL_NONE; +} + +GLenum GLVariablePrecision(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + switch (type.getPrecision()) + { + case EbpHigh: + return GL_HIGH_FLOAT; + case EbpMedium: + return GL_MEDIUM_FLOAT; + case EbpLow: + return GL_LOW_FLOAT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: + UNREACHABLE(); + } + } + else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt) + { + switch (type.getPrecision()) + { + case EbpHigh: + return GL_HIGH_INT; + case EbpMedium: + return GL_MEDIUM_INT; + case EbpLow: + return GL_LOW_INT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: + UNREACHABLE(); + } + } + + // Other types (boolean, sampler) don't have a precision + return GL_NONE; +} + +TString ArrayString(const TType &type) +{ + if (!type.isArray()) + { + return ""; + } + + return "[" + str(type.getArraySize()) + "]"; +} + +bool IsVaryingOut(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqCentroidOut: + case EvqVertexOut: + return true; + + default: break; + } + + return false; +} + +bool IsVaryingIn(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingIn: + case EvqSmoothIn: + case EvqFlatIn: + case EvqCentroidIn: + case EvqFragmentIn: + return true; + + default: break; + } + + return false; +} + +bool IsVarying(TQualifier qualifier) +{ + return IsVaryingIn(qualifier) || IsVaryingOut(qualifier); +} + +InterpolationType GetInterpolationType(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFlatIn: + case EvqFlatOut: + return INTERPOLATION_FLAT; + + case EvqSmoothIn: + case EvqSmoothOut: + case EvqVertexOut: + case EvqFragmentIn: + case EvqVaryingIn: + case EvqVaryingOut: + return INTERPOLATION_SMOOTH; + + case EvqCentroidIn: + case EvqCentroidOut: + return INTERPOLATION_CENTROID; + + default: UNREACHABLE(); + return INTERPOLATION_SMOOTH; + } +} + +TType GetShaderVariableBasicType(const sh::ShaderVariable &var) +{ + switch (var.type) + { + case GL_BOOL: + return TType(EbtBool); + case GL_BOOL_VEC2: + return TType(EbtBool, 2); + case GL_BOOL_VEC3: + return TType(EbtBool, 3); + case GL_BOOL_VEC4: + return TType(EbtBool, 4); + case GL_FLOAT: + return TType(EbtFloat); + case GL_FLOAT_VEC2: + return TType(EbtFloat, 2); + case GL_FLOAT_VEC3: + return TType(EbtFloat, 3); + case GL_FLOAT_VEC4: + return TType(EbtFloat, 4); + case GL_FLOAT_MAT2: + return TType(EbtFloat, 2, 2); + case GL_FLOAT_MAT3: + return TType(EbtFloat, 3, 3); + case GL_FLOAT_MAT4: + return TType(EbtFloat, 4, 4); + case GL_FLOAT_MAT2x3: + return TType(EbtFloat, 2, 3); + case GL_FLOAT_MAT2x4: + return TType(EbtFloat, 2, 4); + case GL_FLOAT_MAT3x2: + return TType(EbtFloat, 3, 2); + case GL_FLOAT_MAT3x4: + return TType(EbtFloat, 3, 4); + case GL_FLOAT_MAT4x2: + return TType(EbtFloat, 4, 2); + case GL_FLOAT_MAT4x3: + return TType(EbtFloat, 4, 3); + case GL_INT: + return TType(EbtInt); + case GL_INT_VEC2: + return TType(EbtInt, 2); + case GL_INT_VEC3: + return TType(EbtInt, 3); + case GL_INT_VEC4: + return TType(EbtInt, 4); + case GL_UNSIGNED_INT: + return TType(EbtUInt); + case GL_UNSIGNED_INT_VEC2: + return TType(EbtUInt, 2); + case GL_UNSIGNED_INT_VEC3: + return TType(EbtUInt, 3); + case GL_UNSIGNED_INT_VEC4: + return TType(EbtUInt, 4); + default: + UNREACHABLE(); + return TType(); + } +} + +TOperator TypeToConstructorOperator(const TType &type) +{ + switch (type.getBasicType()) + { + case EbtFloat: + if (type.isMatrix()) + { + switch (type.getCols()) + { + case 2: + switch (type.getRows()) + { + case 2: + return EOpConstructMat2; + case 3: + return EOpConstructMat2x3; + case 4: + return EOpConstructMat2x4; + default: + break; + } + break; + + case 3: + switch (type.getRows()) + { + case 2: + return EOpConstructMat3x2; + case 3: + return EOpConstructMat3; + case 4: + return EOpConstructMat3x4; + default: + break; + } + break; + + case 4: + switch (type.getRows()) + { + case 2: + return EOpConstructMat4x2; + case 3: + return EOpConstructMat4x3; + case 4: + return EOpConstructMat4; + default: + break; + } + break; + } + } + else + { + switch (type.getNominalSize()) + { + case 1: + return EOpConstructFloat; + case 2: + return EOpConstructVec2; + case 3: + return EOpConstructVec3; + case 4: + return EOpConstructVec4; + default: + break; + } + } + break; + + case EbtInt: + switch (type.getNominalSize()) + { + case 1: + return EOpConstructInt; + case 2: + return EOpConstructIVec2; + case 3: + return EOpConstructIVec3; + case 4: + return EOpConstructIVec4; + default: + break; + } + break; + + case EbtUInt: + switch (type.getNominalSize()) + { + case 1: + return EOpConstructUInt; + case 2: + return EOpConstructUVec2; + case 3: + return EOpConstructUVec3; + case 4: + return EOpConstructUVec4; + default: + break; + } + break; + + case EbtBool: + switch (type.getNominalSize()) + { + case 1: + return EOpConstructBool; + case 2: + return EOpConstructBVec2; + case 3: + return EOpConstructBVec3; + case 4: + return EOpConstructBVec4; + default: + break; + } + break; + + case EbtStruct: + return EOpConstructStruct; + + default: + break; + } + + return EOpNull; +} + +GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable) + : mSymbolTable(symbolTable) +{ +} + +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, InterfaceBlockField *variable); +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, ShaderVariable *variable); +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, Uniform *variable); + +template<> +void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, Varying *variable) +{ + ASSERT(variable); + switch (type.getQualifier()) + { + case EvqVaryingIn: + case EvqVaryingOut: + case EvqVertexOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqCentroidOut: + if (mSymbolTable.isVaryingInvariant(std::string(name.c_str())) || type.isInvariant()) + { + variable->isInvariant = true; + } + break; + default: + break; + } + + variable->interpolation = GetInterpolationType(type.getQualifier()); +} + +template <typename VarT> +void GetVariableTraverser::traverse(const TType &type, + const TString &name, + std::vector<VarT> *output) +{ + const TStructure *structure = type.getStruct(); + + VarT variable; + variable.name = name.c_str(); + variable.arraySize = type.getArraySize(); + + if (!structure) + { + variable.type = GLVariableType(type); + variable.precision = GLVariablePrecision(type); + } + else + { + // Note: this enum value is not exposed outside ANGLE + variable.type = GL_STRUCT_ANGLEX; + variable.structName = structure->name().c_str(); + + const TFieldList &fields = structure->fields(); + + for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + TField *field = fields[fieldIndex]; + traverse(*field->type(), field->name(), &variable.fields); + } + } + setTypeSpecificInfo(type, name, &variable); + visitVariable(&variable); + + ASSERT(output); + output->push_back(variable); +} + +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<ShaderVariable> *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *); + +// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier +bool CanBeInvariantESSL1(TQualifier qualifier) +{ + return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) || + IsBuiltinOutputVariable(qualifier) || + (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing); +} + +// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier +// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier +bool CanBeInvariantESSL3OrGreater(TQualifier qualifier) +{ + return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut || + IsBuiltinOutputVariable(qualifier); +} + +bool IsBuiltinOutputVariable(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqPosition: + case EvqPointSize: + case EvqFragDepth: + case EvqFragDepthEXT: + case EvqFragColor: + case EvqSecondaryFragColorEXT: + case EvqFragData: + case EvqSecondaryFragDataEXT: + return true; + default: + break; + } + return false; +} + +bool IsBuiltinFragmentInputVariable(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFragCoord: + case EvqPointCoord: + case EvqFrontFacing: + return true; + default: + break; + } + return false; +} +} // namespace sh |