xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.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 query test case
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31fProgramInterfaceQueryTestCase.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "es31fProgramInterfaceDefinitionUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluVarTypeUtil.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluStrUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluContextInfo.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "deString.h"
34*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "deSTLUtil.hpp"
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker namespace deqp
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker namespace gles31
40*35238bceSAndroid Build Coastguard Worker {
41*35238bceSAndroid Build Coastguard Worker namespace Functional
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker namespace
44*35238bceSAndroid Build Coastguard Worker {
45*35238bceSAndroid Build Coastguard Worker 
46*35238bceSAndroid Build Coastguard Worker using ProgramInterfaceDefinition::VariablePathComponent;
47*35238bceSAndroid Build Coastguard Worker using ProgramInterfaceDefinition::VariableSearchFilter;
48*35238bceSAndroid Build Coastguard Worker 
getProgramDefaultBlockInterfaceFromStorage(glu::Storage storage)49*35238bceSAndroid Build Coastguard Worker static glw::GLenum getProgramDefaultBlockInterfaceFromStorage(glu::Storage storage)
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker     switch (storage)
52*35238bceSAndroid Build Coastguard Worker     {
53*35238bceSAndroid Build Coastguard Worker     case glu::STORAGE_IN:
54*35238bceSAndroid Build Coastguard Worker     case glu::STORAGE_PATCH_IN:
55*35238bceSAndroid Build Coastguard Worker         return GL_PROGRAM_INPUT;
56*35238bceSAndroid Build Coastguard Worker 
57*35238bceSAndroid Build Coastguard Worker     case glu::STORAGE_OUT:
58*35238bceSAndroid Build Coastguard Worker     case glu::STORAGE_PATCH_OUT:
59*35238bceSAndroid Build Coastguard Worker         return GL_PROGRAM_OUTPUT;
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker     case glu::STORAGE_UNIFORM:
62*35238bceSAndroid Build Coastguard Worker         return GL_UNIFORM;
63*35238bceSAndroid Build Coastguard Worker 
64*35238bceSAndroid Build Coastguard Worker     default:
65*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
66*35238bceSAndroid Build Coastguard Worker         return 0;
67*35238bceSAndroid Build Coastguard Worker     }
68*35238bceSAndroid Build Coastguard Worker }
69*35238bceSAndroid Build Coastguard Worker 
isBufferBackedInterfaceBlockStorage(glu::Storage storage)70*35238bceSAndroid Build Coastguard Worker static bool isBufferBackedInterfaceBlockStorage(glu::Storage storage)
71*35238bceSAndroid Build Coastguard Worker {
72*35238bceSAndroid Build Coastguard Worker     return storage == glu::STORAGE_BUFFER || storage == glu::STORAGE_UNIFORM;
73*35238bceSAndroid Build Coastguard Worker }
74*35238bceSAndroid Build Coastguard Worker 
getRequiredExtensionForStage(glu::ShaderType stage)75*35238bceSAndroid Build Coastguard Worker const char *getRequiredExtensionForStage(glu::ShaderType stage)
76*35238bceSAndroid Build Coastguard Worker {
77*35238bceSAndroid Build Coastguard Worker     switch (stage)
78*35238bceSAndroid Build Coastguard Worker     {
79*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_COMPUTE:
80*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_VERTEX:
81*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_FRAGMENT:
82*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
83*35238bceSAndroid Build Coastguard Worker 
84*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_GEOMETRY:
85*35238bceSAndroid Build Coastguard Worker         return "GL_EXT_geometry_shader";
86*35238bceSAndroid Build Coastguard Worker 
87*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_CONTROL:
88*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_EVALUATION:
89*35238bceSAndroid Build Coastguard Worker         return "GL_EXT_tessellation_shader";
90*35238bceSAndroid Build Coastguard Worker 
91*35238bceSAndroid Build Coastguard Worker     default:
92*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
93*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
94*35238bceSAndroid Build Coastguard Worker     }
95*35238bceSAndroid Build Coastguard Worker }
96*35238bceSAndroid Build Coastguard Worker 
getTypeSize(glu::DataType type)97*35238bceSAndroid Build Coastguard Worker static int getTypeSize(glu::DataType type)
98*35238bceSAndroid Build Coastguard Worker {
99*35238bceSAndroid Build Coastguard Worker     if (type == glu::TYPE_FLOAT)
100*35238bceSAndroid Build Coastguard Worker         return 4;
101*35238bceSAndroid Build Coastguard Worker     else if (type == glu::TYPE_INT || type == glu::TYPE_UINT)
102*35238bceSAndroid Build Coastguard Worker         return 4;
103*35238bceSAndroid Build Coastguard Worker     else if (type == glu::TYPE_BOOL)
104*35238bceSAndroid Build Coastguard Worker         return 4; // uint
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
107*35238bceSAndroid Build Coastguard Worker     return 0;
108*35238bceSAndroid Build Coastguard Worker }
109*35238bceSAndroid Build Coastguard Worker 
getVarTypeSize(const glu::VarType & type)110*35238bceSAndroid Build Coastguard Worker static int getVarTypeSize(const glu::VarType &type)
111*35238bceSAndroid Build Coastguard Worker {
112*35238bceSAndroid Build Coastguard Worker     if (type.isBasicType())
113*35238bceSAndroid Build Coastguard Worker     {
114*35238bceSAndroid Build Coastguard Worker         // return in basic machine units
115*35238bceSAndroid Build Coastguard Worker         return glu::getDataTypeScalarSize(type.getBasicType()) *
116*35238bceSAndroid Build Coastguard Worker                getTypeSize(glu::getDataTypeScalarType(type.getBasicType()));
117*35238bceSAndroid Build Coastguard Worker     }
118*35238bceSAndroid Build Coastguard Worker     else if (type.isStructType())
119*35238bceSAndroid Build Coastguard Worker     {
120*35238bceSAndroid Build Coastguard Worker         int size = 0;
121*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
122*35238bceSAndroid Build Coastguard Worker             size += getVarTypeSize(type.getStructPtr()->getMember(ndx).getType());
123*35238bceSAndroid Build Coastguard Worker         return size;
124*35238bceSAndroid Build Coastguard Worker     }
125*35238bceSAndroid Build Coastguard Worker     else if (type.isArrayType())
126*35238bceSAndroid Build Coastguard Worker     {
127*35238bceSAndroid Build Coastguard Worker         // unsized arrays are handled as if they had only one element
128*35238bceSAndroid Build Coastguard Worker         if (type.getArraySize() == glu::VarType::UNSIZED_ARRAY)
129*35238bceSAndroid Build Coastguard Worker             return getVarTypeSize(type.getElementType());
130*35238bceSAndroid Build Coastguard Worker         else
131*35238bceSAndroid Build Coastguard Worker             return type.getArraySize() * getVarTypeSize(type.getElementType());
132*35238bceSAndroid Build Coastguard Worker     }
133*35238bceSAndroid Build Coastguard Worker     else
134*35238bceSAndroid Build Coastguard Worker     {
135*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
136*35238bceSAndroid Build Coastguard Worker         return 0;
137*35238bceSAndroid Build Coastguard Worker     }
138*35238bceSAndroid Build Coastguard Worker }
139*35238bceSAndroid Build Coastguard Worker 
getMatrixOrderFromPath(const std::vector<VariablePathComponent> & path)140*35238bceSAndroid Build Coastguard Worker static glu::MatrixOrder getMatrixOrderFromPath(const std::vector<VariablePathComponent> &path)
141*35238bceSAndroid Build Coastguard Worker {
142*35238bceSAndroid Build Coastguard Worker     glu::MatrixOrder order = glu::MATRIXORDER_LAST;
143*35238bceSAndroid Build Coastguard Worker 
144*35238bceSAndroid Build Coastguard Worker     // inherit majority
145*35238bceSAndroid Build Coastguard Worker     for (int pathNdx = 0; pathNdx < (int)path.size(); ++pathNdx)
146*35238bceSAndroid Build Coastguard Worker     {
147*35238bceSAndroid Build Coastguard Worker         glu::MatrixOrder matOrder;
148*35238bceSAndroid Build Coastguard Worker 
149*35238bceSAndroid Build Coastguard Worker         if (path[pathNdx].isInterfaceBlock())
150*35238bceSAndroid Build Coastguard Worker             matOrder = path[pathNdx].getInterfaceBlock()->layout.matrixOrder;
151*35238bceSAndroid Build Coastguard Worker         else if (path[pathNdx].isDeclaration())
152*35238bceSAndroid Build Coastguard Worker             matOrder = path[pathNdx].getDeclaration()->layout.matrixOrder;
153*35238bceSAndroid Build Coastguard Worker         else if (path[pathNdx].isVariableType())
154*35238bceSAndroid Build Coastguard Worker             matOrder = glu::MATRIXORDER_LAST;
155*35238bceSAndroid Build Coastguard Worker         else
156*35238bceSAndroid Build Coastguard Worker         {
157*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
158*35238bceSAndroid Build Coastguard Worker             return glu::MATRIXORDER_LAST;
159*35238bceSAndroid Build Coastguard Worker         }
160*35238bceSAndroid Build Coastguard Worker 
161*35238bceSAndroid Build Coastguard Worker         if (matOrder != glu::MATRIXORDER_LAST)
162*35238bceSAndroid Build Coastguard Worker             order = matOrder;
163*35238bceSAndroid Build Coastguard Worker     }
164*35238bceSAndroid Build Coastguard Worker 
165*35238bceSAndroid Build Coastguard Worker     return order;
166*35238bceSAndroid Build Coastguard Worker }
167*35238bceSAndroid Build Coastguard Worker 
168*35238bceSAndroid Build Coastguard Worker class PropValidator
169*35238bceSAndroid Build Coastguard Worker {
170*35238bceSAndroid Build Coastguard Worker public:
171*35238bceSAndroid Build Coastguard Worker     PropValidator(Context &context, ProgramResourcePropFlags validationProp, const char *requiredExtension);
172*35238bceSAndroid Build Coastguard Worker 
173*35238bceSAndroid Build Coastguard Worker     virtual std::string getHumanReadablePropertyString(glw::GLint propVal) const;
174*35238bceSAndroid Build Coastguard Worker     virtual void validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource,
175*35238bceSAndroid Build Coastguard Worker                           glw::GLint propValue, const std::string &implementationName) const = 0;
176*35238bceSAndroid Build Coastguard Worker 
177*35238bceSAndroid Build Coastguard Worker     bool isSupported(void) const;
178*35238bceSAndroid Build Coastguard Worker     bool isSelected(uint32_t caseFlags) const;
179*35238bceSAndroid Build Coastguard Worker 
180*35238bceSAndroid Build Coastguard Worker protected:
181*35238bceSAndroid Build Coastguard Worker     void setError(const std::string &err) const;
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker     tcu::TestContext &m_testCtx;
184*35238bceSAndroid Build Coastguard Worker     const glu::RenderContext &m_renderContext;
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker private:
187*35238bceSAndroid Build Coastguard Worker     const glu::ContextInfo &m_contextInfo;
188*35238bceSAndroid Build Coastguard Worker     const char *m_extension;
189*35238bceSAndroid Build Coastguard Worker     const ProgramResourcePropFlags m_validationProp;
190*35238bceSAndroid Build Coastguard Worker };
191*35238bceSAndroid Build Coastguard Worker 
PropValidator(Context & context,ProgramResourcePropFlags validationProp,const char * requiredExtension)192*35238bceSAndroid Build Coastguard Worker PropValidator::PropValidator(Context &context, ProgramResourcePropFlags validationProp, const char *requiredExtension)
193*35238bceSAndroid Build Coastguard Worker     : m_testCtx(context.getTestContext())
194*35238bceSAndroid Build Coastguard Worker     , m_renderContext(context.getRenderContext())
195*35238bceSAndroid Build Coastguard Worker     , m_contextInfo(context.getContextInfo())
196*35238bceSAndroid Build Coastguard Worker     , m_extension(requiredExtension)
197*35238bceSAndroid Build Coastguard Worker     , m_validationProp(validationProp)
198*35238bceSAndroid Build Coastguard Worker {
199*35238bceSAndroid Build Coastguard Worker }
200*35238bceSAndroid Build Coastguard Worker 
getHumanReadablePropertyString(glw::GLint propVal) const201*35238bceSAndroid Build Coastguard Worker std::string PropValidator::getHumanReadablePropertyString(glw::GLint propVal) const
202*35238bceSAndroid Build Coastguard Worker {
203*35238bceSAndroid Build Coastguard Worker     return de::toString(propVal);
204*35238bceSAndroid Build Coastguard Worker }
205*35238bceSAndroid Build Coastguard Worker 
isSupported(void) const206*35238bceSAndroid Build Coastguard Worker bool PropValidator::isSupported(void) const
207*35238bceSAndroid Build Coastguard Worker {
208*35238bceSAndroid Build Coastguard Worker     if (glu::contextSupports(m_renderContext.getType(), glu::ApiType::es(3, 2)) ||
209*35238bceSAndroid Build Coastguard Worker         glu::contextSupports(m_renderContext.getType(), glu::ApiType::core(4, 5)))
210*35238bceSAndroid Build Coastguard Worker         return true;
211*35238bceSAndroid Build Coastguard Worker     return m_extension == DE_NULL || m_contextInfo.isExtensionSupported(m_extension);
212*35238bceSAndroid Build Coastguard Worker }
213*35238bceSAndroid Build Coastguard Worker 
isSelected(uint32_t caseFlags) const214*35238bceSAndroid Build Coastguard Worker bool PropValidator::isSelected(uint32_t caseFlags) const
215*35238bceSAndroid Build Coastguard Worker {
216*35238bceSAndroid Build Coastguard Worker     return (caseFlags & (uint32_t)m_validationProp) != 0;
217*35238bceSAndroid Build Coastguard Worker }
218*35238bceSAndroid Build Coastguard Worker 
setError(const std::string & err) const219*35238bceSAndroid Build Coastguard Worker void PropValidator::setError(const std::string &err) const
220*35238bceSAndroid Build Coastguard Worker {
221*35238bceSAndroid Build Coastguard Worker     // don't overwrite earlier errors
222*35238bceSAndroid Build Coastguard Worker     if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
223*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, err.c_str());
224*35238bceSAndroid Build Coastguard Worker }
225*35238bceSAndroid Build Coastguard Worker 
226*35238bceSAndroid Build Coastguard Worker class SingleVariableValidator : public PropValidator
227*35238bceSAndroid Build Coastguard Worker {
228*35238bceSAndroid Build Coastguard Worker public:
229*35238bceSAndroid Build Coastguard Worker     SingleVariableValidator(Context &context, ProgramResourcePropFlags validationProp, glw::GLuint programID,
230*35238bceSAndroid Build Coastguard Worker                             const VariableSearchFilter &filter, const char *requiredExtension);
231*35238bceSAndroid Build Coastguard Worker 
232*35238bceSAndroid Build Coastguard Worker     void validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource, glw::GLint propValue,
233*35238bceSAndroid Build Coastguard Worker                   const std::string &implementationName) const;
234*35238bceSAndroid Build Coastguard Worker     virtual void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
235*35238bceSAndroid Build Coastguard Worker                                         glw::GLint propValue, const std::string &implementationName) const = 0;
236*35238bceSAndroid Build Coastguard Worker     virtual void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
237*35238bceSAndroid Build Coastguard Worker                                          const std::string &implementationName) const;
238*35238bceSAndroid Build Coastguard Worker 
239*35238bceSAndroid Build Coastguard Worker protected:
240*35238bceSAndroid Build Coastguard Worker     const VariableSearchFilter m_filter;
241*35238bceSAndroid Build Coastguard Worker     const glw::GLuint m_programID;
242*35238bceSAndroid Build Coastguard Worker };
243*35238bceSAndroid Build Coastguard Worker 
SingleVariableValidator(Context & context,ProgramResourcePropFlags validationProp,glw::GLuint programID,const VariableSearchFilter & filter,const char * requiredExtension)244*35238bceSAndroid Build Coastguard Worker SingleVariableValidator::SingleVariableValidator(Context &context, ProgramResourcePropFlags validationProp,
245*35238bceSAndroid Build Coastguard Worker                                                  glw::GLuint programID, const VariableSearchFilter &filter,
246*35238bceSAndroid Build Coastguard Worker                                                  const char *requiredExtension)
247*35238bceSAndroid Build Coastguard Worker     : PropValidator(context, validationProp, requiredExtension)
248*35238bceSAndroid Build Coastguard Worker     , m_filter(filter)
249*35238bceSAndroid Build Coastguard Worker     , m_programID(programID)
250*35238bceSAndroid Build Coastguard Worker {
251*35238bceSAndroid Build Coastguard Worker }
252*35238bceSAndroid Build Coastguard Worker 
validate(const ProgramInterfaceDefinition::Program * program,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const253*35238bceSAndroid Build Coastguard Worker void SingleVariableValidator::validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource,
254*35238bceSAndroid Build Coastguard Worker                                        glw::GLint propValue, const std::string &implementationName) const
255*35238bceSAndroid Build Coastguard Worker {
256*35238bceSAndroid Build Coastguard Worker     std::vector<VariablePathComponent> path;
257*35238bceSAndroid Build Coastguard Worker 
258*35238bceSAndroid Build Coastguard Worker     if (findProgramVariablePathByPathName(path, program, resource, m_filter))
259*35238bceSAndroid Build Coastguard Worker     {
260*35238bceSAndroid Build Coastguard Worker         const glu::VarType *variable = (path.back().isVariableType()) ? (path.back().getVariableType()) : (DE_NULL);
261*35238bceSAndroid Build Coastguard Worker 
262*35238bceSAndroid Build Coastguard Worker         if (!variable || !variable->isBasicType())
263*35238bceSAndroid Build Coastguard Worker         {
264*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource name \"" << resource
265*35238bceSAndroid Build Coastguard Worker                                << "\" refers to a non-basic type." << tcu::TestLog::EndMessage;
266*35238bceSAndroid Build Coastguard Worker             setError("resource not basic type");
267*35238bceSAndroid Build Coastguard Worker         }
268*35238bceSAndroid Build Coastguard Worker         else
269*35238bceSAndroid Build Coastguard Worker             validateSingleVariable(path, resource, propValue, implementationName);
270*35238bceSAndroid Build Coastguard Worker 
271*35238bceSAndroid Build Coastguard Worker         // finding matching variable in any shader is sufficient
272*35238bceSAndroid Build Coastguard Worker         return;
273*35238bceSAndroid Build Coastguard Worker     }
274*35238bceSAndroid Build Coastguard Worker     else if (deStringBeginsWith(resource.c_str(), "gl_"))
275*35238bceSAndroid Build Coastguard Worker     {
276*35238bceSAndroid Build Coastguard Worker         // special case for builtins
277*35238bceSAndroid Build Coastguard Worker         validateBuiltinVariable(resource, propValue, implementationName);
278*35238bceSAndroid Build Coastguard Worker         return;
279*35238bceSAndroid Build Coastguard Worker     }
280*35238bceSAndroid Build Coastguard Worker 
281*35238bceSAndroid Build Coastguard Worker     // we are only supplied good names, generated by ourselves
282*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
283*35238bceSAndroid Build Coastguard Worker     throw tcu::InternalError("Resource name consistency error");
284*35238bceSAndroid Build Coastguard Worker }
285*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const286*35238bceSAndroid Build Coastguard Worker void SingleVariableValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
287*35238bceSAndroid Build Coastguard Worker                                                       const std::string &implementationName) const
288*35238bceSAndroid Build Coastguard Worker {
289*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
290*35238bceSAndroid Build Coastguard Worker     DE_UNREF(propValue);
291*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
292*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
293*35238bceSAndroid Build Coastguard Worker }
294*35238bceSAndroid Build Coastguard Worker 
295*35238bceSAndroid Build Coastguard Worker class SingleBlockValidator : public PropValidator
296*35238bceSAndroid Build Coastguard Worker {
297*35238bceSAndroid Build Coastguard Worker public:
298*35238bceSAndroid Build Coastguard Worker     SingleBlockValidator(Context &context, ProgramResourcePropFlags validationProp, glw::GLuint programID,
299*35238bceSAndroid Build Coastguard Worker                          const VariableSearchFilter &filter, const char *requiredExtension);
300*35238bceSAndroid Build Coastguard Worker 
301*35238bceSAndroid Build Coastguard Worker     void validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource, glw::GLint propValue,
302*35238bceSAndroid Build Coastguard Worker                   const std::string &implementationName) const;
303*35238bceSAndroid Build Coastguard Worker     virtual void validateSingleBlock(const glu::InterfaceBlock &block, const std::vector<int> &instanceIndex,
304*35238bceSAndroid Build Coastguard Worker                                      const std::string &resource, glw::GLint propValue,
305*35238bceSAndroid Build Coastguard Worker                                      const std::string &implementationName) const = 0;
306*35238bceSAndroid Build Coastguard Worker 
307*35238bceSAndroid Build Coastguard Worker protected:
308*35238bceSAndroid Build Coastguard Worker     const VariableSearchFilter m_filter;
309*35238bceSAndroid Build Coastguard Worker     const glw::GLuint m_programID;
310*35238bceSAndroid Build Coastguard Worker };
311*35238bceSAndroid Build Coastguard Worker 
SingleBlockValidator(Context & context,ProgramResourcePropFlags validationProp,glw::GLuint programID,const VariableSearchFilter & filter,const char * requiredExtension)312*35238bceSAndroid Build Coastguard Worker SingleBlockValidator::SingleBlockValidator(Context &context, ProgramResourcePropFlags validationProp,
313*35238bceSAndroid Build Coastguard Worker                                            glw::GLuint programID, const VariableSearchFilter &filter,
314*35238bceSAndroid Build Coastguard Worker                                            const char *requiredExtension)
315*35238bceSAndroid Build Coastguard Worker     : PropValidator(context, validationProp, requiredExtension)
316*35238bceSAndroid Build Coastguard Worker     , m_filter(filter)
317*35238bceSAndroid Build Coastguard Worker     , m_programID(programID)
318*35238bceSAndroid Build Coastguard Worker {
319*35238bceSAndroid Build Coastguard Worker }
320*35238bceSAndroid Build Coastguard Worker 
validate(const ProgramInterfaceDefinition::Program * program,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const321*35238bceSAndroid Build Coastguard Worker void SingleBlockValidator::validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource,
322*35238bceSAndroid Build Coastguard Worker                                     glw::GLint propValue, const std::string &implementationName) const
323*35238bceSAndroid Build Coastguard Worker {
324*35238bceSAndroid Build Coastguard Worker     glu::VarTokenizer tokenizer(resource.c_str());
325*35238bceSAndroid Build Coastguard Worker     const std::string blockName = tokenizer.getIdentifier();
326*35238bceSAndroid Build Coastguard Worker     std::vector<int> instanceIndex;
327*35238bceSAndroid Build Coastguard Worker 
328*35238bceSAndroid Build Coastguard Worker     tokenizer.advance();
329*35238bceSAndroid Build Coastguard Worker 
330*35238bceSAndroid Build Coastguard Worker     // array index
331*35238bceSAndroid Build Coastguard Worker     while (tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET)
332*35238bceSAndroid Build Coastguard Worker     {
333*35238bceSAndroid Build Coastguard Worker         tokenizer.advance();
334*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_NUMBER);
335*35238bceSAndroid Build Coastguard Worker 
336*35238bceSAndroid Build Coastguard Worker         instanceIndex.push_back(tokenizer.getNumber());
337*35238bceSAndroid Build Coastguard Worker 
338*35238bceSAndroid Build Coastguard Worker         tokenizer.advance();
339*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_RIGHT_BRACKET);
340*35238bceSAndroid Build Coastguard Worker 
341*35238bceSAndroid Build Coastguard Worker         tokenizer.advance();
342*35238bceSAndroid Build Coastguard Worker     }
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker     // no trailing garbage
345*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_END);
346*35238bceSAndroid Build Coastguard Worker 
347*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
348*35238bceSAndroid Build Coastguard Worker     {
349*35238bceSAndroid Build Coastguard Worker         const ProgramInterfaceDefinition::Shader *const shader = program->getShaders()[shaderNdx];
350*35238bceSAndroid Build Coastguard Worker         if (!m_filter.matchesFilter(shader))
351*35238bceSAndroid Build Coastguard Worker             continue;
352*35238bceSAndroid Build Coastguard Worker 
353*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx)
354*35238bceSAndroid Build Coastguard Worker         {
355*35238bceSAndroid Build Coastguard Worker             const glu::InterfaceBlock &block = shader->getDefaultBlock().interfaceBlocks[blockNdx];
356*35238bceSAndroid Build Coastguard Worker 
357*35238bceSAndroid Build Coastguard Worker             if (m_filter.matchesFilter(block) && block.interfaceName == blockName)
358*35238bceSAndroid Build Coastguard Worker             {
359*35238bceSAndroid Build Coastguard Worker                 // dimensions match
360*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(instanceIndex.size() == block.dimensions.size());
361*35238bceSAndroid Build Coastguard Worker 
362*35238bceSAndroid Build Coastguard Worker                 validateSingleBlock(block, instanceIndex, resource, propValue, implementationName);
363*35238bceSAndroid Build Coastguard Worker                 return;
364*35238bceSAndroid Build Coastguard Worker             }
365*35238bceSAndroid Build Coastguard Worker         }
366*35238bceSAndroid Build Coastguard Worker     }
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker     // we are only supplied good names, generated by ourselves
369*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
370*35238bceSAndroid Build Coastguard Worker     throw tcu::InternalError("Resource name consistency error");
371*35238bceSAndroid Build Coastguard Worker }
372*35238bceSAndroid Build Coastguard Worker 
373*35238bceSAndroid Build Coastguard Worker class TypeValidator : public SingleVariableValidator
374*35238bceSAndroid Build Coastguard Worker {
375*35238bceSAndroid Build Coastguard Worker public:
376*35238bceSAndroid Build Coastguard Worker     TypeValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
377*35238bceSAndroid Build Coastguard Worker 
378*35238bceSAndroid Build Coastguard Worker     std::string getHumanReadablePropertyString(glw::GLint propVal) const;
379*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
380*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
381*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
382*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
383*35238bceSAndroid Build Coastguard Worker };
384*35238bceSAndroid Build Coastguard Worker 
TypeValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)385*35238bceSAndroid Build Coastguard Worker TypeValidator::TypeValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter)
386*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_TYPE, programID, filter, DE_NULL)
387*35238bceSAndroid Build Coastguard Worker {
388*35238bceSAndroid Build Coastguard Worker }
389*35238bceSAndroid Build Coastguard Worker 
getHumanReadablePropertyString(glw::GLint propVal) const390*35238bceSAndroid Build Coastguard Worker std::string TypeValidator::getHumanReadablePropertyString(glw::GLint propVal) const
391*35238bceSAndroid Build Coastguard Worker {
392*35238bceSAndroid Build Coastguard Worker     return de::toString(glu::getShaderVarTypeStr(propVal));
393*35238bceSAndroid Build Coastguard Worker }
394*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const395*35238bceSAndroid Build Coastguard Worker void TypeValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
396*35238bceSAndroid Build Coastguard Worker                                            glw::GLint propValue, const std::string &implementationName) const
397*35238bceSAndroid Build Coastguard Worker {
398*35238bceSAndroid Build Coastguard Worker     const glu::VarType *variable = path.back().getVariableType();
399*35238bceSAndroid Build Coastguard Worker 
400*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
401*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
402*35238bceSAndroid Build Coastguard Worker 
403*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting "
404*35238bceSAndroid Build Coastguard Worker                        << glu::getDataTypeName(variable->getBasicType()) << tcu::TestLog::EndMessage;
405*35238bceSAndroid Build Coastguard Worker 
406*35238bceSAndroid Build Coastguard Worker     if (variable->getBasicType() != glu::getDataTypeFromGLType(propValue))
407*35238bceSAndroid Build Coastguard Worker     {
408*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got "
409*35238bceSAndroid Build Coastguard Worker                            << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
410*35238bceSAndroid Build Coastguard Worker         setError("resource type invalid");
411*35238bceSAndroid Build Coastguard Worker     }
412*35238bceSAndroid Build Coastguard Worker }
413*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const414*35238bceSAndroid Build Coastguard Worker void TypeValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
415*35238bceSAndroid Build Coastguard Worker                                             const std::string &implementationName) const
416*35238bceSAndroid Build Coastguard Worker {
417*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
418*35238bceSAndroid Build Coastguard Worker 
419*35238bceSAndroid Build Coastguard Worker     static const struct
420*35238bceSAndroid Build Coastguard Worker     {
421*35238bceSAndroid Build Coastguard Worker         const char *name;
422*35238bceSAndroid Build Coastguard Worker         glu::DataType type;
423*35238bceSAndroid Build Coastguard Worker     } builtins[] = {
424*35238bceSAndroid Build Coastguard Worker         {"gl_Position", glu::TYPE_FLOAT_VEC4},
425*35238bceSAndroid Build Coastguard Worker         {"gl_FragCoord", glu::TYPE_FLOAT_VEC4},
426*35238bceSAndroid Build Coastguard Worker         {"gl_PerVertex.gl_Position", glu::TYPE_FLOAT_VEC4},
427*35238bceSAndroid Build Coastguard Worker         {"gl_VertexID", glu::TYPE_INT},
428*35238bceSAndroid Build Coastguard Worker         {"gl_InvocationID", glu::TYPE_INT},
429*35238bceSAndroid Build Coastguard Worker         {"gl_NumWorkGroups", glu::TYPE_UINT_VEC3},
430*35238bceSAndroid Build Coastguard Worker         {"gl_FragDepth", glu::TYPE_FLOAT},
431*35238bceSAndroid Build Coastguard Worker         {"gl_TessLevelOuter[0]", glu::TYPE_FLOAT},
432*35238bceSAndroid Build Coastguard Worker         {"gl_TessLevelInner[0]", glu::TYPE_FLOAT},
433*35238bceSAndroid Build Coastguard Worker     };
434*35238bceSAndroid Build Coastguard Worker 
435*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtins); ++ndx)
436*35238bceSAndroid Build Coastguard Worker     {
437*35238bceSAndroid Build Coastguard Worker         if (resource == builtins[ndx].name)
438*35238bceSAndroid Build Coastguard Worker         {
439*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting "
440*35238bceSAndroid Build Coastguard Worker                                << glu::getDataTypeName(builtins[ndx].type) << tcu::TestLog::EndMessage;
441*35238bceSAndroid Build Coastguard Worker 
442*35238bceSAndroid Build Coastguard Worker             if (glu::getDataTypeFromGLType(propValue) != builtins[ndx].type)
443*35238bceSAndroid Build Coastguard Worker             {
444*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got "
445*35238bceSAndroid Build Coastguard Worker                                    << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue))
446*35238bceSAndroid Build Coastguard Worker                                    << tcu::TestLog::EndMessage;
447*35238bceSAndroid Build Coastguard Worker                 setError("resource type invalid");
448*35238bceSAndroid Build Coastguard Worker             }
449*35238bceSAndroid Build Coastguard Worker             return;
450*35238bceSAndroid Build Coastguard Worker         }
451*35238bceSAndroid Build Coastguard Worker     }
452*35238bceSAndroid Build Coastguard Worker 
453*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
454*35238bceSAndroid Build Coastguard Worker }
455*35238bceSAndroid Build Coastguard Worker 
456*35238bceSAndroid Build Coastguard Worker class ArraySizeValidator : public SingleVariableValidator
457*35238bceSAndroid Build Coastguard Worker {
458*35238bceSAndroid Build Coastguard Worker public:
459*35238bceSAndroid Build Coastguard Worker     ArraySizeValidator(Context &context, glw::GLuint programID, int unsizedArraySize,
460*35238bceSAndroid Build Coastguard Worker                        const VariableSearchFilter &filter);
461*35238bceSAndroid Build Coastguard Worker 
462*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
463*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
464*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
465*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
466*35238bceSAndroid Build Coastguard Worker 
467*35238bceSAndroid Build Coastguard Worker private:
468*35238bceSAndroid Build Coastguard Worker     const int m_unsizedArraySize;
469*35238bceSAndroid Build Coastguard Worker };
470*35238bceSAndroid Build Coastguard Worker 
ArraySizeValidator(Context & context,glw::GLuint programID,int unsizedArraySize,const VariableSearchFilter & filter)471*35238bceSAndroid Build Coastguard Worker ArraySizeValidator::ArraySizeValidator(Context &context, glw::GLuint programID, int unsizedArraySize,
472*35238bceSAndroid Build Coastguard Worker                                        const VariableSearchFilter &filter)
473*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_ARRAY_SIZE, programID, filter, DE_NULL)
474*35238bceSAndroid Build Coastguard Worker     , m_unsizedArraySize(unsizedArraySize)
475*35238bceSAndroid Build Coastguard Worker {
476*35238bceSAndroid Build Coastguard Worker }
477*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const478*35238bceSAndroid Build Coastguard Worker void ArraySizeValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
479*35238bceSAndroid Build Coastguard Worker                                                 const std::string &resource, glw::GLint propValue,
480*35238bceSAndroid Build Coastguard Worker                                                 const std::string &implementationName) const
481*35238bceSAndroid Build Coastguard Worker {
482*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent nullComponent;
483*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &enclosingcomponent = (path.size() > 1) ? (path[path.size() - 2]) : (nullComponent);
484*35238bceSAndroid Build Coastguard Worker 
485*35238bceSAndroid Build Coastguard Worker     const bool isArray = enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType();
486*35238bceSAndroid Build Coastguard Worker     const bool inUnsizedArray =
487*35238bceSAndroid Build Coastguard Worker         isArray && (enclosingcomponent.getVariableType()->getArraySize() == glu::VarType::UNSIZED_ARRAY);
488*35238bceSAndroid Build Coastguard Worker     const int arraySize = (!isArray)       ? (1) :
489*35238bceSAndroid Build Coastguard Worker                           (inUnsizedArray) ? (m_unsizedArraySize) :
490*35238bceSAndroid Build Coastguard Worker                                              (enclosingcomponent.getVariableType()->getArraySize());
491*35238bceSAndroid Build Coastguard Worker 
492*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(arraySize >= 0);
493*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
494*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
495*35238bceSAndroid Build Coastguard Worker 
496*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize
497*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
498*35238bceSAndroid Build Coastguard Worker 
499*35238bceSAndroid Build Coastguard Worker     if (arraySize != propValue)
500*35238bceSAndroid Build Coastguard Worker     {
501*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
502*35238bceSAndroid Build Coastguard Worker         setError("resource array size invalid");
503*35238bceSAndroid Build Coastguard Worker     }
504*35238bceSAndroid Build Coastguard Worker }
505*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const506*35238bceSAndroid Build Coastguard Worker void ArraySizeValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
507*35238bceSAndroid Build Coastguard Worker                                                  const std::string &implementationName) const
508*35238bceSAndroid Build Coastguard Worker {
509*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
510*35238bceSAndroid Build Coastguard Worker 
511*35238bceSAndroid Build Coastguard Worker     static const struct
512*35238bceSAndroid Build Coastguard Worker     {
513*35238bceSAndroid Build Coastguard Worker         const char *name;
514*35238bceSAndroid Build Coastguard Worker         int arraySize;
515*35238bceSAndroid Build Coastguard Worker     } builtins[] = {
516*35238bceSAndroid Build Coastguard Worker         {"gl_Position", 1},          {"gl_VertexID", 1},      {"gl_FragCoord", 1}, {"gl_PerVertex.gl_Position", 1},
517*35238bceSAndroid Build Coastguard Worker         {"gl_InvocationID", 1},      {"gl_NumWorkGroups", 1}, {"gl_FragDepth", 1}, {"gl_TessLevelOuter[0]", 4},
518*35238bceSAndroid Build Coastguard Worker         {"gl_TessLevelInner[0]", 2},
519*35238bceSAndroid Build Coastguard Worker     };
520*35238bceSAndroid Build Coastguard Worker 
521*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtins); ++ndx)
522*35238bceSAndroid Build Coastguard Worker     {
523*35238bceSAndroid Build Coastguard Worker         if (resource == builtins[ndx].name)
524*35238bceSAndroid Build Coastguard Worker         {
525*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << builtins[ndx].arraySize
526*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
527*35238bceSAndroid Build Coastguard Worker 
528*35238bceSAndroid Build Coastguard Worker             if (propValue != builtins[ndx].arraySize)
529*35238bceSAndroid Build Coastguard Worker             {
530*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
531*35238bceSAndroid Build Coastguard Worker                 setError("resource array size invalid");
532*35238bceSAndroid Build Coastguard Worker             }
533*35238bceSAndroid Build Coastguard Worker             return;
534*35238bceSAndroid Build Coastguard Worker         }
535*35238bceSAndroid Build Coastguard Worker     }
536*35238bceSAndroid Build Coastguard Worker 
537*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
538*35238bceSAndroid Build Coastguard Worker }
539*35238bceSAndroid Build Coastguard Worker 
540*35238bceSAndroid Build Coastguard Worker class ArrayStrideValidator : public SingleVariableValidator
541*35238bceSAndroid Build Coastguard Worker {
542*35238bceSAndroid Build Coastguard Worker public:
543*35238bceSAndroid Build Coastguard Worker     ArrayStrideValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
544*35238bceSAndroid Build Coastguard Worker 
545*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
546*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
547*35238bceSAndroid Build Coastguard Worker };
548*35238bceSAndroid Build Coastguard Worker 
ArrayStrideValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)549*35238bceSAndroid Build Coastguard Worker ArrayStrideValidator::ArrayStrideValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter)
550*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_ARRAY_STRIDE, programID, filter, DE_NULL)
551*35238bceSAndroid Build Coastguard Worker {
552*35238bceSAndroid Build Coastguard Worker }
553*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const554*35238bceSAndroid Build Coastguard Worker void ArrayStrideValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
555*35238bceSAndroid Build Coastguard Worker                                                   const std::string &resource, glw::GLint propValue,
556*35238bceSAndroid Build Coastguard Worker                                                   const std::string &implementationName) const
557*35238bceSAndroid Build Coastguard Worker {
558*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent nullComponent;
559*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &component          = path.back();
560*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &enclosingcomponent = (path.size() > 1) ? (path[path.size() - 2]) : (nullComponent);
561*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &firstComponent     = path.front();
562*35238bceSAndroid Build Coastguard Worker 
563*35238bceSAndroid Build Coastguard Worker     const bool isBufferBlock = firstComponent.isInterfaceBlock() &&
564*35238bceSAndroid Build Coastguard Worker                                isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage);
565*35238bceSAndroid Build Coastguard Worker     const bool isArray = enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType();
566*35238bceSAndroid Build Coastguard Worker     const bool isAtomicCounter = glu::isDataTypeAtomicCounter(
567*35238bceSAndroid Build Coastguard Worker         component.getVariableType()
568*35238bceSAndroid Build Coastguard Worker             ->getBasicType()); // atomic counters are buffer backed with a stride of 4 basic machine units
569*35238bceSAndroid Build Coastguard Worker 
570*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
571*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
572*35238bceSAndroid Build Coastguard Worker 
573*35238bceSAndroid Build Coastguard Worker     // Layout tests will verify layouts of buffer backed arrays properly. Here we just check values are greater or equal to the element size
574*35238bceSAndroid Build Coastguard Worker     if (isBufferBlock && isArray)
575*35238bceSAndroid Build Coastguard Worker     {
576*35238bceSAndroid Build Coastguard Worker         const int elementSize = glu::getDataTypeScalarSize(component.getVariableType()->getBasicType()) *
577*35238bceSAndroid Build Coastguard Worker                                 getTypeSize(glu::getDataTypeScalarType(component.getVariableType()->getBasicType()));
578*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array stride, expecting greater or equal to "
579*35238bceSAndroid Build Coastguard Worker                            << elementSize << tcu::TestLog::EndMessage;
580*35238bceSAndroid Build Coastguard Worker 
581*35238bceSAndroid Build Coastguard Worker         if (propValue < elementSize)
582*35238bceSAndroid Build Coastguard Worker         {
583*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
584*35238bceSAndroid Build Coastguard Worker             setError("resource array stride invalid");
585*35238bceSAndroid Build Coastguard Worker         }
586*35238bceSAndroid Build Coastguard Worker     }
587*35238bceSAndroid Build Coastguard Worker     else
588*35238bceSAndroid Build Coastguard Worker     {
589*35238bceSAndroid Build Coastguard Worker         // Atomics are buffer backed with stride of 4 even though they are not in an interface block
590*35238bceSAndroid Build Coastguard Worker         const int arrayStride = (isAtomicCounter && isArray) ? (4) : (!isBufferBlock && !isAtomicCounter) ? (-1) : (0);
591*35238bceSAndroid Build Coastguard Worker 
592*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array stride, expecting " << arrayStride
593*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
594*35238bceSAndroid Build Coastguard Worker 
595*35238bceSAndroid Build Coastguard Worker         if (arrayStride != propValue)
596*35238bceSAndroid Build Coastguard Worker         {
597*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
598*35238bceSAndroid Build Coastguard Worker             setError("resource array stride invalid");
599*35238bceSAndroid Build Coastguard Worker         }
600*35238bceSAndroid Build Coastguard Worker     }
601*35238bceSAndroid Build Coastguard Worker }
602*35238bceSAndroid Build Coastguard Worker 
603*35238bceSAndroid Build Coastguard Worker class BlockIndexValidator : public SingleVariableValidator
604*35238bceSAndroid Build Coastguard Worker {
605*35238bceSAndroid Build Coastguard Worker public:
606*35238bceSAndroid Build Coastguard Worker     BlockIndexValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
607*35238bceSAndroid Build Coastguard Worker 
608*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
609*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
610*35238bceSAndroid Build Coastguard Worker };
611*35238bceSAndroid Build Coastguard Worker 
BlockIndexValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)612*35238bceSAndroid Build Coastguard Worker BlockIndexValidator::BlockIndexValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter)
613*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_BLOCK_INDEX, programID, filter, DE_NULL)
614*35238bceSAndroid Build Coastguard Worker {
615*35238bceSAndroid Build Coastguard Worker }
616*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const617*35238bceSAndroid Build Coastguard Worker void BlockIndexValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
618*35238bceSAndroid Build Coastguard Worker                                                  const std::string &resource, glw::GLint propValue,
619*35238bceSAndroid Build Coastguard Worker                                                  const std::string &implementationName) const
620*35238bceSAndroid Build Coastguard Worker {
621*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &firstComponent = path.front();
622*35238bceSAndroid Build Coastguard Worker 
623*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
624*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
625*35238bceSAndroid Build Coastguard Worker 
626*35238bceSAndroid Build Coastguard Worker     if (!firstComponent.isInterfaceBlock())
627*35238bceSAndroid Build Coastguard Worker     {
628*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block index, expecting -1"
629*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
630*35238bceSAndroid Build Coastguard Worker 
631*35238bceSAndroid Build Coastguard Worker         if (propValue != -1)
632*35238bceSAndroid Build Coastguard Worker         {
633*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
634*35238bceSAndroid Build Coastguard Worker             setError("resource block index invalid");
635*35238bceSAndroid Build Coastguard Worker         }
636*35238bceSAndroid Build Coastguard Worker     }
637*35238bceSAndroid Build Coastguard Worker     else
638*35238bceSAndroid Build Coastguard Worker     {
639*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block index, expecting a valid block index"
640*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
641*35238bceSAndroid Build Coastguard Worker 
642*35238bceSAndroid Build Coastguard Worker         if (propValue == -1)
643*35238bceSAndroid Build Coastguard Worker         {
644*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
645*35238bceSAndroid Build Coastguard Worker             setError("resource block index invalid");
646*35238bceSAndroid Build Coastguard Worker         }
647*35238bceSAndroid Build Coastguard Worker         else
648*35238bceSAndroid Build Coastguard Worker         {
649*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl = m_renderContext.getFunctions();
650*35238bceSAndroid Build Coastguard Worker             const glw::GLenum interface =
651*35238bceSAndroid Build Coastguard Worker                 (firstComponent.getInterfaceBlock()->storage == glu::STORAGE_UNIFORM) ? (GL_UNIFORM_BLOCK) :
652*35238bceSAndroid Build Coastguard Worker                 (firstComponent.getInterfaceBlock()->storage == glu::STORAGE_BUFFER)  ? (GL_SHADER_STORAGE_BLOCK) :
653*35238bceSAndroid Build Coastguard Worker                                                                                         (0);
654*35238bceSAndroid Build Coastguard Worker             glw::GLint written = 0;
655*35238bceSAndroid Build Coastguard Worker             std::vector<char> nameBuffer(firstComponent.getInterfaceBlock()->interfaceName.size() +
656*35238bceSAndroid Build Coastguard Worker                                              3 * firstComponent.getInterfaceBlock()->dimensions.size() + 2,
657*35238bceSAndroid Build Coastguard Worker                                          '\0'); // +3 for appended "[N]", +1 for '\0' and +1 just for safety
658*35238bceSAndroid Build Coastguard Worker 
659*35238bceSAndroid Build Coastguard Worker             gl.getProgramResourceName(m_programID, interface, propValue, (int)nameBuffer.size() - 1, &written,
660*35238bceSAndroid Build Coastguard Worker                                       &nameBuffer[0]);
661*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(gl.getError(), "query block name");
662*35238bceSAndroid Build Coastguard Worker             TCU_CHECK(written < (int)nameBuffer.size());
663*35238bceSAndroid Build Coastguard Worker             TCU_CHECK(nameBuffer.back() == '\0');
664*35238bceSAndroid Build Coastguard Worker 
665*35238bceSAndroid Build Coastguard Worker             {
666*35238bceSAndroid Build Coastguard Worker                 const std::string blockName(&nameBuffer[0], written);
667*35238bceSAndroid Build Coastguard Worker                 std::ostringstream expectedName;
668*35238bceSAndroid Build Coastguard Worker 
669*35238bceSAndroid Build Coastguard Worker                 expectedName << firstComponent.getInterfaceBlock()->interfaceName;
670*35238bceSAndroid Build Coastguard Worker                 for (int dimensionNdx = 0; dimensionNdx < (int)firstComponent.getInterfaceBlock()->dimensions.size();
671*35238bceSAndroid Build Coastguard Worker                      ++dimensionNdx)
672*35238bceSAndroid Build Coastguard Worker                     expectedName << "[0]";
673*35238bceSAndroid Build Coastguard Worker 
674*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message << "Block name with index " << propValue << " is \""
675*35238bceSAndroid Build Coastguard Worker                                    << blockName << "\"" << tcu::TestLog::EndMessage;
676*35238bceSAndroid Build Coastguard Worker                 if (blockName != expectedName.str())
677*35238bceSAndroid Build Coastguard Worker                 {
678*35238bceSAndroid Build Coastguard Worker                     m_testCtx.getLog() << tcu::TestLog::Message << "\tError, expected " << expectedName.str()
679*35238bceSAndroid Build Coastguard Worker                                        << tcu::TestLog::EndMessage;
680*35238bceSAndroid Build Coastguard Worker                     setError("resource block index invalid");
681*35238bceSAndroid Build Coastguard Worker                 }
682*35238bceSAndroid Build Coastguard Worker             }
683*35238bceSAndroid Build Coastguard Worker         }
684*35238bceSAndroid Build Coastguard Worker     }
685*35238bceSAndroid Build Coastguard Worker }
686*35238bceSAndroid Build Coastguard Worker 
687*35238bceSAndroid Build Coastguard Worker class IsRowMajorValidator : public SingleVariableValidator
688*35238bceSAndroid Build Coastguard Worker {
689*35238bceSAndroid Build Coastguard Worker public:
690*35238bceSAndroid Build Coastguard Worker     IsRowMajorValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
691*35238bceSAndroid Build Coastguard Worker 
692*35238bceSAndroid Build Coastguard Worker     std::string getHumanReadablePropertyString(glw::GLint propVal) const;
693*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
694*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
695*35238bceSAndroid Build Coastguard Worker };
696*35238bceSAndroid Build Coastguard Worker 
IsRowMajorValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)697*35238bceSAndroid Build Coastguard Worker IsRowMajorValidator::IsRowMajorValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter)
698*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, programID, filter, DE_NULL)
699*35238bceSAndroid Build Coastguard Worker {
700*35238bceSAndroid Build Coastguard Worker }
701*35238bceSAndroid Build Coastguard Worker 
getHumanReadablePropertyString(glw::GLint propVal) const702*35238bceSAndroid Build Coastguard Worker std::string IsRowMajorValidator::getHumanReadablePropertyString(glw::GLint propVal) const
703*35238bceSAndroid Build Coastguard Worker {
704*35238bceSAndroid Build Coastguard Worker     return de::toString(glu::getBooleanStr(propVal));
705*35238bceSAndroid Build Coastguard Worker }
706*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const707*35238bceSAndroid Build Coastguard Worker void IsRowMajorValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
708*35238bceSAndroid Build Coastguard Worker                                                  const std::string &resource, glw::GLint propValue,
709*35238bceSAndroid Build Coastguard Worker                                                  const std::string &implementationName) const
710*35238bceSAndroid Build Coastguard Worker {
711*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &component      = path.back();
712*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &firstComponent = path.front();
713*35238bceSAndroid Build Coastguard Worker 
714*35238bceSAndroid Build Coastguard Worker     const bool isBufferBlock = firstComponent.isInterfaceBlock() &&
715*35238bceSAndroid Build Coastguard Worker                                isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage);
716*35238bceSAndroid Build Coastguard Worker     const bool isMatrix = glu::isDataTypeMatrix(component.getVariableType()->getBasicType());
717*35238bceSAndroid Build Coastguard Worker     const int expected =
718*35238bceSAndroid Build Coastguard Worker         (isBufferBlock && isMatrix && getMatrixOrderFromPath(path) == glu::MATRIXORDER_ROW_MAJOR) ? (1) : (0);
719*35238bceSAndroid Build Coastguard Worker 
720*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
721*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
722*35238bceSAndroid Build Coastguard Worker 
723*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix order, expecting IS_ROW_MAJOR = " << expected
724*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
725*35238bceSAndroid Build Coastguard Worker 
726*35238bceSAndroid Build Coastguard Worker     if (propValue != expected)
727*35238bceSAndroid Build Coastguard Worker     {
728*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
729*35238bceSAndroid Build Coastguard Worker         setError("resource matrix order invalid");
730*35238bceSAndroid Build Coastguard Worker     }
731*35238bceSAndroid Build Coastguard Worker }
732*35238bceSAndroid Build Coastguard Worker 
733*35238bceSAndroid Build Coastguard Worker class MatrixStrideValidator : public SingleVariableValidator
734*35238bceSAndroid Build Coastguard Worker {
735*35238bceSAndroid Build Coastguard Worker public:
736*35238bceSAndroid Build Coastguard Worker     MatrixStrideValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
737*35238bceSAndroid Build Coastguard Worker 
738*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
739*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
740*35238bceSAndroid Build Coastguard Worker };
741*35238bceSAndroid Build Coastguard Worker 
MatrixStrideValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)742*35238bceSAndroid Build Coastguard Worker MatrixStrideValidator::MatrixStrideValidator(Context &context, glw::GLuint programID,
743*35238bceSAndroid Build Coastguard Worker                                              const VariableSearchFilter &filter)
744*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_MATRIX_STRIDE, programID, filter, DE_NULL)
745*35238bceSAndroid Build Coastguard Worker {
746*35238bceSAndroid Build Coastguard Worker }
747*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const748*35238bceSAndroid Build Coastguard Worker void MatrixStrideValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
749*35238bceSAndroid Build Coastguard Worker                                                    const std::string &resource, glw::GLint propValue,
750*35238bceSAndroid Build Coastguard Worker                                                    const std::string &implementationName) const
751*35238bceSAndroid Build Coastguard Worker {
752*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &component      = path.back();
753*35238bceSAndroid Build Coastguard Worker     const VariablePathComponent &firstComponent = path.front();
754*35238bceSAndroid Build Coastguard Worker 
755*35238bceSAndroid Build Coastguard Worker     const bool isBufferBlock = firstComponent.isInterfaceBlock() &&
756*35238bceSAndroid Build Coastguard Worker                                isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage);
757*35238bceSAndroid Build Coastguard Worker     const bool isMatrix = glu::isDataTypeMatrix(component.getVariableType()->getBasicType());
758*35238bceSAndroid Build Coastguard Worker 
759*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
760*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
761*35238bceSAndroid Build Coastguard Worker 
762*35238bceSAndroid Build Coastguard Worker     // Layout tests will verify layouts of buffer backed arrays properly. Here we just check the stride is is greater or equal to the row/column size
763*35238bceSAndroid Build Coastguard Worker     if (isBufferBlock && isMatrix)
764*35238bceSAndroid Build Coastguard Worker     {
765*35238bceSAndroid Build Coastguard Worker         const bool columnMajor = getMatrixOrderFromPath(path) != glu::MATRIXORDER_ROW_MAJOR;
766*35238bceSAndroid Build Coastguard Worker         const int numMajorElements =
767*35238bceSAndroid Build Coastguard Worker             (columnMajor) ? (glu::getDataTypeMatrixNumRows(component.getVariableType()->getBasicType())) :
768*35238bceSAndroid Build Coastguard Worker                             (glu::getDataTypeMatrixNumColumns(component.getVariableType()->getBasicType()));
769*35238bceSAndroid Build Coastguard Worker         const int majorSize =
770*35238bceSAndroid Build Coastguard Worker             numMajorElements * getTypeSize(glu::getDataTypeScalarType(component.getVariableType()->getBasicType()));
771*35238bceSAndroid Build Coastguard Worker 
772*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix stride, expecting greater or equal to "
773*35238bceSAndroid Build Coastguard Worker                            << majorSize << tcu::TestLog::EndMessage;
774*35238bceSAndroid Build Coastguard Worker 
775*35238bceSAndroid Build Coastguard Worker         if (propValue < majorSize)
776*35238bceSAndroid Build Coastguard Worker         {
777*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
778*35238bceSAndroid Build Coastguard Worker             setError("resource matrix stride invalid");
779*35238bceSAndroid Build Coastguard Worker         }
780*35238bceSAndroid Build Coastguard Worker     }
781*35238bceSAndroid Build Coastguard Worker     else
782*35238bceSAndroid Build Coastguard Worker     {
783*35238bceSAndroid Build Coastguard Worker         const int matrixStride =
784*35238bceSAndroid Build Coastguard Worker             (!isBufferBlock && !glu::isDataTypeAtomicCounter(component.getVariableType()->getBasicType())) ? (-1) : (0);
785*35238bceSAndroid Build Coastguard Worker 
786*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix stride, expecting " << matrixStride
787*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
788*35238bceSAndroid Build Coastguard Worker 
789*35238bceSAndroid Build Coastguard Worker         if (matrixStride != propValue)
790*35238bceSAndroid Build Coastguard Worker         {
791*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
792*35238bceSAndroid Build Coastguard Worker             setError("resource matrix stride invalid");
793*35238bceSAndroid Build Coastguard Worker         }
794*35238bceSAndroid Build Coastguard Worker     }
795*35238bceSAndroid Build Coastguard Worker }
796*35238bceSAndroid Build Coastguard Worker 
797*35238bceSAndroid Build Coastguard Worker class AtomicCounterBufferIndexVerifier : public SingleVariableValidator
798*35238bceSAndroid Build Coastguard Worker {
799*35238bceSAndroid Build Coastguard Worker public:
800*35238bceSAndroid Build Coastguard Worker     AtomicCounterBufferIndexVerifier(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
801*35238bceSAndroid Build Coastguard Worker 
802*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
803*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
804*35238bceSAndroid Build Coastguard Worker };
805*35238bceSAndroid Build Coastguard Worker 
AtomicCounterBufferIndexVerifier(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)806*35238bceSAndroid Build Coastguard Worker AtomicCounterBufferIndexVerifier::AtomicCounterBufferIndexVerifier(Context &context, glw::GLuint programID,
807*35238bceSAndroid Build Coastguard Worker                                                                    const VariableSearchFilter &filter)
808*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_ATOMIC_COUNTER_BUFFER_INDEX, programID, filter, DE_NULL)
809*35238bceSAndroid Build Coastguard Worker {
810*35238bceSAndroid Build Coastguard Worker }
811*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const812*35238bceSAndroid Build Coastguard Worker void AtomicCounterBufferIndexVerifier::validateSingleVariable(const std::vector<VariablePathComponent> &path,
813*35238bceSAndroid Build Coastguard Worker                                                               const std::string &resource, glw::GLint propValue,
814*35238bceSAndroid Build Coastguard Worker                                                               const std::string &implementationName) const
815*35238bceSAndroid Build Coastguard Worker {
816*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
817*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
818*35238bceSAndroid Build Coastguard Worker 
819*35238bceSAndroid Build Coastguard Worker     if (!glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType()))
820*35238bceSAndroid Build Coastguard Worker     {
821*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying atomic counter buffer index, expecting -1"
822*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
823*35238bceSAndroid Build Coastguard Worker 
824*35238bceSAndroid Build Coastguard Worker         if (propValue != -1)
825*35238bceSAndroid Build Coastguard Worker         {
826*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
827*35238bceSAndroid Build Coastguard Worker             setError("resource atomic counter buffer index invalid");
828*35238bceSAndroid Build Coastguard Worker         }
829*35238bceSAndroid Build Coastguard Worker     }
830*35238bceSAndroid Build Coastguard Worker     else
831*35238bceSAndroid Build Coastguard Worker     {
832*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying atomic counter buffer index, expecting a valid index"
833*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
834*35238bceSAndroid Build Coastguard Worker 
835*35238bceSAndroid Build Coastguard Worker         if (propValue == -1)
836*35238bceSAndroid Build Coastguard Worker         {
837*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
838*35238bceSAndroid Build Coastguard Worker             setError("resource atomic counter buffer index invalid");
839*35238bceSAndroid Build Coastguard Worker         }
840*35238bceSAndroid Build Coastguard Worker         else
841*35238bceSAndroid Build Coastguard Worker         {
842*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl      = m_renderContext.getFunctions();
843*35238bceSAndroid Build Coastguard Worker             glw::GLint numActiveResources = 0;
844*35238bceSAndroid Build Coastguard Worker 
845*35238bceSAndroid Build Coastguard Worker             gl.getProgramInterfaceiv(m_programID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numActiveResources);
846*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(gl.getError(),
847*35238bceSAndroid Build Coastguard Worker                                 "getProgramInterfaceiv(..., GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, ...)");
848*35238bceSAndroid Build Coastguard Worker 
849*35238bceSAndroid Build Coastguard Worker             if (propValue >= numActiveResources)
850*35238bceSAndroid Build Coastguard Worker             {
851*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue
852*35238bceSAndroid Build Coastguard Worker                                    << ", GL_ACTIVE_RESOURCES = " << numActiveResources << tcu::TestLog::EndMessage;
853*35238bceSAndroid Build Coastguard Worker                 setError("resource atomic counter buffer index invalid");
854*35238bceSAndroid Build Coastguard Worker             }
855*35238bceSAndroid Build Coastguard Worker         }
856*35238bceSAndroid Build Coastguard Worker     }
857*35238bceSAndroid Build Coastguard Worker }
858*35238bceSAndroid Build Coastguard Worker 
859*35238bceSAndroid Build Coastguard Worker class LocationValidator : public SingleVariableValidator
860*35238bceSAndroid Build Coastguard Worker {
861*35238bceSAndroid Build Coastguard Worker public:
862*35238bceSAndroid Build Coastguard Worker     LocationValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
863*35238bceSAndroid Build Coastguard Worker 
864*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
865*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
866*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
867*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
868*35238bceSAndroid Build Coastguard Worker };
869*35238bceSAndroid Build Coastguard Worker 
LocationValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)870*35238bceSAndroid Build Coastguard Worker LocationValidator::LocationValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter)
871*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_LOCATION, programID, filter, DE_NULL)
872*35238bceSAndroid Build Coastguard Worker {
873*35238bceSAndroid Build Coastguard Worker }
874*35238bceSAndroid Build Coastguard Worker 
getVariableLocationLength(const glu::VarType & type)875*35238bceSAndroid Build Coastguard Worker static int getVariableLocationLength(const glu::VarType &type)
876*35238bceSAndroid Build Coastguard Worker {
877*35238bceSAndroid Build Coastguard Worker     if (type.isBasicType())
878*35238bceSAndroid Build Coastguard Worker     {
879*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeMatrix(type.getBasicType()))
880*35238bceSAndroid Build Coastguard Worker             return glu::getDataTypeMatrixNumColumns(type.getBasicType());
881*35238bceSAndroid Build Coastguard Worker         else
882*35238bceSAndroid Build Coastguard Worker             return 1;
883*35238bceSAndroid Build Coastguard Worker     }
884*35238bceSAndroid Build Coastguard Worker     else if (type.isStructType())
885*35238bceSAndroid Build Coastguard Worker     {
886*35238bceSAndroid Build Coastguard Worker         int size = 0;
887*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
888*35238bceSAndroid Build Coastguard Worker             size += getVariableLocationLength(type.getStructPtr()->getMember(ndx).getType());
889*35238bceSAndroid Build Coastguard Worker         return size;
890*35238bceSAndroid Build Coastguard Worker     }
891*35238bceSAndroid Build Coastguard Worker     else if (type.isArrayType())
892*35238bceSAndroid Build Coastguard Worker         return type.getArraySize() * getVariableLocationLength(type.getElementType());
893*35238bceSAndroid Build Coastguard Worker     else
894*35238bceSAndroid Build Coastguard Worker     {
895*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
896*35238bceSAndroid Build Coastguard Worker         return 0;
897*35238bceSAndroid Build Coastguard Worker     }
898*35238bceSAndroid Build Coastguard Worker }
899*35238bceSAndroid Build Coastguard Worker 
getIOSubVariableLocation(const std::vector<VariablePathComponent> & path,int startNdx,int currentLocation)900*35238bceSAndroid Build Coastguard Worker static int getIOSubVariableLocation(const std::vector<VariablePathComponent> &path, int startNdx, int currentLocation)
901*35238bceSAndroid Build Coastguard Worker {
902*35238bceSAndroid Build Coastguard Worker     if (currentLocation == -1)
903*35238bceSAndroid Build Coastguard Worker         return -1;
904*35238bceSAndroid Build Coastguard Worker 
905*35238bceSAndroid Build Coastguard Worker     if (path[startNdx].getVariableType()->isBasicType())
906*35238bceSAndroid Build Coastguard Worker         return currentLocation;
907*35238bceSAndroid Build Coastguard Worker     else if (path[startNdx].getVariableType()->isArrayType())
908*35238bceSAndroid Build Coastguard Worker         return getIOSubVariableLocation(path, startNdx + 1, currentLocation);
909*35238bceSAndroid Build Coastguard Worker     else if (path[startNdx].getVariableType()->isStructType())
910*35238bceSAndroid Build Coastguard Worker     {
911*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < path[startNdx].getVariableType()->getStructPtr()->getNumMembers(); ++ndx)
912*35238bceSAndroid Build Coastguard Worker         {
913*35238bceSAndroid Build Coastguard Worker             if (&path[startNdx].getVariableType()->getStructPtr()->getMember(ndx).getType() ==
914*35238bceSAndroid Build Coastguard Worker                 path[startNdx + 1].getVariableType())
915*35238bceSAndroid Build Coastguard Worker                 return getIOSubVariableLocation(path, startNdx + 1, currentLocation);
916*35238bceSAndroid Build Coastguard Worker 
917*35238bceSAndroid Build Coastguard Worker             if (currentLocation != -1)
918*35238bceSAndroid Build Coastguard Worker                 currentLocation += getVariableLocationLength(
919*35238bceSAndroid Build Coastguard Worker                     path[startNdx].getVariableType()->getStructPtr()->getMember(ndx).getType());
920*35238bceSAndroid Build Coastguard Worker         }
921*35238bceSAndroid Build Coastguard Worker 
922*35238bceSAndroid Build Coastguard Worker         // could not find member, never happens
923*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
924*35238bceSAndroid Build Coastguard Worker         return -1;
925*35238bceSAndroid Build Coastguard Worker     }
926*35238bceSAndroid Build Coastguard Worker     else
927*35238bceSAndroid Build Coastguard Worker     {
928*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
929*35238bceSAndroid Build Coastguard Worker         return -1;
930*35238bceSAndroid Build Coastguard Worker     }
931*35238bceSAndroid Build Coastguard Worker }
932*35238bceSAndroid Build Coastguard Worker 
getIOBlockVariableLocation(const std::vector<VariablePathComponent> & path)933*35238bceSAndroid Build Coastguard Worker static int getIOBlockVariableLocation(const std::vector<VariablePathComponent> &path)
934*35238bceSAndroid Build Coastguard Worker {
935*35238bceSAndroid Build Coastguard Worker     const glu::InterfaceBlock *block = path.front().getInterfaceBlock();
936*35238bceSAndroid Build Coastguard Worker     int currentLocation              = block->layout.location;
937*35238bceSAndroid Build Coastguard Worker 
938*35238bceSAndroid Build Coastguard Worker     // Find the block member
939*35238bceSAndroid Build Coastguard Worker     for (int memberNdx = 0; memberNdx < (int)block->variables.size(); ++memberNdx)
940*35238bceSAndroid Build Coastguard Worker     {
941*35238bceSAndroid Build Coastguard Worker         if (block->variables[memberNdx].layout.location != -1)
942*35238bceSAndroid Build Coastguard Worker             currentLocation = block->variables[memberNdx].layout.location;
943*35238bceSAndroid Build Coastguard Worker 
944*35238bceSAndroid Build Coastguard Worker         if (&block->variables[memberNdx] == path[1].getDeclaration())
945*35238bceSAndroid Build Coastguard Worker             break;
946*35238bceSAndroid Build Coastguard Worker 
947*35238bceSAndroid Build Coastguard Worker         // unspecified + unspecified = unspecified
948*35238bceSAndroid Build Coastguard Worker         if (currentLocation != -1)
949*35238bceSAndroid Build Coastguard Worker             currentLocation += getVariableLocationLength(block->variables[memberNdx].varType);
950*35238bceSAndroid Build Coastguard Worker     }
951*35238bceSAndroid Build Coastguard Worker 
952*35238bceSAndroid Build Coastguard Worker     // Find subtype location in the complex type
953*35238bceSAndroid Build Coastguard Worker     return getIOSubVariableLocation(path, 2, currentLocation);
954*35238bceSAndroid Build Coastguard Worker }
955*35238bceSAndroid Build Coastguard Worker 
getExplicitLocationFromPath(const std::vector<VariablePathComponent> & path)956*35238bceSAndroid Build Coastguard Worker static int getExplicitLocationFromPath(const std::vector<VariablePathComponent> &path)
957*35238bceSAndroid Build Coastguard Worker {
958*35238bceSAndroid Build Coastguard Worker     const glu::VariableDeclaration *varDecl =
959*35238bceSAndroid Build Coastguard Worker         (path[0].isInterfaceBlock()) ? (path[1].getDeclaration()) : (path[0].getDeclaration());
960*35238bceSAndroid Build Coastguard Worker 
961*35238bceSAndroid Build Coastguard Worker     if (path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_UNIFORM)
962*35238bceSAndroid Build Coastguard Worker     {
963*35238bceSAndroid Build Coastguard Worker         // inside uniform block
964*35238bceSAndroid Build Coastguard Worker         return -1;
965*35238bceSAndroid Build Coastguard Worker     }
966*35238bceSAndroid Build Coastguard Worker     else if (path.front().isInterfaceBlock() && (path.front().getInterfaceBlock()->storage == glu::STORAGE_IN ||
967*35238bceSAndroid Build Coastguard Worker                                                  path.front().getInterfaceBlock()->storage == glu::STORAGE_OUT ||
968*35238bceSAndroid Build Coastguard Worker                                                  path.front().getInterfaceBlock()->storage == glu::STORAGE_PATCH_IN ||
969*35238bceSAndroid Build Coastguard Worker                                                  path.front().getInterfaceBlock()->storage == glu::STORAGE_PATCH_OUT))
970*35238bceSAndroid Build Coastguard Worker     {
971*35238bceSAndroid Build Coastguard Worker         // inside ioblock
972*35238bceSAndroid Build Coastguard Worker         return getIOBlockVariableLocation(path);
973*35238bceSAndroid Build Coastguard Worker     }
974*35238bceSAndroid Build Coastguard Worker     else if (varDecl->storage == glu::STORAGE_UNIFORM)
975*35238bceSAndroid Build Coastguard Worker     {
976*35238bceSAndroid Build Coastguard Worker         // default block uniform
977*35238bceSAndroid Build Coastguard Worker         return varDecl->layout.location;
978*35238bceSAndroid Build Coastguard Worker     }
979*35238bceSAndroid Build Coastguard Worker     else if (varDecl->storage == glu::STORAGE_IN || varDecl->storage == glu::STORAGE_OUT ||
980*35238bceSAndroid Build Coastguard Worker              varDecl->storage == glu::STORAGE_PATCH_IN || varDecl->storage == glu::STORAGE_PATCH_OUT)
981*35238bceSAndroid Build Coastguard Worker     {
982*35238bceSAndroid Build Coastguard Worker         // default block input/output
983*35238bceSAndroid Build Coastguard Worker         return getIOSubVariableLocation(path, 1, varDecl->layout.location);
984*35238bceSAndroid Build Coastguard Worker     }
985*35238bceSAndroid Build Coastguard Worker     else
986*35238bceSAndroid Build Coastguard Worker     {
987*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
988*35238bceSAndroid Build Coastguard Worker         return -1;
989*35238bceSAndroid Build Coastguard Worker     }
990*35238bceSAndroid Build Coastguard Worker }
991*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const992*35238bceSAndroid Build Coastguard Worker void LocationValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
993*35238bceSAndroid Build Coastguard Worker                                                const std::string &resource, glw::GLint propValue,
994*35238bceSAndroid Build Coastguard Worker                                                const std::string &implementationName) const
995*35238bceSAndroid Build Coastguard Worker {
996*35238bceSAndroid Build Coastguard Worker     const bool isAtomicCounterUniform = glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType());
997*35238bceSAndroid Build Coastguard Worker     const bool isUniformBlockVariable =
998*35238bceSAndroid Build Coastguard Worker         path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_UNIFORM;
999*35238bceSAndroid Build Coastguard Worker     const bool isVertexShader        = m_filter.getShaderTypeBits() == (1u << glu::SHADERTYPE_VERTEX);
1000*35238bceSAndroid Build Coastguard Worker     const bool isFragmentShader      = m_filter.getShaderTypeBits() == (1u << glu::SHADERTYPE_FRAGMENT);
1001*35238bceSAndroid Build Coastguard Worker     const glu::Storage storage       = (path.front().isInterfaceBlock()) ? (path.front().getInterfaceBlock()->storage) :
1002*35238bceSAndroid Build Coastguard Worker                                                                            (path.front().getDeclaration()->storage);
1003*35238bceSAndroid Build Coastguard Worker     const bool isInputVariable       = (storage == glu::STORAGE_IN || storage == glu::STORAGE_PATCH_IN);
1004*35238bceSAndroid Build Coastguard Worker     const bool isOutputVariable      = (storage == glu::STORAGE_OUT || storage == glu::STORAGE_PATCH_OUT);
1005*35238bceSAndroid Build Coastguard Worker     const int explicitLayoutLocation = getExplicitLocationFromPath(path);
1006*35238bceSAndroid Build Coastguard Worker 
1007*35238bceSAndroid Build Coastguard Worker     bool expectLocation;
1008*35238bceSAndroid Build Coastguard Worker     std::string reasonStr;
1009*35238bceSAndroid Build Coastguard Worker 
1010*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1011*35238bceSAndroid Build Coastguard Worker 
1012*35238bceSAndroid Build Coastguard Worker     if (isAtomicCounterUniform)
1013*35238bceSAndroid Build Coastguard Worker     {
1014*35238bceSAndroid Build Coastguard Worker         expectLocation = false;
1015*35238bceSAndroid Build Coastguard Worker         reasonStr      = "Atomic counter uniforms have effective location of -1";
1016*35238bceSAndroid Build Coastguard Worker     }
1017*35238bceSAndroid Build Coastguard Worker     else if (isUniformBlockVariable)
1018*35238bceSAndroid Build Coastguard Worker     {
1019*35238bceSAndroid Build Coastguard Worker         expectLocation = false;
1020*35238bceSAndroid Build Coastguard Worker         reasonStr      = "Uniform block variables have effective location of -1";
1021*35238bceSAndroid Build Coastguard Worker     }
1022*35238bceSAndroid Build Coastguard Worker     else if (isInputVariable && !isVertexShader && explicitLayoutLocation == -1)
1023*35238bceSAndroid Build Coastguard Worker     {
1024*35238bceSAndroid Build Coastguard Worker         expectLocation = false;
1025*35238bceSAndroid Build Coastguard Worker         reasonStr      = "Inputs (except for vertex shader inputs) not declared with a location layout qualifier have "
1026*35238bceSAndroid Build Coastguard Worker                          "effective location of -1";
1027*35238bceSAndroid Build Coastguard Worker     }
1028*35238bceSAndroid Build Coastguard Worker     else if (isOutputVariable && !isFragmentShader && explicitLayoutLocation == -1)
1029*35238bceSAndroid Build Coastguard Worker     {
1030*35238bceSAndroid Build Coastguard Worker         expectLocation = false;
1031*35238bceSAndroid Build Coastguard Worker         reasonStr = "Outputs (except for fragment shader outputs) not declared with a location layout qualifier have "
1032*35238bceSAndroid Build Coastguard Worker                     "effective location of -1";
1033*35238bceSAndroid Build Coastguard Worker     }
1034*35238bceSAndroid Build Coastguard Worker     else
1035*35238bceSAndroid Build Coastguard Worker     {
1036*35238bceSAndroid Build Coastguard Worker         expectLocation = true;
1037*35238bceSAndroid Build Coastguard Worker     }
1038*35238bceSAndroid Build Coastguard Worker 
1039*35238bceSAndroid Build Coastguard Worker     if (!expectLocation)
1040*35238bceSAndroid Build Coastguard Worker     {
1041*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying uniform location, expecting -1. (" << reasonStr << ")"
1042*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1043*35238bceSAndroid Build Coastguard Worker 
1044*35238bceSAndroid Build Coastguard Worker         if (propValue != -1)
1045*35238bceSAndroid Build Coastguard Worker         {
1046*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
1047*35238bceSAndroid Build Coastguard Worker             setError("resource location invalid");
1048*35238bceSAndroid Build Coastguard Worker         }
1049*35238bceSAndroid Build Coastguard Worker     }
1050*35238bceSAndroid Build Coastguard Worker     else
1051*35238bceSAndroid Build Coastguard Worker     {
1052*35238bceSAndroid Build Coastguard Worker         bool locationOk;
1053*35238bceSAndroid Build Coastguard Worker 
1054*35238bceSAndroid Build Coastguard Worker         if (explicitLayoutLocation == -1)
1055*35238bceSAndroid Build Coastguard Worker         {
1056*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting a valid location"
1057*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1058*35238bceSAndroid Build Coastguard Worker             locationOk = (propValue != -1);
1059*35238bceSAndroid Build Coastguard Worker         }
1060*35238bceSAndroid Build Coastguard Worker         else
1061*35238bceSAndroid Build Coastguard Worker         {
1062*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting " << explicitLayoutLocation
1063*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1064*35238bceSAndroid Build Coastguard Worker             locationOk = (propValue == explicitLayoutLocation);
1065*35238bceSAndroid Build Coastguard Worker         }
1066*35238bceSAndroid Build Coastguard Worker 
1067*35238bceSAndroid Build Coastguard Worker         if (!locationOk)
1068*35238bceSAndroid Build Coastguard Worker         {
1069*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
1070*35238bceSAndroid Build Coastguard Worker             setError("resource location invalid");
1071*35238bceSAndroid Build Coastguard Worker         }
1072*35238bceSAndroid Build Coastguard Worker         else
1073*35238bceSAndroid Build Coastguard Worker         {
1074*35238bceSAndroid Build Coastguard Worker             const VariablePathComponent nullComponent;
1075*35238bceSAndroid Build Coastguard Worker             const VariablePathComponent &enclosingcomponent =
1076*35238bceSAndroid Build Coastguard Worker                 (path.size() > 1) ? (path[path.size() - 2]) : (nullComponent);
1077*35238bceSAndroid Build Coastguard Worker             const bool isArray =
1078*35238bceSAndroid Build Coastguard Worker                 enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType();
1079*35238bceSAndroid Build Coastguard Worker 
1080*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl    = m_renderContext.getFunctions();
1081*35238bceSAndroid Build Coastguard Worker             const glw::GLenum interface = getProgramDefaultBlockInterfaceFromStorage(storage);
1082*35238bceSAndroid Build Coastguard Worker 
1083*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message
1084*35238bceSAndroid Build Coastguard Worker                                << "Comparing location to the values returned by GetProgramResourceLocation"
1085*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1086*35238bceSAndroid Build Coastguard Worker 
1087*35238bceSAndroid Build Coastguard Worker             // Test all bottom-level array elements
1088*35238bceSAndroid Build Coastguard Worker             if (isArray)
1089*35238bceSAndroid Build Coastguard Worker             {
1090*35238bceSAndroid Build Coastguard Worker                 const std::string arrayResourceName =
1091*35238bceSAndroid Build Coastguard Worker                     (implementationName.size() > 3) ? (implementationName.substr(0, implementationName.size() - 3)) :
1092*35238bceSAndroid Build Coastguard Worker                                                       (""); // chop "[0]"
1093*35238bceSAndroid Build Coastguard Worker 
1094*35238bceSAndroid Build Coastguard Worker                 for (int arrayElementNdx = 0; arrayElementNdx < enclosingcomponent.getVariableType()->getArraySize();
1095*35238bceSAndroid Build Coastguard Worker                      ++arrayElementNdx)
1096*35238bceSAndroid Build Coastguard Worker                 {
1097*35238bceSAndroid Build Coastguard Worker                     const std::string elementResourceName =
1098*35238bceSAndroid Build Coastguard Worker                         arrayResourceName + "[" + de::toString(arrayElementNdx) + "]";
1099*35238bceSAndroid Build Coastguard Worker                     const glw::GLint location =
1100*35238bceSAndroid Build Coastguard Worker                         gl.getProgramResourceLocation(m_programID, interface, elementResourceName.c_str());
1101*35238bceSAndroid Build Coastguard Worker 
1102*35238bceSAndroid Build Coastguard Worker                     if (location != propValue + arrayElementNdx)
1103*35238bceSAndroid Build Coastguard Worker                     {
1104*35238bceSAndroid Build Coastguard Worker                         m_testCtx.getLog()
1105*35238bceSAndroid Build Coastguard Worker                             << tcu::TestLog::Message << "\tError, getProgramResourceLocation (resource=\""
1106*35238bceSAndroid Build Coastguard Worker                             << elementResourceName << "\") returned location " << location << ", expected "
1107*35238bceSAndroid Build Coastguard Worker                             << (propValue + arrayElementNdx) << tcu::TestLog::EndMessage;
1108*35238bceSAndroid Build Coastguard Worker                         setError("resource location invalid");
1109*35238bceSAndroid Build Coastguard Worker                     }
1110*35238bceSAndroid Build Coastguard Worker                     else
1111*35238bceSAndroid Build Coastguard Worker                         m_testCtx.getLog() << tcu::TestLog::Message << "\tLocation of \"" << elementResourceName
1112*35238bceSAndroid Build Coastguard Worker                                            << "\":\t" << location << tcu::TestLog::EndMessage;
1113*35238bceSAndroid Build Coastguard Worker                 }
1114*35238bceSAndroid Build Coastguard Worker             }
1115*35238bceSAndroid Build Coastguard Worker             else
1116*35238bceSAndroid Build Coastguard Worker             {
1117*35238bceSAndroid Build Coastguard Worker                 const glw::GLint location =
1118*35238bceSAndroid Build Coastguard Worker                     gl.getProgramResourceLocation(m_programID, interface, implementationName.c_str());
1119*35238bceSAndroid Build Coastguard Worker 
1120*35238bceSAndroid Build Coastguard Worker                 if (location != propValue)
1121*35238bceSAndroid Build Coastguard Worker                 {
1122*35238bceSAndroid Build Coastguard Worker                     m_testCtx.getLog() << tcu::TestLog::Message
1123*35238bceSAndroid Build Coastguard Worker                                        << "\tError, getProgramResourceLocation returned location " << location
1124*35238bceSAndroid Build Coastguard Worker                                        << ", expected " << propValue << tcu::TestLog::EndMessage;
1125*35238bceSAndroid Build Coastguard Worker                     setError("resource location invalid");
1126*35238bceSAndroid Build Coastguard Worker                 }
1127*35238bceSAndroid Build Coastguard Worker             }
1128*35238bceSAndroid Build Coastguard Worker         }
1129*35238bceSAndroid Build Coastguard Worker     }
1130*35238bceSAndroid Build Coastguard Worker }
1131*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1132*35238bceSAndroid Build Coastguard Worker void LocationValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1133*35238bceSAndroid Build Coastguard Worker                                                 const std::string &implementationName) const
1134*35238bceSAndroid Build Coastguard Worker {
1135*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1136*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1137*35238bceSAndroid Build Coastguard Worker 
1138*35238bceSAndroid Build Coastguard Worker     // built-ins have no location
1139*35238bceSAndroid Build Coastguard Worker 
1140*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting -1" << tcu::TestLog::EndMessage;
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker     if (propValue != -1)
1143*35238bceSAndroid Build Coastguard Worker     {
1144*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
1145*35238bceSAndroid Build Coastguard Worker         setError("resource location invalid");
1146*35238bceSAndroid Build Coastguard Worker     }
1147*35238bceSAndroid Build Coastguard Worker }
1148*35238bceSAndroid Build Coastguard Worker 
1149*35238bceSAndroid Build Coastguard Worker class VariableNameLengthValidator : public SingleVariableValidator
1150*35238bceSAndroid Build Coastguard Worker {
1151*35238bceSAndroid Build Coastguard Worker public:
1152*35238bceSAndroid Build Coastguard Worker     VariableNameLengthValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
1153*35238bceSAndroid Build Coastguard Worker 
1154*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1155*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1156*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1157*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
1158*35238bceSAndroid Build Coastguard Worker     void validateNameLength(const std::string &implementationName, glw::GLint propValue) const;
1159*35238bceSAndroid Build Coastguard Worker };
1160*35238bceSAndroid Build Coastguard Worker 
VariableNameLengthValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)1161*35238bceSAndroid Build Coastguard Worker VariableNameLengthValidator::VariableNameLengthValidator(Context &context, glw::GLuint programID,
1162*35238bceSAndroid Build Coastguard Worker                                                          const VariableSearchFilter &filter)
1163*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH, programID, filter, DE_NULL)
1164*35238bceSAndroid Build Coastguard Worker {
1165*35238bceSAndroid Build Coastguard Worker }
1166*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1167*35238bceSAndroid Build Coastguard Worker void VariableNameLengthValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1168*35238bceSAndroid Build Coastguard Worker                                                          const std::string &resource, glw::GLint propValue,
1169*35238bceSAndroid Build Coastguard Worker                                                          const std::string &implementationName) const
1170*35238bceSAndroid Build Coastguard Worker {
1171*35238bceSAndroid Build Coastguard Worker     DE_UNREF(path);
1172*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1173*35238bceSAndroid Build Coastguard Worker     validateNameLength(implementationName, propValue);
1174*35238bceSAndroid Build Coastguard Worker }
1175*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1176*35238bceSAndroid Build Coastguard Worker void VariableNameLengthValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1177*35238bceSAndroid Build Coastguard Worker                                                           const std::string &implementationName) const
1178*35238bceSAndroid Build Coastguard Worker {
1179*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1180*35238bceSAndroid Build Coastguard Worker     validateNameLength(implementationName, propValue);
1181*35238bceSAndroid Build Coastguard Worker }
1182*35238bceSAndroid Build Coastguard Worker 
validateNameLength(const std::string & implementationName,glw::GLint propValue) const1183*35238bceSAndroid Build Coastguard Worker void VariableNameLengthValidator::validateNameLength(const std::string &implementationName, glw::GLint propValue) const
1184*35238bceSAndroid Build Coastguard Worker {
1185*35238bceSAndroid Build Coastguard Worker     const int expected = (int)implementationName.length() + 1; // includes null byte
1186*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " ("
1187*35238bceSAndroid Build Coastguard Worker                        << (int)implementationName.length() << " for \"" << implementationName
1188*35238bceSAndroid Build Coastguard Worker                        << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage;
1189*35238bceSAndroid Build Coastguard Worker 
1190*35238bceSAndroid Build Coastguard Worker     if (propValue != expected)
1191*35238bceSAndroid Build Coastguard Worker     {
1192*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue
1193*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1194*35238bceSAndroid Build Coastguard Worker         setError("name length invalid");
1195*35238bceSAndroid Build Coastguard Worker     }
1196*35238bceSAndroid Build Coastguard Worker }
1197*35238bceSAndroid Build Coastguard Worker 
1198*35238bceSAndroid Build Coastguard Worker class OffsetValidator : public SingleVariableValidator
1199*35238bceSAndroid Build Coastguard Worker {
1200*35238bceSAndroid Build Coastguard Worker public:
1201*35238bceSAndroid Build Coastguard Worker     OffsetValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
1202*35238bceSAndroid Build Coastguard Worker 
1203*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1204*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1205*35238bceSAndroid Build Coastguard Worker };
1206*35238bceSAndroid Build Coastguard Worker 
OffsetValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)1207*35238bceSAndroid Build Coastguard Worker OffsetValidator::OffsetValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter)
1208*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_OFFSET, programID, filter, DE_NULL)
1209*35238bceSAndroid Build Coastguard Worker {
1210*35238bceSAndroid Build Coastguard Worker }
1211*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1212*35238bceSAndroid Build Coastguard Worker void OffsetValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1213*35238bceSAndroid Build Coastguard Worker                                              const std::string &resource, glw::GLint propValue,
1214*35238bceSAndroid Build Coastguard Worker                                              const std::string &implementationName) const
1215*35238bceSAndroid Build Coastguard Worker {
1216*35238bceSAndroid Build Coastguard Worker     const bool isAtomicCounterUniform = glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType());
1217*35238bceSAndroid Build Coastguard Worker     const bool isBufferBackedBlockStorage =
1218*35238bceSAndroid Build Coastguard Worker         path.front().isInterfaceBlock() &&
1219*35238bceSAndroid Build Coastguard Worker         isBufferBackedInterfaceBlockStorage(path.front().getInterfaceBlock()->storage);
1220*35238bceSAndroid Build Coastguard Worker 
1221*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1222*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1223*35238bceSAndroid Build Coastguard Worker 
1224*35238bceSAndroid Build Coastguard Worker     if (!isAtomicCounterUniform && !isBufferBackedBlockStorage)
1225*35238bceSAndroid Build Coastguard Worker     {
1226*35238bceSAndroid Build Coastguard Worker         // Not buffer backed
1227*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying offset, expecting -1" << tcu::TestLog::EndMessage;
1228*35238bceSAndroid Build Coastguard Worker 
1229*35238bceSAndroid Build Coastguard Worker         if (propValue != -1)
1230*35238bceSAndroid Build Coastguard Worker         {
1231*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid offset, got " << propValue
1232*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1233*35238bceSAndroid Build Coastguard Worker             setError("offset invalid");
1234*35238bceSAndroid Build Coastguard Worker         }
1235*35238bceSAndroid Build Coastguard Worker     }
1236*35238bceSAndroid Build Coastguard Worker     else
1237*35238bceSAndroid Build Coastguard Worker     {
1238*35238bceSAndroid Build Coastguard Worker         // Expect a valid offset
1239*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying offset, expecting a valid offset"
1240*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1241*35238bceSAndroid Build Coastguard Worker 
1242*35238bceSAndroid Build Coastguard Worker         if (propValue < 0)
1243*35238bceSAndroid Build Coastguard Worker         {
1244*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid offset, got " << propValue
1245*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1246*35238bceSAndroid Build Coastguard Worker             setError("offset invalid");
1247*35238bceSAndroid Build Coastguard Worker         }
1248*35238bceSAndroid Build Coastguard Worker     }
1249*35238bceSAndroid Build Coastguard Worker }
1250*35238bceSAndroid Build Coastguard Worker 
1251*35238bceSAndroid Build Coastguard Worker class VariableReferencedByShaderValidator : public PropValidator
1252*35238bceSAndroid Build Coastguard Worker {
1253*35238bceSAndroid Build Coastguard Worker public:
1254*35238bceSAndroid Build Coastguard Worker     VariableReferencedByShaderValidator(Context &context, glu::ShaderType shaderType,
1255*35238bceSAndroid Build Coastguard Worker                                         const VariableSearchFilter &searchFilter);
1256*35238bceSAndroid Build Coastguard Worker 
1257*35238bceSAndroid Build Coastguard Worker     std::string getHumanReadablePropertyString(glw::GLint propVal) const;
1258*35238bceSAndroid Build Coastguard Worker     void validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource, glw::GLint propValue,
1259*35238bceSAndroid Build Coastguard Worker                   const std::string &implementationName) const;
1260*35238bceSAndroid Build Coastguard Worker 
1261*35238bceSAndroid Build Coastguard Worker private:
1262*35238bceSAndroid Build Coastguard Worker     const VariableSearchFilter m_filter;
1263*35238bceSAndroid Build Coastguard Worker     const glu::ShaderType m_shaderType;
1264*35238bceSAndroid Build Coastguard Worker };
1265*35238bceSAndroid Build Coastguard Worker 
VariableReferencedByShaderValidator(Context & context,glu::ShaderType shaderType,const VariableSearchFilter & searchFilter)1266*35238bceSAndroid Build Coastguard Worker VariableReferencedByShaderValidator::VariableReferencedByShaderValidator(Context &context, glu::ShaderType shaderType,
1267*35238bceSAndroid Build Coastguard Worker                                                                          const VariableSearchFilter &searchFilter)
1268*35238bceSAndroid Build Coastguard Worker     : PropValidator(context, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER, getRequiredExtensionForStage(shaderType))
1269*35238bceSAndroid Build Coastguard Worker     , m_filter(VariableSearchFilter::logicalAnd(VariableSearchFilter::createShaderTypeFilter(shaderType), searchFilter))
1270*35238bceSAndroid Build Coastguard Worker     , m_shaderType(shaderType)
1271*35238bceSAndroid Build Coastguard Worker {
1272*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_shaderType < glu::SHADERTYPE_LAST);
1273*35238bceSAndroid Build Coastguard Worker }
1274*35238bceSAndroid Build Coastguard Worker 
getHumanReadablePropertyString(glw::GLint propVal) const1275*35238bceSAndroid Build Coastguard Worker std::string VariableReferencedByShaderValidator::getHumanReadablePropertyString(glw::GLint propVal) const
1276*35238bceSAndroid Build Coastguard Worker {
1277*35238bceSAndroid Build Coastguard Worker     return de::toString(glu::getBooleanStr(propVal));
1278*35238bceSAndroid Build Coastguard Worker }
1279*35238bceSAndroid Build Coastguard Worker 
validate(const ProgramInterfaceDefinition::Program * program,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1280*35238bceSAndroid Build Coastguard Worker void VariableReferencedByShaderValidator::validate(const ProgramInterfaceDefinition::Program *program,
1281*35238bceSAndroid Build Coastguard Worker                                                    const std::string &resource, glw::GLint propValue,
1282*35238bceSAndroid Build Coastguard Worker                                                    const std::string &implementationName) const
1283*35238bceSAndroid Build Coastguard Worker {
1284*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1285*35238bceSAndroid Build Coastguard Worker 
1286*35238bceSAndroid Build Coastguard Worker     std::vector<VariablePathComponent> unusedPath;
1287*35238bceSAndroid Build Coastguard Worker     const bool referencedByShader = findProgramVariablePathByPathName(unusedPath, program, resource, m_filter);
1288*35238bceSAndroid Build Coastguard Worker 
1289*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying referenced by " << glu::getShaderTypeName(m_shaderType)
1290*35238bceSAndroid Build Coastguard Worker                        << " shader, expecting " << ((referencedByShader) ? ("GL_TRUE") : ("GL_FALSE"))
1291*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
1292*35238bceSAndroid Build Coastguard Worker 
1293*35238bceSAndroid Build Coastguard Worker     if (propValue != ((referencedByShader) ? (1) : (0)))
1294*35238bceSAndroid Build Coastguard Worker     {
1295*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid referenced_by_"
1296*35238bceSAndroid Build Coastguard Worker                            << glu::getShaderTypeName(m_shaderType) << ", got " << propValue << tcu::TestLog::EndMessage;
1297*35238bceSAndroid Build Coastguard Worker         setError("referenced_by_" + std::string(glu::getShaderTypeName(m_shaderType)) + " invalid");
1298*35238bceSAndroid Build Coastguard Worker     }
1299*35238bceSAndroid Build Coastguard Worker }
1300*35238bceSAndroid Build Coastguard Worker 
1301*35238bceSAndroid Build Coastguard Worker class BlockNameLengthValidator : public SingleBlockValidator
1302*35238bceSAndroid Build Coastguard Worker {
1303*35238bceSAndroid Build Coastguard Worker public:
1304*35238bceSAndroid Build Coastguard Worker     BlockNameLengthValidator(Context &context, const glw::GLuint programID, const VariableSearchFilter &filter);
1305*35238bceSAndroid Build Coastguard Worker 
1306*35238bceSAndroid Build Coastguard Worker     void validateSingleBlock(const glu::InterfaceBlock &block, const std::vector<int> &instanceIndex,
1307*35238bceSAndroid Build Coastguard Worker                              const std::string &resource, glw::GLint propValue,
1308*35238bceSAndroid Build Coastguard Worker                              const std::string &implementationName) const;
1309*35238bceSAndroid Build Coastguard Worker };
1310*35238bceSAndroid Build Coastguard Worker 
BlockNameLengthValidator(Context & context,const glw::GLuint programID,const VariableSearchFilter & filter)1311*35238bceSAndroid Build Coastguard Worker BlockNameLengthValidator::BlockNameLengthValidator(Context &context, const glw::GLuint programID,
1312*35238bceSAndroid Build Coastguard Worker                                                    const VariableSearchFilter &filter)
1313*35238bceSAndroid Build Coastguard Worker     : SingleBlockValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH, programID, filter, DE_NULL)
1314*35238bceSAndroid Build Coastguard Worker {
1315*35238bceSAndroid Build Coastguard Worker }
1316*35238bceSAndroid Build Coastguard Worker 
validateSingleBlock(const glu::InterfaceBlock & block,const std::vector<int> & instanceIndex,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1317*35238bceSAndroid Build Coastguard Worker void BlockNameLengthValidator::validateSingleBlock(const glu::InterfaceBlock &block,
1318*35238bceSAndroid Build Coastguard Worker                                                    const std::vector<int> &instanceIndex, const std::string &resource,
1319*35238bceSAndroid Build Coastguard Worker                                                    glw::GLint propValue, const std::string &implementationName) const
1320*35238bceSAndroid Build Coastguard Worker {
1321*35238bceSAndroid Build Coastguard Worker     DE_UNREF(instanceIndex);
1322*35238bceSAndroid Build Coastguard Worker     DE_UNREF(block);
1323*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1324*35238bceSAndroid Build Coastguard Worker 
1325*35238bceSAndroid Build Coastguard Worker     const int expected = (int)implementationName.length() + 1; // includes null byte
1326*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " ("
1327*35238bceSAndroid Build Coastguard Worker                        << (int)implementationName.length() << " for \"" << implementationName
1328*35238bceSAndroid Build Coastguard Worker                        << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage;
1329*35238bceSAndroid Build Coastguard Worker 
1330*35238bceSAndroid Build Coastguard Worker     if (propValue != expected)
1331*35238bceSAndroid Build Coastguard Worker     {
1332*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue
1333*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1334*35238bceSAndroid Build Coastguard Worker         setError("name length invalid");
1335*35238bceSAndroid Build Coastguard Worker     }
1336*35238bceSAndroid Build Coastguard Worker }
1337*35238bceSAndroid Build Coastguard Worker 
1338*35238bceSAndroid Build Coastguard Worker class BufferBindingValidator : public SingleBlockValidator
1339*35238bceSAndroid Build Coastguard Worker {
1340*35238bceSAndroid Build Coastguard Worker public:
1341*35238bceSAndroid Build Coastguard Worker     BufferBindingValidator(Context &context, const glw::GLuint programID, const VariableSearchFilter &filter);
1342*35238bceSAndroid Build Coastguard Worker 
1343*35238bceSAndroid Build Coastguard Worker     void validateSingleBlock(const glu::InterfaceBlock &block, const std::vector<int> &instanceIndex,
1344*35238bceSAndroid Build Coastguard Worker                              const std::string &resource, glw::GLint propValue,
1345*35238bceSAndroid Build Coastguard Worker                              const std::string &implementationName) const;
1346*35238bceSAndroid Build Coastguard Worker };
1347*35238bceSAndroid Build Coastguard Worker 
BufferBindingValidator(Context & context,const glw::GLuint programID,const VariableSearchFilter & filter)1348*35238bceSAndroid Build Coastguard Worker BufferBindingValidator::BufferBindingValidator(Context &context, const glw::GLuint programID,
1349*35238bceSAndroid Build Coastguard Worker                                                const VariableSearchFilter &filter)
1350*35238bceSAndroid Build Coastguard Worker     : SingleBlockValidator(context, PROGRAMRESOURCEPROP_BUFFER_BINDING, programID, filter, DE_NULL)
1351*35238bceSAndroid Build Coastguard Worker {
1352*35238bceSAndroid Build Coastguard Worker }
1353*35238bceSAndroid Build Coastguard Worker 
validateSingleBlock(const glu::InterfaceBlock & block,const std::vector<int> & instanceIndex,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1354*35238bceSAndroid Build Coastguard Worker void BufferBindingValidator::validateSingleBlock(const glu::InterfaceBlock &block,
1355*35238bceSAndroid Build Coastguard Worker                                                  const std::vector<int> &instanceIndex, const std::string &resource,
1356*35238bceSAndroid Build Coastguard Worker                                                  glw::GLint propValue, const std::string &implementationName) const
1357*35238bceSAndroid Build Coastguard Worker {
1358*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1359*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1360*35238bceSAndroid Build Coastguard Worker 
1361*35238bceSAndroid Build Coastguard Worker     if (block.layout.binding != -1)
1362*35238bceSAndroid Build Coastguard Worker     {
1363*35238bceSAndroid Build Coastguard Worker         int flatIndex     = 0;
1364*35238bceSAndroid Build Coastguard Worker         int dimensionSize = 1;
1365*35238bceSAndroid Build Coastguard Worker 
1366*35238bceSAndroid Build Coastguard Worker         for (int dimensionNdx = (int)(block.dimensions.size()) - 1; dimensionNdx >= 0; --dimensionNdx)
1367*35238bceSAndroid Build Coastguard Worker         {
1368*35238bceSAndroid Build Coastguard Worker             flatIndex += dimensionSize * instanceIndex[dimensionNdx];
1369*35238bceSAndroid Build Coastguard Worker             dimensionSize *= block.dimensions[dimensionNdx];
1370*35238bceSAndroid Build Coastguard Worker         }
1371*35238bceSAndroid Build Coastguard Worker 
1372*35238bceSAndroid Build Coastguard Worker         const int expected = (block.dimensions.empty()) ? (block.layout.binding) : (block.layout.binding + flatIndex);
1373*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block binding, expecting " << expected
1374*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1375*35238bceSAndroid Build Coastguard Worker 
1376*35238bceSAndroid Build Coastguard Worker         if (propValue != expected)
1377*35238bceSAndroid Build Coastguard Worker         {
1378*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid buffer binding, got " << propValue
1379*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1380*35238bceSAndroid Build Coastguard Worker             setError("buffer binding invalid");
1381*35238bceSAndroid Build Coastguard Worker         }
1382*35238bceSAndroid Build Coastguard Worker     }
1383*35238bceSAndroid Build Coastguard Worker     else
1384*35238bceSAndroid Build Coastguard Worker     {
1385*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying buffer binding, expecting a valid binding"
1386*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1387*35238bceSAndroid Build Coastguard Worker 
1388*35238bceSAndroid Build Coastguard Worker         if (propValue < 0)
1389*35238bceSAndroid Build Coastguard Worker         {
1390*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid buffer binding, got " << propValue
1391*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1392*35238bceSAndroid Build Coastguard Worker             setError("buffer binding invalid");
1393*35238bceSAndroid Build Coastguard Worker         }
1394*35238bceSAndroid Build Coastguard Worker     }
1395*35238bceSAndroid Build Coastguard Worker }
1396*35238bceSAndroid Build Coastguard Worker 
1397*35238bceSAndroid Build Coastguard Worker class BlockReferencedByShaderValidator : public PropValidator
1398*35238bceSAndroid Build Coastguard Worker {
1399*35238bceSAndroid Build Coastguard Worker public:
1400*35238bceSAndroid Build Coastguard Worker     BlockReferencedByShaderValidator(Context &context, glu::ShaderType shaderType,
1401*35238bceSAndroid Build Coastguard Worker                                      const VariableSearchFilter &searchFilter);
1402*35238bceSAndroid Build Coastguard Worker 
1403*35238bceSAndroid Build Coastguard Worker     std::string getHumanReadablePropertyString(glw::GLint propVal) const;
1404*35238bceSAndroid Build Coastguard Worker     void validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource, glw::GLint propValue,
1405*35238bceSAndroid Build Coastguard Worker                   const std::string &implementationName) const;
1406*35238bceSAndroid Build Coastguard Worker 
1407*35238bceSAndroid Build Coastguard Worker private:
1408*35238bceSAndroid Build Coastguard Worker     const VariableSearchFilter m_filter;
1409*35238bceSAndroid Build Coastguard Worker     const glu::ShaderType m_shaderType;
1410*35238bceSAndroid Build Coastguard Worker };
1411*35238bceSAndroid Build Coastguard Worker 
BlockReferencedByShaderValidator(Context & context,glu::ShaderType shaderType,const VariableSearchFilter & searchFilter)1412*35238bceSAndroid Build Coastguard Worker BlockReferencedByShaderValidator::BlockReferencedByShaderValidator(Context &context, glu::ShaderType shaderType,
1413*35238bceSAndroid Build Coastguard Worker                                                                    const VariableSearchFilter &searchFilter)
1414*35238bceSAndroid Build Coastguard Worker     : PropValidator(context, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER, getRequiredExtensionForStage(shaderType))
1415*35238bceSAndroid Build Coastguard Worker     , m_filter(VariableSearchFilter::logicalAnd(VariableSearchFilter::createShaderTypeFilter(shaderType), searchFilter))
1416*35238bceSAndroid Build Coastguard Worker     , m_shaderType(shaderType)
1417*35238bceSAndroid Build Coastguard Worker {
1418*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_shaderType < glu::SHADERTYPE_LAST);
1419*35238bceSAndroid Build Coastguard Worker }
1420*35238bceSAndroid Build Coastguard Worker 
getHumanReadablePropertyString(glw::GLint propVal) const1421*35238bceSAndroid Build Coastguard Worker std::string BlockReferencedByShaderValidator::getHumanReadablePropertyString(glw::GLint propVal) const
1422*35238bceSAndroid Build Coastguard Worker {
1423*35238bceSAndroid Build Coastguard Worker     return de::toString(glu::getBooleanStr(propVal));
1424*35238bceSAndroid Build Coastguard Worker }
1425*35238bceSAndroid Build Coastguard Worker 
validate(const ProgramInterfaceDefinition::Program * program,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1426*35238bceSAndroid Build Coastguard Worker void BlockReferencedByShaderValidator::validate(const ProgramInterfaceDefinition::Program *program,
1427*35238bceSAndroid Build Coastguard Worker                                                 const std::string &resource, glw::GLint propValue,
1428*35238bceSAndroid Build Coastguard Worker                                                 const std::string &implementationName) const
1429*35238bceSAndroid Build Coastguard Worker {
1430*35238bceSAndroid Build Coastguard Worker     const std::string blockName = glu::parseVariableName(resource.c_str());
1431*35238bceSAndroid Build Coastguard Worker     bool referencedByShader     = false;
1432*35238bceSAndroid Build Coastguard Worker 
1433*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1434*35238bceSAndroid Build Coastguard Worker 
1435*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
1436*35238bceSAndroid Build Coastguard Worker     {
1437*35238bceSAndroid Build Coastguard Worker         const ProgramInterfaceDefinition::Shader *const shader = program->getShaders()[shaderNdx];
1438*35238bceSAndroid Build Coastguard Worker         if (!m_filter.matchesFilter(shader))
1439*35238bceSAndroid Build Coastguard Worker             continue;
1440*35238bceSAndroid Build Coastguard Worker 
1441*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx)
1442*35238bceSAndroid Build Coastguard Worker         {
1443*35238bceSAndroid Build Coastguard Worker             const glu::InterfaceBlock &block = shader->getDefaultBlock().interfaceBlocks[blockNdx];
1444*35238bceSAndroid Build Coastguard Worker 
1445*35238bceSAndroid Build Coastguard Worker             if (m_filter.matchesFilter(block) && block.interfaceName == blockName)
1446*35238bceSAndroid Build Coastguard Worker                 referencedByShader = true;
1447*35238bceSAndroid Build Coastguard Worker         }
1448*35238bceSAndroid Build Coastguard Worker     }
1449*35238bceSAndroid Build Coastguard Worker 
1450*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying referenced by " << glu::getShaderTypeName(m_shaderType)
1451*35238bceSAndroid Build Coastguard Worker                        << " shader, expecting " << ((referencedByShader) ? ("GL_TRUE") : ("GL_FALSE"))
1452*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
1453*35238bceSAndroid Build Coastguard Worker 
1454*35238bceSAndroid Build Coastguard Worker     if (propValue != ((referencedByShader) ? (1) : (0)))
1455*35238bceSAndroid Build Coastguard Worker     {
1456*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid referenced_by_"
1457*35238bceSAndroid Build Coastguard Worker                            << glu::getShaderTypeName(m_shaderType) << ", got " << propValue << tcu::TestLog::EndMessage;
1458*35238bceSAndroid Build Coastguard Worker         setError("referenced_by_" + std::string(glu::getShaderTypeName(m_shaderType)) + " invalid");
1459*35238bceSAndroid Build Coastguard Worker     }
1460*35238bceSAndroid Build Coastguard Worker }
1461*35238bceSAndroid Build Coastguard Worker 
1462*35238bceSAndroid Build Coastguard Worker class TopLevelArraySizeValidator : public SingleVariableValidator
1463*35238bceSAndroid Build Coastguard Worker {
1464*35238bceSAndroid Build Coastguard Worker public:
1465*35238bceSAndroid Build Coastguard Worker     TopLevelArraySizeValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
1466*35238bceSAndroid Build Coastguard Worker 
1467*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1468*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1469*35238bceSAndroid Build Coastguard Worker };
1470*35238bceSAndroid Build Coastguard Worker 
TopLevelArraySizeValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)1471*35238bceSAndroid Build Coastguard Worker TopLevelArraySizeValidator::TopLevelArraySizeValidator(Context &context, glw::GLuint programID,
1472*35238bceSAndroid Build Coastguard Worker                                                        const VariableSearchFilter &filter)
1473*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_SIZE, programID, filter, DE_NULL)
1474*35238bceSAndroid Build Coastguard Worker {
1475*35238bceSAndroid Build Coastguard Worker }
1476*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1477*35238bceSAndroid Build Coastguard Worker void TopLevelArraySizeValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1478*35238bceSAndroid Build Coastguard Worker                                                         const std::string &resource, glw::GLint propValue,
1479*35238bceSAndroid Build Coastguard Worker                                                         const std::string &implementationName) const
1480*35238bceSAndroid Build Coastguard Worker {
1481*35238bceSAndroid Build Coastguard Worker     int expected;
1482*35238bceSAndroid Build Coastguard Worker     std::string reason;
1483*35238bceSAndroid Build Coastguard Worker 
1484*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_BUFFER);
1485*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1486*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1487*35238bceSAndroid Build Coastguard Worker 
1488*35238bceSAndroid Build Coastguard Worker     if (!path[1].getDeclaration()->varType.isArrayType())
1489*35238bceSAndroid Build Coastguard Worker     {
1490*35238bceSAndroid Build Coastguard Worker         expected = 1;
1491*35238bceSAndroid Build Coastguard Worker         reason   = "Top-level block member is not an array";
1492*35238bceSAndroid Build Coastguard Worker     }
1493*35238bceSAndroid Build Coastguard Worker     else if (path[1].getDeclaration()->varType.getElementType().isBasicType())
1494*35238bceSAndroid Build Coastguard Worker     {
1495*35238bceSAndroid Build Coastguard Worker         expected = 1;
1496*35238bceSAndroid Build Coastguard Worker         reason   = "Top-level block member is not an array of an aggregate type";
1497*35238bceSAndroid Build Coastguard Worker     }
1498*35238bceSAndroid Build Coastguard Worker     else if (path[1].getDeclaration()->varType.getArraySize() == glu::VarType::UNSIZED_ARRAY)
1499*35238bceSAndroid Build Coastguard Worker     {
1500*35238bceSAndroid Build Coastguard Worker         expected = 0;
1501*35238bceSAndroid Build Coastguard Worker         reason   = "Top-level block member is an unsized top-level array";
1502*35238bceSAndroid Build Coastguard Worker     }
1503*35238bceSAndroid Build Coastguard Worker     else
1504*35238bceSAndroid Build Coastguard Worker     {
1505*35238bceSAndroid Build Coastguard Worker         expected = path[1].getDeclaration()->varType.getArraySize();
1506*35238bceSAndroid Build Coastguard Worker         reason   = "Top-level block member is a sized top-level array";
1507*35238bceSAndroid Build Coastguard Worker     }
1508*35238bceSAndroid Build Coastguard Worker 
1509*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array size, expecting " << expected << ". ("
1510*35238bceSAndroid Build Coastguard Worker                        << reason << ")." << tcu::TestLog::EndMessage;
1511*35238bceSAndroid Build Coastguard Worker 
1512*35238bceSAndroid Build Coastguard Worker     if (propValue != expected)
1513*35238bceSAndroid Build Coastguard Worker     {
1514*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid top level array size, got " << propValue
1515*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1516*35238bceSAndroid Build Coastguard Worker         setError("top level array size invalid");
1517*35238bceSAndroid Build Coastguard Worker     }
1518*35238bceSAndroid Build Coastguard Worker }
1519*35238bceSAndroid Build Coastguard Worker 
1520*35238bceSAndroid Build Coastguard Worker class TopLevelArrayStrideValidator : public SingleVariableValidator
1521*35238bceSAndroid Build Coastguard Worker {
1522*35238bceSAndroid Build Coastguard Worker public:
1523*35238bceSAndroid Build Coastguard Worker     TopLevelArrayStrideValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
1524*35238bceSAndroid Build Coastguard Worker 
1525*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1526*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1527*35238bceSAndroid Build Coastguard Worker };
1528*35238bceSAndroid Build Coastguard Worker 
TopLevelArrayStrideValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)1529*35238bceSAndroid Build Coastguard Worker TopLevelArrayStrideValidator::TopLevelArrayStrideValidator(Context &context, glw::GLuint programID,
1530*35238bceSAndroid Build Coastguard Worker                                                            const VariableSearchFilter &filter)
1531*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_STRIDE, programID, filter, DE_NULL)
1532*35238bceSAndroid Build Coastguard Worker {
1533*35238bceSAndroid Build Coastguard Worker }
1534*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1535*35238bceSAndroid Build Coastguard Worker void TopLevelArrayStrideValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1536*35238bceSAndroid Build Coastguard Worker                                                           const std::string &resource, glw::GLint propValue,
1537*35238bceSAndroid Build Coastguard Worker                                                           const std::string &implementationName) const
1538*35238bceSAndroid Build Coastguard Worker {
1539*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_BUFFER);
1540*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1541*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1542*35238bceSAndroid Build Coastguard Worker 
1543*35238bceSAndroid Build Coastguard Worker     if (!path[1].getDeclaration()->varType.isArrayType())
1544*35238bceSAndroid Build Coastguard Worker     {
1545*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message
1546*35238bceSAndroid Build Coastguard Worker                            << "Verifying top level array stride, expecting 0. (Top-level block member is not an array)."
1547*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1548*35238bceSAndroid Build Coastguard Worker 
1549*35238bceSAndroid Build Coastguard Worker         if (propValue != 0)
1550*35238bceSAndroid Build Coastguard Worker         {
1551*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, top level array stride, got " << propValue
1552*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1553*35238bceSAndroid Build Coastguard Worker             setError("top level array stride invalid");
1554*35238bceSAndroid Build Coastguard Worker         }
1555*35238bceSAndroid Build Coastguard Worker     }
1556*35238bceSAndroid Build Coastguard Worker     else if (path[1].getDeclaration()->varType.getElementType().isBasicType())
1557*35238bceSAndroid Build Coastguard Worker     {
1558*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message
1559*35238bceSAndroid Build Coastguard Worker                            << "Verifying top level array stride, expecting 0. (Top-level block member is not an array "
1560*35238bceSAndroid Build Coastguard Worker                               "of an aggregate type)."
1561*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1562*35238bceSAndroid Build Coastguard Worker 
1563*35238bceSAndroid Build Coastguard Worker         if (propValue != 0)
1564*35238bceSAndroid Build Coastguard Worker         {
1565*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, top level array stride, got " << propValue
1566*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1567*35238bceSAndroid Build Coastguard Worker             setError("top level array stride invalid");
1568*35238bceSAndroid Build Coastguard Worker         }
1569*35238bceSAndroid Build Coastguard Worker     }
1570*35238bceSAndroid Build Coastguard Worker     else
1571*35238bceSAndroid Build Coastguard Worker     {
1572*35238bceSAndroid Build Coastguard Worker         const int minimumStride = getVarTypeSize(path[1].getDeclaration()->varType.getElementType());
1573*35238bceSAndroid Build Coastguard Worker 
1574*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message
1575*35238bceSAndroid Build Coastguard Worker                            << "Verifying top level array stride, expecting greater or equal to " << minimumStride << "."
1576*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1577*35238bceSAndroid Build Coastguard Worker 
1578*35238bceSAndroid Build Coastguard Worker         if (propValue < minimumStride)
1579*35238bceSAndroid Build Coastguard Worker         {
1580*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid top level array stride, got " << propValue
1581*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1582*35238bceSAndroid Build Coastguard Worker             setError("top level array stride invalid");
1583*35238bceSAndroid Build Coastguard Worker         }
1584*35238bceSAndroid Build Coastguard Worker     }
1585*35238bceSAndroid Build Coastguard Worker }
1586*35238bceSAndroid Build Coastguard Worker 
1587*35238bceSAndroid Build Coastguard Worker class TransformFeedbackResourceValidator : public PropValidator
1588*35238bceSAndroid Build Coastguard Worker {
1589*35238bceSAndroid Build Coastguard Worker public:
1590*35238bceSAndroid Build Coastguard Worker     TransformFeedbackResourceValidator(Context &context, ProgramResourcePropFlags validationProp);
1591*35238bceSAndroid Build Coastguard Worker 
1592*35238bceSAndroid Build Coastguard Worker     void validate(const ProgramInterfaceDefinition::Program *program, const std::string &resource, glw::GLint propValue,
1593*35238bceSAndroid Build Coastguard Worker                   const std::string &implementationName) const;
1594*35238bceSAndroid Build Coastguard Worker 
1595*35238bceSAndroid Build Coastguard Worker private:
1596*35238bceSAndroid Build Coastguard Worker     virtual void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1597*35238bceSAndroid Build Coastguard Worker                                          const std::string &implementationName) const                      = 0;
1598*35238bceSAndroid Build Coastguard Worker     virtual void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1599*35238bceSAndroid Build Coastguard Worker                                         glw::GLint propValue, const std::string &implementationName) const = 0;
1600*35238bceSAndroid Build Coastguard Worker };
1601*35238bceSAndroid Build Coastguard Worker 
TransformFeedbackResourceValidator(Context & context,ProgramResourcePropFlags validationProp)1602*35238bceSAndroid Build Coastguard Worker TransformFeedbackResourceValidator::TransformFeedbackResourceValidator(Context &context,
1603*35238bceSAndroid Build Coastguard Worker                                                                        ProgramResourcePropFlags validationProp)
1604*35238bceSAndroid Build Coastguard Worker     : PropValidator(context, validationProp, DE_NULL)
1605*35238bceSAndroid Build Coastguard Worker {
1606*35238bceSAndroid Build Coastguard Worker }
1607*35238bceSAndroid Build Coastguard Worker 
validate(const ProgramInterfaceDefinition::Program * program,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1608*35238bceSAndroid Build Coastguard Worker void TransformFeedbackResourceValidator::validate(const ProgramInterfaceDefinition::Program *program,
1609*35238bceSAndroid Build Coastguard Worker                                                   const std::string &resource, glw::GLint propValue,
1610*35238bceSAndroid Build Coastguard Worker                                                   const std::string &implementationName) const
1611*35238bceSAndroid Build Coastguard Worker {
1612*35238bceSAndroid Build Coastguard Worker     if (deStringBeginsWith(resource.c_str(), "gl_"))
1613*35238bceSAndroid Build Coastguard Worker     {
1614*35238bceSAndroid Build Coastguard Worker         validateBuiltinVariable(resource, propValue, implementationName);
1615*35238bceSAndroid Build Coastguard Worker     }
1616*35238bceSAndroid Build Coastguard Worker     else
1617*35238bceSAndroid Build Coastguard Worker     {
1618*35238bceSAndroid Build Coastguard Worker         // Check resource name is a xfb output. (quick check)
1619*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
1620*35238bceSAndroid Build Coastguard Worker         bool generatorFound = false;
1621*35238bceSAndroid Build Coastguard Worker 
1622*35238bceSAndroid Build Coastguard Worker         // Check the resource name is a valid transform feedback resource and find the name generating resource
1623*35238bceSAndroid Build Coastguard Worker         for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
1624*35238bceSAndroid Build Coastguard Worker         {
1625*35238bceSAndroid Build Coastguard Worker             const std::string varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
1626*35238bceSAndroid Build Coastguard Worker             std::vector<VariablePathComponent> path;
1627*35238bceSAndroid Build Coastguard Worker             std::vector<std::string> resources;
1628*35238bceSAndroid Build Coastguard Worker 
1629*35238bceSAndroid Build Coastguard Worker             if (!findProgramVariablePathByPathName(path, program, varyingName,
1630*35238bceSAndroid Build Coastguard Worker                                                    VariableSearchFilter::createShaderTypeStorageFilter(
1631*35238bceSAndroid Build Coastguard Worker                                                        getProgramTransformFeedbackStage(program), glu::STORAGE_OUT)))
1632*35238bceSAndroid Build Coastguard Worker             {
1633*35238bceSAndroid Build Coastguard Worker                 // program does not contain feedback varying, not valid program
1634*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
1635*35238bceSAndroid Build Coastguard Worker                 return;
1636*35238bceSAndroid Build Coastguard Worker             }
1637*35238bceSAndroid Build Coastguard Worker 
1638*35238bceSAndroid Build Coastguard Worker             generateVariableTypeResourceNames(resources, varyingName, *path.back().getVariableType(),
1639*35238bceSAndroid Build Coastguard Worker                                               RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
1640*35238bceSAndroid Build Coastguard Worker 
1641*35238bceSAndroid Build Coastguard Worker             if (de::contains(resources.begin(), resources.end(), resource))
1642*35238bceSAndroid Build Coastguard Worker             {
1643*35238bceSAndroid Build Coastguard Worker                 generatorFound = true;
1644*35238bceSAndroid Build Coastguard Worker                 break;
1645*35238bceSAndroid Build Coastguard Worker             }
1646*35238bceSAndroid Build Coastguard Worker         }
1647*35238bceSAndroid Build Coastguard Worker 
1648*35238bceSAndroid Build Coastguard Worker         // resource name was not found, should never happen
1649*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(generatorFound);
1650*35238bceSAndroid Build Coastguard Worker         DE_UNREF(generatorFound);
1651*35238bceSAndroid Build Coastguard Worker #endif
1652*35238bceSAndroid Build Coastguard Worker 
1653*35238bceSAndroid Build Coastguard Worker         // verify resource
1654*35238bceSAndroid Build Coastguard Worker         {
1655*35238bceSAndroid Build Coastguard Worker             std::vector<VariablePathComponent> path;
1656*35238bceSAndroid Build Coastguard Worker 
1657*35238bceSAndroid Build Coastguard Worker             if (!findProgramVariablePathByPathName(path, program, resource,
1658*35238bceSAndroid Build Coastguard Worker                                                    VariableSearchFilter::createShaderTypeStorageFilter(
1659*35238bceSAndroid Build Coastguard Worker                                                        getProgramTransformFeedbackStage(program), glu::STORAGE_OUT)))
1660*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
1661*35238bceSAndroid Build Coastguard Worker 
1662*35238bceSAndroid Build Coastguard Worker             validateSingleVariable(path, resource, propValue, implementationName);
1663*35238bceSAndroid Build Coastguard Worker         }
1664*35238bceSAndroid Build Coastguard Worker     }
1665*35238bceSAndroid Build Coastguard Worker }
1666*35238bceSAndroid Build Coastguard Worker 
1667*35238bceSAndroid Build Coastguard Worker class TransformFeedbackArraySizeValidator : public TransformFeedbackResourceValidator
1668*35238bceSAndroid Build Coastguard Worker {
1669*35238bceSAndroid Build Coastguard Worker public:
1670*35238bceSAndroid Build Coastguard Worker     TransformFeedbackArraySizeValidator(Context &context);
1671*35238bceSAndroid Build Coastguard Worker 
1672*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1673*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
1674*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1675*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1676*35238bceSAndroid Build Coastguard Worker };
1677*35238bceSAndroid Build Coastguard Worker 
TransformFeedbackArraySizeValidator(Context & context)1678*35238bceSAndroid Build Coastguard Worker TransformFeedbackArraySizeValidator::TransformFeedbackArraySizeValidator(Context &context)
1679*35238bceSAndroid Build Coastguard Worker     : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_ARRAY_SIZE)
1680*35238bceSAndroid Build Coastguard Worker {
1681*35238bceSAndroid Build Coastguard Worker }
1682*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1683*35238bceSAndroid Build Coastguard Worker void TransformFeedbackArraySizeValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1684*35238bceSAndroid Build Coastguard Worker                                                                   const std::string &implementationName) const
1685*35238bceSAndroid Build Coastguard Worker {
1686*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1687*35238bceSAndroid Build Coastguard Worker 
1688*35238bceSAndroid Build Coastguard Worker     int arraySize = 0;
1689*35238bceSAndroid Build Coastguard Worker 
1690*35238bceSAndroid Build Coastguard Worker     if (resource == "gl_Position")
1691*35238bceSAndroid Build Coastguard Worker         arraySize = 1;
1692*35238bceSAndroid Build Coastguard Worker     else
1693*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1694*35238bceSAndroid Build Coastguard Worker 
1695*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize
1696*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
1697*35238bceSAndroid Build Coastguard Worker     if (arraySize != propValue)
1698*35238bceSAndroid Build Coastguard Worker     {
1699*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
1700*35238bceSAndroid Build Coastguard Worker         setError("resource array size invalid");
1701*35238bceSAndroid Build Coastguard Worker     }
1702*35238bceSAndroid Build Coastguard Worker }
1703*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1704*35238bceSAndroid Build Coastguard Worker void TransformFeedbackArraySizeValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1705*35238bceSAndroid Build Coastguard Worker                                                                  const std::string &resource, glw::GLint propValue,
1706*35238bceSAndroid Build Coastguard Worker                                                                  const std::string &implementationName) const
1707*35238bceSAndroid Build Coastguard Worker {
1708*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1709*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1710*35238bceSAndroid Build Coastguard Worker 
1711*35238bceSAndroid Build Coastguard Worker     const int arraySize =
1712*35238bceSAndroid Build Coastguard Worker         (path.back().getVariableType()->isArrayType()) ? (path.back().getVariableType()->getArraySize()) : (1);
1713*35238bceSAndroid Build Coastguard Worker 
1714*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize
1715*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
1716*35238bceSAndroid Build Coastguard Worker     if (arraySize != propValue)
1717*35238bceSAndroid Build Coastguard Worker     {
1718*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
1719*35238bceSAndroid Build Coastguard Worker         setError("resource array size invalid");
1720*35238bceSAndroid Build Coastguard Worker     }
1721*35238bceSAndroid Build Coastguard Worker }
1722*35238bceSAndroid Build Coastguard Worker 
1723*35238bceSAndroid Build Coastguard Worker class TransformFeedbackNameLengthValidator : public TransformFeedbackResourceValidator
1724*35238bceSAndroid Build Coastguard Worker {
1725*35238bceSAndroid Build Coastguard Worker public:
1726*35238bceSAndroid Build Coastguard Worker     TransformFeedbackNameLengthValidator(Context &context);
1727*35238bceSAndroid Build Coastguard Worker 
1728*35238bceSAndroid Build Coastguard Worker private:
1729*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1730*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
1731*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1732*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1733*35238bceSAndroid Build Coastguard Worker     void validateVariable(const std::string &implementationName, glw::GLint propValue) const;
1734*35238bceSAndroid Build Coastguard Worker };
1735*35238bceSAndroid Build Coastguard Worker 
TransformFeedbackNameLengthValidator(Context & context)1736*35238bceSAndroid Build Coastguard Worker TransformFeedbackNameLengthValidator::TransformFeedbackNameLengthValidator(Context &context)
1737*35238bceSAndroid Build Coastguard Worker     : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH)
1738*35238bceSAndroid Build Coastguard Worker {
1739*35238bceSAndroid Build Coastguard Worker }
1740*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1741*35238bceSAndroid Build Coastguard Worker void TransformFeedbackNameLengthValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1742*35238bceSAndroid Build Coastguard Worker                                                                    const std::string &implementationName) const
1743*35238bceSAndroid Build Coastguard Worker {
1744*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1745*35238bceSAndroid Build Coastguard Worker     validateVariable(implementationName, propValue);
1746*35238bceSAndroid Build Coastguard Worker }
1747*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1748*35238bceSAndroid Build Coastguard Worker void TransformFeedbackNameLengthValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1749*35238bceSAndroid Build Coastguard Worker                                                                   const std::string &resource, glw::GLint propValue,
1750*35238bceSAndroid Build Coastguard Worker                                                                   const std::string &implementationName) const
1751*35238bceSAndroid Build Coastguard Worker {
1752*35238bceSAndroid Build Coastguard Worker     DE_UNREF(path);
1753*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1754*35238bceSAndroid Build Coastguard Worker     validateVariable(implementationName, propValue);
1755*35238bceSAndroid Build Coastguard Worker }
1756*35238bceSAndroid Build Coastguard Worker 
validateVariable(const std::string & implementationName,glw::GLint propValue) const1757*35238bceSAndroid Build Coastguard Worker void TransformFeedbackNameLengthValidator::validateVariable(const std::string &implementationName,
1758*35238bceSAndroid Build Coastguard Worker                                                             glw::GLint propValue) const
1759*35238bceSAndroid Build Coastguard Worker {
1760*35238bceSAndroid Build Coastguard Worker     const int expected = (int)implementationName.length() + 1; // includes null byte
1761*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " ("
1762*35238bceSAndroid Build Coastguard Worker                        << (int)implementationName.length() << " for \"" << implementationName
1763*35238bceSAndroid Build Coastguard Worker                        << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage;
1764*35238bceSAndroid Build Coastguard Worker 
1765*35238bceSAndroid Build Coastguard Worker     if (propValue != expected)
1766*35238bceSAndroid Build Coastguard Worker     {
1767*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue
1768*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1769*35238bceSAndroid Build Coastguard Worker         setError("name length invalid");
1770*35238bceSAndroid Build Coastguard Worker     }
1771*35238bceSAndroid Build Coastguard Worker }
1772*35238bceSAndroid Build Coastguard Worker 
1773*35238bceSAndroid Build Coastguard Worker class TransformFeedbackTypeValidator : public TransformFeedbackResourceValidator
1774*35238bceSAndroid Build Coastguard Worker {
1775*35238bceSAndroid Build Coastguard Worker public:
1776*35238bceSAndroid Build Coastguard Worker     TransformFeedbackTypeValidator(Context &context);
1777*35238bceSAndroid Build Coastguard Worker 
1778*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1779*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
1780*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1781*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1782*35238bceSAndroid Build Coastguard Worker };
1783*35238bceSAndroid Build Coastguard Worker 
TransformFeedbackTypeValidator(Context & context)1784*35238bceSAndroid Build Coastguard Worker TransformFeedbackTypeValidator::TransformFeedbackTypeValidator(Context &context)
1785*35238bceSAndroid Build Coastguard Worker     : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_TYPE)
1786*35238bceSAndroid Build Coastguard Worker {
1787*35238bceSAndroid Build Coastguard Worker }
1788*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1789*35238bceSAndroid Build Coastguard Worker void TransformFeedbackTypeValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1790*35238bceSAndroid Build Coastguard Worker                                                              const std::string &implementationName) const
1791*35238bceSAndroid Build Coastguard Worker {
1792*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1793*35238bceSAndroid Build Coastguard Worker 
1794*35238bceSAndroid Build Coastguard Worker     glu::DataType varType = glu::TYPE_INVALID;
1795*35238bceSAndroid Build Coastguard Worker 
1796*35238bceSAndroid Build Coastguard Worker     if (resource == "gl_Position")
1797*35238bceSAndroid Build Coastguard Worker         varType = glu::TYPE_FLOAT_VEC4;
1798*35238bceSAndroid Build Coastguard Worker     else
1799*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1800*35238bceSAndroid Build Coastguard Worker 
1801*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(varType)
1802*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
1803*35238bceSAndroid Build Coastguard Worker     if (glu::getDataTypeFromGLType(propValue) != varType)
1804*35238bceSAndroid Build Coastguard Worker     {
1805*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got "
1806*35238bceSAndroid Build Coastguard Worker                            << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
1807*35238bceSAndroid Build Coastguard Worker         setError("resource type invalid");
1808*35238bceSAndroid Build Coastguard Worker     }
1809*35238bceSAndroid Build Coastguard Worker     return;
1810*35238bceSAndroid Build Coastguard Worker }
1811*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1812*35238bceSAndroid Build Coastguard Worker void TransformFeedbackTypeValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1813*35238bceSAndroid Build Coastguard Worker                                                             const std::string &resource, glw::GLint propValue,
1814*35238bceSAndroid Build Coastguard Worker                                                             const std::string &implementationName) const
1815*35238bceSAndroid Build Coastguard Worker {
1816*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1817*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1818*35238bceSAndroid Build Coastguard Worker 
1819*35238bceSAndroid Build Coastguard Worker     // Unlike other interfaces, xfb program interface uses just variable name to refer to arrays of basic types. (Others use "variable[0]")
1820*35238bceSAndroid Build Coastguard Worker     // Thus we might end up querying a type for an array. In this case, return the type of an array element.
1821*35238bceSAndroid Build Coastguard Worker     const glu::VarType &variable    = *path.back().getVariableType();
1822*35238bceSAndroid Build Coastguard Worker     const glu::VarType &elementType = (variable.isArrayType()) ? (variable.getElementType()) : (variable);
1823*35238bceSAndroid Build Coastguard Worker 
1824*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(elementType.isBasicType());
1825*35238bceSAndroid Build Coastguard Worker 
1826*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting "
1827*35238bceSAndroid Build Coastguard Worker                        << glu::getDataTypeName(elementType.getBasicType()) << tcu::TestLog::EndMessage;
1828*35238bceSAndroid Build Coastguard Worker     if (elementType.getBasicType() != glu::getDataTypeFromGLType(propValue))
1829*35238bceSAndroid Build Coastguard Worker     {
1830*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got "
1831*35238bceSAndroid Build Coastguard Worker                            << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage;
1832*35238bceSAndroid Build Coastguard Worker         setError("resource type invalid");
1833*35238bceSAndroid Build Coastguard Worker     }
1834*35238bceSAndroid Build Coastguard Worker }
1835*35238bceSAndroid Build Coastguard Worker 
1836*35238bceSAndroid Build Coastguard Worker class PerPatchValidator : public SingleVariableValidator
1837*35238bceSAndroid Build Coastguard Worker {
1838*35238bceSAndroid Build Coastguard Worker public:
1839*35238bceSAndroid Build Coastguard Worker     PerPatchValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter);
1840*35238bceSAndroid Build Coastguard Worker 
1841*35238bceSAndroid Build Coastguard Worker     std::string getHumanReadablePropertyString(glw::GLint propVal) const;
1842*35238bceSAndroid Build Coastguard Worker     void validateSingleVariable(const std::vector<VariablePathComponent> &path, const std::string &resource,
1843*35238bceSAndroid Build Coastguard Worker                                 glw::GLint propValue, const std::string &implementationName) const;
1844*35238bceSAndroid Build Coastguard Worker     void validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1845*35238bceSAndroid Build Coastguard Worker                                  const std::string &implementationName) const;
1846*35238bceSAndroid Build Coastguard Worker };
1847*35238bceSAndroid Build Coastguard Worker 
PerPatchValidator(Context & context,glw::GLuint programID,const VariableSearchFilter & filter)1848*35238bceSAndroid Build Coastguard Worker PerPatchValidator::PerPatchValidator(Context &context, glw::GLuint programID, const VariableSearchFilter &filter)
1849*35238bceSAndroid Build Coastguard Worker     : SingleVariableValidator(context, PROGRAMRESOURCEPROP_IS_PER_PATCH, programID, filter,
1850*35238bceSAndroid Build Coastguard Worker                               "GL_EXT_tessellation_shader")
1851*35238bceSAndroid Build Coastguard Worker {
1852*35238bceSAndroid Build Coastguard Worker }
1853*35238bceSAndroid Build Coastguard Worker 
getHumanReadablePropertyString(glw::GLint propVal) const1854*35238bceSAndroid Build Coastguard Worker std::string PerPatchValidator::getHumanReadablePropertyString(glw::GLint propVal) const
1855*35238bceSAndroid Build Coastguard Worker {
1856*35238bceSAndroid Build Coastguard Worker     return de::toString(glu::getBooleanStr(propVal));
1857*35238bceSAndroid Build Coastguard Worker }
1858*35238bceSAndroid Build Coastguard Worker 
validateSingleVariable(const std::vector<VariablePathComponent> & path,const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1859*35238bceSAndroid Build Coastguard Worker void PerPatchValidator::validateSingleVariable(const std::vector<VariablePathComponent> &path,
1860*35238bceSAndroid Build Coastguard Worker                                                const std::string &resource, glw::GLint propValue,
1861*35238bceSAndroid Build Coastguard Worker                                                const std::string &implementationName) const
1862*35238bceSAndroid Build Coastguard Worker {
1863*35238bceSAndroid Build Coastguard Worker     const glu::Storage storage = (path.front().isInterfaceBlock()) ? (path.front().getInterfaceBlock()->storage) :
1864*35238bceSAndroid Build Coastguard Worker                                                                      (path.front().getDeclaration()->storage);
1865*35238bceSAndroid Build Coastguard Worker     const int expected         = (storage == glu::STORAGE_PATCH_IN || storage == glu::STORAGE_PATCH_OUT) ? (1) : (0);
1866*35238bceSAndroid Build Coastguard Worker 
1867*35238bceSAndroid Build Coastguard Worker     DE_UNREF(resource);
1868*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1869*35238bceSAndroid Build Coastguard Worker 
1870*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying if is per patch, expecting IS_PER_PATCH = " << expected
1871*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
1872*35238bceSAndroid Build Coastguard Worker 
1873*35238bceSAndroid Build Coastguard Worker     if (propValue != expected)
1874*35238bceSAndroid Build Coastguard Worker     {
1875*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
1876*35238bceSAndroid Build Coastguard Worker         setError("resource is per patch invalid");
1877*35238bceSAndroid Build Coastguard Worker     }
1878*35238bceSAndroid Build Coastguard Worker }
1879*35238bceSAndroid Build Coastguard Worker 
validateBuiltinVariable(const std::string & resource,glw::GLint propValue,const std::string & implementationName) const1880*35238bceSAndroid Build Coastguard Worker void PerPatchValidator::validateBuiltinVariable(const std::string &resource, glw::GLint propValue,
1881*35238bceSAndroid Build Coastguard Worker                                                 const std::string &implementationName) const
1882*35238bceSAndroid Build Coastguard Worker {
1883*35238bceSAndroid Build Coastguard Worker     DE_UNREF(implementationName);
1884*35238bceSAndroid Build Coastguard Worker 
1885*35238bceSAndroid Build Coastguard Worker     static const struct
1886*35238bceSAndroid Build Coastguard Worker     {
1887*35238bceSAndroid Build Coastguard Worker         const char *name;
1888*35238bceSAndroid Build Coastguard Worker         int isPerPatch;
1889*35238bceSAndroid Build Coastguard Worker     } builtins[] = {
1890*35238bceSAndroid Build Coastguard Worker         {"gl_Position", 0},          {"gl_PerVertex.gl_Position", 0}, {"gl_InvocationID", 0},
1891*35238bceSAndroid Build Coastguard Worker         {"gl_TessLevelOuter[0]", 1}, {"gl_TessLevelInner[0]", 1},
1892*35238bceSAndroid Build Coastguard Worker     };
1893*35238bceSAndroid Build Coastguard Worker 
1894*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtins); ++ndx)
1895*35238bceSAndroid Build Coastguard Worker     {
1896*35238bceSAndroid Build Coastguard Worker         if (resource == builtins[ndx].name)
1897*35238bceSAndroid Build Coastguard Worker         {
1898*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message
1899*35238bceSAndroid Build Coastguard Worker                                << "Verifying if is per patch, expecting IS_PER_PATCH = " << builtins[ndx].isPerPatch
1900*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1901*35238bceSAndroid Build Coastguard Worker 
1902*35238bceSAndroid Build Coastguard Worker             if (propValue != builtins[ndx].isPerPatch)
1903*35238bceSAndroid Build Coastguard Worker             {
1904*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage;
1905*35238bceSAndroid Build Coastguard Worker                 setError("resource is per patch invalid");
1906*35238bceSAndroid Build Coastguard Worker             }
1907*35238bceSAndroid Build Coastguard Worker             return;
1908*35238bceSAndroid Build Coastguard Worker         }
1909*35238bceSAndroid Build Coastguard Worker     }
1910*35238bceSAndroid Build Coastguard Worker 
1911*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
1912*35238bceSAndroid Build Coastguard Worker }
1913*35238bceSAndroid Build Coastguard Worker 
1914*35238bceSAndroid Build Coastguard Worker } // namespace
1915*35238bceSAndroid Build Coastguard Worker 
ProgramResourceQueryTestTarget(ProgramInterface interface_,uint32_t propFlags_)1916*35238bceSAndroid Build Coastguard Worker ProgramResourceQueryTestTarget::ProgramResourceQueryTestTarget(ProgramInterface interface_, uint32_t propFlags_)
1917*35238bceSAndroid Build Coastguard Worker     : interface(interface_)
1918*35238bceSAndroid Build Coastguard Worker     , propFlags(propFlags_)
1919*35238bceSAndroid Build Coastguard Worker {
1920*35238bceSAndroid Build Coastguard Worker     switch (interface)
1921*35238bceSAndroid Build Coastguard Worker     {
1922*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM:
1923*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_UNIFORM_INTERFACE_MASK) == propFlags);
1924*35238bceSAndroid Build Coastguard Worker         break;
1925*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM_BLOCK:
1926*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_UNIFORM_BLOCK_INTERFACE_MASK) == propFlags);
1927*35238bceSAndroid Build Coastguard Worker         break;
1928*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
1929*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_SHADER_STORAGE_BLOCK_MASK) == propFlags);
1930*35238bceSAndroid Build Coastguard Worker         break;
1931*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_INPUT:
1932*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_PROGRAM_INPUT_MASK) == propFlags);
1933*35238bceSAndroid Build Coastguard Worker         break;
1934*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_OUTPUT:
1935*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_PROGRAM_OUTPUT_MASK) == propFlags);
1936*35238bceSAndroid Build Coastguard Worker         break;
1937*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_BUFFER_VARIABLE:
1938*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_BUFFER_VARIABLE_MASK) == propFlags);
1939*35238bceSAndroid Build Coastguard Worker         break;
1940*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
1941*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_TRANSFORM_FEEDBACK_VARYING_MASK) == propFlags);
1942*35238bceSAndroid Build Coastguard Worker         break;
1943*35238bceSAndroid Build Coastguard Worker 
1944*35238bceSAndroid Build Coastguard Worker     default:
1945*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1946*35238bceSAndroid Build Coastguard Worker     }
1947*35238bceSAndroid Build Coastguard Worker }
1948*35238bceSAndroid Build Coastguard Worker 
ProgramInterfaceQueryTestCase(Context & context,const char * name,const char * description,ProgramResourceQueryTestTarget queryTarget)1949*35238bceSAndroid Build Coastguard Worker ProgramInterfaceQueryTestCase::ProgramInterfaceQueryTestCase(Context &context, const char *name,
1950*35238bceSAndroid Build Coastguard Worker                                                              const char *description,
1951*35238bceSAndroid Build Coastguard Worker                                                              ProgramResourceQueryTestTarget queryTarget)
1952*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, description)
1953*35238bceSAndroid Build Coastguard Worker     , m_queryTarget(queryTarget)
1954*35238bceSAndroid Build Coastguard Worker {
1955*35238bceSAndroid Build Coastguard Worker }
1956*35238bceSAndroid Build Coastguard Worker 
~ProgramInterfaceQueryTestCase(void)1957*35238bceSAndroid Build Coastguard Worker ProgramInterfaceQueryTestCase::~ProgramInterfaceQueryTestCase(void)
1958*35238bceSAndroid Build Coastguard Worker {
1959*35238bceSAndroid Build Coastguard Worker }
1960*35238bceSAndroid Build Coastguard Worker 
getTargetInterface(void) const1961*35238bceSAndroid Build Coastguard Worker ProgramInterface ProgramInterfaceQueryTestCase::getTargetInterface(void) const
1962*35238bceSAndroid Build Coastguard Worker {
1963*35238bceSAndroid Build Coastguard Worker     return m_queryTarget.interface;
1964*35238bceSAndroid Build Coastguard Worker }
1965*35238bceSAndroid Build Coastguard Worker 
getGLInterfaceEnumValue(ProgramInterface interface)1966*35238bceSAndroid Build Coastguard Worker static glw::GLenum getGLInterfaceEnumValue(ProgramInterface interface)
1967*35238bceSAndroid Build Coastguard Worker {
1968*35238bceSAndroid Build Coastguard Worker     switch (interface)
1969*35238bceSAndroid Build Coastguard Worker     {
1970*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM:
1971*35238bceSAndroid Build Coastguard Worker         return GL_UNIFORM;
1972*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM_BLOCK:
1973*35238bceSAndroid Build Coastguard Worker         return GL_UNIFORM_BLOCK;
1974*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER:
1975*35238bceSAndroid Build Coastguard Worker         return GL_ATOMIC_COUNTER_BUFFER;
1976*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_INPUT:
1977*35238bceSAndroid Build Coastguard Worker         return GL_PROGRAM_INPUT;
1978*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_OUTPUT:
1979*35238bceSAndroid Build Coastguard Worker         return GL_PROGRAM_OUTPUT;
1980*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
1981*35238bceSAndroid Build Coastguard Worker         return GL_TRANSFORM_FEEDBACK_VARYING;
1982*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_BUFFER_VARIABLE:
1983*35238bceSAndroid Build Coastguard Worker         return GL_BUFFER_VARIABLE;
1984*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
1985*35238bceSAndroid Build Coastguard Worker         return GL_SHADER_STORAGE_BLOCK;
1986*35238bceSAndroid Build Coastguard Worker     default:
1987*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1988*35238bceSAndroid Build Coastguard Worker         return 0;
1989*35238bceSAndroid Build Coastguard Worker     }
1990*35238bceSAndroid Build Coastguard Worker }
1991*35238bceSAndroid Build Coastguard Worker 
isInterfaceBlockInterfaceName(const ProgramInterfaceDefinition::Program * program,ProgramInterface interface,const std::string & blockInterfaceName)1992*35238bceSAndroid Build Coastguard Worker static bool isInterfaceBlockInterfaceName(const ProgramInterfaceDefinition::Program *program,
1993*35238bceSAndroid Build Coastguard Worker                                           ProgramInterface interface, const std::string &blockInterfaceName)
1994*35238bceSAndroid Build Coastguard Worker {
1995*35238bceSAndroid Build Coastguard Worker     uint32_t validStorageBits;
1996*35238bceSAndroid Build Coastguard Worker     uint32_t searchStageBits;
1997*35238bceSAndroid Build Coastguard Worker 
1998*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(glu::STORAGE_LAST < 32);
1999*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(glu::SHADERTYPE_LAST < 32);
2000*35238bceSAndroid Build Coastguard Worker 
2001*35238bceSAndroid Build Coastguard Worker     switch (interface)
2002*35238bceSAndroid Build Coastguard Worker     {
2003*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM_BLOCK:
2004*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
2005*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER:
2006*35238bceSAndroid Build Coastguard Worker         return false;
2007*35238bceSAndroid Build Coastguard Worker 
2008*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_INPUT:
2009*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_IN) | (1u << glu::STORAGE_PATCH_IN);
2010*35238bceSAndroid Build Coastguard Worker         searchStageBits  = (1u << program->getFirstStage());
2011*35238bceSAndroid Build Coastguard Worker         break;
2012*35238bceSAndroid Build Coastguard Worker 
2013*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_OUTPUT:
2014*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_OUT) | (1u << glu::STORAGE_PATCH_OUT);
2015*35238bceSAndroid Build Coastguard Worker         searchStageBits  = (1u << program->getLastStage());
2016*35238bceSAndroid Build Coastguard Worker         break;
2017*35238bceSAndroid Build Coastguard Worker 
2018*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
2019*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_OUT);
2020*35238bceSAndroid Build Coastguard Worker         searchStageBits  = (1u << getProgramTransformFeedbackStage(program));
2021*35238bceSAndroid Build Coastguard Worker         break;
2022*35238bceSAndroid Build Coastguard Worker 
2023*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM:
2024*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_UNIFORM);
2025*35238bceSAndroid Build Coastguard Worker         searchStageBits  = 0xFFFFFFFFu;
2026*35238bceSAndroid Build Coastguard Worker         break;
2027*35238bceSAndroid Build Coastguard Worker 
2028*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_BUFFER_VARIABLE:
2029*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_BUFFER);
2030*35238bceSAndroid Build Coastguard Worker         searchStageBits  = 0xFFFFFFFFu;
2031*35238bceSAndroid Build Coastguard Worker         break;
2032*35238bceSAndroid Build Coastguard Worker 
2033*35238bceSAndroid Build Coastguard Worker     default:
2034*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
2035*35238bceSAndroid Build Coastguard Worker         return false;
2036*35238bceSAndroid Build Coastguard Worker     }
2037*35238bceSAndroid Build Coastguard Worker 
2038*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
2039*35238bceSAndroid Build Coastguard Worker     {
2040*35238bceSAndroid Build Coastguard Worker         const ProgramInterfaceDefinition::Shader *const shader = program->getShaders()[shaderNdx];
2041*35238bceSAndroid Build Coastguard Worker         if (((1u << shader->getType()) & searchStageBits) == 0)
2042*35238bceSAndroid Build Coastguard Worker             continue;
2043*35238bceSAndroid Build Coastguard Worker 
2044*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx)
2045*35238bceSAndroid Build Coastguard Worker         {
2046*35238bceSAndroid Build Coastguard Worker             const glu::InterfaceBlock &block = shader->getDefaultBlock().interfaceBlocks[blockNdx];
2047*35238bceSAndroid Build Coastguard Worker 
2048*35238bceSAndroid Build Coastguard Worker             if (((1u << block.storage) & validStorageBits) == 0)
2049*35238bceSAndroid Build Coastguard Worker                 continue;
2050*35238bceSAndroid Build Coastguard Worker 
2051*35238bceSAndroid Build Coastguard Worker             if (block.interfaceName == blockInterfaceName)
2052*35238bceSAndroid Build Coastguard Worker                 return true;
2053*35238bceSAndroid Build Coastguard Worker         }
2054*35238bceSAndroid Build Coastguard Worker     }
2055*35238bceSAndroid Build Coastguard Worker     return false;
2056*35238bceSAndroid Build Coastguard Worker }
2057*35238bceSAndroid Build Coastguard Worker 
getInterfaceBlockInteraceNameByMember(const ProgramInterfaceDefinition::Program * program,ProgramInterface interface,const std::string & memberName)2058*35238bceSAndroid Build Coastguard Worker static std::string getInterfaceBlockInteraceNameByMember(const ProgramInterfaceDefinition::Program *program,
2059*35238bceSAndroid Build Coastguard Worker                                                          ProgramInterface interface, const std::string &memberName)
2060*35238bceSAndroid Build Coastguard Worker {
2061*35238bceSAndroid Build Coastguard Worker     uint32_t validStorageBits;
2062*35238bceSAndroid Build Coastguard Worker     uint32_t searchStageBits;
2063*35238bceSAndroid Build Coastguard Worker 
2064*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(glu::STORAGE_LAST < 32);
2065*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(glu::SHADERTYPE_LAST < 32);
2066*35238bceSAndroid Build Coastguard Worker 
2067*35238bceSAndroid Build Coastguard Worker     switch (interface)
2068*35238bceSAndroid Build Coastguard Worker     {
2069*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM_BLOCK:
2070*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
2071*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER:
2072*35238bceSAndroid Build Coastguard Worker         return "";
2073*35238bceSAndroid Build Coastguard Worker 
2074*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_INPUT:
2075*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_IN) | (1u << glu::STORAGE_PATCH_IN);
2076*35238bceSAndroid Build Coastguard Worker         searchStageBits  = (1u << program->getFirstStage());
2077*35238bceSAndroid Build Coastguard Worker         break;
2078*35238bceSAndroid Build Coastguard Worker 
2079*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_OUTPUT:
2080*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_OUT) | (1u << glu::STORAGE_PATCH_OUT);
2081*35238bceSAndroid Build Coastguard Worker         searchStageBits  = (1u << program->getLastStage());
2082*35238bceSAndroid Build Coastguard Worker         break;
2083*35238bceSAndroid Build Coastguard Worker 
2084*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
2085*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_OUT);
2086*35238bceSAndroid Build Coastguard Worker         searchStageBits  = (1u << getProgramTransformFeedbackStage(program));
2087*35238bceSAndroid Build Coastguard Worker         break;
2088*35238bceSAndroid Build Coastguard Worker 
2089*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM:
2090*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_UNIFORM);
2091*35238bceSAndroid Build Coastguard Worker         searchStageBits  = 0xFFFFFFFFu;
2092*35238bceSAndroid Build Coastguard Worker         break;
2093*35238bceSAndroid Build Coastguard Worker 
2094*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_BUFFER_VARIABLE:
2095*35238bceSAndroid Build Coastguard Worker         validStorageBits = (1u << glu::STORAGE_BUFFER);
2096*35238bceSAndroid Build Coastguard Worker         searchStageBits  = 0xFFFFFFFFu;
2097*35238bceSAndroid Build Coastguard Worker         break;
2098*35238bceSAndroid Build Coastguard Worker 
2099*35238bceSAndroid Build Coastguard Worker     default:
2100*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
2101*35238bceSAndroid Build Coastguard Worker         return "";
2102*35238bceSAndroid Build Coastguard Worker     }
2103*35238bceSAndroid Build Coastguard Worker 
2104*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
2105*35238bceSAndroid Build Coastguard Worker     {
2106*35238bceSAndroid Build Coastguard Worker         const ProgramInterfaceDefinition::Shader *const shader = program->getShaders()[shaderNdx];
2107*35238bceSAndroid Build Coastguard Worker         if (((1u << shader->getType()) & searchStageBits) == 0)
2108*35238bceSAndroid Build Coastguard Worker             continue;
2109*35238bceSAndroid Build Coastguard Worker 
2110*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx)
2111*35238bceSAndroid Build Coastguard Worker         {
2112*35238bceSAndroid Build Coastguard Worker             const glu::InterfaceBlock &block = shader->getDefaultBlock().interfaceBlocks[blockNdx];
2113*35238bceSAndroid Build Coastguard Worker 
2114*35238bceSAndroid Build Coastguard Worker             if (((1u << block.storage) & validStorageBits) == 0)
2115*35238bceSAndroid Build Coastguard Worker                 continue;
2116*35238bceSAndroid Build Coastguard Worker 
2117*35238bceSAndroid Build Coastguard Worker             for (int varNdx = 0; varNdx < (int)block.variables.size(); ++varNdx)
2118*35238bceSAndroid Build Coastguard Worker             {
2119*35238bceSAndroid Build Coastguard Worker                 if (block.variables[varNdx].name == memberName)
2120*35238bceSAndroid Build Coastguard Worker                     return block.interfaceName;
2121*35238bceSAndroid Build Coastguard Worker             }
2122*35238bceSAndroid Build Coastguard Worker         }
2123*35238bceSAndroid Build Coastguard Worker     }
2124*35238bceSAndroid Build Coastguard Worker     return "";
2125*35238bceSAndroid Build Coastguard Worker }
2126*35238bceSAndroid Build Coastguard Worker 
queryAndValidateProps(tcu::TestContext & testCtx,const glw::Functions & gl,glw::GLuint programID,ProgramInterface interface,const char * targetResourceName,const ProgramInterfaceDefinition::Program * programDefinition,const std::vector<glw::GLenum> & props,const std::vector<const PropValidator * > & validators)2127*35238bceSAndroid Build Coastguard Worker static void queryAndValidateProps(tcu::TestContext &testCtx, const glw::Functions &gl, glw::GLuint programID,
2128*35238bceSAndroid Build Coastguard Worker                                   ProgramInterface interface, const char *targetResourceName,
2129*35238bceSAndroid Build Coastguard Worker                                   const ProgramInterfaceDefinition::Program *programDefinition,
2130*35238bceSAndroid Build Coastguard Worker                                   const std::vector<glw::GLenum> &props,
2131*35238bceSAndroid Build Coastguard Worker                                   const std::vector<const PropValidator *> &validators)
2132*35238bceSAndroid Build Coastguard Worker {
2133*35238bceSAndroid Build Coastguard Worker     const glw::GLenum glInterface          = getGLInterfaceEnumValue(interface);
2134*35238bceSAndroid Build Coastguard Worker     std::string implementationResourceName = targetResourceName;
2135*35238bceSAndroid Build Coastguard Worker     glw::GLuint resourceNdx;
2136*35238bceSAndroid Build Coastguard Worker     glw::GLint written = -1;
2137*35238bceSAndroid Build Coastguard Worker 
2138*35238bceSAndroid Build Coastguard Worker     // prefill result buffer with an invalid value. -1 might be valid sometimes, avoid it. Make buffer one larger
2139*35238bceSAndroid Build Coastguard Worker     // to allow detection of too many return values
2140*35238bceSAndroid Build Coastguard Worker     std::vector<glw::GLint> propValues(props.size() + 1, -2);
2141*35238bceSAndroid Build Coastguard Worker 
2142*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(props.size() == validators.size());
2143*35238bceSAndroid Build Coastguard Worker 
2144*35238bceSAndroid Build Coastguard Worker     // query
2145*35238bceSAndroid Build Coastguard Worker 
2146*35238bceSAndroid Build Coastguard Worker     resourceNdx = gl.getProgramResourceIndex(programID, glInterface, targetResourceName);
2147*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "get resource index");
2148*35238bceSAndroid Build Coastguard Worker 
2149*35238bceSAndroid Build Coastguard Worker     if (resourceNdx == GL_INVALID_INDEX)
2150*35238bceSAndroid Build Coastguard Worker     {
2151*35238bceSAndroid Build Coastguard Worker         static const struct
2152*35238bceSAndroid Build Coastguard Worker         {
2153*35238bceSAndroid Build Coastguard Worker             bool removeTrailingArray;  // convert from "target[0]" -> "target"
2154*35238bceSAndroid Build Coastguard Worker             bool removeTrailingMember; // convert from "target.member" -> "target"
2155*35238bceSAndroid Build Coastguard Worker             bool removeIOBlock;        // convert from "InterfaceName.target" -> "target"
2156*35238bceSAndroid Build Coastguard Worker             bool addIOBlock;           // convert from "target" -> "InterfaceName.target"
2157*35238bceSAndroid Build Coastguard Worker             bool addIOBlockArray;      // convert from "target" -> "InterfaceName[0].target"
2158*35238bceSAndroid Build Coastguard Worker         } recoveryStrategies[] = {
2159*35238bceSAndroid Build Coastguard Worker             // try one patch
2160*35238bceSAndroid Build Coastguard Worker             {true, false, false, false, false},
2161*35238bceSAndroid Build Coastguard Worker             {false, true, false, false, false},
2162*35238bceSAndroid Build Coastguard Worker             {false, false, true, false, false},
2163*35238bceSAndroid Build Coastguard Worker             {false, false, false, true, false},
2164*35238bceSAndroid Build Coastguard Worker             {false, false, false, false, true},
2165*35238bceSAndroid Build Coastguard Worker             // patch both ends
2166*35238bceSAndroid Build Coastguard Worker             {true, false, true, false, false},
2167*35238bceSAndroid Build Coastguard Worker             {true, false, false, true, false},
2168*35238bceSAndroid Build Coastguard Worker             {true, false, false, false, true},
2169*35238bceSAndroid Build Coastguard Worker             {false, true, true, false, false},
2170*35238bceSAndroid Build Coastguard Worker             {false, true, false, true, false},
2171*35238bceSAndroid Build Coastguard Worker             {false, true, false, false, true},
2172*35238bceSAndroid Build Coastguard Worker         };
2173*35238bceSAndroid Build Coastguard Worker 
2174*35238bceSAndroid Build Coastguard Worker         // The resource name generation in the GL implementations is very commonly broken. Try to
2175*35238bceSAndroid Build Coastguard Worker         // keep the tests producing useful data even in these cases by attempting to recover from
2176*35238bceSAndroid Build Coastguard Worker         // common naming bugs. Set test result to failure even if recovery succeeded to signal
2177*35238bceSAndroid Build Coastguard Worker         // incorrect name generation.
2178*35238bceSAndroid Build Coastguard Worker 
2179*35238bceSAndroid Build Coastguard Worker         testCtx.getLog() << tcu::TestLog::Message << "getProgramResourceIndex returned GL_INVALID_INDEX for \""
2180*35238bceSAndroid Build Coastguard Worker                          << targetResourceName << "\"" << tcu::TestLog::EndMessage;
2181*35238bceSAndroid Build Coastguard Worker         testCtx.setTestResult(QP_TEST_RESULT_FAIL, "could not find target resource");
2182*35238bceSAndroid Build Coastguard Worker 
2183*35238bceSAndroid Build Coastguard Worker         for (int strategyNdx = 0; strategyNdx < DE_LENGTH_OF_ARRAY(recoveryStrategies); ++strategyNdx)
2184*35238bceSAndroid Build Coastguard Worker         {
2185*35238bceSAndroid Build Coastguard Worker             const std::string resourceName = std::string(targetResourceName);
2186*35238bceSAndroid Build Coastguard Worker             const size_t rootNameEnd       = resourceName.find_first_of(".[");
2187*35238bceSAndroid Build Coastguard Worker             const std::string rootName     = resourceName.substr(0, rootNameEnd);
2188*35238bceSAndroid Build Coastguard Worker             std::string simplifiedResourceName;
2189*35238bceSAndroid Build Coastguard Worker 
2190*35238bceSAndroid Build Coastguard Worker             if (recoveryStrategies[strategyNdx].removeTrailingArray)
2191*35238bceSAndroid Build Coastguard Worker             {
2192*35238bceSAndroid Build Coastguard Worker                 if (de::endsWith(resourceName, "[0]"))
2193*35238bceSAndroid Build Coastguard Worker                     simplifiedResourceName = resourceName.substr(0, resourceName.length() - 3);
2194*35238bceSAndroid Build Coastguard Worker                 else
2195*35238bceSAndroid Build Coastguard Worker                     continue;
2196*35238bceSAndroid Build Coastguard Worker             }
2197*35238bceSAndroid Build Coastguard Worker 
2198*35238bceSAndroid Build Coastguard Worker             if (recoveryStrategies[strategyNdx].removeTrailingMember)
2199*35238bceSAndroid Build Coastguard Worker             {
2200*35238bceSAndroid Build Coastguard Worker                 const size_t lastMember = resourceName.find_last_of('.');
2201*35238bceSAndroid Build Coastguard Worker                 if (lastMember != std::string::npos)
2202*35238bceSAndroid Build Coastguard Worker                     simplifiedResourceName = resourceName.substr(0, lastMember);
2203*35238bceSAndroid Build Coastguard Worker                 else
2204*35238bceSAndroid Build Coastguard Worker                     continue;
2205*35238bceSAndroid Build Coastguard Worker             }
2206*35238bceSAndroid Build Coastguard Worker 
2207*35238bceSAndroid Build Coastguard Worker             if (recoveryStrategies[strategyNdx].removeIOBlock)
2208*35238bceSAndroid Build Coastguard Worker             {
2209*35238bceSAndroid Build Coastguard Worker                 if (deStringBeginsWith(resourceName.c_str(), "gl_PerVertex."))
2210*35238bceSAndroid Build Coastguard Worker                 {
2211*35238bceSAndroid Build Coastguard Worker                     // builtin interface bock, remove block name
2212*35238bceSAndroid Build Coastguard Worker                     simplifiedResourceName = resourceName.substr(13);
2213*35238bceSAndroid Build Coastguard Worker                 }
2214*35238bceSAndroid Build Coastguard Worker                 else if (isInterfaceBlockInterfaceName(programDefinition, interface, rootName))
2215*35238bceSAndroid Build Coastguard Worker                 {
2216*35238bceSAndroid Build Coastguard Worker                     // user-defined inteface block, remove name
2217*35238bceSAndroid Build Coastguard Worker                     const size_t accessorEnd = resourceName.find('.'); // includes potential array accessor
2218*35238bceSAndroid Build Coastguard Worker 
2219*35238bceSAndroid Build Coastguard Worker                     if (accessorEnd != std::string::npos)
2220*35238bceSAndroid Build Coastguard Worker                         simplifiedResourceName = resourceName.substr(0, accessorEnd + 1);
2221*35238bceSAndroid Build Coastguard Worker                     else
2222*35238bceSAndroid Build Coastguard Worker                         continue;
2223*35238bceSAndroid Build Coastguard Worker                 }
2224*35238bceSAndroid Build Coastguard Worker                 else
2225*35238bceSAndroid Build Coastguard Worker                 {
2226*35238bceSAndroid Build Coastguard Worker                     // recovery not applicable
2227*35238bceSAndroid Build Coastguard Worker                     continue;
2228*35238bceSAndroid Build Coastguard Worker                 }
2229*35238bceSAndroid Build Coastguard Worker             }
2230*35238bceSAndroid Build Coastguard Worker 
2231*35238bceSAndroid Build Coastguard Worker             if (recoveryStrategies[strategyNdx].addIOBlock || recoveryStrategies[strategyNdx].addIOBlockArray)
2232*35238bceSAndroid Build Coastguard Worker             {
2233*35238bceSAndroid Build Coastguard Worker                 const std::string arrayAccessor = (recoveryStrategies[strategyNdx].addIOBlockArray) ? ("[0]") : ("");
2234*35238bceSAndroid Build Coastguard Worker 
2235*35238bceSAndroid Build Coastguard Worker                 if (deStringBeginsWith(resourceName.c_str(), "gl_") && resourceName.find('.') == std::string::npos)
2236*35238bceSAndroid Build Coastguard Worker                 {
2237*35238bceSAndroid Build Coastguard Worker                     // free builtin variable, add block name
2238*35238bceSAndroid Build Coastguard Worker                     simplifiedResourceName = "gl_PerVertex" + arrayAccessor + "." + resourceName;
2239*35238bceSAndroid Build Coastguard Worker                 }
2240*35238bceSAndroid Build Coastguard Worker                 else
2241*35238bceSAndroid Build Coastguard Worker                 {
2242*35238bceSAndroid Build Coastguard Worker                     const std::string interafaceName =
2243*35238bceSAndroid Build Coastguard Worker                         getInterfaceBlockInteraceNameByMember(programDefinition, interface, rootName);
2244*35238bceSAndroid Build Coastguard Worker 
2245*35238bceSAndroid Build Coastguard Worker                     if (!interafaceName.empty())
2246*35238bceSAndroid Build Coastguard Worker                     {
2247*35238bceSAndroid Build Coastguard Worker                         // free user variable, add block name
2248*35238bceSAndroid Build Coastguard Worker                         simplifiedResourceName = interafaceName + arrayAccessor + "." + resourceName;
2249*35238bceSAndroid Build Coastguard Worker                     }
2250*35238bceSAndroid Build Coastguard Worker                     else
2251*35238bceSAndroid Build Coastguard Worker                     {
2252*35238bceSAndroid Build Coastguard Worker                         // recovery not applicable
2253*35238bceSAndroid Build Coastguard Worker                         continue;
2254*35238bceSAndroid Build Coastguard Worker                     }
2255*35238bceSAndroid Build Coastguard Worker                 }
2256*35238bceSAndroid Build Coastguard Worker             }
2257*35238bceSAndroid Build Coastguard Worker 
2258*35238bceSAndroid Build Coastguard Worker             if (simplifiedResourceName.empty())
2259*35238bceSAndroid Build Coastguard Worker                 continue;
2260*35238bceSAndroid Build Coastguard Worker 
2261*35238bceSAndroid Build Coastguard Worker             resourceNdx = gl.getProgramResourceIndex(programID, glInterface, simplifiedResourceName.c_str());
2262*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(gl.getError(), "get resource index");
2263*35238bceSAndroid Build Coastguard Worker 
2264*35238bceSAndroid Build Coastguard Worker             // recovery succeeded
2265*35238bceSAndroid Build Coastguard Worker             if (resourceNdx != GL_INVALID_INDEX)
2266*35238bceSAndroid Build Coastguard Worker             {
2267*35238bceSAndroid Build Coastguard Worker                 implementationResourceName = simplifiedResourceName;
2268*35238bceSAndroid Build Coastguard Worker                 testCtx.getLog() << tcu::TestLog::Message
2269*35238bceSAndroid Build Coastguard Worker                                  << "\tResource not found, continuing anyway using index obtained for resource \""
2270*35238bceSAndroid Build Coastguard Worker                                  << simplifiedResourceName << "\"" << tcu::TestLog::EndMessage;
2271*35238bceSAndroid Build Coastguard Worker                 break;
2272*35238bceSAndroid Build Coastguard Worker             }
2273*35238bceSAndroid Build Coastguard Worker         }
2274*35238bceSAndroid Build Coastguard Worker 
2275*35238bceSAndroid Build Coastguard Worker         if (resourceNdx == GL_INVALID_INDEX)
2276*35238bceSAndroid Build Coastguard Worker             return;
2277*35238bceSAndroid Build Coastguard Worker     }
2278*35238bceSAndroid Build Coastguard Worker 
2279*35238bceSAndroid Build Coastguard Worker     gl.getProgramResourceiv(programID, glInterface, resourceNdx, (int)props.size(), &props[0], (int)propValues.size(),
2280*35238bceSAndroid Build Coastguard Worker                             &written, &propValues[0]);
2281*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "get props");
2282*35238bceSAndroid Build Coastguard Worker 
2283*35238bceSAndroid Build Coastguard Worker     if (written != (int)props.size())
2284*35238bceSAndroid Build Coastguard Worker     {
2285*35238bceSAndroid Build Coastguard Worker         testCtx.getLog() << tcu::TestLog::Message
2286*35238bceSAndroid Build Coastguard Worker                          << "getProgramResourceiv returned unexpected number of values, expected " << (int)props.size()
2287*35238bceSAndroid Build Coastguard Worker                          << ", got " << written << tcu::TestLog::EndMessage;
2288*35238bceSAndroid Build Coastguard Worker         testCtx.setTestResult(QP_TEST_RESULT_FAIL, "getProgramResourceiv returned unexpected number of values");
2289*35238bceSAndroid Build Coastguard Worker         return;
2290*35238bceSAndroid Build Coastguard Worker     }
2291*35238bceSAndroid Build Coastguard Worker 
2292*35238bceSAndroid Build Coastguard Worker     if (propValues.back() != -2)
2293*35238bceSAndroid Build Coastguard Worker     {
2294*35238bceSAndroid Build Coastguard Worker         testCtx.getLog() << tcu::TestLog::Message
2295*35238bceSAndroid Build Coastguard Worker                          << "getProgramResourceiv post write buffer guard value was modified, too many return values"
2296*35238bceSAndroid Build Coastguard Worker                          << tcu::TestLog::EndMessage;
2297*35238bceSAndroid Build Coastguard Worker         testCtx.setTestResult(QP_TEST_RESULT_FAIL, "getProgramResourceiv returned unexpected number of values");
2298*35238bceSAndroid Build Coastguard Worker         return;
2299*35238bceSAndroid Build Coastguard Worker     }
2300*35238bceSAndroid Build Coastguard Worker     propValues.pop_back();
2301*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(validators.size() == propValues.size());
2302*35238bceSAndroid Build Coastguard Worker 
2303*35238bceSAndroid Build Coastguard Worker     // log
2304*35238bceSAndroid Build Coastguard Worker 
2305*35238bceSAndroid Build Coastguard Worker     {
2306*35238bceSAndroid Build Coastguard Worker         tcu::MessageBuilder message(&testCtx.getLog());
2307*35238bceSAndroid Build Coastguard Worker         message << "For resource index " << resourceNdx << " (\"" << targetResourceName
2308*35238bceSAndroid Build Coastguard Worker                 << "\") got following properties:\n";
2309*35238bceSAndroid Build Coastguard Worker 
2310*35238bceSAndroid Build Coastguard Worker         for (int propNdx = 0; propNdx < (int)propValues.size(); ++propNdx)
2311*35238bceSAndroid Build Coastguard Worker             message << "\t" << glu::getProgramResourcePropertyName(props[propNdx]) << ":\t"
2312*35238bceSAndroid Build Coastguard Worker                     << validators[propNdx]->getHumanReadablePropertyString(propValues[propNdx]) << "\n";
2313*35238bceSAndroid Build Coastguard Worker 
2314*35238bceSAndroid Build Coastguard Worker         message << tcu::TestLog::EndMessage;
2315*35238bceSAndroid Build Coastguard Worker     }
2316*35238bceSAndroid Build Coastguard Worker 
2317*35238bceSAndroid Build Coastguard Worker     // validate
2318*35238bceSAndroid Build Coastguard Worker 
2319*35238bceSAndroid Build Coastguard Worker     for (int propNdx = 0; propNdx < (int)propValues.size(); ++propNdx)
2320*35238bceSAndroid Build Coastguard Worker         validators[propNdx]->validate(programDefinition, targetResourceName, propValues[propNdx],
2321*35238bceSAndroid Build Coastguard Worker                                       implementationResourceName);
2322*35238bceSAndroid Build Coastguard Worker }
2323*35238bceSAndroid Build Coastguard Worker 
getAndCheckProgramDefinition(void)2324*35238bceSAndroid Build Coastguard Worker const ProgramInterfaceDefinition::Program *ProgramInterfaceQueryTestCase::getAndCheckProgramDefinition(void)
2325*35238bceSAndroid Build Coastguard Worker {
2326*35238bceSAndroid Build Coastguard Worker     const ProgramInterfaceDefinition::Program *programDefinition = getProgramDefinition();
2327*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(programDefinition->isValid());
2328*35238bceSAndroid Build Coastguard Worker 
2329*35238bceSAndroid Build Coastguard Worker     auto type = m_context.getRenderContext().getType();
2330*35238bceSAndroid Build Coastguard Worker     if (glu::contextSupports(type, glu::ApiType::es(3, 2)) || glu::contextSupports(type, glu::ApiType::core(4, 5)))
2331*35238bceSAndroid Build Coastguard Worker     {
2332*35238bceSAndroid Build Coastguard Worker         return programDefinition;
2333*35238bceSAndroid Build Coastguard Worker     }
2334*35238bceSAndroid Build Coastguard Worker 
2335*35238bceSAndroid Build Coastguard Worker     if (programDefinition->hasStage(glu::SHADERTYPE_TESSELLATION_CONTROL) ||
2336*35238bceSAndroid Build Coastguard Worker         programDefinition->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION))
2337*35238bceSAndroid Build Coastguard Worker     {
2338*35238bceSAndroid Build Coastguard Worker         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
2339*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
2340*35238bceSAndroid Build Coastguard Worker     }
2341*35238bceSAndroid Build Coastguard Worker 
2342*35238bceSAndroid Build Coastguard Worker     // Testing IS_PER_PATCH as a part of a larger set is ok, since the extension is checked
2343*35238bceSAndroid Build Coastguard Worker     // before query. However, we don't want IS_PER_PATCH-specific tests to become noop and pass.
2344*35238bceSAndroid Build Coastguard Worker     if (m_queryTarget.propFlags == PROGRAMRESOURCEPROP_IS_PER_PATCH)
2345*35238bceSAndroid Build Coastguard Worker     {
2346*35238bceSAndroid Build Coastguard Worker         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
2347*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
2348*35238bceSAndroid Build Coastguard Worker     }
2349*35238bceSAndroid Build Coastguard Worker 
2350*35238bceSAndroid Build Coastguard Worker     if (programDefinition->hasStage(glu::SHADERTYPE_GEOMETRY))
2351*35238bceSAndroid Build Coastguard Worker     {
2352*35238bceSAndroid Build Coastguard Worker         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
2353*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
2354*35238bceSAndroid Build Coastguard Worker     }
2355*35238bceSAndroid Build Coastguard Worker 
2356*35238bceSAndroid Build Coastguard Worker     if (programContainsIOBlocks(programDefinition))
2357*35238bceSAndroid Build Coastguard Worker     {
2358*35238bceSAndroid Build Coastguard Worker         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_shader_io_blocks"))
2359*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Test requires GL_EXT_shader_io_blocks extension");
2360*35238bceSAndroid Build Coastguard Worker     }
2361*35238bceSAndroid Build Coastguard Worker 
2362*35238bceSAndroid Build Coastguard Worker     return programDefinition;
2363*35238bceSAndroid Build Coastguard Worker }
2364*35238bceSAndroid Build Coastguard Worker 
getMaxPatchVertices(void)2365*35238bceSAndroid Build Coastguard Worker int ProgramInterfaceQueryTestCase::getMaxPatchVertices(void)
2366*35238bceSAndroid Build Coastguard Worker {
2367*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl    = m_context.getRenderContext().getFunctions();
2368*35238bceSAndroid Build Coastguard Worker     glw::GLint maxPatchVertices = 0;
2369*35238bceSAndroid Build Coastguard Worker 
2370*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
2371*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_PATCH_VERTICES)");
2372*35238bceSAndroid Build Coastguard Worker     return maxPatchVertices;
2373*35238bceSAndroid Build Coastguard Worker }
2374*35238bceSAndroid Build Coastguard Worker 
iterate(void)2375*35238bceSAndroid Build Coastguard Worker ProgramInterfaceQueryTestCase::IterateResult ProgramInterfaceQueryTestCase::iterate(void)
2376*35238bceSAndroid Build Coastguard Worker {
2377*35238bceSAndroid Build Coastguard Worker     struct TestProperty
2378*35238bceSAndroid Build Coastguard Worker     {
2379*35238bceSAndroid Build Coastguard Worker         glw::GLenum prop;
2380*35238bceSAndroid Build Coastguard Worker         const PropValidator *validator;
2381*35238bceSAndroid Build Coastguard Worker     };
2382*35238bceSAndroid Build Coastguard Worker 
2383*35238bceSAndroid Build Coastguard Worker     const ProgramInterfaceDefinition::Program *programDefinition = getAndCheckProgramDefinition();
2384*35238bceSAndroid Build Coastguard Worker     const std::vector<std::string> targetResources               = getQueryTargetResources();
2385*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram program(m_context.getRenderContext(), generateProgramInterfaceProgramSources(programDefinition));
2386*35238bceSAndroid Build Coastguard Worker 
2387*35238bceSAndroid Build Coastguard Worker     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2388*35238bceSAndroid Build Coastguard Worker 
2389*35238bceSAndroid Build Coastguard Worker     // Log program
2390*35238bceSAndroid Build Coastguard Worker     {
2391*35238bceSAndroid Build Coastguard Worker         const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program");
2392*35238bceSAndroid Build Coastguard Worker 
2393*35238bceSAndroid Build Coastguard Worker         // Feedback varyings
2394*35238bceSAndroid Build Coastguard Worker         if (!programDefinition->getTransformFeedbackVaryings().empty())
2395*35238bceSAndroid Build Coastguard Worker         {
2396*35238bceSAndroid Build Coastguard Worker             tcu::MessageBuilder builder(&m_testCtx.getLog());
2397*35238bceSAndroid Build Coastguard Worker             builder << "Transform feedback varyings: {";
2398*35238bceSAndroid Build Coastguard Worker             for (int ndx = 0; ndx < (int)programDefinition->getTransformFeedbackVaryings().size(); ++ndx)
2399*35238bceSAndroid Build Coastguard Worker             {
2400*35238bceSAndroid Build Coastguard Worker                 if (ndx)
2401*35238bceSAndroid Build Coastguard Worker                     builder << ", ";
2402*35238bceSAndroid Build Coastguard Worker                 builder << "\"" << programDefinition->getTransformFeedbackVaryings()[ndx] << "\"";
2403*35238bceSAndroid Build Coastguard Worker             }
2404*35238bceSAndroid Build Coastguard Worker             builder << "}" << tcu::TestLog::EndMessage;
2405*35238bceSAndroid Build Coastguard Worker         }
2406*35238bceSAndroid Build Coastguard Worker 
2407*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << program;
2408*35238bceSAndroid Build Coastguard Worker         if (!program.isOk())
2409*35238bceSAndroid Build Coastguard Worker         {
2410*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message
2411*35238bceSAndroid Build Coastguard Worker                                << "Program build failed, checking if program exceeded implementation limits"
2412*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
2413*35238bceSAndroid Build Coastguard Worker             checkProgramResourceUsage(programDefinition, m_context.getRenderContext().getFunctions(),
2414*35238bceSAndroid Build Coastguard Worker                                       m_testCtx.getLog());
2415*35238bceSAndroid Build Coastguard Worker 
2416*35238bceSAndroid Build Coastguard Worker             // within limits
2417*35238bceSAndroid Build Coastguard Worker             throw tcu::TestError("could not build program");
2418*35238bceSAndroid Build Coastguard Worker         }
2419*35238bceSAndroid Build Coastguard Worker     }
2420*35238bceSAndroid Build Coastguard Worker 
2421*35238bceSAndroid Build Coastguard Worker     // Check interface props
2422*35238bceSAndroid Build Coastguard Worker 
2423*35238bceSAndroid Build Coastguard Worker     switch (m_queryTarget.interface)
2424*35238bceSAndroid Build Coastguard Worker     {
2425*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM:
2426*35238bceSAndroid Build Coastguard Worker     {
2427*35238bceSAndroid Build Coastguard Worker         const VariableSearchFilter uniformFilter = VariableSearchFilter::createStorageFilter(glu::STORAGE_UNIFORM);
2428*35238bceSAndroid Build Coastguard Worker 
2429*35238bceSAndroid Build Coastguard Worker         const TypeValidator typeValidator(m_context, program.getProgram(), uniformFilter);
2430*35238bceSAndroid Build Coastguard Worker         const ArraySizeValidator arraySizeValidator(m_context, program.getProgram(), -1, uniformFilter);
2431*35238bceSAndroid Build Coastguard Worker         const ArrayStrideValidator arrayStrideValidator(m_context, program.getProgram(), uniformFilter);
2432*35238bceSAndroid Build Coastguard Worker         const BlockIndexValidator blockIndexValidator(m_context, program.getProgram(), uniformFilter);
2433*35238bceSAndroid Build Coastguard Worker         const IsRowMajorValidator isRowMajorValidator(m_context, program.getProgram(), uniformFilter);
2434*35238bceSAndroid Build Coastguard Worker         const MatrixStrideValidator matrixStrideValidator(m_context, program.getProgram(), uniformFilter);
2435*35238bceSAndroid Build Coastguard Worker         const AtomicCounterBufferIndexVerifier atomicCounterBufferIndexVerifier(m_context, program.getProgram(),
2436*35238bceSAndroid Build Coastguard Worker                                                                                 uniformFilter);
2437*35238bceSAndroid Build Coastguard Worker         const LocationValidator locationValidator(m_context, program.getProgram(), uniformFilter);
2438*35238bceSAndroid Build Coastguard Worker         const VariableNameLengthValidator nameLengthValidator(m_context, program.getProgram(), uniformFilter);
2439*35238bceSAndroid Build Coastguard Worker         const OffsetValidator offsetVerifier(m_context, program.getProgram(), uniformFilter);
2440*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByVertexVerifier(m_context, glu::SHADERTYPE_VERTEX,
2441*35238bceSAndroid Build Coastguard Worker                                                                              uniformFilter);
2442*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByFragmentVerifier(m_context, glu::SHADERTYPE_FRAGMENT,
2443*35238bceSAndroid Build Coastguard Worker                                                                                uniformFilter);
2444*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByComputeVerifier(m_context, glu::SHADERTYPE_COMPUTE,
2445*35238bceSAndroid Build Coastguard Worker                                                                               uniformFilter);
2446*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByGeometryVerifier(m_context, glu::SHADERTYPE_GEOMETRY,
2447*35238bceSAndroid Build Coastguard Worker                                                                                uniformFilter);
2448*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByTessControlVerifier(
2449*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, uniformFilter);
2450*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByTessEvaluationVerifier(
2451*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, uniformFilter);
2452*35238bceSAndroid Build Coastguard Worker 
2453*35238bceSAndroid Build Coastguard Worker         const TestProperty allProperties[] = {
2454*35238bceSAndroid Build Coastguard Worker             {GL_ARRAY_SIZE, &arraySizeValidator},
2455*35238bceSAndroid Build Coastguard Worker             {GL_ARRAY_STRIDE, &arrayStrideValidator},
2456*35238bceSAndroid Build Coastguard Worker             {GL_ATOMIC_COUNTER_BUFFER_INDEX, &atomicCounterBufferIndexVerifier},
2457*35238bceSAndroid Build Coastguard Worker             {GL_BLOCK_INDEX, &blockIndexValidator},
2458*35238bceSAndroid Build Coastguard Worker             {GL_IS_ROW_MAJOR, &isRowMajorValidator},
2459*35238bceSAndroid Build Coastguard Worker             {GL_LOCATION, &locationValidator},
2460*35238bceSAndroid Build Coastguard Worker             {GL_MATRIX_STRIDE, &matrixStrideValidator},
2461*35238bceSAndroid Build Coastguard Worker             {GL_NAME_LENGTH, &nameLengthValidator},
2462*35238bceSAndroid Build Coastguard Worker             {GL_OFFSET, &offsetVerifier},
2463*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier},
2464*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier},
2465*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier},
2466*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier},
2467*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier},
2468*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier},
2469*35238bceSAndroid Build Coastguard Worker             {GL_TYPE, &typeValidator},
2470*35238bceSAndroid Build Coastguard Worker         };
2471*35238bceSAndroid Build Coastguard Worker 
2472*35238bceSAndroid Build Coastguard Worker         for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
2473*35238bceSAndroid Build Coastguard Worker         {
2474*35238bceSAndroid Build Coastguard Worker             const tcu::ScopedLogSection section(m_testCtx.getLog(), "UniformResource",
2475*35238bceSAndroid Build Coastguard Worker                                                 "Uniform resource \"" + targetResources[targetResourceNdx] + "\"");
2476*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2477*35238bceSAndroid Build Coastguard Worker             std::vector<glw::GLenum> props;
2478*35238bceSAndroid Build Coastguard Worker             std::vector<const PropValidator *> validators;
2479*35238bceSAndroid Build Coastguard Worker 
2480*35238bceSAndroid Build Coastguard Worker             for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
2481*35238bceSAndroid Build Coastguard Worker             {
2482*35238bceSAndroid Build Coastguard Worker                 if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
2483*35238bceSAndroid Build Coastguard Worker                     allProperties[propNdx].validator->isSupported())
2484*35238bceSAndroid Build Coastguard Worker                 {
2485*35238bceSAndroid Build Coastguard Worker                     props.push_back(allProperties[propNdx].prop);
2486*35238bceSAndroid Build Coastguard Worker                     validators.push_back(allProperties[propNdx].validator);
2487*35238bceSAndroid Build Coastguard Worker                 }
2488*35238bceSAndroid Build Coastguard Worker             }
2489*35238bceSAndroid Build Coastguard Worker 
2490*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(!props.empty());
2491*35238bceSAndroid Build Coastguard Worker 
2492*35238bceSAndroid Build Coastguard Worker             queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface,
2493*35238bceSAndroid Build Coastguard Worker                                   targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
2494*35238bceSAndroid Build Coastguard Worker         }
2495*35238bceSAndroid Build Coastguard Worker 
2496*35238bceSAndroid Build Coastguard Worker         break;
2497*35238bceSAndroid Build Coastguard Worker     }
2498*35238bceSAndroid Build Coastguard Worker 
2499*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_UNIFORM_BLOCK:
2500*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
2501*35238bceSAndroid Build Coastguard Worker     {
2502*35238bceSAndroid Build Coastguard Worker         const glu::Storage storage             = (m_queryTarget.interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ?
2503*35238bceSAndroid Build Coastguard Worker                                                      (glu::STORAGE_UNIFORM) :
2504*35238bceSAndroid Build Coastguard Worker                                                      (glu::STORAGE_BUFFER);
2505*35238bceSAndroid Build Coastguard Worker         const VariableSearchFilter blockFilter = VariableSearchFilter::createStorageFilter(storage);
2506*35238bceSAndroid Build Coastguard Worker 
2507*35238bceSAndroid Build Coastguard Worker         const BlockNameLengthValidator nameLengthValidator(m_context, program.getProgram(), blockFilter);
2508*35238bceSAndroid Build Coastguard Worker         const BlockReferencedByShaderValidator referencedByVertexVerifier(m_context, glu::SHADERTYPE_VERTEX,
2509*35238bceSAndroid Build Coastguard Worker                                                                           blockFilter);
2510*35238bceSAndroid Build Coastguard Worker         const BlockReferencedByShaderValidator referencedByFragmentVerifier(m_context, glu::SHADERTYPE_FRAGMENT,
2511*35238bceSAndroid Build Coastguard Worker                                                                             blockFilter);
2512*35238bceSAndroid Build Coastguard Worker         const BlockReferencedByShaderValidator referencedByComputeVerifier(m_context, glu::SHADERTYPE_COMPUTE,
2513*35238bceSAndroid Build Coastguard Worker                                                                            blockFilter);
2514*35238bceSAndroid Build Coastguard Worker         const BlockReferencedByShaderValidator referencedByGeometryVerifier(m_context, glu::SHADERTYPE_GEOMETRY,
2515*35238bceSAndroid Build Coastguard Worker                                                                             blockFilter);
2516*35238bceSAndroid Build Coastguard Worker         const BlockReferencedByShaderValidator referencedByTessControlVerifier(
2517*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, blockFilter);
2518*35238bceSAndroid Build Coastguard Worker         const BlockReferencedByShaderValidator referencedByTessEvaluationVerifier(
2519*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, blockFilter);
2520*35238bceSAndroid Build Coastguard Worker         const BufferBindingValidator bufferBindingValidator(m_context, program.getProgram(), blockFilter);
2521*35238bceSAndroid Build Coastguard Worker 
2522*35238bceSAndroid Build Coastguard Worker         const TestProperty allProperties[] = {
2523*35238bceSAndroid Build Coastguard Worker             {GL_NAME_LENGTH, &nameLengthValidator},
2524*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier},
2525*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier},
2526*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier},
2527*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier},
2528*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier},
2529*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier},
2530*35238bceSAndroid Build Coastguard Worker             {GL_BUFFER_BINDING, &bufferBindingValidator},
2531*35238bceSAndroid Build Coastguard Worker         };
2532*35238bceSAndroid Build Coastguard Worker 
2533*35238bceSAndroid Build Coastguard Worker         for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
2534*35238bceSAndroid Build Coastguard Worker         {
2535*35238bceSAndroid Build Coastguard Worker             const tcu::ScopedLogSection section(m_testCtx.getLog(), "BlockResource",
2536*35238bceSAndroid Build Coastguard Worker                                                 "Interface block \"" + targetResources[targetResourceNdx] + "\"");
2537*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2538*35238bceSAndroid Build Coastguard Worker             std::vector<glw::GLenum> props;
2539*35238bceSAndroid Build Coastguard Worker             std::vector<const PropValidator *> validators;
2540*35238bceSAndroid Build Coastguard Worker 
2541*35238bceSAndroid Build Coastguard Worker             for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
2542*35238bceSAndroid Build Coastguard Worker             {
2543*35238bceSAndroid Build Coastguard Worker                 if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
2544*35238bceSAndroid Build Coastguard Worker                     allProperties[propNdx].validator->isSupported())
2545*35238bceSAndroid Build Coastguard Worker                 {
2546*35238bceSAndroid Build Coastguard Worker                     props.push_back(allProperties[propNdx].prop);
2547*35238bceSAndroid Build Coastguard Worker                     validators.push_back(allProperties[propNdx].validator);
2548*35238bceSAndroid Build Coastguard Worker                 }
2549*35238bceSAndroid Build Coastguard Worker             }
2550*35238bceSAndroid Build Coastguard Worker 
2551*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(!props.empty());
2552*35238bceSAndroid Build Coastguard Worker 
2553*35238bceSAndroid Build Coastguard Worker             queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface,
2554*35238bceSAndroid Build Coastguard Worker                                   targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
2555*35238bceSAndroid Build Coastguard Worker         }
2556*35238bceSAndroid Build Coastguard Worker 
2557*35238bceSAndroid Build Coastguard Worker         break;
2558*35238bceSAndroid Build Coastguard Worker     }
2559*35238bceSAndroid Build Coastguard Worker 
2560*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_INPUT:
2561*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_PROGRAM_OUTPUT:
2562*35238bceSAndroid Build Coastguard Worker     {
2563*35238bceSAndroid Build Coastguard Worker         const bool isInputCase            = (m_queryTarget.interface == PROGRAMINTERFACE_PROGRAM_INPUT);
2564*35238bceSAndroid Build Coastguard Worker         const glu::Storage varyingStorage = (isInputCase) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT);
2565*35238bceSAndroid Build Coastguard Worker         const glu::Storage patchStorage   = (isInputCase) ? (glu::STORAGE_PATCH_IN) : (glu::STORAGE_PATCH_OUT);
2566*35238bceSAndroid Build Coastguard Worker         const glu::ShaderType shaderType =
2567*35238bceSAndroid Build Coastguard Worker             (isInputCase) ? (programDefinition->getFirstStage()) : (programDefinition->getLastStage());
2568*35238bceSAndroid Build Coastguard Worker         const int unsizedArraySize =
2569*35238bceSAndroid Build Coastguard Worker             (isInputCase && shaderType == glu::SHADERTYPE_GEOMETRY) ?
2570*35238bceSAndroid Build Coastguard Worker                 (1) // input points
2571*35238bceSAndroid Build Coastguard Worker             :
2572*35238bceSAndroid Build Coastguard Worker             (isInputCase && shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) ?
2573*35238bceSAndroid Build Coastguard Worker                 (getMaxPatchVertices()) // input batch size
2574*35238bceSAndroid Build Coastguard Worker             :
2575*35238bceSAndroid Build Coastguard Worker             (!isInputCase && shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) ?
2576*35238bceSAndroid Build Coastguard Worker                 (programDefinition->getTessellationNumOutputPatchVertices()) // output batch size
2577*35238bceSAndroid Build Coastguard Worker             :
2578*35238bceSAndroid Build Coastguard Worker             (isInputCase && shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION) ?
2579*35238bceSAndroid Build Coastguard Worker                 (getMaxPatchVertices()) // input batch size
2580*35238bceSAndroid Build Coastguard Worker                 :
2581*35238bceSAndroid Build Coastguard Worker                 (-1);
2582*35238bceSAndroid Build Coastguard Worker         const VariableSearchFilter variableFilter = VariableSearchFilter::logicalAnd(
2583*35238bceSAndroid Build Coastguard Worker             VariableSearchFilter::createShaderTypeFilter(shaderType),
2584*35238bceSAndroid Build Coastguard Worker             VariableSearchFilter::logicalOr(VariableSearchFilter::createStorageFilter(varyingStorage),
2585*35238bceSAndroid Build Coastguard Worker                                             VariableSearchFilter::createStorageFilter(patchStorage)));
2586*35238bceSAndroid Build Coastguard Worker 
2587*35238bceSAndroid Build Coastguard Worker         const TypeValidator typeValidator(m_context, program.getProgram(), variableFilter);
2588*35238bceSAndroid Build Coastguard Worker         const ArraySizeValidator arraySizeValidator(m_context, program.getProgram(), unsizedArraySize, variableFilter);
2589*35238bceSAndroid Build Coastguard Worker         const LocationValidator locationValidator(m_context, program.getProgram(), variableFilter);
2590*35238bceSAndroid Build Coastguard Worker         const VariableNameLengthValidator nameLengthValidator(m_context, program.getProgram(), variableFilter);
2591*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByVertexVerifier(m_context, glu::SHADERTYPE_VERTEX,
2592*35238bceSAndroid Build Coastguard Worker                                                                              variableFilter);
2593*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByFragmentVerifier(m_context, glu::SHADERTYPE_FRAGMENT,
2594*35238bceSAndroid Build Coastguard Worker                                                                                variableFilter);
2595*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByComputeVerifier(m_context, glu::SHADERTYPE_COMPUTE,
2596*35238bceSAndroid Build Coastguard Worker                                                                               variableFilter);
2597*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByGeometryVerifier(m_context, glu::SHADERTYPE_GEOMETRY,
2598*35238bceSAndroid Build Coastguard Worker                                                                                variableFilter);
2599*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByTessControlVerifier(
2600*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, variableFilter);
2601*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByTessEvaluationVerifier(
2602*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, variableFilter);
2603*35238bceSAndroid Build Coastguard Worker         const PerPatchValidator perPatchValidator(m_context, program.getProgram(), variableFilter);
2604*35238bceSAndroid Build Coastguard Worker 
2605*35238bceSAndroid Build Coastguard Worker         const TestProperty allProperties[] = {
2606*35238bceSAndroid Build Coastguard Worker             {GL_ARRAY_SIZE, &arraySizeValidator},
2607*35238bceSAndroid Build Coastguard Worker             {GL_LOCATION, &locationValidator},
2608*35238bceSAndroid Build Coastguard Worker             {GL_NAME_LENGTH, &nameLengthValidator},
2609*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier},
2610*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier},
2611*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier},
2612*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier},
2613*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier},
2614*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier},
2615*35238bceSAndroid Build Coastguard Worker             {GL_TYPE, &typeValidator},
2616*35238bceSAndroid Build Coastguard Worker             {GL_IS_PER_PATCH, &perPatchValidator},
2617*35238bceSAndroid Build Coastguard Worker         };
2618*35238bceSAndroid Build Coastguard Worker 
2619*35238bceSAndroid Build Coastguard Worker         for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
2620*35238bceSAndroid Build Coastguard Worker         {
2621*35238bceSAndroid Build Coastguard Worker             const std::string resourceInterfaceName =
2622*35238bceSAndroid Build Coastguard Worker                 (m_queryTarget.interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? ("Input") : ("Output");
2623*35238bceSAndroid Build Coastguard Worker             const tcu::ScopedLogSection section(m_testCtx.getLog(), "BlockResource",
2624*35238bceSAndroid Build Coastguard Worker                                                 resourceInterfaceName + " resource \"" +
2625*35238bceSAndroid Build Coastguard Worker                                                     targetResources[targetResourceNdx] + "\"");
2626*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2627*35238bceSAndroid Build Coastguard Worker             std::vector<glw::GLenum> props;
2628*35238bceSAndroid Build Coastguard Worker             std::vector<const PropValidator *> validators;
2629*35238bceSAndroid Build Coastguard Worker 
2630*35238bceSAndroid Build Coastguard Worker             for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
2631*35238bceSAndroid Build Coastguard Worker             {
2632*35238bceSAndroid Build Coastguard Worker                 if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
2633*35238bceSAndroid Build Coastguard Worker                     allProperties[propNdx].validator->isSupported())
2634*35238bceSAndroid Build Coastguard Worker                 {
2635*35238bceSAndroid Build Coastguard Worker                     props.push_back(allProperties[propNdx].prop);
2636*35238bceSAndroid Build Coastguard Worker                     validators.push_back(allProperties[propNdx].validator);
2637*35238bceSAndroid Build Coastguard Worker                 }
2638*35238bceSAndroid Build Coastguard Worker             }
2639*35238bceSAndroid Build Coastguard Worker 
2640*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(!props.empty());
2641*35238bceSAndroid Build Coastguard Worker 
2642*35238bceSAndroid Build Coastguard Worker             queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface,
2643*35238bceSAndroid Build Coastguard Worker                                   targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
2644*35238bceSAndroid Build Coastguard Worker         }
2645*35238bceSAndroid Build Coastguard Worker 
2646*35238bceSAndroid Build Coastguard Worker         break;
2647*35238bceSAndroid Build Coastguard Worker     }
2648*35238bceSAndroid Build Coastguard Worker 
2649*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_BUFFER_VARIABLE:
2650*35238bceSAndroid Build Coastguard Worker     {
2651*35238bceSAndroid Build Coastguard Worker         const VariableSearchFilter variableFilter = VariableSearchFilter::createStorageFilter(glu::STORAGE_BUFFER);
2652*35238bceSAndroid Build Coastguard Worker 
2653*35238bceSAndroid Build Coastguard Worker         const TypeValidator typeValidator(m_context, program.getProgram(), variableFilter);
2654*35238bceSAndroid Build Coastguard Worker         const ArraySizeValidator arraySizeValidator(m_context, program.getProgram(), 0, variableFilter);
2655*35238bceSAndroid Build Coastguard Worker         const ArrayStrideValidator arrayStrideValidator(m_context, program.getProgram(), variableFilter);
2656*35238bceSAndroid Build Coastguard Worker         const BlockIndexValidator blockIndexValidator(m_context, program.getProgram(), variableFilter);
2657*35238bceSAndroid Build Coastguard Worker         const IsRowMajorValidator isRowMajorValidator(m_context, program.getProgram(), variableFilter);
2658*35238bceSAndroid Build Coastguard Worker         const MatrixStrideValidator matrixStrideValidator(m_context, program.getProgram(), variableFilter);
2659*35238bceSAndroid Build Coastguard Worker         const OffsetValidator offsetValidator(m_context, program.getProgram(), variableFilter);
2660*35238bceSAndroid Build Coastguard Worker         const VariableNameLengthValidator nameLengthValidator(m_context, program.getProgram(), variableFilter);
2661*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByVertexVerifier(m_context, glu::SHADERTYPE_VERTEX,
2662*35238bceSAndroid Build Coastguard Worker                                                                              variableFilter);
2663*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByFragmentVerifier(m_context, glu::SHADERTYPE_FRAGMENT,
2664*35238bceSAndroid Build Coastguard Worker                                                                                variableFilter);
2665*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByComputeVerifier(m_context, glu::SHADERTYPE_COMPUTE,
2666*35238bceSAndroid Build Coastguard Worker                                                                               variableFilter);
2667*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByGeometryVerifier(m_context, glu::SHADERTYPE_GEOMETRY,
2668*35238bceSAndroid Build Coastguard Worker                                                                                variableFilter);
2669*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByTessControlVerifier(
2670*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, variableFilter);
2671*35238bceSAndroid Build Coastguard Worker         const VariableReferencedByShaderValidator referencedByTessEvaluationVerifier(
2672*35238bceSAndroid Build Coastguard Worker             m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, variableFilter);
2673*35238bceSAndroid Build Coastguard Worker         const TopLevelArraySizeValidator topLevelArraySizeValidator(m_context, program.getProgram(), variableFilter);
2674*35238bceSAndroid Build Coastguard Worker         const TopLevelArrayStrideValidator topLevelArrayStrideValidator(m_context, program.getProgram(),
2675*35238bceSAndroid Build Coastguard Worker                                                                         variableFilter);
2676*35238bceSAndroid Build Coastguard Worker 
2677*35238bceSAndroid Build Coastguard Worker         const TestProperty allProperties[] = {
2678*35238bceSAndroid Build Coastguard Worker             {GL_ARRAY_SIZE, &arraySizeValidator},
2679*35238bceSAndroid Build Coastguard Worker             {GL_ARRAY_STRIDE, &arrayStrideValidator},
2680*35238bceSAndroid Build Coastguard Worker             {GL_BLOCK_INDEX, &blockIndexValidator},
2681*35238bceSAndroid Build Coastguard Worker             {GL_IS_ROW_MAJOR, &isRowMajorValidator},
2682*35238bceSAndroid Build Coastguard Worker             {GL_MATRIX_STRIDE, &matrixStrideValidator},
2683*35238bceSAndroid Build Coastguard Worker             {GL_NAME_LENGTH, &nameLengthValidator},
2684*35238bceSAndroid Build Coastguard Worker             {GL_OFFSET, &offsetValidator},
2685*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier},
2686*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier},
2687*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier},
2688*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier},
2689*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier},
2690*35238bceSAndroid Build Coastguard Worker             {GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier},
2691*35238bceSAndroid Build Coastguard Worker             {GL_TOP_LEVEL_ARRAY_SIZE, &topLevelArraySizeValidator},
2692*35238bceSAndroid Build Coastguard Worker             {GL_TOP_LEVEL_ARRAY_STRIDE, &topLevelArrayStrideValidator},
2693*35238bceSAndroid Build Coastguard Worker             {GL_TYPE, &typeValidator},
2694*35238bceSAndroid Build Coastguard Worker         };
2695*35238bceSAndroid Build Coastguard Worker 
2696*35238bceSAndroid Build Coastguard Worker         for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
2697*35238bceSAndroid Build Coastguard Worker         {
2698*35238bceSAndroid Build Coastguard Worker             const tcu::ScopedLogSection section(m_testCtx.getLog(), "BufferVariableResource",
2699*35238bceSAndroid Build Coastguard Worker                                                 "Buffer variable \"" + targetResources[targetResourceNdx] + "\"");
2700*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2701*35238bceSAndroid Build Coastguard Worker             std::vector<glw::GLenum> props;
2702*35238bceSAndroid Build Coastguard Worker             std::vector<const PropValidator *> validators;
2703*35238bceSAndroid Build Coastguard Worker 
2704*35238bceSAndroid Build Coastguard Worker             for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
2705*35238bceSAndroid Build Coastguard Worker             {
2706*35238bceSAndroid Build Coastguard Worker                 if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
2707*35238bceSAndroid Build Coastguard Worker                     allProperties[propNdx].validator->isSupported())
2708*35238bceSAndroid Build Coastguard Worker                 {
2709*35238bceSAndroid Build Coastguard Worker                     props.push_back(allProperties[propNdx].prop);
2710*35238bceSAndroid Build Coastguard Worker                     validators.push_back(allProperties[propNdx].validator);
2711*35238bceSAndroid Build Coastguard Worker                 }
2712*35238bceSAndroid Build Coastguard Worker             }
2713*35238bceSAndroid Build Coastguard Worker 
2714*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(!props.empty());
2715*35238bceSAndroid Build Coastguard Worker 
2716*35238bceSAndroid Build Coastguard Worker             queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface,
2717*35238bceSAndroid Build Coastguard Worker                                   targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
2718*35238bceSAndroid Build Coastguard Worker         }
2719*35238bceSAndroid Build Coastguard Worker 
2720*35238bceSAndroid Build Coastguard Worker         break;
2721*35238bceSAndroid Build Coastguard Worker     }
2722*35238bceSAndroid Build Coastguard Worker 
2723*35238bceSAndroid Build Coastguard Worker     case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
2724*35238bceSAndroid Build Coastguard Worker     {
2725*35238bceSAndroid Build Coastguard Worker         const TransformFeedbackTypeValidator typeValidator(m_context);
2726*35238bceSAndroid Build Coastguard Worker         const TransformFeedbackArraySizeValidator arraySizeValidator(m_context);
2727*35238bceSAndroid Build Coastguard Worker         const TransformFeedbackNameLengthValidator nameLengthValidator(m_context);
2728*35238bceSAndroid Build Coastguard Worker 
2729*35238bceSAndroid Build Coastguard Worker         const TestProperty allProperties[] = {
2730*35238bceSAndroid Build Coastguard Worker             {GL_ARRAY_SIZE, &arraySizeValidator},
2731*35238bceSAndroid Build Coastguard Worker             {GL_NAME_LENGTH, &nameLengthValidator},
2732*35238bceSAndroid Build Coastguard Worker             {GL_TYPE, &typeValidator},
2733*35238bceSAndroid Build Coastguard Worker         };
2734*35238bceSAndroid Build Coastguard Worker 
2735*35238bceSAndroid Build Coastguard Worker         for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx)
2736*35238bceSAndroid Build Coastguard Worker         {
2737*35238bceSAndroid Build Coastguard Worker             const tcu::ScopedLogSection section(m_testCtx.getLog(), "XFBVariableResource",
2738*35238bceSAndroid Build Coastguard Worker                                                 "Transform feedback varying \"" + targetResources[targetResourceNdx] +
2739*35238bceSAndroid Build Coastguard Worker                                                     "\"");
2740*35238bceSAndroid Build Coastguard Worker             const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2741*35238bceSAndroid Build Coastguard Worker             std::vector<glw::GLenum> props;
2742*35238bceSAndroid Build Coastguard Worker             std::vector<const PropValidator *> validators;
2743*35238bceSAndroid Build Coastguard Worker 
2744*35238bceSAndroid Build Coastguard Worker             for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx)
2745*35238bceSAndroid Build Coastguard Worker             {
2746*35238bceSAndroid Build Coastguard Worker                 if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) &&
2747*35238bceSAndroid Build Coastguard Worker                     allProperties[propNdx].validator->isSupported())
2748*35238bceSAndroid Build Coastguard Worker                 {
2749*35238bceSAndroid Build Coastguard Worker                     props.push_back(allProperties[propNdx].prop);
2750*35238bceSAndroid Build Coastguard Worker                     validators.push_back(allProperties[propNdx].validator);
2751*35238bceSAndroid Build Coastguard Worker                 }
2752*35238bceSAndroid Build Coastguard Worker             }
2753*35238bceSAndroid Build Coastguard Worker 
2754*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(!props.empty());
2755*35238bceSAndroid Build Coastguard Worker 
2756*35238bceSAndroid Build Coastguard Worker             queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface,
2757*35238bceSAndroid Build Coastguard Worker                                   targetResources[targetResourceNdx].c_str(), programDefinition, props, validators);
2758*35238bceSAndroid Build Coastguard Worker         }
2759*35238bceSAndroid Build Coastguard Worker 
2760*35238bceSAndroid Build Coastguard Worker         break;
2761*35238bceSAndroid Build Coastguard Worker     }
2762*35238bceSAndroid Build Coastguard Worker 
2763*35238bceSAndroid Build Coastguard Worker     default:
2764*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
2765*35238bceSAndroid Build Coastguard Worker     }
2766*35238bceSAndroid Build Coastguard Worker 
2767*35238bceSAndroid Build Coastguard Worker     return STOP;
2768*35238bceSAndroid Build Coastguard Worker }
2769*35238bceSAndroid Build Coastguard Worker 
checkLimit(glw::GLenum pname,int usage,const glw::Functions & gl,tcu::TestLog & log)2770*35238bceSAndroid Build Coastguard Worker static bool checkLimit(glw::GLenum pname, int usage, const glw::Functions &gl, tcu::TestLog &log)
2771*35238bceSAndroid Build Coastguard Worker {
2772*35238bceSAndroid Build Coastguard Worker     if (usage > 0)
2773*35238bceSAndroid Build Coastguard Worker     {
2774*35238bceSAndroid Build Coastguard Worker         glw::GLint limit = 0;
2775*35238bceSAndroid Build Coastguard Worker         gl.getIntegerv(pname, &limit);
2776*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "query limits");
2777*35238bceSAndroid Build Coastguard Worker 
2778*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "\t" << glu::getGettableStateStr(pname) << " = " << limit << ", test requires "
2779*35238bceSAndroid Build Coastguard Worker             << usage << tcu::TestLog::EndMessage;
2780*35238bceSAndroid Build Coastguard Worker 
2781*35238bceSAndroid Build Coastguard Worker         if (limit < usage)
2782*35238bceSAndroid Build Coastguard Worker         {
2783*35238bceSAndroid Build Coastguard Worker             log << tcu::TestLog::Message << "\t\tLimit exceeded" << tcu::TestLog::EndMessage;
2784*35238bceSAndroid Build Coastguard Worker             return false;
2785*35238bceSAndroid Build Coastguard Worker         }
2786*35238bceSAndroid Build Coastguard Worker     }
2787*35238bceSAndroid Build Coastguard Worker 
2788*35238bceSAndroid Build Coastguard Worker     return true;
2789*35238bceSAndroid Build Coastguard Worker }
2790*35238bceSAndroid Build Coastguard Worker 
checkShaderResourceUsage(const ProgramInterfaceDefinition::Program * program,const ProgramInterfaceDefinition::Shader * shader,const glw::Functions & gl,tcu::TestLog & log)2791*35238bceSAndroid Build Coastguard Worker static bool checkShaderResourceUsage(const ProgramInterfaceDefinition::Program *program,
2792*35238bceSAndroid Build Coastguard Worker                                      const ProgramInterfaceDefinition::Shader *shader, const glw::Functions &gl,
2793*35238bceSAndroid Build Coastguard Worker                                      tcu::TestLog &log)
2794*35238bceSAndroid Build Coastguard Worker {
2795*35238bceSAndroid Build Coastguard Worker     const ProgramInterfaceDefinition::ShaderResourceUsage usage = getShaderResourceUsage(program, shader);
2796*35238bceSAndroid Build Coastguard Worker 
2797*35238bceSAndroid Build Coastguard Worker     switch (shader->getType())
2798*35238bceSAndroid Build Coastguard Worker     {
2799*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_VERTEX:
2800*35238bceSAndroid Build Coastguard Worker     {
2801*35238bceSAndroid Build Coastguard Worker         const struct
2802*35238bceSAndroid Build Coastguard Worker         {
2803*35238bceSAndroid Build Coastguard Worker             glw::GLenum pname;
2804*35238bceSAndroid Build Coastguard Worker             int usage;
2805*35238bceSAndroid Build Coastguard Worker         } restrictions[] = {
2806*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_ATTRIBS, usage.numInputVectors},
2807*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents},
2808*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_UNIFORM_VECTORS, usage.numUniformVectors},
2809*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_UNIFORM_BLOCKS, usage.numUniformBlocks},
2810*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_OUTPUT_COMPONENTS, usage.numOutputComponents},
2811*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, usage.numSamplers},
2812*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers},
2813*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_ATOMIC_COUNTERS, usage.numAtomicCounters},
2814*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_IMAGE_UNIFORMS, usage.numImages},
2815*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, usage.numCombinedUniformComponents},
2816*35238bceSAndroid Build Coastguard Worker             {GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks},
2817*35238bceSAndroid Build Coastguard Worker         };
2818*35238bceSAndroid Build Coastguard Worker 
2819*35238bceSAndroid Build Coastguard Worker         bool allOk = true;
2820*35238bceSAndroid Build Coastguard Worker 
2821*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "Vertex shader:" << tcu::TestLog::EndMessage;
2822*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
2823*35238bceSAndroid Build Coastguard Worker             allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
2824*35238bceSAndroid Build Coastguard Worker 
2825*35238bceSAndroid Build Coastguard Worker         return allOk;
2826*35238bceSAndroid Build Coastguard Worker     }
2827*35238bceSAndroid Build Coastguard Worker 
2828*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_FRAGMENT:
2829*35238bceSAndroid Build Coastguard Worker     {
2830*35238bceSAndroid Build Coastguard Worker         const struct
2831*35238bceSAndroid Build Coastguard Worker         {
2832*35238bceSAndroid Build Coastguard Worker             glw::GLenum pname;
2833*35238bceSAndroid Build Coastguard Worker             int usage;
2834*35238bceSAndroid Build Coastguard Worker         } restrictions[] = {
2835*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents},
2836*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_UNIFORM_VECTORS, usage.numUniformVectors},
2837*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_UNIFORM_BLOCKS, usage.numUniformBlocks},
2838*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_INPUT_COMPONENTS, usage.numInputComponents},
2839*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TEXTURE_IMAGE_UNITS, usage.numSamplers},
2840*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers},
2841*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_ATOMIC_COUNTERS, usage.numAtomicCounters},
2842*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_IMAGE_UNIFORMS, usage.numImages},
2843*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, usage.numCombinedUniformComponents},
2844*35238bceSAndroid Build Coastguard Worker             {GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks},
2845*35238bceSAndroid Build Coastguard Worker         };
2846*35238bceSAndroid Build Coastguard Worker 
2847*35238bceSAndroid Build Coastguard Worker         bool allOk = true;
2848*35238bceSAndroid Build Coastguard Worker 
2849*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "Fragment shader:" << tcu::TestLog::EndMessage;
2850*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
2851*35238bceSAndroid Build Coastguard Worker             allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
2852*35238bceSAndroid Build Coastguard Worker 
2853*35238bceSAndroid Build Coastguard Worker         return allOk;
2854*35238bceSAndroid Build Coastguard Worker     }
2855*35238bceSAndroid Build Coastguard Worker 
2856*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_COMPUTE:
2857*35238bceSAndroid Build Coastguard Worker     {
2858*35238bceSAndroid Build Coastguard Worker         const struct
2859*35238bceSAndroid Build Coastguard Worker         {
2860*35238bceSAndroid Build Coastguard Worker             glw::GLenum pname;
2861*35238bceSAndroid Build Coastguard Worker             int usage;
2862*35238bceSAndroid Build Coastguard Worker         } restrictions[] = {
2863*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMPUTE_UNIFORM_BLOCKS, usage.numUniformBlocks},
2864*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, usage.numSamplers},
2865*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMPUTE_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents},
2866*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers},
2867*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMPUTE_ATOMIC_COUNTERS, usage.numAtomicCounters},
2868*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMPUTE_IMAGE_UNIFORMS, usage.numImages},
2869*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS, usage.numCombinedUniformComponents},
2870*35238bceSAndroid Build Coastguard Worker             {GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks},
2871*35238bceSAndroid Build Coastguard Worker         };
2872*35238bceSAndroid Build Coastguard Worker 
2873*35238bceSAndroid Build Coastguard Worker         bool allOk = true;
2874*35238bceSAndroid Build Coastguard Worker 
2875*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "Compute shader:" << tcu::TestLog::EndMessage;
2876*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
2877*35238bceSAndroid Build Coastguard Worker             allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
2878*35238bceSAndroid Build Coastguard Worker 
2879*35238bceSAndroid Build Coastguard Worker         return allOk;
2880*35238bceSAndroid Build Coastguard Worker     }
2881*35238bceSAndroid Build Coastguard Worker 
2882*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_GEOMETRY:
2883*35238bceSAndroid Build Coastguard Worker     {
2884*35238bceSAndroid Build Coastguard Worker         const int totalOutputComponents = program->getGeometryNumOutputVertices() * usage.numOutputComponents;
2885*35238bceSAndroid Build Coastguard Worker         const struct
2886*35238bceSAndroid Build Coastguard Worker         {
2887*35238bceSAndroid Build Coastguard Worker             glw::GLenum pname;
2888*35238bceSAndroid Build Coastguard Worker             int usage;
2889*35238bceSAndroid Build Coastguard Worker         } restrictions[] = {
2890*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents},
2891*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_UNIFORM_BLOCKS, usage.numUniformBlocks},
2892*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_INPUT_COMPONENTS, usage.numInputComponents},
2893*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, usage.numOutputComponents},
2894*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_OUTPUT_VERTICES, (int)program->getGeometryNumOutputVertices()},
2895*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, totalOutputComponents},
2896*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, usage.numSamplers},
2897*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers},
2898*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_ATOMIC_COUNTERS, usage.numAtomicCounters},
2899*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_IMAGE_UNIFORMS, usage.numImages},
2900*35238bceSAndroid Build Coastguard Worker             {GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks},
2901*35238bceSAndroid Build Coastguard Worker         };
2902*35238bceSAndroid Build Coastguard Worker 
2903*35238bceSAndroid Build Coastguard Worker         bool allOk = true;
2904*35238bceSAndroid Build Coastguard Worker 
2905*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "Geometry shader:" << tcu::TestLog::EndMessage;
2906*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
2907*35238bceSAndroid Build Coastguard Worker             allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
2908*35238bceSAndroid Build Coastguard Worker 
2909*35238bceSAndroid Build Coastguard Worker         return allOk;
2910*35238bceSAndroid Build Coastguard Worker     }
2911*35238bceSAndroid Build Coastguard Worker 
2912*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_CONTROL:
2913*35238bceSAndroid Build Coastguard Worker     {
2914*35238bceSAndroid Build Coastguard Worker         const int totalOutputComponents = program->getTessellationNumOutputPatchVertices() * usage.numOutputComponents +
2915*35238bceSAndroid Build Coastguard Worker                                           usage.numPatchOutputComponents;
2916*35238bceSAndroid Build Coastguard Worker         const struct
2917*35238bceSAndroid Build Coastguard Worker         {
2918*35238bceSAndroid Build Coastguard Worker             glw::GLenum pname;
2919*35238bceSAndroid Build Coastguard Worker             int usage;
2920*35238bceSAndroid Build Coastguard Worker         } restrictions[] = {
2921*35238bceSAndroid Build Coastguard Worker             {GL_MAX_PATCH_VERTICES, (int)program->getTessellationNumOutputPatchVertices()},
2922*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_PATCH_COMPONENTS, usage.numPatchOutputComponents},
2923*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents},
2924*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, usage.numUniformBlocks},
2925*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, usage.numInputComponents},
2926*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, usage.numOutputComponents},
2927*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS, totalOutputComponents},
2928*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS, usage.numSamplers},
2929*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers},
2930*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, usage.numAtomicCounters},
2931*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, usage.numImages},
2932*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks},
2933*35238bceSAndroid Build Coastguard Worker         };
2934*35238bceSAndroid Build Coastguard Worker 
2935*35238bceSAndroid Build Coastguard Worker         bool allOk = true;
2936*35238bceSAndroid Build Coastguard Worker 
2937*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "Tessellation control shader:" << tcu::TestLog::EndMessage;
2938*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
2939*35238bceSAndroid Build Coastguard Worker             allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
2940*35238bceSAndroid Build Coastguard Worker 
2941*35238bceSAndroid Build Coastguard Worker         return allOk;
2942*35238bceSAndroid Build Coastguard Worker     }
2943*35238bceSAndroid Build Coastguard Worker 
2944*35238bceSAndroid Build Coastguard Worker     case glu::SHADERTYPE_TESSELLATION_EVALUATION:
2945*35238bceSAndroid Build Coastguard Worker     {
2946*35238bceSAndroid Build Coastguard Worker         const struct
2947*35238bceSAndroid Build Coastguard Worker         {
2948*35238bceSAndroid Build Coastguard Worker             glw::GLenum pname;
2949*35238bceSAndroid Build Coastguard Worker             int usage;
2950*35238bceSAndroid Build Coastguard Worker         } restrictions[] = {
2951*35238bceSAndroid Build Coastguard Worker             {GL_MAX_PATCH_VERTICES, (int)program->getTessellationNumOutputPatchVertices()},
2952*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_PATCH_COMPONENTS, usage.numPatchInputComponents},
2953*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents},
2954*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, usage.numUniformBlocks},
2955*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, usage.numInputComponents},
2956*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, usage.numOutputComponents},
2957*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS, usage.numSamplers},
2958*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers},
2959*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, usage.numAtomicCounters},
2960*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, usage.numImages},
2961*35238bceSAndroid Build Coastguard Worker             {GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks},
2962*35238bceSAndroid Build Coastguard Worker         };
2963*35238bceSAndroid Build Coastguard Worker 
2964*35238bceSAndroid Build Coastguard Worker         bool allOk = true;
2965*35238bceSAndroid Build Coastguard Worker 
2966*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "Tessellation evaluation shader:" << tcu::TestLog::EndMessage;
2967*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
2968*35238bceSAndroid Build Coastguard Worker             allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
2969*35238bceSAndroid Build Coastguard Worker 
2970*35238bceSAndroid Build Coastguard Worker         return allOk;
2971*35238bceSAndroid Build Coastguard Worker     }
2972*35238bceSAndroid Build Coastguard Worker 
2973*35238bceSAndroid Build Coastguard Worker     default:
2974*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
2975*35238bceSAndroid Build Coastguard Worker         return false;
2976*35238bceSAndroid Build Coastguard Worker     }
2977*35238bceSAndroid Build Coastguard Worker }
2978*35238bceSAndroid Build Coastguard Worker 
checkProgramCombinedResourceUsage(const ProgramInterfaceDefinition::Program * program,const glw::Functions & gl,tcu::TestLog & log)2979*35238bceSAndroid Build Coastguard Worker static bool checkProgramCombinedResourceUsage(const ProgramInterfaceDefinition::Program *program,
2980*35238bceSAndroid Build Coastguard Worker                                               const glw::Functions &gl, tcu::TestLog &log)
2981*35238bceSAndroid Build Coastguard Worker {
2982*35238bceSAndroid Build Coastguard Worker     const ProgramInterfaceDefinition::ProgramResourceUsage usage = getCombinedProgramResourceUsage(program);
2983*35238bceSAndroid Build Coastguard Worker 
2984*35238bceSAndroid Build Coastguard Worker     const struct
2985*35238bceSAndroid Build Coastguard Worker     {
2986*35238bceSAndroid Build Coastguard Worker         glw::GLenum pname;
2987*35238bceSAndroid Build Coastguard Worker         int usage;
2988*35238bceSAndroid Build Coastguard Worker     } restrictions[] = {
2989*35238bceSAndroid Build Coastguard Worker         {GL_MAX_UNIFORM_BUFFER_BINDINGS, usage.uniformBufferMaxBinding + 1},
2990*35238bceSAndroid Build Coastguard Worker         {GL_MAX_UNIFORM_BLOCK_SIZE, usage.uniformBufferMaxSize},
2991*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_UNIFORM_BLOCKS, usage.numUniformBlocks},
2992*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, usage.numCombinedVertexUniformComponents},
2993*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, usage.numCombinedFragmentUniformComponents},
2994*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, usage.numCombinedGeometryUniformComponents},
2995*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS, usage.numCombinedTessControlUniformComponents},
2996*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS, usage.numCombinedTessEvalUniformComponents},
2997*35238bceSAndroid Build Coastguard Worker         {GL_MAX_VARYING_COMPONENTS, usage.numVaryingComponents},
2998*35238bceSAndroid Build Coastguard Worker         {GL_MAX_VARYING_VECTORS, usage.numVaryingVectors},
2999*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, usage.numCombinedSamplers},
3000*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, usage.numCombinedOutputResources},
3001*35238bceSAndroid Build Coastguard Worker         {GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, usage.atomicCounterBufferMaxBinding + 1},
3002*35238bceSAndroid Build Coastguard Worker         {GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, usage.atomicCounterBufferMaxSize},
3003*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers},
3004*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_ATOMIC_COUNTERS, usage.numAtomicCounters},
3005*35238bceSAndroid Build Coastguard Worker         {GL_MAX_IMAGE_UNITS, usage.maxImageBinding + 1},
3006*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_IMAGE_UNIFORMS, usage.numCombinedImages},
3007*35238bceSAndroid Build Coastguard Worker         {GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, usage.shaderStorageBufferMaxBinding + 1},
3008*35238bceSAndroid Build Coastguard Worker         {GL_MAX_SHADER_STORAGE_BLOCK_SIZE, usage.shaderStorageBufferMaxSize},
3009*35238bceSAndroid Build Coastguard Worker         {GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks},
3010*35238bceSAndroid Build Coastguard Worker         {GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, usage.numXFBInterleavedComponents},
3011*35238bceSAndroid Build Coastguard Worker         {GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, usage.numXFBSeparateAttribs},
3012*35238bceSAndroid Build Coastguard Worker         {GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, usage.numXFBSeparateComponents},
3013*35238bceSAndroid Build Coastguard Worker         {GL_MAX_DRAW_BUFFERS, usage.fragmentOutputMaxBinding + 1},
3014*35238bceSAndroid Build Coastguard Worker     };
3015*35238bceSAndroid Build Coastguard Worker 
3016*35238bceSAndroid Build Coastguard Worker     bool allOk = true;
3017*35238bceSAndroid Build Coastguard Worker 
3018*35238bceSAndroid Build Coastguard Worker     log << tcu::TestLog::Message << "Program combined:" << tcu::TestLog::EndMessage;
3019*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx)
3020*35238bceSAndroid Build Coastguard Worker         allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log);
3021*35238bceSAndroid Build Coastguard Worker 
3022*35238bceSAndroid Build Coastguard Worker     return allOk;
3023*35238bceSAndroid Build Coastguard Worker }
3024*35238bceSAndroid Build Coastguard Worker 
checkProgramResourceUsage(const ProgramInterfaceDefinition::Program * program,const glw::Functions & gl,tcu::TestLog & log)3025*35238bceSAndroid Build Coastguard Worker void checkProgramResourceUsage(const ProgramInterfaceDefinition::Program *program, const glw::Functions &gl,
3026*35238bceSAndroid Build Coastguard Worker                                tcu::TestLog &log)
3027*35238bceSAndroid Build Coastguard Worker {
3028*35238bceSAndroid Build Coastguard Worker     bool limitExceeded = false;
3029*35238bceSAndroid Build Coastguard Worker 
3030*35238bceSAndroid Build Coastguard Worker     for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
3031*35238bceSAndroid Build Coastguard Worker         limitExceeded |= !checkShaderResourceUsage(program, program->getShaders()[shaderNdx], gl, log);
3032*35238bceSAndroid Build Coastguard Worker 
3033*35238bceSAndroid Build Coastguard Worker     limitExceeded |= !checkProgramCombinedResourceUsage(program, gl, log);
3034*35238bceSAndroid Build Coastguard Worker 
3035*35238bceSAndroid Build Coastguard Worker     if (limitExceeded)
3036*35238bceSAndroid Build Coastguard Worker     {
3037*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message << "One or more resource limits exceeded" << tcu::TestLog::EndMessage;
3038*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("one or more resource limits exceeded");
3039*35238bceSAndroid Build Coastguard Worker     }
3040*35238bceSAndroid Build Coastguard Worker }
3041*35238bceSAndroid Build Coastguard Worker 
3042*35238bceSAndroid Build Coastguard Worker } // namespace Functional
3043*35238bceSAndroid Build Coastguard Worker } // namespace gles31
3044*35238bceSAndroid Build Coastguard Worker } // namespace deqp
3045