xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.1 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Program interface
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31fProgramInterfaceDefinition.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "es31fProgramInterfaceDefinitionUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "gluVarType.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "deSTLUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
31*35238bceSAndroid Build Coastguard Worker 
32*35238bceSAndroid Build Coastguard Worker #include <set>
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker namespace deqp
35*35238bceSAndroid Build Coastguard Worker {
36*35238bceSAndroid Build Coastguard Worker namespace gles31
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker namespace Functional
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker namespace ProgramInterfaceDefinition
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker namespace
43*35238bceSAndroid Build Coastguard Worker {
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker static const glu::ShaderType s_shaderStageOrder[] = {
46*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_COMPUTE,
47*35238bceSAndroid Build Coastguard Worker 
48*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_VERTEX,
49*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_TESSELLATION_CONTROL,
50*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_TESSELLATION_EVALUATION,
51*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_GEOMETRY,
52*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_FRAGMENT,
53*35238bceSAndroid Build Coastguard Worker 
54*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_RAYGEN,
55*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_ANY_HIT,
56*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_CLOSEST_HIT,
57*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_MISS,
58*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_INTERSECTION,
59*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_CALLABLE,
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_TASK,
62*35238bceSAndroid Build Coastguard Worker     glu::SHADERTYPE_MESH,
63*35238bceSAndroid Build Coastguard Worker };
64*35238bceSAndroid Build Coastguard Worker 
65*35238bceSAndroid Build Coastguard Worker // s_shaderStageOrder does not contain ShaderType_LAST
66*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_shaderStageOrder) == glu::SHADERTYPE_LAST);
67*35238bceSAndroid Build Coastguard Worker 
containsMatchingSubtype(const glu::VarType & varType,bool (* predicate)(glu::DataType))68*35238bceSAndroid Build Coastguard Worker static bool containsMatchingSubtype(const glu::VarType &varType, bool (*predicate)(glu::DataType))
69*35238bceSAndroid Build Coastguard Worker {
70*35238bceSAndroid Build Coastguard Worker     if (varType.isBasicType() && predicate(varType.getBasicType()))
71*35238bceSAndroid Build Coastguard Worker         return true;
72*35238bceSAndroid Build Coastguard Worker 
73*35238bceSAndroid Build Coastguard Worker     if (varType.isArrayType())
74*35238bceSAndroid Build Coastguard Worker         return containsMatchingSubtype(varType.getElementType(), predicate);
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker     if (varType.isStructType())
77*35238bceSAndroid Build Coastguard Worker         for (int memberNdx = 0; memberNdx < varType.getStructPtr()->getNumMembers(); ++memberNdx)
78*35238bceSAndroid Build Coastguard Worker             if (containsMatchingSubtype(varType.getStructPtr()->getMember(memberNdx).getType(), predicate))
79*35238bceSAndroid Build Coastguard Worker                 return true;
80*35238bceSAndroid Build Coastguard Worker 
81*35238bceSAndroid Build Coastguard Worker     return false;
82*35238bceSAndroid Build Coastguard Worker }
83*35238bceSAndroid Build Coastguard Worker 
containsMatchingSubtype(const std::vector<glu::VariableDeclaration> & decls,bool (* predicate)(glu::DataType))84*35238bceSAndroid Build Coastguard Worker static bool containsMatchingSubtype(const std::vector<glu::VariableDeclaration> &decls,
85*35238bceSAndroid Build Coastguard Worker                                     bool (*predicate)(glu::DataType))
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker     for (int varNdx = 0; varNdx < (int)decls.size(); ++varNdx)
88*35238bceSAndroid Build Coastguard Worker         if (containsMatchingSubtype(decls[varNdx].varType, predicate))
89*35238bceSAndroid Build Coastguard Worker             return true;
90*35238bceSAndroid Build Coastguard Worker     return false;
91*35238bceSAndroid Build Coastguard Worker }
92*35238bceSAndroid Build Coastguard Worker 
isOpaqueType(glu::DataType type)93*35238bceSAndroid Build Coastguard Worker static bool isOpaqueType(glu::DataType type)
94*35238bceSAndroid Build Coastguard Worker {
95*35238bceSAndroid Build Coastguard Worker     return glu::isDataTypeAtomicCounter(type) || glu::isDataTypeImage(type) || glu::isDataTypeSampler(type);
96*35238bceSAndroid Build Coastguard Worker }
97*35238bceSAndroid Build Coastguard Worker 
getShaderStageIndex(glu::ShaderType stage)98*35238bceSAndroid Build Coastguard Worker static int getShaderStageIndex(glu::ShaderType stage)
99*35238bceSAndroid Build Coastguard Worker {
100*35238bceSAndroid Build Coastguard Worker     const glu::ShaderType *const it =
101*35238bceSAndroid Build Coastguard Worker         std::find(DE_ARRAY_BEGIN(s_shaderStageOrder), DE_ARRAY_END(s_shaderStageOrder), stage);
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker     if (it == DE_ARRAY_END(s_shaderStageOrder))
104*35238bceSAndroid Build Coastguard Worker         return -1;
105*35238bceSAndroid Build Coastguard Worker     else
106*35238bceSAndroid Build Coastguard Worker     {
107*35238bceSAndroid Build Coastguard Worker         const int index = (int)(it - DE_ARRAY_BEGIN(s_shaderStageOrder));
108*35238bceSAndroid Build Coastguard Worker         return index;
109*35238bceSAndroid Build Coastguard Worker     }
110*35238bceSAndroid Build Coastguard Worker }
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker } // namespace
113*35238bceSAndroid Build Coastguard Worker 
Shader(glu::ShaderType type,glu::GLSLVersion version)114*35238bceSAndroid Build Coastguard Worker Shader::Shader(glu::ShaderType type, glu::GLSLVersion version) : m_shaderType(type), m_version(version)
115*35238bceSAndroid Build Coastguard Worker {
116*35238bceSAndroid Build Coastguard Worker }
117*35238bceSAndroid Build Coastguard Worker 
~Shader(void)118*35238bceSAndroid Build Coastguard Worker Shader::~Shader(void)
119*35238bceSAndroid Build Coastguard Worker {
120*35238bceSAndroid Build Coastguard Worker }
121*35238bceSAndroid Build Coastguard Worker 
isIllegalVertexInput(const glu::VarType & varType)122*35238bceSAndroid Build Coastguard Worker static bool isIllegalVertexInput(const glu::VarType &varType)
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker     // booleans, opaque types, arrays, structs are not allowed as inputs
125*35238bceSAndroid Build Coastguard Worker     if (!varType.isBasicType())
126*35238bceSAndroid Build Coastguard Worker         return true;
127*35238bceSAndroid Build Coastguard Worker     if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
128*35238bceSAndroid Build Coastguard Worker         return true;
129*35238bceSAndroid Build Coastguard Worker     return false;
130*35238bceSAndroid Build Coastguard Worker }
131*35238bceSAndroid Build Coastguard Worker 
isIllegalVertexOutput(const glu::VarType & varType,bool insideAStruct=false,bool insideAnArray=false)132*35238bceSAndroid Build Coastguard Worker static bool isIllegalVertexOutput(const glu::VarType &varType, bool insideAStruct = false, bool insideAnArray = false)
133*35238bceSAndroid Build Coastguard Worker {
134*35238bceSAndroid Build Coastguard Worker     // booleans, opaque types, arrays of arrays, arrays of structs, array in struct, struct struct are not allowed as vertex outputs
135*35238bceSAndroid Build Coastguard Worker 
136*35238bceSAndroid Build Coastguard Worker     if (varType.isBasicType())
137*35238bceSAndroid Build Coastguard Worker     {
138*35238bceSAndroid Build Coastguard Worker         const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) &&
139*35238bceSAndroid Build Coastguard Worker                                   !glu::isDataTypeVector(varType.getBasicType()) &&
140*35238bceSAndroid Build Coastguard Worker                                   !glu::isDataTypeMatrix(varType.getBasicType());
141*35238bceSAndroid Build Coastguard Worker 
142*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
143*35238bceSAndroid Build Coastguard Worker             return true;
144*35238bceSAndroid Build Coastguard Worker 
145*35238bceSAndroid Build Coastguard Worker         if (isOpaqueType)
146*35238bceSAndroid Build Coastguard Worker             return true;
147*35238bceSAndroid Build Coastguard Worker 
148*35238bceSAndroid Build Coastguard Worker         return false;
149*35238bceSAndroid Build Coastguard Worker     }
150*35238bceSAndroid Build Coastguard Worker     else if (varType.isArrayType())
151*35238bceSAndroid Build Coastguard Worker     {
152*35238bceSAndroid Build Coastguard Worker         if (insideAnArray || insideAStruct)
153*35238bceSAndroid Build Coastguard Worker             return true;
154*35238bceSAndroid Build Coastguard Worker 
155*35238bceSAndroid Build Coastguard Worker         return isIllegalVertexOutput(varType.getElementType(), insideAStruct, true);
156*35238bceSAndroid Build Coastguard Worker     }
157*35238bceSAndroid Build Coastguard Worker     else if (varType.isStructType())
158*35238bceSAndroid Build Coastguard Worker     {
159*35238bceSAndroid Build Coastguard Worker         if (insideAnArray || insideAStruct)
160*35238bceSAndroid Build Coastguard Worker             return true;
161*35238bceSAndroid Build Coastguard Worker 
162*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
163*35238bceSAndroid Build Coastguard Worker             if (isIllegalVertexOutput(varType.getStructPtr()->getMember(ndx).getType(), true, insideAnArray))
164*35238bceSAndroid Build Coastguard Worker                 return true;
165*35238bceSAndroid Build Coastguard Worker 
166*35238bceSAndroid Build Coastguard Worker         return false;
167*35238bceSAndroid Build Coastguard Worker     }
168*35238bceSAndroid Build Coastguard Worker     else
169*35238bceSAndroid Build Coastguard Worker     {
170*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
171*35238bceSAndroid Build Coastguard Worker         return true;
172*35238bceSAndroid Build Coastguard Worker     }
173*35238bceSAndroid Build Coastguard Worker }
174*35238bceSAndroid Build Coastguard Worker 
isIllegalFragmentInput(const glu::VarType & varType)175*35238bceSAndroid Build Coastguard Worker static bool isIllegalFragmentInput(const glu::VarType &varType)
176*35238bceSAndroid Build Coastguard Worker {
177*35238bceSAndroid Build Coastguard Worker     return isIllegalVertexOutput(varType);
178*35238bceSAndroid Build Coastguard Worker }
179*35238bceSAndroid Build Coastguard Worker 
isIllegalFragmentOutput(const glu::VarType & varType,bool insideAnArray=false)180*35238bceSAndroid Build Coastguard Worker static bool isIllegalFragmentOutput(const glu::VarType &varType, bool insideAnArray = false)
181*35238bceSAndroid Build Coastguard Worker {
182*35238bceSAndroid Build Coastguard Worker     // booleans, opaque types, matrices, structs, arrays of arrays are not allowed as outputs
183*35238bceSAndroid Build Coastguard Worker 
184*35238bceSAndroid Build Coastguard Worker     if (varType.isBasicType())
185*35238bceSAndroid Build Coastguard Worker     {
186*35238bceSAndroid Build Coastguard Worker         const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) &&
187*35238bceSAndroid Build Coastguard Worker                                   !glu::isDataTypeVector(varType.getBasicType()) &&
188*35238bceSAndroid Build Coastguard Worker                                   !glu::isDataTypeMatrix(varType.getBasicType());
189*35238bceSAndroid Build Coastguard Worker 
190*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeBoolOrBVec(varType.getBasicType()) || isOpaqueType ||
191*35238bceSAndroid Build Coastguard Worker             glu::isDataTypeMatrix(varType.getBasicType()))
192*35238bceSAndroid Build Coastguard Worker             return true;
193*35238bceSAndroid Build Coastguard Worker         return false;
194*35238bceSAndroid Build Coastguard Worker     }
195*35238bceSAndroid Build Coastguard Worker     else if (varType.isArrayType())
196*35238bceSAndroid Build Coastguard Worker     {
197*35238bceSAndroid Build Coastguard Worker         if (insideAnArray)
198*35238bceSAndroid Build Coastguard Worker             return true;
199*35238bceSAndroid Build Coastguard Worker         return isIllegalFragmentOutput(varType.getElementType(), true);
200*35238bceSAndroid Build Coastguard Worker     }
201*35238bceSAndroid Build Coastguard Worker     else if (varType.isStructType())
202*35238bceSAndroid Build Coastguard Worker         return true;
203*35238bceSAndroid Build Coastguard Worker     else
204*35238bceSAndroid Build Coastguard Worker     {
205*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
206*35238bceSAndroid Build Coastguard Worker         return true;
207*35238bceSAndroid Build Coastguard Worker     }
208*35238bceSAndroid Build Coastguard Worker }
209*35238bceSAndroid Build Coastguard Worker 
isTypeIntegerOrContainsIntegers(const glu::VarType & varType)210*35238bceSAndroid Build Coastguard Worker static bool isTypeIntegerOrContainsIntegers(const glu::VarType &varType)
211*35238bceSAndroid Build Coastguard Worker {
212*35238bceSAndroid Build Coastguard Worker     if (varType.isBasicType())
213*35238bceSAndroid Build Coastguard Worker         return glu::isDataTypeIntOrIVec(varType.getBasicType()) || glu::isDataTypeUintOrUVec(varType.getBasicType());
214*35238bceSAndroid Build Coastguard Worker     else if (varType.isArrayType())
215*35238bceSAndroid Build Coastguard Worker         return isTypeIntegerOrContainsIntegers(varType.getElementType());
216*35238bceSAndroid Build Coastguard Worker     else if (varType.isStructType())
217*35238bceSAndroid Build Coastguard Worker     {
218*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
219*35238bceSAndroid Build Coastguard Worker             if (isTypeIntegerOrContainsIntegers(varType.getStructPtr()->getMember(ndx).getType()))
220*35238bceSAndroid Build Coastguard Worker                 return true;
221*35238bceSAndroid Build Coastguard Worker         return false;
222*35238bceSAndroid Build Coastguard Worker     }
223*35238bceSAndroid Build Coastguard Worker     else
224*35238bceSAndroid Build Coastguard Worker     {
225*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
226*35238bceSAndroid Build Coastguard Worker         return true;
227*35238bceSAndroid Build Coastguard Worker     }
228*35238bceSAndroid Build Coastguard Worker }
229*35238bceSAndroid Build Coastguard Worker 
isValid(void) const230*35238bceSAndroid Build Coastguard Worker bool Shader::isValid(void) const
231*35238bceSAndroid Build Coastguard Worker {
232*35238bceSAndroid Build Coastguard Worker     // Default block variables
233*35238bceSAndroid Build Coastguard Worker     {
234*35238bceSAndroid Build Coastguard Worker         for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
235*35238bceSAndroid Build Coastguard Worker         {
236*35238bceSAndroid Build Coastguard Worker             // atomic declaration in the default block without binding
237*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].layout.binding == -1 &&
238*35238bceSAndroid Build Coastguard Worker                 containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter))
239*35238bceSAndroid Build Coastguard Worker                 return false;
240*35238bceSAndroid Build Coastguard Worker 
241*35238bceSAndroid Build Coastguard Worker             // atomic declaration in a struct
242*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].varType.isStructType() &&
243*35238bceSAndroid Build Coastguard Worker                 containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter))
244*35238bceSAndroid Build Coastguard Worker                 return false;
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker             // Unsupported layout qualifiers
247*35238bceSAndroid Build Coastguard Worker 
248*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].layout.matrixOrder != glu::MATRIXORDER_LAST)
249*35238bceSAndroid Build Coastguard Worker                 return false;
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker             if (containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeSampler))
252*35238bceSAndroid Build Coastguard Worker             {
253*35238bceSAndroid Build Coastguard Worker                 const glu::Layout layoutWithLocationAndBinding(m_defaultBlock.variables[varNdx].layout.location,
254*35238bceSAndroid Build Coastguard Worker                                                                m_defaultBlock.variables[varNdx].layout.binding);
255*35238bceSAndroid Build Coastguard Worker 
256*35238bceSAndroid Build Coastguard Worker                 if (m_defaultBlock.variables[varNdx].layout != layoutWithLocationAndBinding)
257*35238bceSAndroid Build Coastguard Worker                     return false;
258*35238bceSAndroid Build Coastguard Worker             }
259*35238bceSAndroid Build Coastguard Worker         }
260*35238bceSAndroid Build Coastguard Worker     }
261*35238bceSAndroid Build Coastguard Worker 
262*35238bceSAndroid Build Coastguard Worker     // Interface blocks
263*35238bceSAndroid Build Coastguard Worker     {
264*35238bceSAndroid Build Coastguard Worker         for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
265*35238bceSAndroid Build Coastguard Worker         {
266*35238bceSAndroid Build Coastguard Worker             // ES31 disallows interface block array arrays
267*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.size() > 1)
268*35238bceSAndroid Build Coastguard Worker                 return false;
269*35238bceSAndroid Build Coastguard Worker 
270*35238bceSAndroid Build Coastguard Worker             // Interface block arrays must have instance name
271*35238bceSAndroid Build Coastguard Worker             if (!m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty() &&
272*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].instanceName.empty())
273*35238bceSAndroid Build Coastguard Worker                 return false;
274*35238bceSAndroid Build Coastguard Worker 
275*35238bceSAndroid Build Coastguard Worker             // Opaque types in interface block
276*35238bceSAndroid Build Coastguard Worker             if (containsMatchingSubtype(m_defaultBlock.interfaceBlocks[interfaceNdx].variables, isOpaqueType))
277*35238bceSAndroid Build Coastguard Worker                 return false;
278*35238bceSAndroid Build Coastguard Worker         }
279*35238bceSAndroid Build Coastguard Worker     }
280*35238bceSAndroid Build Coastguard Worker 
281*35238bceSAndroid Build Coastguard Worker     // Shader type specific
282*35238bceSAndroid Build Coastguard Worker 
283*35238bceSAndroid Build Coastguard Worker     if (m_shaderType == glu::SHADERTYPE_VERTEX)
284*35238bceSAndroid Build Coastguard Worker     {
285*35238bceSAndroid Build Coastguard Worker         for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
286*35238bceSAndroid Build Coastguard Worker         {
287*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN &&
288*35238bceSAndroid Build Coastguard Worker                 isIllegalVertexInput(m_defaultBlock.variables[varNdx].varType))
289*35238bceSAndroid Build Coastguard Worker                 return false;
290*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT &&
291*35238bceSAndroid Build Coastguard Worker                 isIllegalVertexOutput(m_defaultBlock.variables[varNdx].varType))
292*35238bceSAndroid Build Coastguard Worker                 return false;
293*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT &&
294*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT &&
295*35238bceSAndroid Build Coastguard Worker                 isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
296*35238bceSAndroid Build Coastguard Worker                 return false;
297*35238bceSAndroid Build Coastguard Worker         }
298*35238bceSAndroid Build Coastguard Worker         for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
299*35238bceSAndroid Build Coastguard Worker         {
300*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN ||
301*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN ||
302*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
303*35238bceSAndroid Build Coastguard Worker             {
304*35238bceSAndroid Build Coastguard Worker                 return false;
305*35238bceSAndroid Build Coastguard Worker             }
306*35238bceSAndroid Build Coastguard Worker         }
307*35238bceSAndroid Build Coastguard Worker     }
308*35238bceSAndroid Build Coastguard Worker     else if (m_shaderType == glu::SHADERTYPE_FRAGMENT)
309*35238bceSAndroid Build Coastguard Worker     {
310*35238bceSAndroid Build Coastguard Worker         for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
311*35238bceSAndroid Build Coastguard Worker         {
312*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN &&
313*35238bceSAndroid Build Coastguard Worker                 isIllegalFragmentInput(m_defaultBlock.variables[varNdx].varType))
314*35238bceSAndroid Build Coastguard Worker                 return false;
315*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN &&
316*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT &&
317*35238bceSAndroid Build Coastguard Worker                 isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
318*35238bceSAndroid Build Coastguard Worker                 return false;
319*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT &&
320*35238bceSAndroid Build Coastguard Worker                 isIllegalFragmentOutput(m_defaultBlock.variables[varNdx].varType))
321*35238bceSAndroid Build Coastguard Worker                 return false;
322*35238bceSAndroid Build Coastguard Worker         }
323*35238bceSAndroid Build Coastguard Worker         for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
324*35238bceSAndroid Build Coastguard Worker         {
325*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN ||
326*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT ||
327*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
328*35238bceSAndroid Build Coastguard Worker             {
329*35238bceSAndroid Build Coastguard Worker                 return false;
330*35238bceSAndroid Build Coastguard Worker             }
331*35238bceSAndroid Build Coastguard Worker         }
332*35238bceSAndroid Build Coastguard Worker     }
333*35238bceSAndroid Build Coastguard Worker     else if (m_shaderType == glu::SHADERTYPE_COMPUTE)
334*35238bceSAndroid Build Coastguard Worker     {
335*35238bceSAndroid Build Coastguard Worker         for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
336*35238bceSAndroid Build Coastguard Worker         {
337*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN ||
338*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN ||
339*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT ||
340*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
341*35238bceSAndroid Build Coastguard Worker             {
342*35238bceSAndroid Build Coastguard Worker                 return false;
343*35238bceSAndroid Build Coastguard Worker             }
344*35238bceSAndroid Build Coastguard Worker         }
345*35238bceSAndroid Build Coastguard Worker         for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
346*35238bceSAndroid Build Coastguard Worker         {
347*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN ||
348*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN ||
349*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT ||
350*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
351*35238bceSAndroid Build Coastguard Worker             {
352*35238bceSAndroid Build Coastguard Worker                 return false;
353*35238bceSAndroid Build Coastguard Worker             }
354*35238bceSAndroid Build Coastguard Worker         }
355*35238bceSAndroid Build Coastguard Worker     }
356*35238bceSAndroid Build Coastguard Worker     else if (m_shaderType == glu::SHADERTYPE_GEOMETRY)
357*35238bceSAndroid Build Coastguard Worker     {
358*35238bceSAndroid Build Coastguard Worker         for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
359*35238bceSAndroid Build Coastguard Worker         {
360*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN ||
361*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
362*35238bceSAndroid Build Coastguard Worker             {
363*35238bceSAndroid Build Coastguard Worker                 return false;
364*35238bceSAndroid Build Coastguard Worker             }
365*35238bceSAndroid Build Coastguard Worker             // arrayed input
366*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN &&
367*35238bceSAndroid Build Coastguard Worker                 !m_defaultBlock.variables[varNdx].varType.isArrayType())
368*35238bceSAndroid Build Coastguard Worker                 return false;
369*35238bceSAndroid Build Coastguard Worker         }
370*35238bceSAndroid Build Coastguard Worker         for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
371*35238bceSAndroid Build Coastguard Worker         {
372*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN ||
373*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
374*35238bceSAndroid Build Coastguard Worker             {
375*35238bceSAndroid Build Coastguard Worker                 return false;
376*35238bceSAndroid Build Coastguard Worker             }
377*35238bceSAndroid Build Coastguard Worker             // arrayed input
378*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN &&
379*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
380*35238bceSAndroid Build Coastguard Worker                 return false;
381*35238bceSAndroid Build Coastguard Worker         }
382*35238bceSAndroid Build Coastguard Worker     }
383*35238bceSAndroid Build Coastguard Worker     else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
384*35238bceSAndroid Build Coastguard Worker     {
385*35238bceSAndroid Build Coastguard Worker         for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
386*35238bceSAndroid Build Coastguard Worker         {
387*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN)
388*35238bceSAndroid Build Coastguard Worker                 return false;
389*35238bceSAndroid Build Coastguard Worker             // arrayed input
390*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN &&
391*35238bceSAndroid Build Coastguard Worker                 !m_defaultBlock.variables[varNdx].varType.isArrayType())
392*35238bceSAndroid Build Coastguard Worker                 return false;
393*35238bceSAndroid Build Coastguard Worker             // arrayed output
394*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT &&
395*35238bceSAndroid Build Coastguard Worker                 !m_defaultBlock.variables[varNdx].varType.isArrayType())
396*35238bceSAndroid Build Coastguard Worker                 return false;
397*35238bceSAndroid Build Coastguard Worker         }
398*35238bceSAndroid Build Coastguard Worker         for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
399*35238bceSAndroid Build Coastguard Worker         {
400*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN)
401*35238bceSAndroid Build Coastguard Worker                 return false;
402*35238bceSAndroid Build Coastguard Worker             // arrayed input
403*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN &&
404*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
405*35238bceSAndroid Build Coastguard Worker                 return false;
406*35238bceSAndroid Build Coastguard Worker             // arrayed output
407*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT &&
408*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
409*35238bceSAndroid Build Coastguard Worker                 return false;
410*35238bceSAndroid Build Coastguard Worker         }
411*35238bceSAndroid Build Coastguard Worker     }
412*35238bceSAndroid Build Coastguard Worker     else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
413*35238bceSAndroid Build Coastguard Worker     {
414*35238bceSAndroid Build Coastguard Worker         for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
415*35238bceSAndroid Build Coastguard Worker         {
416*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
417*35238bceSAndroid Build Coastguard Worker                 return false;
418*35238bceSAndroid Build Coastguard Worker             // arrayed input
419*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN &&
420*35238bceSAndroid Build Coastguard Worker                 !m_defaultBlock.variables[varNdx].varType.isArrayType())
421*35238bceSAndroid Build Coastguard Worker                 return false;
422*35238bceSAndroid Build Coastguard Worker         }
423*35238bceSAndroid Build Coastguard Worker         for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
424*35238bceSAndroid Build Coastguard Worker         {
425*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
426*35238bceSAndroid Build Coastguard Worker                 return false;
427*35238bceSAndroid Build Coastguard Worker             // arrayed input
428*35238bceSAndroid Build Coastguard Worker             if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN &&
429*35238bceSAndroid Build Coastguard Worker                 m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
430*35238bceSAndroid Build Coastguard Worker                 return false;
431*35238bceSAndroid Build Coastguard Worker         }
432*35238bceSAndroid Build Coastguard Worker     }
433*35238bceSAndroid Build Coastguard Worker     else
434*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
435*35238bceSAndroid Build Coastguard Worker 
436*35238bceSAndroid Build Coastguard Worker     return true;
437*35238bceSAndroid Build Coastguard Worker }
438*35238bceSAndroid Build Coastguard Worker 
Program(void)439*35238bceSAndroid Build Coastguard Worker Program::Program(void) : m_separable(false), m_xfbMode(0), m_geoNumOutputVertices(0), m_tessNumOutputVertices(0)
440*35238bceSAndroid Build Coastguard Worker {
441*35238bceSAndroid Build Coastguard Worker }
442*35238bceSAndroid Build Coastguard Worker 
collectStructPtrs(std::set<const glu::StructType * > & dst,const glu::VarType & type)443*35238bceSAndroid Build Coastguard Worker static void collectStructPtrs(std::set<const glu::StructType *> &dst, const glu::VarType &type)
444*35238bceSAndroid Build Coastguard Worker {
445*35238bceSAndroid Build Coastguard Worker     if (type.isArrayType())
446*35238bceSAndroid Build Coastguard Worker         collectStructPtrs(dst, type.getElementType());
447*35238bceSAndroid Build Coastguard Worker     else if (type.isStructType())
448*35238bceSAndroid Build Coastguard Worker     {
449*35238bceSAndroid Build Coastguard Worker         dst.insert(type.getStructPtr());
450*35238bceSAndroid Build Coastguard Worker 
451*35238bceSAndroid Build Coastguard Worker         for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
452*35238bceSAndroid Build Coastguard Worker             collectStructPtrs(dst, type.getStructPtr()->getMember(memberNdx).getType());
453*35238bceSAndroid Build Coastguard Worker     }
454*35238bceSAndroid Build Coastguard Worker }
455*35238bceSAndroid Build Coastguard Worker 
~Program(void)456*35238bceSAndroid Build Coastguard Worker Program::~Program(void)
457*35238bceSAndroid Build Coastguard Worker {
458*35238bceSAndroid Build Coastguard Worker     // delete shader struct types, need to be done by the program since shaders might share struct types
459*35238bceSAndroid Build Coastguard Worker     {
460*35238bceSAndroid Build Coastguard Worker         std::set<const glu::StructType *> structTypes;
461*35238bceSAndroid Build Coastguard Worker 
462*35238bceSAndroid Build Coastguard Worker         for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
463*35238bceSAndroid Build Coastguard Worker         {
464*35238bceSAndroid Build Coastguard Worker             for (int varNdx = 0; varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.variables.size(); ++varNdx)
465*35238bceSAndroid Build Coastguard Worker                 collectStructPtrs(structTypes, m_shaders[shaderNdx]->m_defaultBlock.variables[varNdx].varType);
466*35238bceSAndroid Build Coastguard Worker 
467*35238bceSAndroid Build Coastguard Worker             for (int interfaceNdx = 0; interfaceNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks.size();
468*35238bceSAndroid Build Coastguard Worker                  ++interfaceNdx)
469*35238bceSAndroid Build Coastguard Worker                 for (int varNdx = 0;
470*35238bceSAndroid Build Coastguard Worker                      varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables.size();
471*35238bceSAndroid Build Coastguard Worker                      ++varNdx)
472*35238bceSAndroid Build Coastguard Worker                     collectStructPtrs(
473*35238bceSAndroid Build Coastguard Worker                         structTypes,
474*35238bceSAndroid Build Coastguard Worker                         m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables[varNdx].varType);
475*35238bceSAndroid Build Coastguard Worker         }
476*35238bceSAndroid Build Coastguard Worker 
477*35238bceSAndroid Build Coastguard Worker         for (std::set<const glu::StructType *>::iterator it = structTypes.begin(); it != structTypes.end(); ++it)
478*35238bceSAndroid Build Coastguard Worker             delete *it;
479*35238bceSAndroid Build Coastguard Worker     }
480*35238bceSAndroid Build Coastguard Worker 
481*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
482*35238bceSAndroid Build Coastguard Worker         delete m_shaders[shaderNdx];
483*35238bceSAndroid Build Coastguard Worker     m_shaders.clear();
484*35238bceSAndroid Build Coastguard Worker }
485*35238bceSAndroid Build Coastguard Worker 
addShader(glu::ShaderType type,glu::GLSLVersion version)486*35238bceSAndroid Build Coastguard Worker Shader *Program::addShader(glu::ShaderType type, glu::GLSLVersion version)
487*35238bceSAndroid Build Coastguard Worker {
488*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(type < glu::SHADERTYPE_LAST);
489*35238bceSAndroid Build Coastguard Worker 
490*35238bceSAndroid Build Coastguard Worker     Shader *shader;
491*35238bceSAndroid Build Coastguard Worker 
492*35238bceSAndroid Build Coastguard Worker     // make sure push_back() cannot throw
493*35238bceSAndroid Build Coastguard Worker     m_shaders.reserve(m_shaders.size() + 1);
494*35238bceSAndroid Build Coastguard Worker 
495*35238bceSAndroid Build Coastguard Worker     shader = new Shader(type, version);
496*35238bceSAndroid Build Coastguard Worker     m_shaders.push_back(shader);
497*35238bceSAndroid Build Coastguard Worker 
498*35238bceSAndroid Build Coastguard Worker     return shader;
499*35238bceSAndroid Build Coastguard Worker }
500*35238bceSAndroid Build Coastguard Worker 
setSeparable(bool separable)501*35238bceSAndroid Build Coastguard Worker void Program::setSeparable(bool separable)
502*35238bceSAndroid Build Coastguard Worker {
503*35238bceSAndroid Build Coastguard Worker     m_separable = separable;
504*35238bceSAndroid Build Coastguard Worker }
505*35238bceSAndroid Build Coastguard Worker 
isSeparable(void) const506*35238bceSAndroid Build Coastguard Worker bool Program::isSeparable(void) const
507*35238bceSAndroid Build Coastguard Worker {
508*35238bceSAndroid Build Coastguard Worker     return m_separable;
509*35238bceSAndroid Build Coastguard Worker }
510*35238bceSAndroid Build Coastguard Worker 
getShaders(void) const511*35238bceSAndroid Build Coastguard Worker const std::vector<Shader *> &Program::getShaders(void) const
512*35238bceSAndroid Build Coastguard Worker {
513*35238bceSAndroid Build Coastguard Worker     return m_shaders;
514*35238bceSAndroid Build Coastguard Worker }
515*35238bceSAndroid Build Coastguard Worker 
getFirstStage(void) const516*35238bceSAndroid Build Coastguard Worker glu::ShaderType Program::getFirstStage(void) const
517*35238bceSAndroid Build Coastguard Worker {
518*35238bceSAndroid Build Coastguard Worker     const int nullValue = DE_LENGTH_OF_ARRAY(s_shaderStageOrder);
519*35238bceSAndroid Build Coastguard Worker     int firstStage      = nullValue;
520*35238bceSAndroid Build Coastguard Worker 
521*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
522*35238bceSAndroid Build Coastguard Worker     {
523*35238bceSAndroid Build Coastguard Worker         const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
524*35238bceSAndroid Build Coastguard Worker         if (index != -1)
525*35238bceSAndroid Build Coastguard Worker             firstStage = de::min(firstStage, index);
526*35238bceSAndroid Build Coastguard Worker     }
527*35238bceSAndroid Build Coastguard Worker 
528*35238bceSAndroid Build Coastguard Worker     if (firstStage == nullValue)
529*35238bceSAndroid Build Coastguard Worker         return glu::SHADERTYPE_LAST;
530*35238bceSAndroid Build Coastguard Worker     else
531*35238bceSAndroid Build Coastguard Worker         return s_shaderStageOrder[firstStage];
532*35238bceSAndroid Build Coastguard Worker }
533*35238bceSAndroid Build Coastguard Worker 
getLastStage(void) const534*35238bceSAndroid Build Coastguard Worker glu::ShaderType Program::getLastStage(void) const
535*35238bceSAndroid Build Coastguard Worker {
536*35238bceSAndroid Build Coastguard Worker     const int nullValue = -1;
537*35238bceSAndroid Build Coastguard Worker     int lastStage       = nullValue;
538*35238bceSAndroid Build Coastguard Worker 
539*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
540*35238bceSAndroid Build Coastguard Worker     {
541*35238bceSAndroid Build Coastguard Worker         const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
542*35238bceSAndroid Build Coastguard Worker         if (index != -1)
543*35238bceSAndroid Build Coastguard Worker             lastStage = de::max(lastStage, index);
544*35238bceSAndroid Build Coastguard Worker     }
545*35238bceSAndroid Build Coastguard Worker 
546*35238bceSAndroid Build Coastguard Worker     if (lastStage == nullValue)
547*35238bceSAndroid Build Coastguard Worker         return glu::SHADERTYPE_LAST;
548*35238bceSAndroid Build Coastguard Worker     else
549*35238bceSAndroid Build Coastguard Worker         return s_shaderStageOrder[lastStage];
550*35238bceSAndroid Build Coastguard Worker }
551*35238bceSAndroid Build Coastguard Worker 
hasStage(glu::ShaderType stage) const552*35238bceSAndroid Build Coastguard Worker bool Program::hasStage(glu::ShaderType stage) const
553*35238bceSAndroid Build Coastguard Worker {
554*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
555*35238bceSAndroid Build Coastguard Worker     {
556*35238bceSAndroid Build Coastguard Worker         if (m_shaders[shaderNdx]->getType() == stage)
557*35238bceSAndroid Build Coastguard Worker             return true;
558*35238bceSAndroid Build Coastguard Worker     }
559*35238bceSAndroid Build Coastguard Worker     return false;
560*35238bceSAndroid Build Coastguard Worker }
561*35238bceSAndroid Build Coastguard Worker 
addTransformFeedbackVarying(const std::string & varName)562*35238bceSAndroid Build Coastguard Worker void Program::addTransformFeedbackVarying(const std::string &varName)
563*35238bceSAndroid Build Coastguard Worker {
564*35238bceSAndroid Build Coastguard Worker     m_xfbVaryings.push_back(varName);
565*35238bceSAndroid Build Coastguard Worker }
566*35238bceSAndroid Build Coastguard Worker 
getTransformFeedbackVaryings(void) const567*35238bceSAndroid Build Coastguard Worker const std::vector<std::string> &Program::getTransformFeedbackVaryings(void) const
568*35238bceSAndroid Build Coastguard Worker {
569*35238bceSAndroid Build Coastguard Worker     return m_xfbVaryings;
570*35238bceSAndroid Build Coastguard Worker }
571*35238bceSAndroid Build Coastguard Worker 
setTransformFeedbackMode(uint32_t mode)572*35238bceSAndroid Build Coastguard Worker void Program::setTransformFeedbackMode(uint32_t mode)
573*35238bceSAndroid Build Coastguard Worker {
574*35238bceSAndroid Build Coastguard Worker     m_xfbMode = mode;
575*35238bceSAndroid Build Coastguard Worker }
576*35238bceSAndroid Build Coastguard Worker 
getTransformFeedbackMode(void) const577*35238bceSAndroid Build Coastguard Worker uint32_t Program::getTransformFeedbackMode(void) const
578*35238bceSAndroid Build Coastguard Worker {
579*35238bceSAndroid Build Coastguard Worker     return m_xfbMode;
580*35238bceSAndroid Build Coastguard Worker }
581*35238bceSAndroid Build Coastguard Worker 
getGeometryNumOutputVertices(void) const582*35238bceSAndroid Build Coastguard Worker uint32_t Program::getGeometryNumOutputVertices(void) const
583*35238bceSAndroid Build Coastguard Worker {
584*35238bceSAndroid Build Coastguard Worker     return m_geoNumOutputVertices;
585*35238bceSAndroid Build Coastguard Worker }
586*35238bceSAndroid Build Coastguard Worker 
setGeometryNumOutputVertices(uint32_t vertices)587*35238bceSAndroid Build Coastguard Worker void Program::setGeometryNumOutputVertices(uint32_t vertices)
588*35238bceSAndroid Build Coastguard Worker {
589*35238bceSAndroid Build Coastguard Worker     m_geoNumOutputVertices = vertices;
590*35238bceSAndroid Build Coastguard Worker }
591*35238bceSAndroid Build Coastguard Worker 
getTessellationNumOutputPatchVertices(void) const592*35238bceSAndroid Build Coastguard Worker uint32_t Program::getTessellationNumOutputPatchVertices(void) const
593*35238bceSAndroid Build Coastguard Worker {
594*35238bceSAndroid Build Coastguard Worker     return m_tessNumOutputVertices;
595*35238bceSAndroid Build Coastguard Worker }
596*35238bceSAndroid Build Coastguard Worker 
setTessellationNumOutputPatchVertices(uint32_t vertices)597*35238bceSAndroid Build Coastguard Worker void Program::setTessellationNumOutputPatchVertices(uint32_t vertices)
598*35238bceSAndroid Build Coastguard Worker {
599*35238bceSAndroid Build Coastguard Worker     m_tessNumOutputVertices = vertices;
600*35238bceSAndroid Build Coastguard Worker }
601*35238bceSAndroid Build Coastguard Worker 
isValid(void) const602*35238bceSAndroid Build Coastguard Worker bool Program::isValid(void) const
603*35238bceSAndroid Build Coastguard Worker {
604*35238bceSAndroid Build Coastguard Worker     const bool isOpenGLES   = (m_shaders.empty()) ? (false) : (glu::glslVersionIsES(m_shaders[0]->getVersion()));
605*35238bceSAndroid Build Coastguard Worker     bool computePresent     = false;
606*35238bceSAndroid Build Coastguard Worker     bool vertexPresent      = false;
607*35238bceSAndroid Build Coastguard Worker     bool fragmentPresent    = false;
608*35238bceSAndroid Build Coastguard Worker     bool tessControlPresent = false;
609*35238bceSAndroid Build Coastguard Worker     bool tessEvalPresent    = false;
610*35238bceSAndroid Build Coastguard Worker     bool geometryPresent    = false;
611*35238bceSAndroid Build Coastguard Worker 
612*35238bceSAndroid Build Coastguard Worker     if (m_shaders.empty())
613*35238bceSAndroid Build Coastguard Worker         return false;
614*35238bceSAndroid Build Coastguard Worker 
615*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
616*35238bceSAndroid Build Coastguard Worker         if (!m_shaders[ndx]->isValid())
617*35238bceSAndroid Build Coastguard Worker             return false;
618*35238bceSAndroid Build Coastguard Worker 
619*35238bceSAndroid Build Coastguard Worker     // same version
620*35238bceSAndroid Build Coastguard Worker     for (int ndx = 1; ndx < (int)m_shaders.size(); ++ndx)
621*35238bceSAndroid Build Coastguard Worker         if (m_shaders[0]->getVersion() != m_shaders[ndx]->getVersion())
622*35238bceSAndroid Build Coastguard Worker             return false;
623*35238bceSAndroid Build Coastguard Worker 
624*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
625*35238bceSAndroid Build Coastguard Worker     {
626*35238bceSAndroid Build Coastguard Worker         switch (m_shaders[ndx]->getType())
627*35238bceSAndroid Build Coastguard Worker         {
628*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_COMPUTE:
629*35238bceSAndroid Build Coastguard Worker             computePresent = true;
630*35238bceSAndroid Build Coastguard Worker             break;
631*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_VERTEX:
632*35238bceSAndroid Build Coastguard Worker             vertexPresent = true;
633*35238bceSAndroid Build Coastguard Worker             break;
634*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_FRAGMENT:
635*35238bceSAndroid Build Coastguard Worker             fragmentPresent = true;
636*35238bceSAndroid Build Coastguard Worker             break;
637*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_TESSELLATION_CONTROL:
638*35238bceSAndroid Build Coastguard Worker             tessControlPresent = true;
639*35238bceSAndroid Build Coastguard Worker             break;
640*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_TESSELLATION_EVALUATION:
641*35238bceSAndroid Build Coastguard Worker             tessEvalPresent = true;
642*35238bceSAndroid Build Coastguard Worker             break;
643*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_GEOMETRY:
644*35238bceSAndroid Build Coastguard Worker             geometryPresent = true;
645*35238bceSAndroid Build Coastguard Worker             break;
646*35238bceSAndroid Build Coastguard Worker         default:
647*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
648*35238bceSAndroid Build Coastguard Worker             break;
649*35238bceSAndroid Build Coastguard Worker         }
650*35238bceSAndroid Build Coastguard Worker     }
651*35238bceSAndroid Build Coastguard Worker     // compute present -> no other stages present
652*35238bceSAndroid Build Coastguard Worker     {
653*35238bceSAndroid Build Coastguard Worker         const bool nonComputePresent =
654*35238bceSAndroid Build Coastguard Worker             vertexPresent || fragmentPresent || tessControlPresent || tessEvalPresent || geometryPresent;
655*35238bceSAndroid Build Coastguard Worker         if (computePresent && nonComputePresent)
656*35238bceSAndroid Build Coastguard Worker             return false;
657*35238bceSAndroid Build Coastguard Worker     }
658*35238bceSAndroid Build Coastguard Worker 
659*35238bceSAndroid Build Coastguard Worker     // must contain both vertex and fragment shaders
660*35238bceSAndroid Build Coastguard Worker     if (!computePresent && !m_separable)
661*35238bceSAndroid Build Coastguard Worker     {
662*35238bceSAndroid Build Coastguard Worker         if (!vertexPresent || !fragmentPresent)
663*35238bceSAndroid Build Coastguard Worker             return false;
664*35238bceSAndroid Build Coastguard Worker     }
665*35238bceSAndroid Build Coastguard Worker 
666*35238bceSAndroid Build Coastguard Worker     // tess.Eval present <=> tess.Control present
667*35238bceSAndroid Build Coastguard Worker     if (!m_separable)
668*35238bceSAndroid Build Coastguard Worker     {
669*35238bceSAndroid Build Coastguard Worker         if (tessEvalPresent != tessControlPresent)
670*35238bceSAndroid Build Coastguard Worker             return false;
671*35238bceSAndroid Build Coastguard Worker     }
672*35238bceSAndroid Build Coastguard Worker 
673*35238bceSAndroid Build Coastguard Worker     if ((m_tessNumOutputVertices != 0) != (tessControlPresent || tessEvalPresent))
674*35238bceSAndroid Build Coastguard Worker         return false;
675*35238bceSAndroid Build Coastguard Worker 
676*35238bceSAndroid Build Coastguard Worker     if ((m_geoNumOutputVertices != 0) != geometryPresent)
677*35238bceSAndroid Build Coastguard Worker         return false;
678*35238bceSAndroid Build Coastguard Worker 
679*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)m_xfbVaryings.size(); ++ndx)
680*35238bceSAndroid Build Coastguard Worker     {
681*35238bceSAndroid Build Coastguard Worker         // user-defined
682*35238bceSAndroid Build Coastguard Worker         if (!de::beginsWith(m_xfbVaryings[ndx], "gl_"))
683*35238bceSAndroid Build Coastguard Worker         {
684*35238bceSAndroid Build Coastguard Worker             std::vector<ProgramInterfaceDefinition::VariablePathComponent> path;
685*35238bceSAndroid Build Coastguard Worker             if (!findProgramVariablePathByPathName(path, this, m_xfbVaryings[ndx],
686*35238bceSAndroid Build Coastguard Worker                                                    VariableSearchFilter::createShaderTypeStorageFilter(
687*35238bceSAndroid Build Coastguard Worker                                                        getProgramTransformFeedbackStage(this), glu::STORAGE_OUT)))
688*35238bceSAndroid Build Coastguard Worker                 return false;
689*35238bceSAndroid Build Coastguard Worker             if (!path.back().isVariableType())
690*35238bceSAndroid Build Coastguard Worker                 return false;
691*35238bceSAndroid Build Coastguard Worker 
692*35238bceSAndroid Build Coastguard Worker             // Khronos bug #12787 disallowed capturing whole structs in OpenGL ES.
693*35238bceSAndroid Build Coastguard Worker             if (path.back().getVariableType()->isStructType() && isOpenGLES)
694*35238bceSAndroid Build Coastguard Worker                 return false;
695*35238bceSAndroid Build Coastguard Worker         }
696*35238bceSAndroid Build Coastguard Worker     }
697*35238bceSAndroid Build Coastguard Worker 
698*35238bceSAndroid Build Coastguard Worker     return true;
699*35238bceSAndroid Build Coastguard Worker }
700*35238bceSAndroid Build Coastguard Worker 
701*35238bceSAndroid Build Coastguard Worker } // namespace ProgramInterfaceDefinition
702*35238bceSAndroid Build Coastguard Worker } // namespace Functional
703*35238bceSAndroid Build Coastguard Worker } // namespace gles31
704*35238bceSAndroid Build Coastguard Worker } // namespace deqp
705