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 | |
12 | namespace sh |
13 | { |
14 | |
15 | namespace |
16 | { |
17 | constexpr const ImmutableString kGlPointCoordString("gl_PointCoord" ); |
18 | } // anonymous namespace |
19 | |
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 | // |
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 | |
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 | |
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 | |
102 | bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) |
103 | { |
104 | ensureVersionIsAtLeast(GLSL_VERSION_120); |
105 | return true; |
106 | } |
107 | |
108 | void 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 | |
127 | bool 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 | |
144 | void TVersionGLSL::ensureVersionIsAtLeast(int version) |
145 | { |
146 | mVersion = std::max(version, mVersion); |
147 | } |
148 | |
149 | } // namespace sh |
150 | |