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