13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 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 Texture unit usage tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \todo [2012-07-12 nuutti] Come up with a good way to make these tests faster.
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fTextureUnitTests.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsTextureTestUtil.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuMatrix.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sglrContextUtil.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sglrReferenceContext.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sglrGLContext.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3;
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Mat3;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Mat4;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glw; // GL types
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::TextureTestUtil;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int VIEWPORT_WIDTH				= 128;
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int VIEWPORT_HEIGHT			= 128;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_WIDTH_2D			= 128;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_HEIGHT_2D			= 128;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \note Cube map texture size is larger in order to make minifications possible - otherwise would need to display different faces at same time.
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_WIDTH_CUBE			= 256;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_HEIGHT_CUBE		= 256;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_WIDTH_2D_ARRAY		= 64;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_HEIGHT_2D_ARRAY	= 64;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_LAYERS_2D_ARRAY	= 4;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_WIDTH_3D			= 32;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_HEIGHT_3D			= 32;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int TEXTURE_DEPTH_3D			= 32;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int GRID_CELL_SIZE				= 8;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const GLenum s_testSizedInternalFormats[] =
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA32F,
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA32I,
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA32UI,
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA16F,
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA16I,
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA16UI,
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA8,
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA8I,
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA8UI,
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_SRGB8_ALPHA8,
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB10_A2,
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB10_A2UI,
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA4,
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB5_A1,
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGBA8_SNORM,
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB8,
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB565,
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R11F_G11F_B10F,
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB32F,
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB32I,
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB32UI,
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB16F,
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB16I,
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB16UI,
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB8_SNORM,
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB8I,
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB8UI,
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_SRGB8,
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RGB9_E5,
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG32F,
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG32I,
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG32UI,
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG16F,
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG16I,
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG16UI,
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG8,
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG8I,
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG8UI,
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_RG8_SNORM,
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R32F,
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R32I,
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R32UI,
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R16F,
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R16I,
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R16UI,
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R8,
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R8I,
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R8UI,
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_R8_SNORM
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const GLenum s_testWrapModes[] =
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_CLAMP_TO_EDGE,
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_REPEAT,
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_MIRRORED_REPEAT,
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const GLenum s_testMinFilters[] =
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_NEAREST,
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_LINEAR,
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_NEAREST_MIPMAP_NEAREST,
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_LINEAR_MIPMAP_NEAREST,
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_NEAREST_MIPMAP_LINEAR,
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_LINEAR_MIPMAP_LINEAR
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const GLenum s_testNonMipmapMinFilters[] =
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_NEAREST,
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_LINEAR
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const GLenum s_testNearestMinFilters[] =
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_NEAREST,
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_NEAREST_MIPMAP_NEAREST
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const GLenum s_testMagFilters[] =
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_NEAREST,
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_LINEAR
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const GLenum s_cubeFaceTargets[] =
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Extend a 3x3 transformation matrix to an equivalent 4x4 transformation matrix (i.e. 1.0 in right-down cell, 0.0's in other new cells).
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic Mat4 matExtend3To4 (const Mat3& mat)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Mat4 res;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int rowNdx = 0; rowNdx < 3; rowNdx++)
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec3 row = mat.getRow(rowNdx);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		res.setRow(rowNdx, Vec4(row.x(), row.y(), row.z(), 0.0f));
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res.setRow(3, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return res;
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic string generateMultiTexFragmentShader (int numUnits, const vector<GLenum>& unitTypes, const vector<glu::DataType>& samplerTypes)
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// The fragment shader calculates the average of a set of textures.
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string samplersStr;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string matricesStr;
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string scalesStr;
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string biasesStr;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string lookupsStr;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string colorMultiplier = "(1.0/" + de::toString(numUnits) + ".0)";
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numUnits; ndx++)
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string ndxStr				= de::toString(ndx);
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string samplerName			= "u_sampler" + ndxStr;
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string transformationName	= "u_trans" + ndxStr;
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string scaleName			= "u_texScale" + ndxStr;
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string biasName				= "u_texBias" + ndxStr;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		samplersStr += string("") + "uniform highp " + glu::getDataTypeName(samplerTypes[ndx]) + " " + samplerName + ";\n";
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		matricesStr += "uniform highp mat4 " + transformationName + ";\n";
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		scalesStr += "uniform highp vec4 " + scaleName + ";\n";
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		biasesStr += "uniform highp vec4 " + biasName + ";\n";
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string lookupCoord = transformationName + "*vec4(v_coord, 1.0, 1.0)";
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (unitTypes[ndx] == GL_TEXTURE_2D)
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			lookupCoord = "vec2(" + lookupCoord + ")";
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			lookupCoord = "vec3(" + lookupCoord + ")";
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		lookupsStr += "\tcolor += " + colorMultiplier + "*(vec4(texture(" + samplerName + ", " + lookupCoord + "))*" + scaleName + " + " + biasName + ");\n";
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return "#version 300 es\n"
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "layout(location = 0) out mediump vec4 o_color;\n" +
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   samplersStr +
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   matricesStr +
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   scalesStr +
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   biasesStr +
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "in highp vec2 v_coord;\n"
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "\n"
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "void main (void)\n"
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "{\n"
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "	mediump vec4 color = vec4(0.0);\n" +
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   lookupsStr +
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "	o_color = color;\n"
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "}\n";
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic sglr::pdec::ShaderProgramDeclaration generateShaderProgramDeclaration (int numUnits, const vector<GLenum>& unitTypes, const vector<glu::DataType>& samplerTypes)
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sglr::pdec::ShaderProgramDeclaration decl;
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numUnits; ++ndx)
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string samplerName			= "u_sampler" + de::toString(ndx);
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string transformationName	= "u_trans" + de::toString(ndx);
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string scaleName			= "u_texScale" + de::toString(ndx);
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string biasName				= "u_texBias" + de::toString(ndx);
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		decl << sglr::pdec::Uniform(samplerName, samplerTypes[ndx]);
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		decl << sglr::pdec::Uniform(transformationName, glu::TYPE_FLOAT_MAT4);
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		decl << sglr::pdec::Uniform(scaleName, glu::TYPE_FLOAT_VEC4);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		decl << sglr::pdec::Uniform(biasName, glu::TYPE_FLOAT_VEC4);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << sglr::pdec::VertexSource("#version 300 es\n"
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "in highp vec4 a_position;\n"
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "in highp vec2 a_coord;\n"
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "out highp vec2 v_coord;\n"
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "\n"
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "void main (void)\n"
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "{\n"
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "	gl_Position = a_position;\n"
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "	v_coord = a_coord;\n"
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 "}\n");
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	decl << sglr::pdec::FragmentSource(generateMultiTexFragmentShader(numUnits, unitTypes, samplerTypes));
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return decl;
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Calculates values that will be used in calculateLod().
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Vector<tcu::Vec2, 3> calculateLodDerivateParts (const Mat4& transformation)
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Calculate transformed coordinates of three screen corners.
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec3 trans00 = (transformation * Vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec3 trans01 = (transformation * Vec4(0.0f, 1.0f, 1.0f, 1.0f)).xyz();
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec3 trans10 = (transformation * Vec4(1.0f, 0.0f, 1.0f, 1.0f)).xyz();
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Vector<tcu::Vec2, 3>(Vec2(trans10.x() - trans00.x(), trans01.x() - trans00.x()),
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 Vec2(trans10.y() - trans00.y(), trans01.y() - trans00.y()),
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 Vec2(trans10.z() - trans00.z(), trans01.z() - trans00.z()));
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Calculates the maximum allowed lod from derivates
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float calculateLodMax(const tcu::Vector<tcu::Vec2, 3>& derivateParts, const tcu::IVec3& textureSize, const Vec2& screenDerivate)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float mu = de::max(de::abs(dudx), de::abs(dudy));
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(mu + mv + mw);
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Calculates the minimum allowed lod from derivates
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float calculateLodMin(const tcu::Vector<tcu::Vec2, 3>& derivateParts, const tcu::IVec3& textureSize, const Vec2& screenDerivate)
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float mu = de::max(de::abs(dudx), de::abs(dudy));
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(de::max(mu, de::max(mv, mw)));
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MultiTexShader : public sglr::ShaderProgram
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							MultiTexShader	(deUint32 randSeed,
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 int numUnits,
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const vector<GLenum>& unitTypes,
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const vector<glu::DataType>& samplerTypes,
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const vector<Vec4>& texScales,
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const vector<Vec4>& texBiases,
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 const vector<int>& num2dArrayLayers); // \note 2d array layer "coordinate" isn't normalized, so this is needed here.
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					setUniforms		(sglr::Context& context, deUint32 program) const;
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					makeSafeLods	(const vector<IVec3>& textureSizes, const IVec2& viewportSize); // Modifies texture coordinates so that LODs aren't too close to x.5 or 0.0 .
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					shadeVertices	(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int									m_numUnits;
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<GLenum>						m_unitTypes;		// 2d, cube map, 2d array or 3d.
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec4>						m_texScales;
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec4>						m_texBiases;
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Mat4>						m_transformations;
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<tcu::Vector<tcu::Vec2, 3> >	m_lodDerivateParts;	// Parts of lod derivates; computed in init(), used in eval().
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryMultiTexShader::MultiTexShader (deUint32 randSeed,
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								int numUnits,
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const vector<GLenum>& unitTypes,
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const vector<glu::DataType>& samplerTypes,
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const vector<Vec4>& texScales,
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const vector<Vec4>& texBiases,
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								const vector<int>& num2dArrayLayers)
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: sglr::ShaderProgram	(generateShaderProgramDeclaration(numUnits, unitTypes, samplerTypes))
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_numUnits		(numUnits)
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_unitTypes		(unitTypes)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_texScales		(texScales)
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_texBiases		(texBiases)
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// 2d-to-cube-face transformations.
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note 2d coordinates range from 0 to 1 and cube face coordinates from -1 to 1, so scaling is done as well.
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float s_cubeTransforms[][3*3] =
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  0.0f,  0.0f, -1.0f,
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f, -2.0f,  1.0f,
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   2.0f,  0.0f, -1.0f },
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  0.0f,  0.0f,  1.0f,
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f, -2.0f,  1.0f,
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  -2.0f,  0.0f,  1.0f },
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  2.0f,  0.0f, -1.0f,
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f,  0.0f, -1.0f,
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f, -2.0f,  1.0f },
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  2.0f,  0.0f, -1.0f,
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f,  0.0f,  1.0f,
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f,  2.0f, -1.0f },
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ -2.0f,  0.0f,  1.0f,
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f, -2.0f,  1.0f,
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f,  0.0f, -1.0f },
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  2.0f,  0.0f, -1.0f,
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f, -2.0f,  1.0f,
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   0.0f,  0.0f,  1.0f }
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Generate transformation matrices.
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random rnd(randSeed);
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_transformations.reserve(m_numUnits);
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_lodDerivateParts.reserve(m_numUnits);
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int tex2dArrayNdx = 0; // Keep track of 2d texture array index.
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)m_unitTypes.size() == m_numUnits);
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_unitTypes[unitNdx] == GL_TEXTURE_2D)
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float rotAngle				= rnd.getFloat(0.0f, 2.0f*DE_PI);
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float xScaleFactor			= rnd.getFloat(0.7f, 1.5f);
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float yScaleFactor			= rnd.getFloat(0.7f, 1.5f);
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float xShearAmount			= rnd.getFloat(0.0f, 0.5f);
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float yShearAmount			= rnd.getFloat(0.0f, 0.5f);
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float xTranslationAmount	= rnd.getFloat(-0.5f, 0.5f);
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float yTranslationAmount	= rnd.getFloat(-0.5f, 0.5f);
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			static const float tempOffsetData[3*3] = // For temporarily centering the coordinates to get nicer transformations.
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				1.0f,  0.0f, -0.5f,
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,  1.0f, -0.5f,
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,  0.0f,  1.0f
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float rotTransfData[3*3] =
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deFloatCos(rotAngle),	-deFloatSin(rotAngle),	0.0f,
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deFloatSin(rotAngle),	deFloatCos(rotAngle),	0.0f,
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,					0.0f,					1.0f
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float scaleTransfData[3*3] =
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				xScaleFactor,	0.0f,			0.0f,
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,			yScaleFactor,	0.0f,
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,			0.0f,			1.0f
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float xShearTransfData[3*3] =
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				1.0f,			xShearAmount,	0.0f,
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,			1.0f,			0.0f,
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,			0.0f,			1.0f
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float yShearTransfData[3*3] =
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				1.0f,			0.0f,			0.0f,
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				yShearAmount,	1.0f,			0.0f,
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,			0.0f,			1.0f
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float translationTransfData[3*3] =
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				1.0f,	0.0f,	xTranslationAmount,
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,	1.0f,	yTranslationAmount,
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				0.0f,	0.0f,	1.0f
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Mat4 transformation = matExtend3To4(Mat3(tempOffsetData) *
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												Mat3(translationTransfData) *
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												Mat3(rotTransfData) *
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												Mat3(scaleTransfData) *
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												Mat3(xShearTransfData) *
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												Mat3(yShearTransfData) *
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												(Mat3(tempOffsetData) * (-1.0f)));
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_transformations.push_back(transformation);
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (m_unitTypes[unitNdx] == GL_TEXTURE_CUBE_MAP)
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_STATIC_ASSERT((int)tcu::CUBEFACE_LAST == DE_LENGTH_OF_ARRAY(s_cubeTransforms));
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float planarTransData[3*3];
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// In case of a cube map, we only want to render one face, so the transformation needs to be restricted - only enlarging scaling is done.
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int i = 0; i < DE_LENGTH_OF_ARRAY(planarTransData); i++)
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (i == 0 || i == 4)
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					planarTransData[i] = rnd.getFloat(0.1f, 0.9f); // Two first diagonal cells control the scaling.
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (i == 8)
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					planarTransData[i] = 1.0f;
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					planarTransData[i] = 0.0f;
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		faceNdx			= rnd.getInt(0, (int)tcu::CUBEFACE_LAST - 1);
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Mat3	planarTrans		(planarTransData);												// Planar, face-agnostic transformation.
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Mat4	finalTrans		= matExtend3To4(Mat3(s_cubeTransforms[faceNdx]) * planarTrans);	// Final transformation from planar to cube map coordinates, including the transformation just generated.
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Mat4	planarTrans4x4	= matExtend3To4(planarTrans);
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_lodDerivateParts.push_back(calculateLodDerivateParts(planarTrans4x4));
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_transformations.push_back(finalTrans);
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(m_unitTypes[unitNdx] == GL_TEXTURE_3D || m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY);
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float transData[4*4];
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int i = 0; i < 4*4; i++)
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				float sign = rnd.getBool() ? 1.0f : -1.0f;
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				transData[i] = rnd.getFloat(0.7f, 1.4f) * sign;
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Mat4 transformation(transData);
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY)
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Z direction: Translate by 0.5 and scale by layer amount.
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				float numLayers = (float)num2dArrayLayers[tex2dArrayNdx];
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				static const float zTranslationTransfData[4*4] =
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					1.0f, 0.0f, 0.0f, 0.0f,
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					0.0f, 1.0f, 0.0f, 0.0f,
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					0.0f, 0.0f, 1.0f, 0.5f,
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					0.0f, 0.0f, 0.0f, 1.0f
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				};
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				float zScaleTransfData[4*4] =
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					1.0f,		0.0f,		0.0f,		0.0f,
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					0.0f,		1.0f,		0.0f,		0.0f,
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					0.0f,		0.0f,		numLayers,	0.0f,
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					0.0f,		0.0f,		0.0f,		1.0f
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				};
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				transformation = transformation * Mat4(zScaleTransfData) * Mat4(zTranslationTransfData);
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tex2dArrayNdx++;
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_transformations.push_back(Mat4(transformation));
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MultiTexShader::setUniforms (sglr::Context& ctx, deUint32 program) const
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ctx.useProgram(program);
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Sampler and matrix uniforms.
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_numUnits; ndx++)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string			ndxStr		= de::toString(ndx);
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ctx.uniform1i(ctx.getUniformLocation(program, ("u_sampler" + ndxStr).c_str()), ndx);
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ctx.uniformMatrix4fv(ctx.getUniformLocation(program, ("u_trans" + ndxStr).c_str()), 1, GL_FALSE, (GLfloat*)&m_transformations[ndx].getColumnMajorData()[0]);
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texScale" + ndxStr).c_str()), 1, m_texScales[ndx].getPtr());
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texBias" + ndxStr).c_str()), 1, m_texBiases[ndx].getPtr());
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MultiTexShader::makeSafeLods (const vector<IVec3>& textureSizes, const IVec2& viewportSize)
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)textureSizes.size() == m_numUnits);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float shrinkScaleMat2dData[3*3] =
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0.95f,	0.0f,	0.0f,
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0.0f,	0.95f,	0.0f,
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0.0f,	0.0f,	1.0f
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float shrinkScaleMat3dData[3*3] =
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0.95f,	0.0f,	0.0f,
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0.0f,	0.95f,	0.0f,
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		0.0f,	0.0f,	0.95f
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Mat4 shrinkScaleMat2d = matExtend3To4(Mat3(shrinkScaleMat2dData));
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Mat4 shrinkScaleMat3d = matExtend3To4(Mat3(shrinkScaleMat3dData));
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec2 screenDerivate(1.0f / (float)viewportSize.x(), 1.0f / (float)viewportSize.y());
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// As long as LOD is too close to 0.0 or is positive and too close to a something-and-a-half (0.5, 1.5, 2.5 etc) or allowed lod range could round to different levels, zoom in a little to get a safer LOD.
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (;;)
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float threshold = 0.1f;
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float epsilon	= 0.01f;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float lodMax = calculateLodMax(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float lodMin = calculateLodMin(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32 maxLevel = (lodMax + epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMax + epsilon + 0.5f) - 1);
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deInt32 minLevel = (lodMin - epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMin - epsilon + 0.5f) - 1);
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (de::abs(lodMax) < threshold || (lodMax > 0.0f && de::abs(deFloatFrac(lodMax) - 0.5f) < threshold) ||
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				de::abs(lodMin) < threshold || (lodMin > 0.0f && de::abs(deFloatFrac(lodMin) - 0.5f) < threshold) ||
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				maxLevel != minLevel)
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_transformations[unitNdx] = (m_unitTypes[unitNdx] == GL_TEXTURE_3D ? shrinkScaleMat3d : shrinkScaleMat2d) * m_transformations[unitNdx];
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_lodDerivateParts[unitNdx] = calculateLodDerivateParts(m_transformations[unitNdx]);
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MultiTexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rr::VertexPacket& packet = *(packets[packetNdx]);
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MultiTexShader::shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)m_unitTypes.size() == m_numUnits);
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)m_transformations.size() == m_numUnits);
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)m_lodDerivateParts.size() == m_numUnits);
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rr::FragmentPacket& packet				= packets[packetNdx];
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			colorMultiplier		= 1.0f / (float)m_numUnits;
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec4				outColors[4]		= { Vec4(0.0f), Vec4(0.0f), Vec4(0.0f), Vec4(0.0f) };
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec4 texSamples[4];
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Read tex coords
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec2 texCoords[4] =
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				rr::readTriangleVarying<float>(packet, context, 0, 0).xy(),
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				rr::readTriangleVarying<float>(packet, context, 0, 1).xy(),
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				rr::readTriangleVarying<float>(packet, context, 0, 2).xy(),
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				rr::readTriangleVarying<float>(packet, context, 0, 3).xy(),
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Transform
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Vec3 coords3D[4] =
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(m_transformations[unitNdx] * Vec4(texCoords[0].x(), texCoords[0].y(), 1.0f, 1.0f)).xyz(),
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(m_transformations[unitNdx] * Vec4(texCoords[1].x(), texCoords[1].y(), 1.0f, 1.0f)).xyz(),
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(m_transformations[unitNdx] * Vec4(texCoords[2].x(), texCoords[2].y(), 1.0f, 1.0f)).xyz(),
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				(m_transformations[unitNdx] * Vec4(texCoords[3].x(), texCoords[3].y(), 1.0f, 1.0f)).xyz(),
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// To 2D
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec2 coords2D[4] =
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				coords3D[0].xy(),
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				coords3D[1].xy(),
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				coords3D[2].xy(),
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				coords3D[3].xy(),
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			};
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Sample
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			switch (m_unitTypes[unitNdx])
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D:			m_uniforms[4*unitNdx].sampler.tex2D->sample4(texSamples, coords2D);			break;
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_CUBE_MAP:	m_uniforms[4*unitNdx].sampler.texCube->sample4(texSamples, coords3D);		break;
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D_ARRAY:	m_uniforms[4*unitNdx].sampler.tex2DArray->sample4(texSamples, coords3D);	break;
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_3D:			m_uniforms[4*unitNdx].sampler.tex3D->sample4(texSamples, coords3D);			break;
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				default:
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(DE_FALSE);
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Add to sum
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				outColors[fragNdx] += colorMultiplier * (texSamples[fragNdx]*m_texScales[unitNdx] + m_texBiases[unitNdx]);
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// output
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, outColors[fragNdx]);
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TextureUnitCase : public TestCase
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum CaseType
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_ONLY_2D = 0,
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_ONLY_CUBE,
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_ONLY_2D_ARRAY,
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_ONLY_3D,
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_MIXED,
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CASE_LAST
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								TextureUnitCase		(Context& context, const char* name, const char* desc, int numUnits /* \note If non-positive, use all units */, CaseType caseType, deUint32 randSeed);
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~TextureUnitCase	(void);
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init				(void);
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit				(void);
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate				(void);
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct TextureParameters
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum internalFormat;
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum wrapModeS;
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum wrapModeT;
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum wrapModeR;
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum minFilter;
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum magFilter;
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									TextureUnitCase			(const TextureUnitCase& other);
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TextureUnitCase&				operator=				(const TextureUnitCase& other);
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							upload2dTexture			(int texNdx, sglr::Context& context);
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							uploadCubeTexture		(int texNdx, sglr::Context& context);
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							upload2dArrayTexture	(int texNdx, sglr::Context& context);
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							upload3dTexture			(int texNdx, sglr::Context& context);
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void							render					(sglr::Context& context);
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int						m_numUnitsParam;
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const CaseType					m_caseType;
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32					m_randSeed;
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								m_numTextures;	//!< \note Needed in addition to m_numUnits since same texture may be bound to many texture units.
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int								m_numUnits;		//!< = m_numUnitsParam > 0 ? m_numUnitsParam : implementationDefinedMaximum
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<GLenum>					m_textureTypes;
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<TextureParameters>		m_textureParams;
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<tcu::Texture2D*>			m_textures2d;
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<tcu::TextureCube*>		m_texturesCube;
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<tcu::Texture2DArray*>	m_textures2dArray;
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<tcu::Texture3D*>			m_textures3d;
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>						m_unitTextures;	//!< Which texture is used in a particular unit.
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<int>						m_ndxTexType;	//!< Index of a texture in m_textures2d, m_texturesCube, m_textures2dArray or m_textures3d, depending on texture type.
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MultiTexShader*					m_shader;
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7433c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureUnitCase::TextureUnitCase (Context& context, const char* name, const char* desc, int numUnits, CaseType caseType, deUint32 randSeed)
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, tcu::NODETYPE_SELF_VALIDATE, name, desc)
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numUnitsParam	(numUnits)
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_caseType		(caseType)
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_randSeed		(randSeed)
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_shader			(DE_NULL)
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureUnitCase::~TextureUnitCase (void)
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TextureUnitCase::deinit();
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitCase::deinit (void)
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<tcu::Texture2D*>::iterator i = m_textures2d.begin(); i != m_textures2d.end(); i++)
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_textures2d.clear();
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<tcu::TextureCube*>::iterator i = m_texturesCube.begin(); i != m_texturesCube.end(); i++)
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_texturesCube.clear();
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<tcu::Texture2DArray*>::iterator i = m_textures2dArray.begin(); i != m_textures2dArray.end(); i++)
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_textures2dArray.clear();
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (vector<tcu::Texture3D*>::iterator i = m_textures3d.begin(); i != m_textures3d.end(); i++)
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete *i;
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_textures3d.clear();
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_shader;
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_shader = DE_NULL;
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitCase::init (void)
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_numUnits = m_numUnitsParam > 0 ? m_numUnitsParam : m_context.getContextInfo().getInt(GL_MAX_TEXTURE_IMAGE_UNITS);
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Make the textures.
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestLog&	log	= m_testCtx.getLog();
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::Random		rnd	(m_randSeed);
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (rnd.getFloat() < 0.7f)
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_numTextures = m_numUnits;											// In most cases use one unit per texture.
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_numTextures = rnd.getInt(deMax32(1, m_numUnits - 2), m_numUnits);	// Sometimes assign same texture to multiple units.
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << tcu::TestLog::Message << ("Using " + de::toString(m_numUnits) + " texture unit(s) and " + de::toString(m_numTextures) + " texture(s)").c_str() << tcu::TestLog::EndMessage;
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_textureTypes.reserve(m_numTextures);
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_textureParams.reserve(m_numTextures);
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_ndxTexType.reserve(m_numTextures);
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Generate textures.
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Either fixed or randomized target types, and randomized parameters for every texture.
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TextureParameters	params;
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_STATIC_ASSERT(CASE_ONLY_2D == 0 && CASE_MIXED + 1 == CASE_LAST);
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						texType			= m_caseType == CASE_MIXED ? rnd.getInt(0, (int)CASE_MIXED - 1) : (int)m_caseType;
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					is2dTex			= texType == 0;
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isCubeTex		= texType == 1;
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					is2dArrayTex	= texType == 2;
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					is3dTex			= texType == 3;
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(is2dTex || isCubeTex || is2dArrayTex || is3dTex);
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLenum					type			= is2dTex		? GL_TEXTURE_2D		: isCubeTex ? GL_TEXTURE_CUBE_MAP	: is2dArrayTex ? GL_TEXTURE_2D_ARRAY		: GL_TEXTURE_3D;
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				texWidth		= is2dTex		? TEXTURE_WIDTH_2D	: isCubeTex ? TEXTURE_WIDTH_CUBE	: is2dArrayTex ? TEXTURE_WIDTH_2D_ARRAY		: TEXTURE_WIDTH_3D;
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				texHeight		= is2dTex		? TEXTURE_HEIGHT_2D	: isCubeTex ? TEXTURE_HEIGHT_CUBE	: is2dArrayTex ? TEXTURE_HEIGHT_2D_ARRAY	: TEXTURE_HEIGHT_3D;
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				texDepth		= is3dTex ? TEXTURE_DEPTH_3D : 1;
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int				texLayers		= is2dArrayTex ? TEXTURE_LAYERS_2D_ARRAY : 1;
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					mipmaps			= (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight) && deIsPowerOfTwo32(texDepth));
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						numLevels		= mipmaps ? deLog2Floor32(de::max(de::max(texWidth, texHeight), texDepth))+1 : 1;
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.internalFormat = s_testSizedInternalFormats[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testSizedInternalFormats) - 1)];
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(params.internalFormat);
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.wrapModeS = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.wrapModeT = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.wrapModeR = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			params.magFilter = isFilterable ? s_testMagFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMagFilters) - 1)] : GL_NEAREST;
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (mipmaps)
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				params.minFilter = isFilterable ?
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					s_testMinFilters			[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMinFilters) - 1)] :
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					s_testNearestMinFilters		[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNearestMinFilters) - 1)];
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				params.minFilter = isFilterable ?
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					s_testNonMipmapMinFilters	[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNonMipmapMinFilters) - 1)] :
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					GL_NEAREST;
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textureTypes.push_back(type);
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textureParams.push_back(params);
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Create new texture.
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TextureFormat texFormat = glu::mapGLInternalFormat((deUint32)params.internalFormat);
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (is2dTex)
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_ndxTexType.push_back((int)m_textures2d.size()); // Remember the index this texture has in the 2d texture vector.
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_textures2d.push_back(new tcu::Texture2D(texFormat, texWidth, texHeight));
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (isCubeTex)
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_ndxTexType.push_back((int)m_texturesCube.size()); // Remember the index this texture has in the cube texture vector.
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(texWidth == texHeight);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_texturesCube.push_back(new tcu::TextureCube(texFormat, texWidth));
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (is2dArrayTex)
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_ndxTexType.push_back((int)m_textures2dArray.size()); // Remember the index this texture has in the 2d array texture vector.
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_textures2dArray.push_back(new tcu::Texture2DArray(texFormat, texWidth, texHeight, texLayers));
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_ndxTexType.push_back((int)m_textures3d.size()); // Remember the index this texture has in the 3d vector.
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_textures3d.push_back(new tcu::Texture3D(texFormat, texWidth, texHeight, texDepth));
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec4					cBias		= fmtInfo.valueMin;
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Fill with grid texture.
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int numFaces = isCubeTex ? (int)tcu::CUBEFACE_LAST : 1;
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int face = 0; face < numFaces; face++)
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32 rgb	= rnd.getUint32() & 0x00ffffff;
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32 alpha	= 0xff000000;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32 colorA = alpha | rgb;
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deUint32 colorB = alpha | ((~rgb) & 0x00ffffff);
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (is2dTex)
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_textures2d.back()->allocLevel(levelNdx);
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (isCubeTex)
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_texturesCube.back()->allocLevel((tcu::CubeFace)face, levelNdx);
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (is2dArrayTex)
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_textures2dArray.back()->allocLevel(levelNdx);
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_textures3d.back()->allocLevel(levelNdx);
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int curCellSize = deMax32(1, GRID_CELL_SIZE >> levelNdx); // \note Scale grid cell size for mipmaps.
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					tcu::PixelBufferAccess access = is2dTex			? m_textures2d.back()->getLevel(levelNdx)
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  : isCubeTex		? m_texturesCube.back()->getLevelFace(levelNdx, (tcu::CubeFace)face)
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  : is2dArrayTex	? m_textures2dArray.back()->getLevel(levelNdx)
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  :					  m_textures3d.back()->getLevel(levelNdx);
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					tcu::fillWithGrid(access, curCellSize, toVec4(tcu::RGBA(colorA))*cScale + cBias, toVec4(tcu::RGBA(colorB))*cScale + cBias);
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Assign a texture index to each unit.
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_unitTextures.reserve(m_numUnits);
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Every texture is used at least once.
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < m_numTextures; i++)
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_unitTextures.push_back(i);
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Assign a random texture to remaining units.
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while ((int)m_unitTextures.size() < m_numUnits)
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_unitTextures.push_back(rnd.getInt(0, m_numTextures - 1));
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rnd.shuffle(m_unitTextures.begin(), m_unitTextures.end());
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Generate information for shader.
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<GLenum>			unitTypes;
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<Vec4>			texScales;
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<Vec4>			texBiases;
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<glu::DataType>	samplerTypes;
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<int>				num2dArrayLayers;
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		unitTypes.reserve(m_numUnits);
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		texScales.reserve(m_numUnits);
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		texBiases.reserve(m_numUnits);
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		samplerTypes.reserve(m_numUnits);
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		num2dArrayLayers.reserve(m_numUnits);
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < m_numUnits; i++)
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int						texNdx		= m_unitTextures[i];
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLenum					type		= m_textureTypes[texNdx];
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TextureFormat		fmt			= glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat);
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(fmt);
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			unitTypes.push_back(type);
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (type == GL_TEXTURE_2D_ARRAY)
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				num2dArrayLayers.push_back(m_textures2dArray[m_ndxTexType[texNdx]]->getNumLayers());
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			texScales.push_back(fmtInfo.lookupScale);
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			texBiases.push_back(fmtInfo.lookupBias);
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			switch (type)
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D:			samplerTypes.push_back(glu::getSampler2DType(fmt));			break;
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_CUBE_MAP:	samplerTypes.push_back(glu::getSamplerCubeType(fmt));		break;
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D_ARRAY:	samplerTypes.push_back(glu::getSampler2DArrayType(fmt));	break;
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_3D:			samplerTypes.push_back(glu::getSampler3DType(fmt));			break;
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				default:
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(DE_FALSE);
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Create shader.
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_shader == DE_NULL);
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_shader = new MultiTexShader(rnd.getUint32(), m_numUnits, unitTypes, samplerTypes, texScales, texBiases, num2dArrayLayers);
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception&)
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Clean up to save memory.
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TextureUnitCase::deinit();
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureUnitCase::IterateResult TextureUnitCase::iterate (void)
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::RenderContext&			renderCtx			= m_context.getRenderContext();
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RenderTarget&	renderTarget		= renderCtx.getRenderTarget();
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&				log					= m_testCtx.getLog();
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random					rnd					(m_randSeed);
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							viewportWidth		= deMin32(VIEWPORT_WIDTH, renderTarget.getWidth());
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							viewportHeight		= deMin32(VIEWPORT_HEIGHT, renderTarget.getHeight());
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							viewportX			= rnd.getInt(0, renderTarget.getWidth() - viewportWidth);
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							viewportY			= rnd.getInt(0, renderTarget.getHeight() - viewportHeight);
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface				gles3Frame			(viewportWidth, viewportHeight);
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface				refFrame			(viewportWidth, viewportHeight);
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// First we do some tricks to make the LODs safer wrt. precision issues. See MultiTexShader::makeSafeLods().
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<IVec3> texSizes;
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		texSizes.reserve(m_numUnits);
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < m_numUnits; i++)
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		texNdx			= m_unitTextures[i];
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		texNdxInType	= m_ndxTexType[texNdx];
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLenum	type			= m_textureTypes[texNdx];
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			switch (type)
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D:			texSizes.push_back(IVec3(m_textures2d[texNdxInType]->getWidth(),		m_textures2d[texNdxInType]->getHeight(),		0));										break;
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_CUBE_MAP:	texSizes.push_back(IVec3(m_texturesCube[texNdxInType]->getSize(),		m_texturesCube[texNdxInType]->getSize(),		0));										break;
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D_ARRAY:	texSizes.push_back(IVec3(m_textures2dArray[texNdxInType]->getWidth(),	m_textures2dArray[texNdxInType]->getHeight(),	0));										break;
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_3D:			texSizes.push_back(IVec3(m_textures3d[texNdxInType]->getWidth(),		m_textures3d[texNdxInType]->getHeight(),		m_textures3d[texNdxInType]->getDepth()));	break;
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				default:
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(DE_FALSE);
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_shader->makeSafeLods(texSizes, IVec2(viewportWidth, viewportHeight));
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render using GLES3.
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS|sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(viewportX, viewportY, viewportWidth, viewportHeight));
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		render(context);
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		context.readPixels(gles3Frame, 0, 0, viewportWidth, viewportHeight);
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render reference image.
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, viewportWidth, viewportHeight);
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		render(context);
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		context.readPixels(refFrame, 0, 0, viewportWidth, viewportHeight);
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare images.
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		threshold	= 0.001f;
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			isOk		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles3Frame, threshold, tcu::COMPARE_LOG_RESULT);
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Store test result.
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							isOk ? "Pass"				: "Image comparison failed");
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitCase::upload2dTexture (int texNdx, sglr::Context& context)
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						ndx2d		= m_ndxTexType[texNdx];
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture2D*	texture		= m_textures2d[ndx2d];
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::TransferFormat		formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (texture->isLevelEmpty(levelNdx))
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::ConstPixelBufferAccess		access	= texture->getLevel(levelNdx);
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int								width	= access.getWidth();
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int								height	= access.getHeight();
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		context.texImage2D(GL_TEXTURE_2D, levelNdx, m_textureParams[texNdx].internalFormat, width, height, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d texture image data");
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitCase::uploadCubeTexture (int texNdx, sglr::Context& context)
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							ndxCube		= m_ndxTexType[texNdx];
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureCube*		texture		= m_texturesCube[ndxCube];
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++)
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (texture->isLevelEmpty((tcu::CubeFace)face, levelNdx))
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::ConstPixelBufferAccess		access	= texture->getLevelFace(levelNdx, (tcu::CubeFace)face);
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int								width	= access.getWidth();
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int								height	= access.getHeight();
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			context.texImage2D(s_cubeFaceTargets[face], levelNdx, m_textureParams[texNdx].internalFormat, width, height, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(context.getError(), "Set cube map image data");
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitCase::upload2dArrayTexture (int texNdx, sglr::Context& context)
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							ndx2dArray	= m_ndxTexType[texNdx];
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture2DArray*	texture		= m_textures2dArray[ndx2dArray];
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (texture->isLevelEmpty(levelNdx))
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::ConstPixelBufferAccess	access	= texture->getLevel(levelNdx);
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							width	= access.getWidth();
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							height	= access.getHeight();
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							layers	= access.getDepth();
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*width*height);
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		context.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_textureParams[texNdx].internalFormat, width, height, layers, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d array texture image data");
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitCase::upload3dTexture (int texNdx, sglr::Context& context)
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							ndx3d		= m_ndxTexType[texNdx];
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture3D*		texture		= m_textures3d[ndx3d];
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (texture->isLevelEmpty(levelNdx))
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::ConstPixelBufferAccess	access	= texture->getLevel(levelNdx);
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							width	= access.getWidth();
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							height	= access.getHeight();
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int							depth	= access.getDepth();
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*width*height);
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		context.texImage3D(GL_TEXTURE_3D, levelNdx, m_textureParams[texNdx].internalFormat, width, height, depth, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(context.getError(), "Set 3d texture image data");
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitCase::render (sglr::Context& context)
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Setup textures.
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint32>	textureGLNames;
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<bool>		isTextureSetUp(m_numTextures, false); // \note Same texture may be bound to multiple units, but we only want to set up parameters and data once per texture.
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	textureGLNames.resize(m_numTextures);
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.genTextures(m_numTextures, &textureGLNames[0]);
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(context.getError(), "Generate textures");
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int texNdx = m_unitTextures[unitNdx];
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Bind texture to unit.
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		context.activeTexture(GL_TEXTURE0 + unitNdx);
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(context.getError(), "Set active texture");
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		context.bindTexture(m_textureTypes[texNdx], textureGLNames[texNdx]);
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(context.getError(), "Bind texture");
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isTextureSetUp[texNdx])
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Binding this texture for first time, so set parameters and data.
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_S, m_textureParams[texNdx].wrapModeS);
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_T, m_textureParams[texNdx].wrapModeT);
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_textureTypes[texNdx] == GL_TEXTURE_3D)
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_R, m_textureParams[texNdx].wrapModeR);
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MIN_FILTER, m_textureParams[texNdx].minFilter);
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MAG_FILTER, m_textureParams[texNdx].magFilter);
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(context.getError(), "Set texture parameters");
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			switch (m_textureTypes[texNdx])
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D:			upload2dTexture(texNdx, context);		break;
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_CUBE_MAP:	uploadCubeTexture(texNdx, context);		break;
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_2D_ARRAY:	upload2dArrayTexture(texNdx, context);	break;
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case GL_TEXTURE_3D:			upload3dTexture(texNdx, context);		break;
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				default:
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(DE_FALSE);
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			isTextureSetUp[texNdx] = true; // Don't set up this texture's parameters and data again later.
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(context.getError(), "Set textures");
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Setup shader
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 shaderID = context.createProgram(m_shader);
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Draw.
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_shader->setUniforms(context, shaderID);
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(context.getError(), "Draw");
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Delete previously generated texture names.
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.deleteTextures(m_numTextures, &textureGLNames[0]);
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(context.getError(), "Delete textures");
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureUnitTests::TextureUnitTests (Context& context)
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "units", "Texture Unit Usage Tests")
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12293c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureUnitTests::~TextureUnitTests (void)
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureUnitTests::init (void)
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int numTestsPerGroup = 10;
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int unitCounts[] =
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		2,
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		4,
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		8,
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1 // \note Negative stands for the implementation-specified maximum.
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int unitCountNdx = 0; unitCountNdx < DE_LENGTH_OF_ARRAY(unitCounts); unitCountNdx++)
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int numUnits = unitCounts[unitCountNdx];
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		string countGroupName = (unitCounts[unitCountNdx] < 0 ? "all" : de::toString(numUnits)) + "_units";
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* countGroup = new tcu::TestCaseGroup(m_testCtx, countGroupName.c_str(), "");
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(countGroup);
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_STATIC_ASSERT((int)TextureUnitCase::CASE_ONLY_2D == 0);
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseType = (int)TextureUnitCase::CASE_ONLY_2D; caseType < (int)TextureUnitCase::CASE_LAST; caseType++)
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char* caseTypeGroupName = (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D		? "only_2d"
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_CUBE		? "only_cube"
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D_ARRAY	? "only_2d_array"
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_3D		? "only_3d"
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_MIXED			? "mixed"
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  : DE_NULL;
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(caseTypeGroupName != DE_NULL);
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* caseTypeGroup = new tcu::TestCaseGroup(m_testCtx, caseTypeGroupName, "");
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			countGroup->addChild(caseTypeGroup);
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int testNdx = 0; testNdx < numTestsPerGroup; testNdx++)
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				caseTypeGroup->addChild(new TextureUnitCase(m_context, de::toString(testNdx).c_str(), "", numUnits, (TextureUnitCase::CaseType)caseType, deUint32Hash((deUint32)testNdx)));
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1279