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