1//
2// Copyright (c) 2002-2012 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/VersionGLSL.h"
8
9#include "angle_gl.h"
10#include "compiler/translator/Symbol.h"
11
12namespace sh
13{
14
15namespace
16{
17constexpr const ImmutableString kGlPointCoordString("gl_PointCoord");
18} // anonymous namespace
19
20int 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//
69TVersionGLSL::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
83void 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
92bool 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
102bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node)
103{
104 ensureVersionIsAtLeast(GLSL_VERSION_120);
105 return true;
106}
107
108void TVersionGLSL::visitFunctionPrototype(TIntermFunctionPrototype *node)
109{
110 size_t paramCount = node->getFunction()->getParamCount();
111 for (size_t i = 0; i < paramCount; ++i)
112 {
113 const TVariable *param = node->getFunction()->getParam(i);
114 const TType &type = param->getType();
115 if (type.isArray())
116 {
117 TQualifier qualifier = type.getQualifier();
118 if ((qualifier == EvqOut) || (qualifier == EvqInOut))
119 {
120 ensureVersionIsAtLeast(GLSL_VERSION_120);
121 break;
122 }
123 }
124 }
125}
126
127bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
128{
129 if (node->getOp() == EOpConstruct && node->getType().isMatrix())
130 {
131 const TIntermSequence &sequence = *(node->getSequence());
132 if (sequence.size() == 1)
133 {
134 TIntermTyped *typed = sequence.front()->getAsTyped();
135 if (typed && typed->isMatrix())
136 {
137 ensureVersionIsAtLeast(GLSL_VERSION_120);
138 }
139 }
140 }
141 return true;
142}
143
144void TVersionGLSL::ensureVersionIsAtLeast(int version)
145{
146 mVersion = std::max(version, mVersion);
147}
148
149} // namespace sh
150