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/glsl/VersionGLSL.h"
8
9 #include "angle_gl.h"
10 #include "compiler/translator/Symbol.h"
11
12 namespace sh
13 {
14
15 namespace
16 {
17 constexpr const ImmutableString kGlPointCoordString("gl_PointCoord");
18 } // anonymous namespace
19
ShaderOutputTypeToGLSLVersion(ShShaderOutput output)20 int ShaderOutputTypeToGLSLVersion(ShShaderOutput output)
21 {
22 switch (output)
23 {
24 case SH_GLSL_130_OUTPUT:
25 return GLSL_VERSION_130;
26 case SH_GLSL_140_OUTPUT:
27 return GLSL_VERSION_140;
28 case SH_GLSL_150_CORE_OUTPUT:
29 return GLSL_VERSION_150;
30 case SH_GLSL_330_CORE_OUTPUT:
31 return GLSL_VERSION_330;
32 case SH_GLSL_400_CORE_OUTPUT:
33 return GLSL_VERSION_400;
34 case SH_GLSL_410_CORE_OUTPUT:
35 return GLSL_VERSION_410;
36 case SH_GLSL_420_CORE_OUTPUT:
37 return GLSL_VERSION_420;
38 case SH_GLSL_430_CORE_OUTPUT:
39 return GLSL_VERSION_430;
40 case SH_GLSL_440_CORE_OUTPUT:
41 return GLSL_VERSION_440;
42 case SH_GLSL_450_CORE_OUTPUT:
43 return GLSL_VERSION_450;
44 case SH_GLSL_COMPATIBILITY_OUTPUT:
45 return GLSL_VERSION_110;
46 default:
47 UNREACHABLE();
48 return 0;
49 }
50 }
51
52 // We need to scan for the following:
53 // 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
54 // but only at the global scope.
55 // 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
56 // but inside any scope.
57 // 3. Call to a matrix constructor with another matrix as argument.
58 // (These constructors were reserved in GLSL version 1.10.)
59 // 4. Arrays as "out" function parameters.
60 // GLSL spec section 6.1.1: "When calling a function, expressions that do
61 // not evaluate to l-values cannot be passed to parameters declared as
62 // out or inout."
63 // GLSL 1.1 section 5.8: "Other binary or unary expressions,
64 // non-dereferenced arrays, function names, swizzles with repeated fields,
65 // and constants cannot be l-values."
66 // GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
67 // are built-in types, entire structures or arrays... are all l-values."
68 //
TVersionGLSL(sh::GLenum type,const TPragma & pragma,ShShaderOutput output)69 TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output)
70 : TIntermTraverser(true, false, false)
71 {
72 mVersion = ShaderOutputTypeToGLSLVersion(output);
73 if (pragma.stdgl.invariantAll)
74 {
75 ensureVersionIsAtLeast(GLSL_VERSION_120);
76 }
77 if (type == GL_COMPUTE_SHADER)
78 {
79 ensureVersionIsAtLeast(GLSL_VERSION_430);
80 }
81 }
82
visitSymbol(TIntermSymbol * node)83 void TVersionGLSL::visitSymbol(TIntermSymbol *node)
84 {
85 if (node->variable().symbolType() == SymbolType::BuiltIn &&
86 node->getName() == kGlPointCoordString)
87 {
88 ensureVersionIsAtLeast(GLSL_VERSION_120);
89 }
90 }
91
visitDeclaration(Visit,TIntermDeclaration * node)92 bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node)
93 {
94 const TIntermSequence &sequence = *(node->getSequence());
95 if (sequence.front()->getAsTyped()->getType().isInvariant())
96 {
97 ensureVersionIsAtLeast(GLSL_VERSION_120);
98 }
99 return true;
100 }
101
visitGlobalQualifierDeclaration(Visit,TIntermGlobalQualifierDeclaration * node)102 bool TVersionGLSL::visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *node)
103 {
104 if (node->isPrecise())
105 {
106 ensureVersionIsAtLeast(GLSL_VERSION_420);
107 }
108 else
109 {
110 ensureVersionIsAtLeast(GLSL_VERSION_120);
111 }
112 return true;
113 }
114
visitFunctionPrototype(TIntermFunctionPrototype * node)115 void TVersionGLSL::visitFunctionPrototype(TIntermFunctionPrototype *node)
116 {
117 size_t paramCount = node->getFunction()->getParamCount();
118 for (size_t i = 0; i < paramCount; ++i)
119 {
120 const TVariable *param = node->getFunction()->getParam(i);
121 const TType &type = param->getType();
122 if (type.isArray())
123 {
124 TQualifier qualifier = type.getQualifier();
125 if ((qualifier == EvqParamOut) || (qualifier == EvqParamInOut))
126 {
127 ensureVersionIsAtLeast(GLSL_VERSION_120);
128 break;
129 }
130 }
131 }
132 }
133
visitAggregate(Visit,TIntermAggregate * node)134 bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
135 {
136 if (node->getOp() == EOpConstruct && node->getType().isMatrix())
137 {
138 const TIntermSequence &sequence = *(node->getSequence());
139 if (sequence.size() == 1)
140 {
141 TIntermTyped *typed = sequence.front()->getAsTyped();
142 if (typed && typed->isMatrix())
143 {
144 ensureVersionIsAtLeast(GLSL_VERSION_120);
145 }
146 }
147 }
148 return true;
149 }
150
ensureVersionIsAtLeast(int version)151 void TVersionGLSL::ensureVersionIsAtLeast(int version)
152 {
153 mVersion = std::max(version, mVersion);
154 }
155
156 } // namespace sh
157