1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/VersionGLSL.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,140 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 + 1.10 +#include "compiler/VersionGLSL.h" 1.11 + 1.12 +static const int GLSL_VERSION_110 = 110; 1.13 +static const int GLSL_VERSION_120 = 120; 1.14 + 1.15 +// We need to scan for the following: 1.16 +// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders 1.17 +// but only at the global scope. 1.18 +// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader 1.19 +// but inside any scope. 1.20 +// 3. Call to a matrix constructor with another matrix as argument. 1.21 +// (These constructors were reserved in GLSL version 1.10.) 1.22 +// 4. Arrays as "out" function parameters. 1.23 +// GLSL spec section 6.1.1: "When calling a function, expressions that do 1.24 +// not evaluate to l-values cannot be passed to parameters declared as 1.25 +// out or inout." 1.26 +// GLSL 1.1 section 5.8: "Other binary or unary expressions, 1.27 +// non-dereferenced arrays, function names, swizzles with repeated fields, 1.28 +// and constants cannot be l-values." 1.29 +// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that 1.30 +// are built-in types, entire structures or arrays... are all l-values." 1.31 +// 1.32 +// TODO(alokp): The following two cases of invariant decalaration get lost 1.33 +// during parsing - they do not get carried over to the intermediate tree. 1.34 +// Handle these cases: 1.35 +// 1. When a pragma is used to force all output variables to be invariant: 1.36 +// - #pragma STDGL invariant(all) 1.37 +// 2. When a previously decalared or built-in variable is marked invariant: 1.38 +// - invariant gl_Position; 1.39 +// - varying vec3 color; invariant color; 1.40 +// 1.41 +TVersionGLSL::TVersionGLSL(ShShaderType type) 1.42 + : mShaderType(type), 1.43 + mVersion(GLSL_VERSION_110) 1.44 +{ 1.45 +} 1.46 + 1.47 +void TVersionGLSL::visitSymbol(TIntermSymbol* node) 1.48 +{ 1.49 + if (node->getSymbol() == "gl_PointCoord") 1.50 + updateVersion(GLSL_VERSION_120); 1.51 +} 1.52 + 1.53 +void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*) 1.54 +{ 1.55 +} 1.56 + 1.57 +bool TVersionGLSL::visitBinary(Visit, TIntermBinary*) 1.58 +{ 1.59 + return true; 1.60 +} 1.61 + 1.62 +bool TVersionGLSL::visitUnary(Visit, TIntermUnary*) 1.63 +{ 1.64 + return true; 1.65 +} 1.66 + 1.67 +bool TVersionGLSL::visitSelection(Visit, TIntermSelection*) 1.68 +{ 1.69 + return true; 1.70 +} 1.71 + 1.72 +bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node) 1.73 +{ 1.74 + bool visitChildren = true; 1.75 + 1.76 + switch (node->getOp()) { 1.77 + case EOpSequence: 1.78 + // We need to visit sequence children to get to global or inner scope. 1.79 + visitChildren = true; 1.80 + break; 1.81 + case EOpDeclaration: { 1.82 + const TIntermSequence& sequence = node->getSequence(); 1.83 + TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); 1.84 + if ((qualifier == EvqInvariantVaryingIn) || 1.85 + (qualifier == EvqInvariantVaryingOut)) { 1.86 + updateVersion(GLSL_VERSION_120); 1.87 + } 1.88 + break; 1.89 + } 1.90 + case EOpParameters: { 1.91 + const TIntermSequence& params = node->getSequence(); 1.92 + for (TIntermSequence::const_iterator iter = params.begin(); 1.93 + iter != params.end(); ++iter) 1.94 + { 1.95 + const TIntermTyped* param = (*iter)->getAsTyped(); 1.96 + if (param->isArray()) 1.97 + { 1.98 + TQualifier qualifier = param->getQualifier(); 1.99 + if ((qualifier == EvqOut) || (qualifier == EvqInOut)) 1.100 + { 1.101 + updateVersion(GLSL_VERSION_120); 1.102 + break; 1.103 + } 1.104 + } 1.105 + } 1.106 + // Fully processed. No need to visit children. 1.107 + visitChildren = false; 1.108 + break; 1.109 + } 1.110 + case EOpConstructMat2: 1.111 + case EOpConstructMat3: 1.112 + case EOpConstructMat4: { 1.113 + const TIntermSequence& sequence = node->getSequence(); 1.114 + if (sequence.size() == 1) { 1.115 + TIntermTyped* typed = sequence.front()->getAsTyped(); 1.116 + if (typed && typed->isMatrix()) { 1.117 + updateVersion(GLSL_VERSION_120); 1.118 + } 1.119 + } 1.120 + break; 1.121 + } 1.122 + 1.123 + default: break; 1.124 + } 1.125 + 1.126 + return visitChildren; 1.127 +} 1.128 + 1.129 +bool TVersionGLSL::visitLoop(Visit, TIntermLoop*) 1.130 +{ 1.131 + return true; 1.132 +} 1.133 + 1.134 +bool TVersionGLSL::visitBranch(Visit, TIntermBranch*) 1.135 +{ 1.136 + return true; 1.137 +} 1.138 + 1.139 +void TVersionGLSL::updateVersion(int version) 1.140 +{ 1.141 + mVersion = std::max(version, mVersion); 1.142 +} 1.143 +