1 //
2 // Copyright (c) 2002-2010 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/VersionGLSL.h"
8
9 static const int GLSL_VERSION_110 = 110;
10 static const int GLSL_VERSION_120 = 120;
11
12 // We need to scan for two things:
13 // 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
14 // but only at the global scope.
15 // 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
16 // but inside any scope.
17 // So we need to scan the entire fragment shader but only the global scope
18 // of vertex shader.
19 //
20 // TODO(alokp): The following two cases of invariant decalaration get lost
21 // during parsing - they do not get carried over to the intermediate tree.
22 // Handle these cases:
23 // 1. When a pragma is used to force all output variables to be invariant:
24 // - #pragma STDGL invariant(all)
25 // 2. When a previously decalared or built-in variable is marked invariant:
26 // - invariant gl_Position;
27 // - varying vec3 color; invariant color;
28 //
TVersionGLSL(ShShaderType type)29 TVersionGLSL::TVersionGLSL(ShShaderType type)
30 : mShaderType(type),
31 mVersion(GLSL_VERSION_110)
32 {
33 }
34
visitSymbol(TIntermSymbol * node)35 void TVersionGLSL::visitSymbol(TIntermSymbol* node)
36 {
37 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
38
39 if (node->getSymbol() == "gl_PointCoord")
40 updateVersion(GLSL_VERSION_120);
41 }
42
visitConstantUnion(TIntermConstantUnion *)43 void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
44 {
45 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
46 }
47
visitBinary(Visit,TIntermBinary *)48 bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
49 {
50 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
51 return true;
52 }
53
visitUnary(Visit,TIntermUnary *)54 bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
55 {
56 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
57 return true;
58 }
59
visitSelection(Visit,TIntermSelection *)60 bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
61 {
62 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
63 return true;
64 }
65
visitAggregate(Visit,TIntermAggregate * node)66 bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
67 {
68 // We need to scan the entire fragment shader but only the global scope
69 // of vertex shader.
70 bool visitChildren = mShaderType == SH_FRAGMENT_SHADER ? true : false;
71
72 switch (node->getOp()) {
73 case EOpSequence:
74 // We need to visit sequence children to get to global or inner scope.
75 visitChildren = true;
76 break;
77 case EOpDeclaration: {
78 const TIntermSequence& sequence = node->getSequence();
79 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
80 if ((qualifier == EvqInvariantVaryingIn) ||
81 (qualifier == EvqInvariantVaryingOut)) {
82 updateVersion(GLSL_VERSION_120);
83 }
84 break;
85 }
86 default: break;
87 }
88
89 return visitChildren;
90 }
91
visitLoop(Visit,TIntermLoop *)92 bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
93 {
94 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
95 return true;
96 }
97
visitBranch(Visit,TIntermBranch *)98 bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
99 {
100 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
101 return true;
102 }
103
updateVersion(int version)104 void TVersionGLSL::updateVersion(int version)
105 {
106 mVersion = std::max(version, mVersion);
107 }
108
109