13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Opaque type (sampler, buffer, atomic counter, ...) indexing tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \todo [2014-03-05 pyry] Extend with following:
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *  + sampler: different filtering modes, multiple sizes, incomplete textures
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *  + SSBO: write, atomic op, unsized array .length()
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fOpaqueTypeIndexingTests.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTexture.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderUtil.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluProgramInterfaceQuery.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::ShaderExecUtil;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glu;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TextureFormat;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef de::UniquePtr<ShaderExecutor> ShaderExecutorPtr;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum IndexExprType
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INDEX_EXPR_TYPE_CONST_LITERAL	= 0,
718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	INDEX_EXPR_TYPE_CONST_EXPRESSION,
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INDEX_EXPR_TYPE_UNIFORM,
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INDEX_EXPR_TYPE_DYNAMIC_UNIFORM,
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INDEX_EXPR_TYPE_LAST
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum TextureType
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TEXTURE_TYPE_1D = 0,
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TEXTURE_TYPE_2D,
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TEXTURE_TYPE_CUBE,
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TEXTURE_TYPE_2D_ARRAY,
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TEXTURE_TYPE_3D,
85fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	TEXTURE_TYPE_CUBE_ARRAY,
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TEXTURE_TYPE_LAST
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void declareUniformIndexVars (std::ostream& str, const char* varPrefix, int numVars)
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < numVars; varNdx++)
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		str << "uniform highp int " << varPrefix << varNdx << ";\n";
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void uploadUniformIndices (const glw::Functions& gl, deUint32 program, const char* varPrefix, int numIndices, const int* indices)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int varNdx = 0; varNdx < numIndices; varNdx++)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string	varName		= varPrefix + de::toString(varNdx);
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		loc			= gl.getUniformLocation(program, varName.c_str());
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK_MSG(loc >= 0, ("No location assigned for uniform '" + varName + "'").c_str());
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1i(loc, indices[varNdx]);
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T>
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic T maxElement (const std::vector<T>& elements)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T maxElem = elements[0];
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t ndx = 1; ndx < elements.size(); ndx++)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		maxElem = de::max(maxElem, elements[ndx]);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return maxElem;
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic TextureType getTextureType (glu::DataType samplerType)
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (samplerType)
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_1D:
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_1D:
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_1D:
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_1D_SHADOW:
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TEXTURE_TYPE_1D;
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D:
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_2D:
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_2D:
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D_SHADOW:
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TEXTURE_TYPE_2D;
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_CUBE:
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_CUBE:
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_CUBE:
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_CUBE_SHADOW:
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TEXTURE_TYPE_CUBE;
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D_ARRAY:
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TEXTURE_TYPE_2D_ARRAY;
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_3D:
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_3D:
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_3D:
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TEXTURE_TYPE_3D;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
152fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_SAMPLER_CUBE_ARRAY:
153fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW:
154fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
155fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
156fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			return TEXTURE_TYPE_CUBE_ARRAY;
157fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
159fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_THROW(InternalError, "Invalid sampler type");
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isShadowSampler (glu::DataType samplerType)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return samplerType == glu::TYPE_SAMPLER_1D_SHADOW		||
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   samplerType == glu::TYPE_SAMPLER_2D_SHADOW		||
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   samplerType == glu::TYPE_SAMPLER_2D_ARRAY_SHADOW	||
168fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		   samplerType == glu::TYPE_SAMPLER_CUBE_SHADOW		||
169fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		   samplerType == glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW;
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::DataType getSamplerOutputType (glu::DataType samplerType)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (samplerType)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_1D:
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D:
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_CUBE:
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D_ARRAY:
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_3D:
181fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_SAMPLER_CUBE_ARRAY:
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return glu::TYPE_FLOAT_VEC4;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_1D_SHADOW:
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D_SHADOW:
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_CUBE_SHADOW:
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
188fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW:
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return glu::TYPE_FLOAT;
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_1D:
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_2D:
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_CUBE:
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT_SAMPLER_3D:
196fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return glu::TYPE_INT_VEC4;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_1D:
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_2D:
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_CUBE:
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT_SAMPLER_3D:
204fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return glu::TYPE_UINT_VEC4;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
208fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_THROW(InternalError, "Invalid sampler type");
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::TextureFormat getSamplerTextureFormat (glu::DataType samplerType)
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		outType			= getSamplerOutputType(samplerType);
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		outScalarType	= glu::getDataTypeScalarType(outType);
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (outScalarType)
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT:
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (isShadowSampler(samplerType))
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_INT:		return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8);
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_UINT:	return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8);
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
229fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_THROW(InternalError, "Invalid sampler type");
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::DataType getSamplerCoordType (glu::DataType samplerType)
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TextureType	texType		= getTextureType(samplerType);
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numCoords	= 0;
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (texType)
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
240fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_1D:			numCoords = 1;	break;
241fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_2D:			numCoords = 2;	break;
242fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_2D_ARRAY:		numCoords = 3;	break;
243fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_CUBE:			numCoords = 3;	break;
244fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_3D:			numCoords = 3;	break;
245fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_CUBE_ARRAY:	numCoords = 4;	break;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
247fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_THROW(InternalError, "Invalid texture type");
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
250fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	if (isShadowSampler(samplerType) && samplerType != TYPE_SAMPLER_CUBE_ARRAY_SHADOW)
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numCoords += 1;
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inRange(numCoords, 1, 4));
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numCoords == 1 ? glu::TYPE_FLOAT : glu::getDataTypeFloatVec(numCoords);
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getGLTextureTarget (TextureType texType)
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (texType)
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
262fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_1D:			return GL_TEXTURE_1D;
263fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_2D:			return GL_TEXTURE_2D;
264fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_2D_ARRAY:		return GL_TEXTURE_2D_ARRAY;
265fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_CUBE:			return GL_TEXTURE_CUBE_MAP;
266fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_3D:			return GL_TEXTURE_3D;
267fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_CUBE_ARRAY:	return GL_TEXTURE_CUBE_MAP_ARRAY;
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
269fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_THROW(InternalError, "Invalid texture type");
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void setupTexture (const glw::Functions&	gl,
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  deUint32				texture,
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  glu::DataType			samplerType,
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  tcu::TextureFormat	texFormat,
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const void*			color)
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TextureType			texType		= getTextureType(samplerType);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				texTarget	= getGLTextureTarget(texType);
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				intFormat	= glu::getInternalFormat(texFormat);
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::TransferFormat	transferFmt	= glu::getTransferFormat(texFormat);
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2014-03-04 pyry] Use larger than 1x1 textures?
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindTexture(texTarget, texture);
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (texType)
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TEXTURE_TYPE_1D:
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.texStorage1D(texTarget, 1, intFormat, 1);
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.texSubImage1D(texTarget, 0, 0, 1, transferFmt.format, transferFmt.dataType, color);
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TEXTURE_TYPE_2D:
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.texStorage2D(texTarget, 1, intFormat, 1, 1);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.texSubImage2D(texTarget, 0, 0, 0, 1, 1, transferFmt.format, transferFmt.dataType, color);
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TEXTURE_TYPE_2D_ARRAY:
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TEXTURE_TYPE_3D:
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.texStorage3D(texTarget, 1, intFormat, 1, 1, 1);
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.texSubImage3D(texTarget, 0, 0, 0, 0, 1, 1, 1, transferFmt.format, transferFmt.dataType, color);
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
306fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		case TEXTURE_TYPE_CUBE_ARRAY:
307fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			gl.texStorage3D(texTarget, 1, intFormat, 1, 1, 6);
308fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			for (int zoffset = 0; zoffset < 6; ++zoffset)
309fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
310fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos					gl.texSubImage3D(texTarget, 0, 0, 0, zoffset, 1, 1, 1, transferFmt.format, transferFmt.dataType, color);
311fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			break;
312fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TEXTURE_TYPE_CUBE:
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.texStorage2D(texTarget, 1, intFormat, 1, 1);
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.texSubImage2D(glu::getGLCubeFace((tcu::CubeFace)face), 0, 0, 0, 1, 1, transferFmt.format, transferFmt.dataType, color);
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
320fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_THROW(InternalError, "Invalid texture type");
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.texParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.texParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isShadowSampler(samplerType))
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.texParameteri(texTarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture setup failed");
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SamplerIndexingCase : public TestCase
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							SamplerIndexingCase			(Context& context, const char* name, const char* description, glu::ShaderType shaderType, glu::DataType samplerType, IndexExprType indexExprType);
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~SamplerIndexingCase		(void);
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init						(void);
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate						(void);
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							SamplerIndexingCase			(const SamplerIndexingCase&);
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SamplerIndexingCase&	operator=					(const SamplerIndexingCase&);
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
345fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	void					getShaderSpec				(ShaderSpec* spec, int numSamplers, int numLookups, const int* lookupIndices, const RenderContext& renderContext) const;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ShaderType	m_shaderType;
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::DataType		m_samplerType;
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const IndexExprType		m_indexExprType;
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySamplerIndexingCase::SamplerIndexingCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType, glu::DataType samplerType, IndexExprType indexExprType)
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, name, description)
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shaderType		(shaderType)
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_samplerType		(samplerType)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_indexExprType	(indexExprType)
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3603c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySamplerIndexingCase::~SamplerIndexingCase (void)
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SamplerIndexingCase::init (void)
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
366fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
367fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	{
368fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_shaderType == SHADERTYPE_GEOMETRY)
369fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
370fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"),
371fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_geometry_shader extension is required to run geometry shader tests.");
372fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
373fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_shaderType == SHADERTYPE_TESSELLATION_CONTROL || m_shaderType == SHADERTYPE_TESSELLATION_EVALUATION)
374fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
375fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"),
376fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_tessellation_shader extension is required to run tessellation shader tests.");
377fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
378fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL && m_indexExprType != INDEX_EXPR_TYPE_CONST_EXPRESSION)
379fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
380fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_gpu_shader5"),
381fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_gpu_shader5 extension is required for dynamic indexing of sampler arrays.");
382b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi
383b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi		if (m_samplerType == TYPE_SAMPLER_CUBE_ARRAY
3841d463a0af03170dc5306552bb9128fc782e9866dMika Isojärvi			|| m_samplerType == TYPE_SAMPLER_CUBE_ARRAY_SHADOW
3851d463a0af03170dc5306552bb9128fc782e9866dMika Isojärvi			|| m_samplerType == TYPE_INT_SAMPLER_CUBE_ARRAY
3861d463a0af03170dc5306552bb9128fc782e9866dMika Isojärvi			|| m_samplerType == TYPE_UINT_SAMPLER_CUBE_ARRAY)
387b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi		{
388b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi			TCU_CHECK_AND_THROW(NotSupportedError,
389b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi				m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array"),
390b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi				"GL_EXT_texture_cube_map_array extension is required for cube map arrays.");
391b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi		}
392fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	}
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
395fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulosvoid SamplerIndexingCase::getShaderSpec (ShaderSpec* spec, int numSamplers, int numLookups, const int* lookupIndices, const RenderContext& renderContext) const
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			samplersName	= "sampler";
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			coordsName		= "coords";
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			indicesPrefix	= "index";
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			resultPrefix	= "result";
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DataType		coordType		= getSamplerCoordType(m_samplerType);
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DataType		outType			= getSamplerOutputType(m_samplerType);
403cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool			supportsES32	= contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
404fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	std::ostringstream	global;
405fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	std::ostringstream	code;
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec->inputs.push_back(Symbol(coordsName, VarType(coordType, PRECISION_HIGHP)));
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
409cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL && m_indexExprType != INDEX_EXPR_TYPE_CONST_EXPRESSION)
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		global << "#extension GL_EXT_gpu_shader5 : require\n";
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
412cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32
4131d463a0af03170dc5306552bb9128fc782e9866dMika Isojärvi		&& (m_samplerType == TYPE_SAMPLER_CUBE_ARRAY
4141d463a0af03170dc5306552bb9128fc782e9866dMika Isojärvi			|| m_samplerType == TYPE_SAMPLER_CUBE_ARRAY_SHADOW
4151d463a0af03170dc5306552bb9128fc782e9866dMika Isojärvi			|| m_samplerType == TYPE_INT_SAMPLER_CUBE_ARRAY
4161d463a0af03170dc5306552bb9128fc782e9866dMika Isojärvi			|| m_samplerType == TYPE_UINT_SAMPLER_CUBE_ARRAY))
417b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi	{
418b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi		global << "#extension GL_EXT_texture_cube_map_array: require\n";
419b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi	}
420b6f1116e0be4af1657a382fcce1fcea0d21cf416Mika Isojärvi
4218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
4228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		global << "const highp int indexBase = 1;\n";
4238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	global <<
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform highp " << getDataTypeName(m_samplerType) << " " << samplersName << "[" << numSamplers << "];\n";
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string varName = indicesPrefix + de::toString(lookupNdx);
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			spec->inputs.push_back(Symbol(varName, VarType(TYPE_INT, PRECISION_HIGHP)));
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		declareUniformIndexVars(global, indicesPrefix, numLookups);
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string varName = resultPrefix + de::toString(lookupNdx);
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		spec->outputs.push_back(Symbol(varName, VarType(outType, PRECISION_HIGHP)));
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		code << resultPrefix << "" << lookupNdx << " = texture(" << samplersName << "[";
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL)
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code << lookupIndices[lookupNdx];
4508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
4518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			code << "indexBase + " << (lookupIndices[lookupNdx]-1);
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code << indicesPrefix << lookupNdx;
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
455fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
456fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		code << "], " << coordsName << (m_samplerType == TYPE_SAMPLER_CUBE_ARRAY_SHADOW ? ", 0.0" : "") << ");\n";
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
459cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	spec->version				= supportsES32 ? GLSL_VERSION_320_ES : GLSL_VERSION_310_ES;
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec->globalDeclarations	= global.str();
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec->source				= code.str();
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void fillTextureData (const tcu::PixelBufferAccess& access, de::Random& rnd)
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(access.getHeight() == 1 && access.getDepth() == 1);
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (access.getFormat().order == TextureFormat::D)
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Texture uses odd values, lookup even values to avoid precision issues.
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float values[] = { 0.1f, 0.3f, 0.5f, 0.7f, 0.9f };
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < access.getWidth(); ndx++)
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			access.setPixDepth(rnd.choose<float>(DE_ARRAY_BEGIN(values), DE_ARRAY_END(values)), ndx, 0);
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK_INTERNAL(access.getFormat().order == TextureFormat::RGBA && access.getFormat().getPixelSize() == 4);
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < access.getWidth(); ndx++)
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			*((deUint32*)access.getDataPtr() + ndx) = rnd.getUint32();
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4853c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySamplerIndexingCase::IterateResult SamplerIndexingCase::iterate (void)
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numInvocations		= 64;
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numSamplers			= 8;
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						numLookups			= 4;
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DataType					coordType			= getSamplerCoordType(m_samplerType);
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const DataType					outputType			= getSamplerOutputType(m_samplerType);
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TextureFormat				texFormat			= getSamplerTextureFormat(m_samplerType);
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						outLookupStride		= numInvocations*getDataTypeScalarSize(outputType);
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>						lookupIndices		(numLookups);
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>					coords;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>				outData;
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint8>					texData				(numSamplers * texFormat.getPixelSize());
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::PixelBufferAccess	refTexAccess		(texFormat, numSamplers, 1, 1, &texData[0]);
499fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderSpec						shaderSpec;
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random						rnd					(deInt32Hash(m_samplerType) ^ deInt32Hash(m_shaderType) ^ deInt32Hash(m_indexExprType));
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numLookups; ndx++)
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		lookupIndices[ndx] = rnd.getInt(0, numSamplers-1);
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
506fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	getShaderSpec(&shaderSpec, numSamplers, numLookups, &lookupIndices[0], m_context.getRenderContext());
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	coords.resize(numInvocations * getDataTypeScalarSize(coordType));
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
510fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	if (m_samplerType != TYPE_SAMPLER_CUBE_ARRAY_SHADOW && isShadowSampler(m_samplerType))
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Use different comparison value per invocation.
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Texture uses odd values, comparison even values.
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	numCoordComps	= getDataTypeScalarSize(coordType);
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float	cmpValues[]		= { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f };
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			coords[invocationNdx*numCoordComps + (numCoordComps-1)] = rnd.choose<float>(DE_ARRAY_BEGIN(cmpValues), DE_ARRAY_END(cmpValues));
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fillTextureData(refTexAccess, rnd);
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	outData.resize(numLookups*outLookupStride);
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const RenderContext&	renderCtx		= m_context.getRenderContext();
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions&	gl				= renderCtx.getFunctions();
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderExecutorPtr		executor		(createExecutor(m_context.getRenderContext(), m_shaderType, shaderSpec));
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TextureVector			textures		(renderCtx, numSamplers);
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			inputs;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			outputs;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<int>				expandedIndices;
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				maxIndex		= maxElement(lookupIndices);
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *executor;
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!executor->isOk())
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("Compile failed");
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		executor->useProgram();
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2014-03-05 pyry] Do we want to randomize tex unit assignments?
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int samplerNdx = 0; samplerNdx < numSamplers; samplerNdx++)
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string	samplerName	= string("sampler[") + de::toString(samplerNdx) + "]";
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		samplerLoc	= gl.getUniformLocation(executor->getProgram(), samplerName.c_str());
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (samplerNdx > maxIndex && samplerLoc < 0)
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue; // Unused uniform eliminated by compiler
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK_MSG(samplerLoc >= 0, (string("No location for uniform '") + samplerName + "' found").c_str());
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.activeTexture(GL_TEXTURE0 + samplerNdx);
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			setupTexture(gl, textures[samplerNdx], m_samplerType, texFormat, &texData[samplerNdx*texFormat.getPixelSize()]);
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.uniform1i(samplerLoc, samplerNdx);
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		inputs.push_back(&coords[0]);
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			expandedIndices.resize(numInvocations * lookupIndices.size());
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int invNdx = 0; invNdx < numInvocations; invNdx++)
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					expandedIndices[lookupNdx*numInvocations + invNdx] = lookupIndices[lookupNdx];
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				inputs.push_back(&expandedIndices[lookupNdx*numInvocations]);
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			uploadUniformIndices(gl, executor->getProgram(), "index", numLookups, &lookupIndices[0]);
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			outputs.push_back(&outData[outLookupStride*lookupNdx]);
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Setup failed");
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		executor->execute(numInvocations, &inputs[0], &outputs[0]);
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isShadowSampler(m_samplerType))
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Sampler	refSampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, false /* non-normalized */,
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 tcu::Sampler::COMPAREMODE_LESS);
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numCoordComps	= getDataTypeScalarSize(coordType);
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK_INTERNAL(getDataTypeScalarSize(outputType) == 1);
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Each invocation may have different results.
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	coord	= coords[invocationNdx*numCoordComps + (numCoordComps-1)];
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		texNdx		= lookupIndices[lookupNdx];
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		result		= *((const float*)(const deUint8*)&outData[lookupNdx*outLookupStride + invocationNdx]);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		reference	= refTexAccess.sample2DCompare(refSampler, tcu::Sampler::NEAREST, coord, (float)texNdx, 0.0f, tcu::IVec3(0));
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (de::abs(result-reference) > 0.005f)
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "ERROR: at invocation " << invocationNdx << ", lookup " << lookupNdx << ": expected "
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << reference << ", got " << result
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid lookup result");
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK_INTERNAL(getDataTypeScalarSize(outputType) == 4);
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Validate results from first invocation
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		texNdx	= lookupIndices[lookupNdx];
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8*	resPtr	= (const deUint8*)&outData[lookupNdx*outLookupStride];
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool			isOk;
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (outputType == TYPE_FLOAT_VEC4)
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float			threshold		= 1.0f / 256.0f;
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec4		reference		= refTexAccess.getPixel(texNdx, 0);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float*		floatPtr		= (const float*)resPtr;
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec4		result			(floatPtr[0], floatPtr[1], floatPtr[2], floatPtr[3]);
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = boolAll(lessThanEqual(abs(reference-result), tcu::Vec4(threshold)));
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "ERROR: at lookup " << lookupNdx << ": expected "
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << reference << ", got " << result
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::UVec4	reference		= refTexAccess.getPixelUint(texNdx, 0);
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32*		uintPtr			= (const deUint32*)resPtr;
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::UVec4	result			(uintPtr[0], uintPtr[1], uintPtr[2], uintPtr[3]);
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				isOk = boolAll(equal(reference, result));
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "ERROR: at lookup " << lookupNdx << ": expected "
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << reference << ", got " << result
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!isOk && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid lookup result");
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Check results of other invocations against first one
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int invocationNdx = 1; invocationNdx < numInvocations; invocationNdx++)
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int lookupNdx = 0; lookupNdx < numLookups; lookupNdx++)
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32*		refPtr		= &outData[lookupNdx*outLookupStride];
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32*		resPtr		= refPtr + invocationNdx*4;
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool				isOk		= true;
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int ndx = 0; ndx < 4; ndx++)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					isOk = isOk && (refPtr[ndx] == resPtr[ndx]);
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "ERROR: invocation " << invocationNdx << " result "
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << tcu::formatArray(tcu::Format::HexIterator<deUint32>(resPtr), tcu::Format::HexIterator<deUint32>(resPtr+4))
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << " for lookup " << lookupNdx << " doesn't match result from first invocation "
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << tcu::formatArray(tcu::Format::HexIterator<deUint32>(refPtr), tcu::Format::HexIterator<deUint32>(refPtr+4))
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Inconsistent lookup results");
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BlockArrayIndexingCase : public TestCase
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum BlockType
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BLOCKTYPE_UNIFORM = 0,
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BLOCKTYPE_BUFFER,
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BLOCKTYPE_LAST
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								BlockArrayIndexingCase		(Context& context, const char* name, const char* description, BlockType blockType, IndexExprType indexExprType, ShaderType shaderType);
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~BlockArrayIndexingCase		(void);
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init						(void);
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate						(void);
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								BlockArrayIndexingCase		(const BlockArrayIndexingCase&);
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BlockArrayIndexingCase&		operator=					(const BlockArrayIndexingCase&);
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
715fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	void						getShaderSpec				(ShaderSpec* spec, int numInstances, int numReads, const int* readIndices, const RenderContext& renderContext) const;
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const BlockType				m_blockType;
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const IndexExprType			m_indexExprType;
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const ShaderType			m_shaderType;
7208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
7218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int					m_numInstances;
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBlockArrayIndexingCase::BlockArrayIndexingCase (Context& context, const char* name, const char* description, BlockType blockType, IndexExprType indexExprType, ShaderType shaderType)
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, name, description)
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_blockType		(blockType)
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_indexExprType	(indexExprType)
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shaderType		(shaderType)
7298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	, m_numInstances	(4)
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBlockArrayIndexingCase::~BlockArrayIndexingCase (void)
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid BlockArrayIndexingCase::init (void)
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
739fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
740fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	{
741fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_shaderType == SHADERTYPE_GEOMETRY)
742fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
743fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"),
744fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_geometry_shader extension is required to run geometry shader tests.");
745fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
746fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_shaderType == SHADERTYPE_TESSELLATION_CONTROL || m_shaderType == SHADERTYPE_TESSELLATION_EVALUATION)
747fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
748fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"),
749fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_tessellation_shader extension is required to run tessellation shader tests.");
750fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
751fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL && m_indexExprType != INDEX_EXPR_TYPE_CONST_EXPRESSION)
752fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
753fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_gpu_shader5"),
754fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_gpu_shader5 extension is required for dynamic indexing of interface blocks.");
755fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	}
7568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
7578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (m_blockType == BLOCKTYPE_BUFFER)
7588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
7598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const deUint32 limitPnames[] =
7608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
7618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,
7628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,
7638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
7648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,
7658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,
7668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS
7678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		};
7688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
7698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
7708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		int						maxBlocks	= 0;
7718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
7728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		gl.getIntegerv(limitPnames[m_shaderType], &maxBlocks);
7738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
7748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
775cd2b79270f855a8ed8cce24c51d51f0b005e3854Mika Isojärvi		if (maxBlocks < 2 + m_numInstances)
7768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			throw tcu::NotSupportedError("Not enough shader storage blocks supported for shader type");
7778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
780fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulosvoid BlockArrayIndexingCase::getShaderSpec (ShaderSpec* spec, int numInstances, int numReads, const int* readIndices, const RenderContext& renderContext) const
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			binding			= 2;
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			blockName		= "Block";
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			instanceName	= "block";
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			indicesPrefix	= "index";
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			resultPrefix	= "result";
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			interfaceName	= m_blockType == BLOCKTYPE_UNIFORM ? "uniform" : "buffer";
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			layout			= m_blockType == BLOCKTYPE_UNIFORM ? "std140" : "std430";
789cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool			supportsES32	= contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
790fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	std::ostringstream	global;
791fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	std::ostringstream	code;
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL && m_indexExprType != INDEX_EXPR_TYPE_CONST_EXPRESSION)
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		global << "#extension GL_EXT_gpu_shader5 : require\n";
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
7978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		global << "const highp int indexBase = 1;\n";
7988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	global <<
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"layout(" << layout << ", binding = " << binding << ") " << interfaceName << " " << blockName << "\n"
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	uint value;\n"
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"} " << instanceName << "[" << numInstances << "];\n";
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < numReads; readNdx++)
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string varName = indicesPrefix + de::toString(readNdx);
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			spec->inputs.push_back(Symbol(varName, VarType(TYPE_INT, PRECISION_HIGHP)));
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		declareUniformIndexVars(global, indicesPrefix, numReads);
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int readNdx = 0; readNdx < numReads; readNdx++)
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string varName = resultPrefix + de::toString(readNdx);
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		spec->outputs.push_back(Symbol(varName, VarType(TYPE_UINT, PRECISION_HIGHP)));
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int readNdx = 0; readNdx < numReads; readNdx++)
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		code << resultPrefix << readNdx << " = " << instanceName << "[";
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL)
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code << readIndices[readNdx];
8288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
8298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			code << "indexBase + " << (readIndices[readNdx]-1);
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code << indicesPrefix << readNdx;
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		code << "].value;\n";
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
836cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	spec->version				= supportsES32 ? GLSL_VERSION_320_ES : GLSL_VERSION_310_ES;
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec->globalDeclarations	= global.str();
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec->source				= code.str();
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryBlockArrayIndexingCase::IterateResult BlockArrayIndexingCase::iterate (void)
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numInvocations		= 32;
8448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int			numInstances		= m_numInstances;
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numReads			= 4;
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>			readIndices			(numReads);
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>	inValues			(numInstances);
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>	outValues			(numInvocations*numReads);
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderSpec			shaderSpec;
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random			rnd					(deInt32Hash(m_shaderType) ^ deInt32Hash(m_blockType) ^ deInt32Hash(m_indexExprType));
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int readNdx = 0; readNdx < numReads; readNdx++)
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		readIndices[readNdx] = rnd.getInt(0, numInstances-1);
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		inValues[instanceNdx] = rnd.getUint32();
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
858fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	getShaderSpec(&shaderSpec, numInstances, numReads, &readIndices[0], m_context.getRenderContext());
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const RenderContext&	renderCtx		= m_context.getRenderContext();
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glw::Functions&	gl				= renderCtx.getFunctions();
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int				baseBinding		= 2;
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BufferVector		buffers			(renderCtx, numInstances);
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32			bufTarget		= m_blockType == BLOCKTYPE_BUFFER ? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER;
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderExecutorPtr		shaderExecutor	(createExecutor(renderCtx, m_shaderType, shaderSpec));
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<int>				expandedIndices;
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			inputs;
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			outputs;
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *shaderExecutor;
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!shaderExecutor->isOk())
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("Compile failed");
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shaderExecutor->useProgram();
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(bufTarget, buffers[instanceNdx]);
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bufferData(bufTarget, (glw::GLsizeiptr)sizeof(deUint32), &inValues[instanceNdx], GL_STATIC_DRAW);
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBufferBase(bufTarget, baseBinding+instanceNdx, buffers[instanceNdx]);
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			expandedIndices.resize(numInvocations * readIndices.size());
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int readNdx = 0; readNdx < numReads; readNdx++)
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int* dst = &expandedIndices[numInvocations*readNdx];
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill(dst, dst+numInvocations, readIndices[readNdx]);
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int readNdx = 0; readNdx < numReads; readNdx++)
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				inputs.push_back(&expandedIndices[readNdx*numInvocations]);
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			uploadUniformIndices(gl, shaderExecutor->getProgram(), "index", numReads, &readIndices[0]);
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < numReads; readNdx++)
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			outputs.push_back(&outValues[readNdx*numInvocations]);
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Setup failed");
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shaderExecutor->execute(numInvocations, inputs.empty() ? DE_NULL : &inputs[0], &outputs[0]);
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int readNdx = 0; readNdx < numReads; readNdx++)
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	refValue	= inValues[readIndices[readNdx]];
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	resValue	= outValues[readNdx*numInvocations + invocationNdx];
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (refValue != resValue)
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "ERROR: at invocation " << invocationNdx
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   << ", read " << readNdx << ": expected "
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   << tcu::toHex(refValue) << ", got " << tcu::toHex(resValue)
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   << TestLog::EndMessage;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid result value");
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AtomicCounterIndexingCase : public TestCase
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								AtomicCounterIndexingCase		(Context& context, const char* name, const char* description, IndexExprType indexExprType, ShaderType shaderType);
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~AtomicCounterIndexingCase		(void);
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init							(void);
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate							(void);
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								AtomicCounterIndexingCase		(const AtomicCounterIndexingCase&);
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AtomicCounterIndexingCase&	operator=						(const AtomicCounterIndexingCase&);
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
947fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	void						getShaderSpec					(ShaderSpec* spec, int numCounters, int numOps, const int* opIndices, const RenderContext& renderContext) const;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const IndexExprType			m_indexExprType;
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ShaderType		m_shaderType;
951351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi	deInt32						m_numCounters;
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9543c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAtomicCounterIndexingCase::AtomicCounterIndexingCase (Context& context, const char* name, const char* description, IndexExprType indexExprType, ShaderType shaderType)
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, name, description)
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_indexExprType	(indexExprType)
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shaderType		(shaderType)
958351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi	, m_numCounters		(0)
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAtomicCounterIndexingCase::~AtomicCounterIndexingCase (void)
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
966351f82f2be0cd8818879c6c140eaa027aed0b848Mika IsojärvideUint32 getMaxAtomicCounterEnum (glu::ShaderType type)
967351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi{
968351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi	switch (type)
969351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi	{
970351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		case glu::SHADERTYPE_VERTEX:					return GL_MAX_VERTEX_ATOMIC_COUNTERS;
971351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		case glu::SHADERTYPE_FRAGMENT:					return GL_MAX_FRAGMENT_ATOMIC_COUNTERS;
972351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		case glu::SHADERTYPE_GEOMETRY:					return GL_MAX_GEOMETRY_ATOMIC_COUNTERS;
973351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		case glu::SHADERTYPE_COMPUTE:					return GL_MAX_COMPUTE_ATOMIC_COUNTERS;
974351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		case glu::SHADERTYPE_TESSELLATION_CONTROL:		return GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS;
975351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		case glu::SHADERTYPE_TESSELLATION_EVALUATION:	return GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS;
976351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi
977351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		default:
978351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi			DE_FATAL("Unknown shader type");
979351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi			return -1;
980351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi	}
981351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi}
982351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid AtomicCounterIndexingCase::init (void)
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
985fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
986fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	{
987fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_shaderType == SHADERTYPE_GEOMETRY)
988fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
989fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"),
990fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_geometry_shader extension is required to run geometry shader tests.");
991fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
992fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_shaderType == SHADERTYPE_TESSELLATION_CONTROL || m_shaderType == SHADERTYPE_TESSELLATION_EVALUATION)
993fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
994fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"),
995fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_tessellation_shader extension is required to run tessellation shader tests.");
996fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos
997fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		if (m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL && m_indexExprType != INDEX_EXPR_TYPE_CONST_EXPRESSION)
998fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_CHECK_AND_THROW(NotSupportedError,
999fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				m_context.getContextInfo().isExtensionSupported("GL_EXT_gpu_shader5"),
1000fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos				"GL_EXT_gpu_shader5 extension is required for dynamic indexing of atomic counters.");
1001fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	}
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1004351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		m_context.getRenderContext().getFunctions().getIntegerv(getMaxAtomicCounterEnum(m_shaderType),
1005351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi																&m_numCounters);
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1007351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		if (m_numCounters < 1)
1008fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		{
1009fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			const string message =  "Atomic counters not supported in " + string(glu::getShaderTypeName(m_shaderType)) + " shader";
1010fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TCU_THROW(NotSupportedError, message.c_str());
1011fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		}
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1015fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulosvoid AtomicCounterIndexingCase::getShaderSpec (ShaderSpec* spec, int numCounters, int numOps, const int* opIndices, const RenderContext& renderContext) const
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			indicesPrefix	= "index";
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*			resultPrefix	= "result";
1019cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool			supportsES32	= contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
1020fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	std::ostringstream	global;
1021fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos	std::ostringstream	code;
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && m_indexExprType != INDEX_EXPR_TYPE_CONST_LITERAL && m_indexExprType != INDEX_EXPR_TYPE_CONST_EXPRESSION)
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		global << "#extension GL_EXT_gpu_shader5 : require\n";
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
10278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		global << "const highp int indexBase = 1;\n";
10288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	global <<
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"layout(binding = 0) uniform atomic_uint counter[" << numCounters << "];\n";
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int opNdx = 0; opNdx < numOps; opNdx++)
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string varName = indicesPrefix + de::toString(opNdx);
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			spec->inputs.push_back(Symbol(varName, VarType(TYPE_INT, PRECISION_HIGHP)));
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		declareUniformIndexVars(global, indicesPrefix, numOps);
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int opNdx = 0; opNdx < numOps; opNdx++)
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const string varName = resultPrefix + de::toString(opNdx);
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		spec->outputs.push_back(Symbol(varName, VarType(TYPE_UINT, PRECISION_HIGHP)));
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int opNdx = 0; opNdx < numOps; opNdx++)
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		code << resultPrefix << opNdx << " = atomicCounterIncrement(counter[";
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL)
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code << opIndices[opNdx];
10558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else if (m_indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
10568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			code << "indexBase + " << (opIndices[opNdx]-1);
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			code << indicesPrefix << opNdx;
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		code << "]);\n";
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	spec->version				= supportsES32 ? GLSL_VERSION_320_ES : GLSL_VERSION_310_ES;
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec->globalDeclarations	= global.str();
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	spec->source				= code.str();
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10683c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAtomicCounterIndexingCase::IterateResult AtomicCounterIndexingCase::iterate (void)
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const RenderContext&	renderCtx			= m_context.getRenderContext();
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl					= renderCtx.getFunctions();
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Buffer			counterBuffer		(renderCtx);
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numInvocations		= 32;
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				numOps				= 4;
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>				opIndices			(numOps);
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>		outValues			(numInvocations*numOps);
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShaderSpec				shaderSpec;
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random				rnd					(deInt32Hash(m_shaderType) ^ deInt32Hash(m_indexExprType));
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int opNdx = 0; opNdx < numOps; opNdx++)
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		opIndices[opNdx] = rnd.getInt(0, numOps-1);
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1084351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi	getShaderSpec(&shaderSpec, m_numCounters, numOps, &opIndices[0], m_context.getRenderContext());
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1087351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		const BufferVector		buffers			(renderCtx, m_numCounters);
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderExecutorPtr		shaderExecutor	(createExecutor(renderCtx, m_shaderType, shaderSpec));
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<int>				expandedIndices;
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			inputs;
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<void*>			outputs;
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *shaderExecutor;
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!shaderExecutor->isOk())
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("Compile failed");
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				bufSize		= getProgramResourceInt(gl, shaderExecutor->getProgram(), GL_ATOMIC_COUNTER_BUFFER, 0, GL_BUFFER_DATA_SIZE);
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				maxNdx		= maxElement(opIndices);
1101351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi			std::vector<deUint8>	emptyData	(m_numCounters*4, 0);
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (bufSize < (maxNdx+1)*4)
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_FAIL((string("GL reported invalid buffer size " + de::toString(bufSize)).c_str()));
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, *counterBuffer);
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, (glw::GLsizeiptr)emptyData.size(), &emptyData[0], GL_STATIC_DRAW);
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, *counterBuffer);
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "Atomic counter buffer initialization failed");
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shaderExecutor->useProgram();
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_indexExprType == INDEX_EXPR_TYPE_DYNAMIC_UNIFORM)
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			expandedIndices.resize(numInvocations * opIndices.size());
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int opNdx = 0; opNdx < numOps; opNdx++)
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int* dst = &expandedIndices[numInvocations*opNdx];
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				std::fill(dst, dst+numInvocations, opIndices[opNdx]);
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int opNdx = 0; opNdx < numOps; opNdx++)
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				inputs.push_back(&expandedIndices[opNdx*numInvocations]);
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_indexExprType == INDEX_EXPR_TYPE_UNIFORM)
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			uploadUniformIndices(gl, shaderExecutor->getProgram(), "index", numOps, &opIndices[0]);
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int opNdx = 0; opNdx < numOps; opNdx++)
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			outputs.push_back(&outValues[opNdx*numInvocations]);
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Setup failed");
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shaderExecutor->execute(numInvocations, inputs.empty() ? DE_NULL : &inputs[0], &outputs[0]);
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1141351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		vector<int>				numHits			(m_numCounters, 0);	// Number of hits per counter.
1142351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		vector<deUint32>		counterValues	(m_numCounters);
1143351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		vector<vector<bool> >	counterMasks	(m_numCounters);
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int opNdx = 0; opNdx < numOps; opNdx++)
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numHits[opIndices[opNdx]] += 1;
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Read counter values
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const void* mapPtr = DE_NULL;
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			try
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1154351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi				mapPtr = gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, m_numCounters*4, GL_MAP_READ_BIT);
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER)");
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_CHECK(mapPtr);
1157351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi				std::copy((const deUint32*)mapPtr, (const deUint32*)mapPtr + m_numCounters, &counterValues[0]);
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			catch (...)
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (mapPtr)
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw;
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Verify counter values
1169351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		for (int counterNdx = 0; counterNdx < m_numCounters; counterNdx++)
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32		refCount	= (deUint32)(numHits[counterNdx]*numInvocations);
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32		resCount	= counterValues[counterNdx];
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (refCount != resCount)
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_testCtx.getLog() << TestLog::Message << "ERROR: atomic counter " << counterNdx << " has value " << resCount
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													   << ", expected " << refCount
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								   << TestLog::EndMessage;
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid atomic counter value");
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Allocate bitmasks - one bit per each valid result value
1186351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi		for (int counterNdx = 0; counterNdx < m_numCounters; counterNdx++)
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	counterValue	= numHits[counterNdx]*numInvocations;
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			counterMasks[counterNdx].resize(counterValue, false);
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Verify result values from shaders
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int invocationNdx = 0; invocationNdx < numInvocations; invocationNdx++)
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int opNdx = 0; opNdx < numOps; opNdx++)
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		counterNdx	= opIndices[opNdx];
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32	resValue	= outValues[opNdx*numInvocations + invocationNdx];
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		rangeOk		= de::inBounds(resValue, 0u, (deUint32)counterMasks[counterNdx].size());
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		notSeen		= rangeOk && !counterMasks[counterNdx][resValue];
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= rangeOk && notSeen;
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_testCtx.getLog() << TestLog::Message << "ERROR: at invocation " << invocationNdx
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << ", op " << opNdx << ": got invalid result value "
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														   << resValue
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									   << TestLog::EndMessage;
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid result value");
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Mark as used - no other invocation should see this value from same counter.
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					counterMasks[counterNdx][resValue] = true;
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Consistency check - all masks should be 1 now
1224351f82f2be0cd8818879c6c140eaa027aed0b848Mika Isojärvi			for (int counterNdx = 0; counterNdx < m_numCounters; counterNdx++)
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (vector<bool>::const_iterator i = counterMasks[counterNdx].begin(); i != counterMasks[counterNdx].end(); i++)
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					TCU_CHECK_INTERNAL(*i);
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12373c827367444ee418f129b2c238299f49d3264554Jarkko PoyryOpaqueTypeIndexingTests::OpaqueTypeIndexingTests (Context& context)
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "opaque_type_indexing", "Opaque Type Indexing Tests")
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12423c827367444ee418f129b2c238299f49d3264554Jarkko PoyryOpaqueTypeIndexingTests::~OpaqueTypeIndexingTests (void)
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid OpaqueTypeIndexingTests::init (void)
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		IndexExprType	type;
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		description;
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} indexingTypes[] =
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ INDEX_EXPR_TYPE_CONST_LITERAL,	"const_literal",		"Indexing by constant literal"					},
12568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{ INDEX_EXPR_TYPE_CONST_EXPRESSION,	"const_expression",		"Indexing by constant expression"				},
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ INDEX_EXPR_TYPE_UNIFORM,			"uniform",				"Indexing by uniform value"						},
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ INDEX_EXPR_TYPE_DYNAMIC_UNIFORM,	"dynamically_uniform",	"Indexing by dynamically uniform expression"	}
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShaderType		type;
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} shaderTypes[] =
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1267fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		{ SHADERTYPE_VERTEX,					"vertex"					},
1268fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		{ SHADERTYPE_FRAGMENT,					"fragment"					},
1269fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		{ SHADERTYPE_COMPUTE,					"compute"					},
1270fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		{ SHADERTYPE_GEOMETRY,					"geometry"					},
1271fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		{ SHADERTYPE_TESSELLATION_CONTROL,		"tessellation_control"		},
1272fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos		{ SHADERTYPE_TESSELLATION_EVALUATION,	"tessellation_evaluation"	}
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .sampler
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const DataType samplerTypes[] =
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// \note 1D images will be added by a later extension.
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//			TYPE_SAMPLER_1D,
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_SAMPLER_2D,
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_SAMPLER_CUBE,
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_SAMPLER_2D_ARRAY,
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_SAMPLER_3D,
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//			TYPE_SAMPLER_1D_SHADOW,
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_SAMPLER_2D_SHADOW,
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_SAMPLER_CUBE_SHADOW,
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_SAMPLER_2D_ARRAY_SHADOW,
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//			TYPE_INT_SAMPLER_1D,
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_INT_SAMPLER_2D,
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_INT_SAMPLER_CUBE,
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_INT_SAMPLER_2D_ARRAY,
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_INT_SAMPLER_3D,
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//			TYPE_UINT_SAMPLER_1D,
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_UINT_SAMPLER_2D,
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_UINT_SAMPLER_CUBE,
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_UINT_SAMPLER_2D_ARRAY,
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TYPE_UINT_SAMPLER_3D,
1299fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TYPE_SAMPLER_CUBE_ARRAY,
1300fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
1301fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TYPE_INT_SAMPLER_CUBE_ARRAY,
1302fb059fdb43c8b6073ada028a68124263c59a000aPyry Haulos			TYPE_UINT_SAMPLER_CUBE_ARRAY
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const samplerGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Sampler Array Indexing Tests");
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(samplerGroup);
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int indexTypeNdx = 0; indexTypeNdx < DE_LENGTH_OF_ARRAY(indexingTypes); indexTypeNdx++)
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const IndexExprType			indexExprType	= indexingTypes[indexTypeNdx].type;
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* const	indexGroup		= new tcu::TestCaseGroup(m_testCtx, indexingTypes[indexTypeNdx].name, indexingTypes[indexTypeNdx].description);
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			samplerGroup->addChild(indexGroup);
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(shaderTypes); shaderTypeNdx++)
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const ShaderType			shaderType		= shaderTypes[shaderTypeNdx].type;
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::TestCaseGroup* const	shaderGroup		= new tcu::TestCaseGroup(m_testCtx, shaderTypes[shaderTypeNdx].name, "");
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				indexGroup->addChild(shaderGroup);
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int samplerTypeNdx = 0; samplerTypeNdx < DE_LENGTH_OF_ARRAY(samplerTypes); samplerTypeNdx++)
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const DataType	samplerType	= samplerTypes[samplerTypeNdx];
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const char*		samplerName	= getDataTypeName(samplerType);
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const string	caseName	= de::toLower(samplerName);
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					shaderGroup->addChild(new SamplerIndexingCase(m_context, caseName.c_str(), "", shaderType, samplerType, indexExprType));
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .ubo / .ssbo / .atomic_counter
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const	uboGroup	= new tcu::TestCaseGroup(m_testCtx, "ubo",				"Uniform Block Instance Array Indexing Tests");
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const	ssboGroup	= new tcu::TestCaseGroup(m_testCtx, "ssbo",				"Buffer Block Instance Array Indexing Tests");
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const	acGroup		= new tcu::TestCaseGroup(m_testCtx, "atomic_counter",	"Atomic Counter Array Indexing Tests");
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(uboGroup);
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(ssboGroup);
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(acGroup);
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int indexTypeNdx = 0; indexTypeNdx < DE_LENGTH_OF_ARRAY(indexingTypes); indexTypeNdx++)
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const IndexExprType		indexExprType		= indexingTypes[indexTypeNdx].type;
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*				indexExprName		= indexingTypes[indexTypeNdx].name;
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*				indexExprDesc		= indexingTypes[indexTypeNdx].description;
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(shaderTypes); shaderTypeNdx++)
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const ShaderType		shaderType		= shaderTypes[shaderTypeNdx].type;
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string			name			= string(indexExprName) + "_" + shaderTypes[shaderTypeNdx].name;
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				uboGroup->addChild	(new BlockArrayIndexingCase		(m_context, name.c_str(), indexExprDesc, BlockArrayIndexingCase::BLOCKTYPE_UNIFORM,	indexExprType, shaderType));
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				acGroup->addChild	(new AtomicCounterIndexingCase	(m_context, name.c_str(), indexExprDesc, indexExprType, shaderType));
13548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
13558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				if (indexExprType == INDEX_EXPR_TYPE_CONST_LITERAL || indexExprType == INDEX_EXPR_TYPE_CONST_EXPRESSION)
13568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					ssboGroup->addChild	(new BlockArrayIndexingCase		(m_context, name.c_str(), indexExprDesc, BlockArrayIndexingCase::BLOCKTYPE_BUFFER,	indexExprType, shaderType));
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1365