xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fTextureUnitTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.0 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Texture unit usage tests.
22*35238bceSAndroid Build Coastguard Worker  *
23*35238bceSAndroid Build Coastguard Worker  * \todo [2012-07-12 nuutti] Come up with a good way to make these tests faster.
24*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "es3fTextureUnitTests.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "glsTextureTestUtil.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluTextureUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluContextInfo.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "gluTextureUtil.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuImageCompare.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "tcuMatrix.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "sglrContextUtil.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "sglrReferenceContext.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "sglrGLContext.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
39*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
40*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
41*35238bceSAndroid Build Coastguard Worker 
42*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
43*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker using std::string;
46*35238bceSAndroid Build Coastguard Worker using std::vector;
47*35238bceSAndroid Build Coastguard Worker using tcu::IVec2;
48*35238bceSAndroid Build Coastguard Worker using tcu::IVec3;
49*35238bceSAndroid Build Coastguard Worker using tcu::Mat3;
50*35238bceSAndroid Build Coastguard Worker using tcu::Mat4;
51*35238bceSAndroid Build Coastguard Worker using tcu::Vec2;
52*35238bceSAndroid Build Coastguard Worker using tcu::Vec3;
53*35238bceSAndroid Build Coastguard Worker using tcu::Vec4;
54*35238bceSAndroid Build Coastguard Worker using namespace glw; // GL types
55*35238bceSAndroid Build Coastguard Worker 
56*35238bceSAndroid Build Coastguard Worker namespace deqp
57*35238bceSAndroid Build Coastguard Worker {
58*35238bceSAndroid Build Coastguard Worker 
59*35238bceSAndroid Build Coastguard Worker using namespace gls::TextureTestUtil;
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker namespace gles3
62*35238bceSAndroid Build Coastguard Worker {
63*35238bceSAndroid Build Coastguard Worker namespace Functional
64*35238bceSAndroid Build Coastguard Worker {
65*35238bceSAndroid Build Coastguard Worker 
66*35238bceSAndroid Build Coastguard Worker static const int VIEWPORT_WIDTH  = 128;
67*35238bceSAndroid Build Coastguard Worker static const int VIEWPORT_HEIGHT = 128;
68*35238bceSAndroid Build Coastguard Worker 
69*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_WIDTH_2D  = 128;
70*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_HEIGHT_2D = 128;
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker // \note Cube map texture size is larger in order to make minifications possible - otherwise would need to display different faces at same time.
73*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_WIDTH_CUBE  = 256;
74*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_HEIGHT_CUBE = 256;
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_WIDTH_2D_ARRAY  = 64;
77*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_HEIGHT_2D_ARRAY = 64;
78*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_LAYERS_2D_ARRAY = 4;
79*35238bceSAndroid Build Coastguard Worker 
80*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_WIDTH_3D  = 32;
81*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_HEIGHT_3D = 32;
82*35238bceSAndroid Build Coastguard Worker static const int TEXTURE_DEPTH_3D  = 32;
83*35238bceSAndroid Build Coastguard Worker 
84*35238bceSAndroid Build Coastguard Worker static const int GRID_CELL_SIZE = 8;
85*35238bceSAndroid Build Coastguard Worker 
86*35238bceSAndroid Build Coastguard Worker static const GLenum s_testSizedInternalFormats[] = {
87*35238bceSAndroid Build Coastguard Worker     GL_RGBA32F,    GL_RGBA32I,        GL_RGBA32UI, GL_RGBA16F,    GL_RGBA16I, GL_RGBA16UI, GL_RGBA8,       GL_RGBA8I,
88*35238bceSAndroid Build Coastguard Worker     GL_RGBA8UI,    GL_SRGB8_ALPHA8,   GL_RGB10_A2, GL_RGB10_A2UI, GL_RGBA4,   GL_RGB5_A1,  GL_RGBA8_SNORM, GL_RGB8,
89*35238bceSAndroid Build Coastguard Worker     GL_RGB565,     GL_R11F_G11F_B10F, GL_RGB32F,   GL_RGB32I,     GL_RGB32UI, GL_RGB16F,   GL_RGB16I,      GL_RGB16UI,
90*35238bceSAndroid Build Coastguard Worker     GL_RGB8_SNORM, GL_RGB8I,          GL_RGB8UI,   GL_SRGB8,      GL_RGB9_E5, GL_RG32F,    GL_RG32I,       GL_RG32UI,
91*35238bceSAndroid Build Coastguard Worker     GL_RG16F,      GL_RG16I,          GL_RG16UI,   GL_RG8,        GL_RG8I,    GL_RG8UI,    GL_RG8_SNORM,   GL_R32F,
92*35238bceSAndroid Build Coastguard Worker     GL_R32I,       GL_R32UI,          GL_R16F,     GL_R16I,       GL_R16UI,   GL_R8,       GL_R8I,         GL_R8UI,
93*35238bceSAndroid Build Coastguard Worker     GL_R8_SNORM};
94*35238bceSAndroid Build Coastguard Worker 
95*35238bceSAndroid Build Coastguard Worker static const GLenum s_testWrapModes[] = {
96*35238bceSAndroid Build Coastguard Worker     GL_CLAMP_TO_EDGE,
97*35238bceSAndroid Build Coastguard Worker     GL_REPEAT,
98*35238bceSAndroid Build Coastguard Worker     GL_MIRRORED_REPEAT,
99*35238bceSAndroid Build Coastguard Worker };
100*35238bceSAndroid Build Coastguard Worker 
101*35238bceSAndroid Build Coastguard Worker static const GLenum s_testMinFilters[] = {GL_NEAREST,
102*35238bceSAndroid Build Coastguard Worker                                           GL_LINEAR,
103*35238bceSAndroid Build Coastguard Worker                                           GL_NEAREST_MIPMAP_NEAREST,
104*35238bceSAndroid Build Coastguard Worker                                           GL_LINEAR_MIPMAP_NEAREST,
105*35238bceSAndroid Build Coastguard Worker                                           GL_NEAREST_MIPMAP_LINEAR,
106*35238bceSAndroid Build Coastguard Worker                                           GL_LINEAR_MIPMAP_LINEAR};
107*35238bceSAndroid Build Coastguard Worker 
108*35238bceSAndroid Build Coastguard Worker static const GLenum s_testNonMipmapMinFilters[] = {GL_NEAREST, GL_LINEAR};
109*35238bceSAndroid Build Coastguard Worker 
110*35238bceSAndroid Build Coastguard Worker static const GLenum s_testNearestMinFilters[] = {GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST};
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker static const GLenum s_testMagFilters[] = {GL_NEAREST, GL_LINEAR};
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker static const GLenum s_cubeFaceTargets[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
115*35238bceSAndroid Build Coastguard Worker                                            GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
116*35238bceSAndroid Build Coastguard Worker                                            GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
117*35238bceSAndroid Build Coastguard Worker 
118*35238bceSAndroid Build Coastguard Worker // 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).
matExtend3To4(const Mat3 & mat)119*35238bceSAndroid Build Coastguard Worker static Mat4 matExtend3To4(const Mat3 &mat)
120*35238bceSAndroid Build Coastguard Worker {
121*35238bceSAndroid Build Coastguard Worker     Mat4 res;
122*35238bceSAndroid Build Coastguard Worker     for (int rowNdx = 0; rowNdx < 3; rowNdx++)
123*35238bceSAndroid Build Coastguard Worker     {
124*35238bceSAndroid Build Coastguard Worker         Vec3 row = mat.getRow(rowNdx);
125*35238bceSAndroid Build Coastguard Worker         res.setRow(rowNdx, Vec4(row.x(), row.y(), row.z(), 0.0f));
126*35238bceSAndroid Build Coastguard Worker     }
127*35238bceSAndroid Build Coastguard Worker     res.setRow(3, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
128*35238bceSAndroid Build Coastguard Worker 
129*35238bceSAndroid Build Coastguard Worker     return res;
130*35238bceSAndroid Build Coastguard Worker }
131*35238bceSAndroid Build Coastguard Worker 
generateMultiTexFragmentShader(int numUnits,const vector<GLenum> & unitTypes,const vector<glu::DataType> & samplerTypes)132*35238bceSAndroid Build Coastguard Worker static string generateMultiTexFragmentShader(int numUnits, const vector<GLenum> &unitTypes,
133*35238bceSAndroid Build Coastguard Worker                                              const vector<glu::DataType> &samplerTypes)
134*35238bceSAndroid Build Coastguard Worker {
135*35238bceSAndroid Build Coastguard Worker     // The fragment shader calculates the average of a set of textures.
136*35238bceSAndroid Build Coastguard Worker 
137*35238bceSAndroid Build Coastguard Worker     string samplersStr;
138*35238bceSAndroid Build Coastguard Worker     string matricesStr;
139*35238bceSAndroid Build Coastguard Worker     string scalesStr;
140*35238bceSAndroid Build Coastguard Worker     string biasesStr;
141*35238bceSAndroid Build Coastguard Worker     string lookupsStr;
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker     string colorMultiplier = "(1.0/" + de::toString(numUnits) + ".0)";
144*35238bceSAndroid Build Coastguard Worker 
145*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numUnits; ndx++)
146*35238bceSAndroid Build Coastguard Worker     {
147*35238bceSAndroid Build Coastguard Worker         string ndxStr             = de::toString(ndx);
148*35238bceSAndroid Build Coastguard Worker         string samplerName        = "u_sampler" + ndxStr;
149*35238bceSAndroid Build Coastguard Worker         string transformationName = "u_trans" + ndxStr;
150*35238bceSAndroid Build Coastguard Worker         string scaleName          = "u_texScale" + ndxStr;
151*35238bceSAndroid Build Coastguard Worker         string biasName           = "u_texBias" + ndxStr;
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker         samplersStr +=
154*35238bceSAndroid Build Coastguard Worker             string("") + "uniform highp " + glu::getDataTypeName(samplerTypes[ndx]) + " " + samplerName + ";\n";
155*35238bceSAndroid Build Coastguard Worker         matricesStr += "uniform highp mat4 " + transformationName + ";\n";
156*35238bceSAndroid Build Coastguard Worker         scalesStr += "uniform highp vec4 " + scaleName + ";\n";
157*35238bceSAndroid Build Coastguard Worker         biasesStr += "uniform highp vec4 " + biasName + ";\n";
158*35238bceSAndroid Build Coastguard Worker 
159*35238bceSAndroid Build Coastguard Worker         string lookupCoord = transformationName + "*vec4(v_coord, 1.0, 1.0)";
160*35238bceSAndroid Build Coastguard Worker 
161*35238bceSAndroid Build Coastguard Worker         if (unitTypes[ndx] == GL_TEXTURE_2D)
162*35238bceSAndroid Build Coastguard Worker             lookupCoord = "vec2(" + lookupCoord + ")";
163*35238bceSAndroid Build Coastguard Worker         else
164*35238bceSAndroid Build Coastguard Worker             lookupCoord = "vec3(" + lookupCoord + ")";
165*35238bceSAndroid Build Coastguard Worker 
166*35238bceSAndroid Build Coastguard Worker         lookupsStr += "\tcolor += " + colorMultiplier + "*(vec4(texture(" + samplerName + ", " + lookupCoord + "))*" +
167*35238bceSAndroid Build Coastguard Worker                       scaleName + " + " + biasName + ");\n";
168*35238bceSAndroid Build Coastguard Worker     }
169*35238bceSAndroid Build Coastguard Worker 
170*35238bceSAndroid Build Coastguard Worker     return "#version 300 es\n"
171*35238bceSAndroid Build Coastguard Worker            "layout(location = 0) out mediump vec4 o_color;\n" +
172*35238bceSAndroid Build Coastguard Worker            samplersStr + matricesStr + scalesStr + biasesStr +
173*35238bceSAndroid Build Coastguard Worker            "in highp vec2 v_coord;\n"
174*35238bceSAndroid Build Coastguard Worker            "\n"
175*35238bceSAndroid Build Coastguard Worker            "void main (void)\n"
176*35238bceSAndroid Build Coastguard Worker            "{\n"
177*35238bceSAndroid Build Coastguard Worker            "    mediump vec4 color = vec4(0.0);\n" +
178*35238bceSAndroid Build Coastguard Worker            lookupsStr +
179*35238bceSAndroid Build Coastguard Worker            "    o_color = color;\n"
180*35238bceSAndroid Build Coastguard Worker            "}\n";
181*35238bceSAndroid Build Coastguard Worker }
182*35238bceSAndroid Build Coastguard Worker 
generateShaderProgramDeclaration(int numUnits,const vector<GLenum> & unitTypes,const vector<glu::DataType> & samplerTypes)183*35238bceSAndroid Build Coastguard Worker static sglr::pdec::ShaderProgramDeclaration generateShaderProgramDeclaration(int numUnits,
184*35238bceSAndroid Build Coastguard Worker                                                                              const vector<GLenum> &unitTypes,
185*35238bceSAndroid Build Coastguard Worker                                                                              const vector<glu::DataType> &samplerTypes)
186*35238bceSAndroid Build Coastguard Worker {
187*35238bceSAndroid Build Coastguard Worker     sglr::pdec::ShaderProgramDeclaration decl;
188*35238bceSAndroid Build Coastguard Worker 
189*35238bceSAndroid Build Coastguard Worker     decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
190*35238bceSAndroid Build Coastguard Worker     decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
191*35238bceSAndroid Build Coastguard Worker     decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
192*35238bceSAndroid Build Coastguard Worker     decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
193*35238bceSAndroid Build Coastguard Worker 
194*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numUnits; ++ndx)
195*35238bceSAndroid Build Coastguard Worker     {
196*35238bceSAndroid Build Coastguard Worker         string samplerName        = "u_sampler" + de::toString(ndx);
197*35238bceSAndroid Build Coastguard Worker         string transformationName = "u_trans" + de::toString(ndx);
198*35238bceSAndroid Build Coastguard Worker         string scaleName          = "u_texScale" + de::toString(ndx);
199*35238bceSAndroid Build Coastguard Worker         string biasName           = "u_texBias" + de::toString(ndx);
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker         decl << sglr::pdec::Uniform(samplerName, samplerTypes[ndx]);
202*35238bceSAndroid Build Coastguard Worker         decl << sglr::pdec::Uniform(transformationName, glu::TYPE_FLOAT_MAT4);
203*35238bceSAndroid Build Coastguard Worker         decl << sglr::pdec::Uniform(scaleName, glu::TYPE_FLOAT_VEC4);
204*35238bceSAndroid Build Coastguard Worker         decl << sglr::pdec::Uniform(biasName, glu::TYPE_FLOAT_VEC4);
205*35238bceSAndroid Build Coastguard Worker     }
206*35238bceSAndroid Build Coastguard Worker 
207*35238bceSAndroid Build Coastguard Worker     decl << sglr::pdec::VertexSource("#version 300 es\n"
208*35238bceSAndroid Build Coastguard Worker                                      "in highp vec4 a_position;\n"
209*35238bceSAndroid Build Coastguard Worker                                      "in highp vec2 a_coord;\n"
210*35238bceSAndroid Build Coastguard Worker                                      "out highp vec2 v_coord;\n"
211*35238bceSAndroid Build Coastguard Worker                                      "\n"
212*35238bceSAndroid Build Coastguard Worker                                      "void main (void)\n"
213*35238bceSAndroid Build Coastguard Worker                                      "{\n"
214*35238bceSAndroid Build Coastguard Worker                                      "    gl_Position = a_position;\n"
215*35238bceSAndroid Build Coastguard Worker                                      "    v_coord = a_coord;\n"
216*35238bceSAndroid Build Coastguard Worker                                      "}\n");
217*35238bceSAndroid Build Coastguard Worker     decl << sglr::pdec::FragmentSource(generateMultiTexFragmentShader(numUnits, unitTypes, samplerTypes));
218*35238bceSAndroid Build Coastguard Worker 
219*35238bceSAndroid Build Coastguard Worker     return decl;
220*35238bceSAndroid Build Coastguard Worker }
221*35238bceSAndroid Build Coastguard Worker 
222*35238bceSAndroid Build Coastguard Worker // Calculates values that will be used in calculateLod().
calculateLodDerivateParts(const Mat4 & transformation)223*35238bceSAndroid Build Coastguard Worker static tcu::Vector<tcu::Vec2, 3> calculateLodDerivateParts(const Mat4 &transformation)
224*35238bceSAndroid Build Coastguard Worker {
225*35238bceSAndroid Build Coastguard Worker     // Calculate transformed coordinates of three screen corners.
226*35238bceSAndroid Build Coastguard Worker     Vec3 trans00 = (transformation * Vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
227*35238bceSAndroid Build Coastguard Worker     Vec3 trans01 = (transformation * Vec4(0.0f, 1.0f, 1.0f, 1.0f)).xyz();
228*35238bceSAndroid Build Coastguard Worker     Vec3 trans10 = (transformation * Vec4(1.0f, 0.0f, 1.0f, 1.0f)).xyz();
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker     return tcu::Vector<tcu::Vec2, 3>(Vec2(trans10.x() - trans00.x(), trans01.x() - trans00.x()),
231*35238bceSAndroid Build Coastguard Worker                                      Vec2(trans10.y() - trans00.y(), trans01.y() - trans00.y()),
232*35238bceSAndroid Build Coastguard Worker                                      Vec2(trans10.z() - trans00.z(), trans01.z() - trans00.z()));
233*35238bceSAndroid Build Coastguard Worker }
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker // Calculates the maximum allowed lod from derivates
calculateLodMax(const tcu::Vector<tcu::Vec2,3> & derivateParts,const tcu::IVec3 & textureSize,const Vec2 & screenDerivate)236*35238bceSAndroid Build Coastguard Worker static float calculateLodMax(const tcu::Vector<tcu::Vec2, 3> &derivateParts, const tcu::IVec3 &textureSize,
237*35238bceSAndroid Build Coastguard Worker                              const Vec2 &screenDerivate)
238*35238bceSAndroid Build Coastguard Worker {
239*35238bceSAndroid Build Coastguard Worker     float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
240*35238bceSAndroid Build Coastguard Worker     float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
241*35238bceSAndroid Build Coastguard Worker     float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
242*35238bceSAndroid Build Coastguard Worker     float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
243*35238bceSAndroid Build Coastguard Worker     float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
244*35238bceSAndroid Build Coastguard Worker     float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker     const float mu = de::max(de::abs(dudx), de::abs(dudy));
247*35238bceSAndroid Build Coastguard Worker     const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
248*35238bceSAndroid Build Coastguard Worker     const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
249*35238bceSAndroid Build Coastguard Worker     return deFloatLog2(mu + mv + mw);
250*35238bceSAndroid Build Coastguard Worker }
251*35238bceSAndroid Build Coastguard Worker 
252*35238bceSAndroid Build Coastguard Worker // Calculates the minimum allowed lod from derivates
calculateLodMin(const tcu::Vector<tcu::Vec2,3> & derivateParts,const tcu::IVec3 & textureSize,const Vec2 & screenDerivate)253*35238bceSAndroid Build Coastguard Worker static float calculateLodMin(const tcu::Vector<tcu::Vec2, 3> &derivateParts, const tcu::IVec3 &textureSize,
254*35238bceSAndroid Build Coastguard Worker                              const Vec2 &screenDerivate)
255*35238bceSAndroid Build Coastguard Worker {
256*35238bceSAndroid Build Coastguard Worker     float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
257*35238bceSAndroid Build Coastguard Worker     float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
258*35238bceSAndroid Build Coastguard Worker     float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
259*35238bceSAndroid Build Coastguard Worker     float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
260*35238bceSAndroid Build Coastguard Worker     float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
261*35238bceSAndroid Build Coastguard Worker     float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();
262*35238bceSAndroid Build Coastguard Worker 
263*35238bceSAndroid Build Coastguard Worker     const float mu = de::max(de::abs(dudx), de::abs(dudy));
264*35238bceSAndroid Build Coastguard Worker     const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
265*35238bceSAndroid Build Coastguard Worker     const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
266*35238bceSAndroid Build Coastguard Worker     return deFloatLog2(de::max(mu, de::max(mv, mw)));
267*35238bceSAndroid Build Coastguard Worker }
268*35238bceSAndroid Build Coastguard Worker 
269*35238bceSAndroid Build Coastguard Worker class MultiTexShader : public sglr::ShaderProgram
270*35238bceSAndroid Build Coastguard Worker {
271*35238bceSAndroid Build Coastguard Worker public:
272*35238bceSAndroid Build Coastguard Worker     MultiTexShader(uint32_t randSeed, int numUnits, const vector<GLenum> &unitTypes,
273*35238bceSAndroid Build Coastguard Worker                    const vector<glu::DataType> &samplerTypes, const vector<Vec4> &texScales,
274*35238bceSAndroid Build Coastguard Worker                    const vector<Vec4> &texBiases,
275*35238bceSAndroid Build Coastguard Worker                    const vector<int> &
276*35238bceSAndroid Build Coastguard Worker                        num2dArrayLayers); // \note 2d array layer "coordinate" isn't normalized, so this is needed here.
277*35238bceSAndroid Build Coastguard Worker 
278*35238bceSAndroid Build Coastguard Worker     void setUniforms(sglr::Context &context, uint32_t program) const;
279*35238bceSAndroid Build Coastguard Worker     void makeSafeLods(
280*35238bceSAndroid Build Coastguard Worker         const vector<IVec3> &textureSizes,
281*35238bceSAndroid Build Coastguard Worker         const IVec2 &viewportSize); // Modifies texture coordinates so that LODs aren't too close to x.5 or 0.0 .
282*35238bceSAndroid Build Coastguard Worker 
283*35238bceSAndroid Build Coastguard Worker private:
284*35238bceSAndroid Build Coastguard Worker     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const;
285*35238bceSAndroid Build Coastguard Worker     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
286*35238bceSAndroid Build Coastguard Worker                         const rr::FragmentShadingContext &context) const;
287*35238bceSAndroid Build Coastguard Worker 
288*35238bceSAndroid Build Coastguard Worker     int m_numUnits;
289*35238bceSAndroid Build Coastguard Worker     vector<GLenum> m_unitTypes; // 2d, cube map, 2d array or 3d.
290*35238bceSAndroid Build Coastguard Worker     vector<Vec4> m_texScales;
291*35238bceSAndroid Build Coastguard Worker     vector<Vec4> m_texBiases;
292*35238bceSAndroid Build Coastguard Worker     vector<Mat4> m_transformations;
293*35238bceSAndroid Build Coastguard Worker     vector<tcu::Vector<tcu::Vec2, 3>> m_lodDerivateParts; // Parts of lod derivates; computed in init(), used in eval().
294*35238bceSAndroid Build Coastguard Worker };
295*35238bceSAndroid Build Coastguard Worker 
MultiTexShader(uint32_t randSeed,int numUnits,const vector<GLenum> & unitTypes,const vector<glu::DataType> & samplerTypes,const vector<Vec4> & texScales,const vector<Vec4> & texBiases,const vector<int> & num2dArrayLayers)296*35238bceSAndroid Build Coastguard Worker MultiTexShader::MultiTexShader(uint32_t randSeed, int numUnits, const vector<GLenum> &unitTypes,
297*35238bceSAndroid Build Coastguard Worker                                const vector<glu::DataType> &samplerTypes, const vector<Vec4> &texScales,
298*35238bceSAndroid Build Coastguard Worker                                const vector<Vec4> &texBiases, const vector<int> &num2dArrayLayers)
299*35238bceSAndroid Build Coastguard Worker     : sglr::ShaderProgram(generateShaderProgramDeclaration(numUnits, unitTypes, samplerTypes))
300*35238bceSAndroid Build Coastguard Worker     , m_numUnits(numUnits)
301*35238bceSAndroid Build Coastguard Worker     , m_unitTypes(unitTypes)
302*35238bceSAndroid Build Coastguard Worker     , m_texScales(texScales)
303*35238bceSAndroid Build Coastguard Worker     , m_texBiases(texBiases)
304*35238bceSAndroid Build Coastguard Worker {
305*35238bceSAndroid Build Coastguard Worker     // 2d-to-cube-face transformations.
306*35238bceSAndroid Build Coastguard Worker     // \note 2d coordinates range from 0 to 1 and cube face coordinates from -1 to 1, so scaling is done as well.
307*35238bceSAndroid Build Coastguard Worker     static const float s_cubeTransforms[][3 * 3] = {// Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
308*35238bceSAndroid Build Coastguard Worker                                                     {0.0f, 0.0f, -1.0f, 0.0f, -2.0f, 1.0f, 2.0f, 0.0f, -1.0f},
309*35238bceSAndroid Build Coastguard Worker                                                     // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
310*35238bceSAndroid Build Coastguard Worker                                                     {0.0f, 0.0f, 1.0f, 0.0f, -2.0f, 1.0f, -2.0f, 0.0f, 1.0f},
311*35238bceSAndroid Build Coastguard Worker                                                     // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
312*35238bceSAndroid Build Coastguard Worker                                                     {2.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, -2.0f, 1.0f},
313*35238bceSAndroid Build Coastguard Worker                                                     // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
314*35238bceSAndroid Build Coastguard Worker                                                     {2.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, -1.0f},
315*35238bceSAndroid Build Coastguard Worker                                                     // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
316*35238bceSAndroid Build Coastguard Worker                                                     {-2.0f, 0.0f, 1.0f, 0.0f, -2.0f, 1.0f, 0.0f, 0.0f, -1.0f},
317*35238bceSAndroid Build Coastguard Worker                                                     // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
318*35238bceSAndroid Build Coastguard Worker                                                     {2.0f, 0.0f, -1.0f, 0.0f, -2.0f, 1.0f, 0.0f, 0.0f, 1.0f}};
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker     // Generate transformation matrices.
321*35238bceSAndroid Build Coastguard Worker 
322*35238bceSAndroid Build Coastguard Worker     de::Random rnd(randSeed);
323*35238bceSAndroid Build Coastguard Worker 
324*35238bceSAndroid Build Coastguard Worker     m_transformations.reserve(m_numUnits);
325*35238bceSAndroid Build Coastguard Worker     m_lodDerivateParts.reserve(m_numUnits);
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker     int tex2dArrayNdx = 0; // Keep track of 2d texture array index.
328*35238bceSAndroid Build Coastguard Worker 
329*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((int)m_unitTypes.size() == m_numUnits);
330*35238bceSAndroid Build Coastguard Worker 
331*35238bceSAndroid Build Coastguard Worker     for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
332*35238bceSAndroid Build Coastguard Worker     {
333*35238bceSAndroid Build Coastguard Worker         if (m_unitTypes[unitNdx] == GL_TEXTURE_2D)
334*35238bceSAndroid Build Coastguard Worker         {
335*35238bceSAndroid Build Coastguard Worker             float rotAngle           = rnd.getFloat(0.0f, 2.0f * DE_PI);
336*35238bceSAndroid Build Coastguard Worker             float xScaleFactor       = rnd.getFloat(0.7f, 1.5f);
337*35238bceSAndroid Build Coastguard Worker             float yScaleFactor       = rnd.getFloat(0.7f, 1.5f);
338*35238bceSAndroid Build Coastguard Worker             float xShearAmount       = rnd.getFloat(0.0f, 0.5f);
339*35238bceSAndroid Build Coastguard Worker             float yShearAmount       = rnd.getFloat(0.0f, 0.5f);
340*35238bceSAndroid Build Coastguard Worker             float xTranslationAmount = rnd.getFloat(-0.5f, 0.5f);
341*35238bceSAndroid Build Coastguard Worker             float yTranslationAmount = rnd.getFloat(-0.5f, 0.5f);
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker             static const float
344*35238bceSAndroid Build Coastguard Worker                 tempOffsetData[3 * 3] = // For temporarily centering the coordinates to get nicer transformations.
345*35238bceSAndroid Build Coastguard Worker                 {1.0f, 0.0f, -0.5f, 0.0f, 1.0f, -0.5f, 0.0f, 0.0f, 1.0f};
346*35238bceSAndroid Build Coastguard Worker             float rotTransfData[3 * 3]         = {deFloatCos(rotAngle),
347*35238bceSAndroid Build Coastguard Worker                                                   -deFloatSin(rotAngle),
348*35238bceSAndroid Build Coastguard Worker                                                   0.0f,
349*35238bceSAndroid Build Coastguard Worker                                                   deFloatSin(rotAngle),
350*35238bceSAndroid Build Coastguard Worker                                                   deFloatCos(rotAngle),
351*35238bceSAndroid Build Coastguard Worker                                                   0.0f,
352*35238bceSAndroid Build Coastguard Worker                                                   0.0f,
353*35238bceSAndroid Build Coastguard Worker                                                   0.0f,
354*35238bceSAndroid Build Coastguard Worker                                                   1.0f};
355*35238bceSAndroid Build Coastguard Worker             float scaleTransfData[3 * 3]       = {xScaleFactor, 0.0f, 0.0f, 0.0f, yScaleFactor, 0.0f, 0.0f, 0.0f, 1.0f};
356*35238bceSAndroid Build Coastguard Worker             float xShearTransfData[3 * 3]      = {1.0f, xShearAmount, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
357*35238bceSAndroid Build Coastguard Worker             float yShearTransfData[3 * 3]      = {1.0f, 0.0f, 0.0f, yShearAmount, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
358*35238bceSAndroid Build Coastguard Worker             float translationTransfData[3 * 3] = {1.0f, 0.0f, xTranslationAmount, 0.0f, 1.0f, yTranslationAmount, 0.0f,
359*35238bceSAndroid Build Coastguard Worker                                                   0.0f, 1.0f};
360*35238bceSAndroid Build Coastguard Worker 
361*35238bceSAndroid Build Coastguard Worker             Mat4 transformation = matExtend3To4(Mat3(tempOffsetData) * Mat3(translationTransfData) *
362*35238bceSAndroid Build Coastguard Worker                                                 Mat3(rotTransfData) * Mat3(scaleTransfData) * Mat3(xShearTransfData) *
363*35238bceSAndroid Build Coastguard Worker                                                 Mat3(yShearTransfData) * (Mat3(tempOffsetData) * (-1.0f)));
364*35238bceSAndroid Build Coastguard Worker 
365*35238bceSAndroid Build Coastguard Worker             m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
366*35238bceSAndroid Build Coastguard Worker             m_transformations.push_back(transformation);
367*35238bceSAndroid Build Coastguard Worker         }
368*35238bceSAndroid Build Coastguard Worker         else if (m_unitTypes[unitNdx] == GL_TEXTURE_CUBE_MAP)
369*35238bceSAndroid Build Coastguard Worker         {
370*35238bceSAndroid Build Coastguard Worker             DE_STATIC_ASSERT((int)tcu::CUBEFACE_LAST == DE_LENGTH_OF_ARRAY(s_cubeTransforms));
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker             float planarTransData[3 * 3];
373*35238bceSAndroid Build Coastguard Worker 
374*35238bceSAndroid Build Coastguard Worker             // 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.
375*35238bceSAndroid Build Coastguard Worker 
376*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < DE_LENGTH_OF_ARRAY(planarTransData); i++)
377*35238bceSAndroid Build Coastguard Worker             {
378*35238bceSAndroid Build Coastguard Worker                 if (i == 0 || i == 4)
379*35238bceSAndroid Build Coastguard Worker                     planarTransData[i] = rnd.getFloat(0.1f, 0.9f); // Two first diagonal cells control the scaling.
380*35238bceSAndroid Build Coastguard Worker                 else if (i == 8)
381*35238bceSAndroid Build Coastguard Worker                     planarTransData[i] = 1.0f;
382*35238bceSAndroid Build Coastguard Worker                 else
383*35238bceSAndroid Build Coastguard Worker                     planarTransData[i] = 0.0f;
384*35238bceSAndroid Build Coastguard Worker             }
385*35238bceSAndroid Build Coastguard Worker 
386*35238bceSAndroid Build Coastguard Worker             int faceNdx = rnd.getInt(0, (int)tcu::CUBEFACE_LAST - 1);
387*35238bceSAndroid Build Coastguard Worker             Mat3 planarTrans(planarTransData); // Planar, face-agnostic transformation.
388*35238bceSAndroid Build Coastguard Worker             Mat4 finalTrans = matExtend3To4(
389*35238bceSAndroid Build Coastguard Worker                 Mat3(s_cubeTransforms[faceNdx]) *
390*35238bceSAndroid Build Coastguard Worker                 planarTrans); // Final transformation from planar to cube map coordinates, including the transformation just generated.
391*35238bceSAndroid Build Coastguard Worker             Mat4 planarTrans4x4 = matExtend3To4(planarTrans);
392*35238bceSAndroid Build Coastguard Worker 
393*35238bceSAndroid Build Coastguard Worker             m_lodDerivateParts.push_back(calculateLodDerivateParts(planarTrans4x4));
394*35238bceSAndroid Build Coastguard Worker             m_transformations.push_back(finalTrans);
395*35238bceSAndroid Build Coastguard Worker         }
396*35238bceSAndroid Build Coastguard Worker         else
397*35238bceSAndroid Build Coastguard Worker         {
398*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(m_unitTypes[unitNdx] == GL_TEXTURE_3D || m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY);
399*35238bceSAndroid Build Coastguard Worker 
400*35238bceSAndroid Build Coastguard Worker             float transData[4 * 4];
401*35238bceSAndroid Build Coastguard Worker 
402*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < 4 * 4; i++)
403*35238bceSAndroid Build Coastguard Worker             {
404*35238bceSAndroid Build Coastguard Worker                 float sign   = rnd.getBool() ? 1.0f : -1.0f;
405*35238bceSAndroid Build Coastguard Worker                 transData[i] = rnd.getFloat(0.7f, 1.4f) * sign;
406*35238bceSAndroid Build Coastguard Worker             }
407*35238bceSAndroid Build Coastguard Worker 
408*35238bceSAndroid Build Coastguard Worker             Mat4 transformation(transData);
409*35238bceSAndroid Build Coastguard Worker 
410*35238bceSAndroid Build Coastguard Worker             if (m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY)
411*35238bceSAndroid Build Coastguard Worker             {
412*35238bceSAndroid Build Coastguard Worker                 // Z direction: Translate by 0.5 and scale by layer amount.
413*35238bceSAndroid Build Coastguard Worker 
414*35238bceSAndroid Build Coastguard Worker                 float numLayers = (float)num2dArrayLayers[tex2dArrayNdx];
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker                 static const float zTranslationTransfData[4 * 4] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
417*35238bceSAndroid Build Coastguard Worker                                                                     0.0f, 0.0f, 1.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f};
418*35238bceSAndroid Build Coastguard Worker 
419*35238bceSAndroid Build Coastguard Worker                 float zScaleTransfData[4 * 4] = {1.0f, 0.0f, 0.0f,      0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
420*35238bceSAndroid Build Coastguard Worker                                                  0.0f, 0.0f, numLayers, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
421*35238bceSAndroid Build Coastguard Worker 
422*35238bceSAndroid Build Coastguard Worker                 transformation = transformation * Mat4(zScaleTransfData) * Mat4(zTranslationTransfData);
423*35238bceSAndroid Build Coastguard Worker 
424*35238bceSAndroid Build Coastguard Worker                 tex2dArrayNdx++;
425*35238bceSAndroid Build Coastguard Worker             }
426*35238bceSAndroid Build Coastguard Worker 
427*35238bceSAndroid Build Coastguard Worker             m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
428*35238bceSAndroid Build Coastguard Worker             m_transformations.push_back(Mat4(transformation));
429*35238bceSAndroid Build Coastguard Worker         }
430*35238bceSAndroid Build Coastguard Worker     }
431*35238bceSAndroid Build Coastguard Worker }
432*35238bceSAndroid Build Coastguard Worker 
setUniforms(sglr::Context & ctx,uint32_t program) const433*35238bceSAndroid Build Coastguard Worker void MultiTexShader::setUniforms(sglr::Context &ctx, uint32_t program) const
434*35238bceSAndroid Build Coastguard Worker {
435*35238bceSAndroid Build Coastguard Worker     ctx.useProgram(program);
436*35238bceSAndroid Build Coastguard Worker 
437*35238bceSAndroid Build Coastguard Worker     // Sampler and matrix uniforms.
438*35238bceSAndroid Build Coastguard Worker 
439*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < m_numUnits; ndx++)
440*35238bceSAndroid Build Coastguard Worker     {
441*35238bceSAndroid Build Coastguard Worker         string ndxStr = de::toString(ndx);
442*35238bceSAndroid Build Coastguard Worker 
443*35238bceSAndroid Build Coastguard Worker         ctx.uniform1i(ctx.getUniformLocation(program, ("u_sampler" + ndxStr).c_str()), ndx);
444*35238bceSAndroid Build Coastguard Worker         ctx.uniformMatrix4fv(ctx.getUniformLocation(program, ("u_trans" + ndxStr).c_str()), 1, GL_FALSE,
445*35238bceSAndroid Build Coastguard Worker                              (GLfloat *)&m_transformations[ndx].getColumnMajorData()[0]);
446*35238bceSAndroid Build Coastguard Worker         ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texScale" + ndxStr).c_str()), 1, m_texScales[ndx].getPtr());
447*35238bceSAndroid Build Coastguard Worker         ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texBias" + ndxStr).c_str()), 1, m_texBiases[ndx].getPtr());
448*35238bceSAndroid Build Coastguard Worker     }
449*35238bceSAndroid Build Coastguard Worker }
450*35238bceSAndroid Build Coastguard Worker 
makeSafeLods(const vector<IVec3> & textureSizes,const IVec2 & viewportSize)451*35238bceSAndroid Build Coastguard Worker void MultiTexShader::makeSafeLods(const vector<IVec3> &textureSizes, const IVec2 &viewportSize)
452*35238bceSAndroid Build Coastguard Worker {
453*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((int)textureSizes.size() == m_numUnits);
454*35238bceSAndroid Build Coastguard Worker 
455*35238bceSAndroid Build Coastguard Worker     static const float shrinkScaleMat2dData[3 * 3] = {0.95f, 0.0f, 0.0f, 0.0f, 0.95f, 0.0f, 0.0f, 0.0f, 1.0f};
456*35238bceSAndroid Build Coastguard Worker     static const float shrinkScaleMat3dData[3 * 3] = {0.95f, 0.0f, 0.0f, 0.0f, 0.95f, 0.0f, 0.0f, 0.0f, 0.95f};
457*35238bceSAndroid Build Coastguard Worker     Mat4 shrinkScaleMat2d                          = matExtend3To4(Mat3(shrinkScaleMat2dData));
458*35238bceSAndroid Build Coastguard Worker     Mat4 shrinkScaleMat3d                          = matExtend3To4(Mat3(shrinkScaleMat3dData));
459*35238bceSAndroid Build Coastguard Worker 
460*35238bceSAndroid Build Coastguard Worker     Vec2 screenDerivate(1.0f / (float)viewportSize.x(), 1.0f / (float)viewportSize.y());
461*35238bceSAndroid Build Coastguard Worker 
462*35238bceSAndroid Build Coastguard Worker     for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
463*35238bceSAndroid Build Coastguard Worker     {
464*35238bceSAndroid Build Coastguard Worker         // 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.
465*35238bceSAndroid Build Coastguard Worker         for (;;)
466*35238bceSAndroid Build Coastguard Worker         {
467*35238bceSAndroid Build Coastguard Worker             const float threshold = 0.1f;
468*35238bceSAndroid Build Coastguard Worker             const float epsilon   = 0.01f;
469*35238bceSAndroid Build Coastguard Worker 
470*35238bceSAndroid Build Coastguard Worker             const float lodMax = calculateLodMax(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);
471*35238bceSAndroid Build Coastguard Worker             const float lodMin = calculateLodMin(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);
472*35238bceSAndroid Build Coastguard Worker 
473*35238bceSAndroid Build Coastguard Worker             const int32_t maxLevel =
474*35238bceSAndroid Build Coastguard Worker                 (lodMax + epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMax + epsilon + 0.5f) - 1);
475*35238bceSAndroid Build Coastguard Worker             const int32_t minLevel =
476*35238bceSAndroid Build Coastguard Worker                 (lodMin - epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMin - epsilon + 0.5f) - 1);
477*35238bceSAndroid Build Coastguard Worker 
478*35238bceSAndroid Build Coastguard Worker             if (de::abs(lodMax) < threshold || (lodMax > 0.0f && de::abs(deFloatFrac(lodMax) - 0.5f) < threshold) ||
479*35238bceSAndroid Build Coastguard Worker                 de::abs(lodMin) < threshold || (lodMin > 0.0f && de::abs(deFloatFrac(lodMin) - 0.5f) < threshold) ||
480*35238bceSAndroid Build Coastguard Worker                 maxLevel != minLevel)
481*35238bceSAndroid Build Coastguard Worker             {
482*35238bceSAndroid Build Coastguard Worker                 m_transformations[unitNdx] =
483*35238bceSAndroid Build Coastguard Worker                     (m_unitTypes[unitNdx] == GL_TEXTURE_3D ? shrinkScaleMat3d : shrinkScaleMat2d) *
484*35238bceSAndroid Build Coastguard Worker                     m_transformations[unitNdx];
485*35238bceSAndroid Build Coastguard Worker                 m_lodDerivateParts[unitNdx] = calculateLodDerivateParts(m_transformations[unitNdx]);
486*35238bceSAndroid Build Coastguard Worker             }
487*35238bceSAndroid Build Coastguard Worker             else
488*35238bceSAndroid Build Coastguard Worker                 break;
489*35238bceSAndroid Build Coastguard Worker         }
490*35238bceSAndroid Build Coastguard Worker     }
491*35238bceSAndroid Build Coastguard Worker }
492*35238bceSAndroid Build Coastguard Worker 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const493*35238bceSAndroid Build Coastguard Worker void MultiTexShader::shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets,
494*35238bceSAndroid Build Coastguard Worker                                    const int numPackets) const
495*35238bceSAndroid Build Coastguard Worker {
496*35238bceSAndroid Build Coastguard Worker     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
497*35238bceSAndroid Build Coastguard Worker     {
498*35238bceSAndroid Build Coastguard Worker         rr::VertexPacket &packet = *(packets[packetNdx]);
499*35238bceSAndroid Build Coastguard Worker 
500*35238bceSAndroid Build Coastguard Worker         packet.position   = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
501*35238bceSAndroid Build Coastguard Worker         packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
502*35238bceSAndroid Build Coastguard Worker     }
503*35238bceSAndroid Build Coastguard Worker }
504*35238bceSAndroid Build Coastguard Worker 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const505*35238bceSAndroid Build Coastguard Worker void MultiTexShader::shadeFragments(rr::FragmentPacket *packets, const int numPackets,
506*35238bceSAndroid Build Coastguard Worker                                     const rr::FragmentShadingContext &context) const
507*35238bceSAndroid Build Coastguard Worker {
508*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((int)m_unitTypes.size() == m_numUnits);
509*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((int)m_transformations.size() == m_numUnits);
510*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((int)m_lodDerivateParts.size() == m_numUnits);
511*35238bceSAndroid Build Coastguard Worker 
512*35238bceSAndroid Build Coastguard Worker     for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
513*35238bceSAndroid Build Coastguard Worker     {
514*35238bceSAndroid Build Coastguard Worker         rr::FragmentPacket &packet  = packets[packetNdx];
515*35238bceSAndroid Build Coastguard Worker         const float colorMultiplier = 1.0f / (float)m_numUnits;
516*35238bceSAndroid Build Coastguard Worker         Vec4 outColors[4]           = {Vec4(0.0f), Vec4(0.0f), Vec4(0.0f), Vec4(0.0f)};
517*35238bceSAndroid Build Coastguard Worker 
518*35238bceSAndroid Build Coastguard Worker         for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
519*35238bceSAndroid Build Coastguard Worker         {
520*35238bceSAndroid Build Coastguard Worker             tcu::Vec4 texSamples[4];
521*35238bceSAndroid Build Coastguard Worker 
522*35238bceSAndroid Build Coastguard Worker             // Read tex coords
523*35238bceSAndroid Build Coastguard Worker             const tcu::Vec2 texCoords[4] = {
524*35238bceSAndroid Build Coastguard Worker                 rr::readTriangleVarying<float>(packet, context, 0, 0).xy(),
525*35238bceSAndroid Build Coastguard Worker                 rr::readTriangleVarying<float>(packet, context, 0, 1).xy(),
526*35238bceSAndroid Build Coastguard Worker                 rr::readTriangleVarying<float>(packet, context, 0, 2).xy(),
527*35238bceSAndroid Build Coastguard Worker                 rr::readTriangleVarying<float>(packet, context, 0, 3).xy(),
528*35238bceSAndroid Build Coastguard Worker             };
529*35238bceSAndroid Build Coastguard Worker 
530*35238bceSAndroid Build Coastguard Worker             // Transform
531*35238bceSAndroid Build Coastguard Worker             tcu::Vec3 coords3D[4] = {
532*35238bceSAndroid Build Coastguard Worker                 (m_transformations[unitNdx] * Vec4(texCoords[0].x(), texCoords[0].y(), 1.0f, 1.0f)).xyz(),
533*35238bceSAndroid Build Coastguard Worker                 (m_transformations[unitNdx] * Vec4(texCoords[1].x(), texCoords[1].y(), 1.0f, 1.0f)).xyz(),
534*35238bceSAndroid Build Coastguard Worker                 (m_transformations[unitNdx] * Vec4(texCoords[2].x(), texCoords[2].y(), 1.0f, 1.0f)).xyz(),
535*35238bceSAndroid Build Coastguard Worker                 (m_transformations[unitNdx] * Vec4(texCoords[3].x(), texCoords[3].y(), 1.0f, 1.0f)).xyz(),
536*35238bceSAndroid Build Coastguard Worker             };
537*35238bceSAndroid Build Coastguard Worker 
538*35238bceSAndroid Build Coastguard Worker             // To 2D
539*35238bceSAndroid Build Coastguard Worker             const tcu::Vec2 coords2D[4] = {
540*35238bceSAndroid Build Coastguard Worker                 coords3D[0].xy(),
541*35238bceSAndroid Build Coastguard Worker                 coords3D[1].xy(),
542*35238bceSAndroid Build Coastguard Worker                 coords3D[2].xy(),
543*35238bceSAndroid Build Coastguard Worker                 coords3D[3].xy(),
544*35238bceSAndroid Build Coastguard Worker             };
545*35238bceSAndroid Build Coastguard Worker 
546*35238bceSAndroid Build Coastguard Worker             // Sample
547*35238bceSAndroid Build Coastguard Worker             switch (m_unitTypes[unitNdx])
548*35238bceSAndroid Build Coastguard Worker             {
549*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D:
550*35238bceSAndroid Build Coastguard Worker                 m_uniforms[4 * unitNdx].sampler.tex2D->sample4(texSamples, coords2D);
551*35238bceSAndroid Build Coastguard Worker                 break;
552*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_CUBE_MAP:
553*35238bceSAndroid Build Coastguard Worker                 m_uniforms[4 * unitNdx].sampler.texCube->sample4(texSamples, coords3D);
554*35238bceSAndroid Build Coastguard Worker                 break;
555*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D_ARRAY:
556*35238bceSAndroid Build Coastguard Worker                 m_uniforms[4 * unitNdx].sampler.tex2DArray->sample4(texSamples, coords3D);
557*35238bceSAndroid Build Coastguard Worker                 break;
558*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_3D:
559*35238bceSAndroid Build Coastguard Worker                 m_uniforms[4 * unitNdx].sampler.tex3D->sample4(texSamples, coords3D);
560*35238bceSAndroid Build Coastguard Worker                 break;
561*35238bceSAndroid Build Coastguard Worker             default:
562*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
563*35238bceSAndroid Build Coastguard Worker             }
564*35238bceSAndroid Build Coastguard Worker 
565*35238bceSAndroid Build Coastguard Worker             // Add to sum
566*35238bceSAndroid Build Coastguard Worker             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
567*35238bceSAndroid Build Coastguard Worker                 outColors[fragNdx] +=
568*35238bceSAndroid Build Coastguard Worker                     colorMultiplier * (texSamples[fragNdx] * m_texScales[unitNdx] + m_texBiases[unitNdx]);
569*35238bceSAndroid Build Coastguard Worker         }
570*35238bceSAndroid Build Coastguard Worker 
571*35238bceSAndroid Build Coastguard Worker         // output
572*35238bceSAndroid Build Coastguard Worker         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
573*35238bceSAndroid Build Coastguard Worker             rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, outColors[fragNdx]);
574*35238bceSAndroid Build Coastguard Worker     }
575*35238bceSAndroid Build Coastguard Worker }
576*35238bceSAndroid Build Coastguard Worker 
577*35238bceSAndroid Build Coastguard Worker class TextureUnitCase : public TestCase
578*35238bceSAndroid Build Coastguard Worker {
579*35238bceSAndroid Build Coastguard Worker public:
580*35238bceSAndroid Build Coastguard Worker     enum CaseType
581*35238bceSAndroid Build Coastguard Worker     {
582*35238bceSAndroid Build Coastguard Worker         CASE_ONLY_2D = 0,
583*35238bceSAndroid Build Coastguard Worker         CASE_ONLY_CUBE,
584*35238bceSAndroid Build Coastguard Worker         CASE_ONLY_2D_ARRAY,
585*35238bceSAndroid Build Coastguard Worker         CASE_ONLY_3D,
586*35238bceSAndroid Build Coastguard Worker         CASE_MIXED,
587*35238bceSAndroid Build Coastguard Worker 
588*35238bceSAndroid Build Coastguard Worker         CASE_LAST
589*35238bceSAndroid Build Coastguard Worker     };
590*35238bceSAndroid Build Coastguard Worker     TextureUnitCase(Context &context, const char *name, const char *desc,
591*35238bceSAndroid Build Coastguard Worker                     int numUnits /* \note If non-positive, use all units */, CaseType caseType, uint32_t randSeed);
592*35238bceSAndroid Build Coastguard Worker     ~TextureUnitCase(void);
593*35238bceSAndroid Build Coastguard Worker 
594*35238bceSAndroid Build Coastguard Worker     void init(void);
595*35238bceSAndroid Build Coastguard Worker     void deinit(void);
596*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
597*35238bceSAndroid Build Coastguard Worker 
598*35238bceSAndroid Build Coastguard Worker private:
599*35238bceSAndroid Build Coastguard Worker     struct TextureParameters
600*35238bceSAndroid Build Coastguard Worker     {
601*35238bceSAndroid Build Coastguard Worker         GLenum internalFormat;
602*35238bceSAndroid Build Coastguard Worker         GLenum wrapModeS;
603*35238bceSAndroid Build Coastguard Worker         GLenum wrapModeT;
604*35238bceSAndroid Build Coastguard Worker         GLenum wrapModeR;
605*35238bceSAndroid Build Coastguard Worker         GLenum minFilter;
606*35238bceSAndroid Build Coastguard Worker         GLenum magFilter;
607*35238bceSAndroid Build Coastguard Worker     };
608*35238bceSAndroid Build Coastguard Worker 
609*35238bceSAndroid Build Coastguard Worker     TextureUnitCase(const TextureUnitCase &other);
610*35238bceSAndroid Build Coastguard Worker     TextureUnitCase &operator=(const TextureUnitCase &other);
611*35238bceSAndroid Build Coastguard Worker 
612*35238bceSAndroid Build Coastguard Worker     void upload2dTexture(int texNdx, sglr::Context &context);
613*35238bceSAndroid Build Coastguard Worker     void uploadCubeTexture(int texNdx, sglr::Context &context);
614*35238bceSAndroid Build Coastguard Worker     void upload2dArrayTexture(int texNdx, sglr::Context &context);
615*35238bceSAndroid Build Coastguard Worker     void upload3dTexture(int texNdx, sglr::Context &context);
616*35238bceSAndroid Build Coastguard Worker 
617*35238bceSAndroid Build Coastguard Worker     void render(sglr::Context &context);
618*35238bceSAndroid Build Coastguard Worker 
619*35238bceSAndroid Build Coastguard Worker     const int m_numUnitsParam;
620*35238bceSAndroid Build Coastguard Worker     const CaseType m_caseType;
621*35238bceSAndroid Build Coastguard Worker     const uint32_t m_randSeed;
622*35238bceSAndroid Build Coastguard Worker 
623*35238bceSAndroid Build Coastguard Worker     int m_numTextures; //!< \note Needed in addition to m_numUnits since same texture may be bound to many texture units.
624*35238bceSAndroid Build Coastguard Worker     int m_numUnits;    //!< = m_numUnitsParam > 0 ? m_numUnitsParam : implementationDefinedMaximum
625*35238bceSAndroid Build Coastguard Worker 
626*35238bceSAndroid Build Coastguard Worker     vector<GLenum> m_textureTypes;
627*35238bceSAndroid Build Coastguard Worker     vector<TextureParameters> m_textureParams;
628*35238bceSAndroid Build Coastguard Worker     vector<tcu::Texture2D *> m_textures2d;
629*35238bceSAndroid Build Coastguard Worker     vector<tcu::TextureCube *> m_texturesCube;
630*35238bceSAndroid Build Coastguard Worker     vector<tcu::Texture2DArray *> m_textures2dArray;
631*35238bceSAndroid Build Coastguard Worker     vector<tcu::Texture3D *> m_textures3d;
632*35238bceSAndroid Build Coastguard Worker     vector<int> m_unitTextures; //!< Which texture is used in a particular unit.
633*35238bceSAndroid Build Coastguard Worker     vector<int>
634*35238bceSAndroid Build Coastguard Worker         m_ndxTexType; //!< Index of a texture in m_textures2d, m_texturesCube, m_textures2dArray or m_textures3d, depending on texture type.
635*35238bceSAndroid Build Coastguard Worker     MultiTexShader *m_shader;
636*35238bceSAndroid Build Coastguard Worker };
637*35238bceSAndroid Build Coastguard Worker 
TextureUnitCase(Context & context,const char * name,const char * desc,int numUnits,CaseType caseType,uint32_t randSeed)638*35238bceSAndroid Build Coastguard Worker TextureUnitCase::TextureUnitCase(Context &context, const char *name, const char *desc, int numUnits, CaseType caseType,
639*35238bceSAndroid Build Coastguard Worker                                  uint32_t randSeed)
640*35238bceSAndroid Build Coastguard Worker     : TestCase(context, tcu::NODETYPE_SELF_VALIDATE, name, desc)
641*35238bceSAndroid Build Coastguard Worker     , m_numUnitsParam(numUnits)
642*35238bceSAndroid Build Coastguard Worker     , m_caseType(caseType)
643*35238bceSAndroid Build Coastguard Worker     , m_randSeed(randSeed)
644*35238bceSAndroid Build Coastguard Worker     , m_numTextures(0)
645*35238bceSAndroid Build Coastguard Worker     , m_numUnits(0)
646*35238bceSAndroid Build Coastguard Worker     , m_shader(DE_NULL)
647*35238bceSAndroid Build Coastguard Worker {
648*35238bceSAndroid Build Coastguard Worker }
649*35238bceSAndroid Build Coastguard Worker 
~TextureUnitCase(void)650*35238bceSAndroid Build Coastguard Worker TextureUnitCase::~TextureUnitCase(void)
651*35238bceSAndroid Build Coastguard Worker {
652*35238bceSAndroid Build Coastguard Worker     TextureUnitCase::deinit();
653*35238bceSAndroid Build Coastguard Worker }
654*35238bceSAndroid Build Coastguard Worker 
deinit(void)655*35238bceSAndroid Build Coastguard Worker void TextureUnitCase::deinit(void)
656*35238bceSAndroid Build Coastguard Worker {
657*35238bceSAndroid Build Coastguard Worker     for (vector<tcu::Texture2D *>::iterator i = m_textures2d.begin(); i != m_textures2d.end(); i++)
658*35238bceSAndroid Build Coastguard Worker         delete *i;
659*35238bceSAndroid Build Coastguard Worker     m_textures2d.clear();
660*35238bceSAndroid Build Coastguard Worker 
661*35238bceSAndroid Build Coastguard Worker     for (vector<tcu::TextureCube *>::iterator i = m_texturesCube.begin(); i != m_texturesCube.end(); i++)
662*35238bceSAndroid Build Coastguard Worker         delete *i;
663*35238bceSAndroid Build Coastguard Worker     m_texturesCube.clear();
664*35238bceSAndroid Build Coastguard Worker 
665*35238bceSAndroid Build Coastguard Worker     for (vector<tcu::Texture2DArray *>::iterator i = m_textures2dArray.begin(); i != m_textures2dArray.end(); i++)
666*35238bceSAndroid Build Coastguard Worker         delete *i;
667*35238bceSAndroid Build Coastguard Worker     m_textures2dArray.clear();
668*35238bceSAndroid Build Coastguard Worker 
669*35238bceSAndroid Build Coastguard Worker     for (vector<tcu::Texture3D *>::iterator i = m_textures3d.begin(); i != m_textures3d.end(); i++)
670*35238bceSAndroid Build Coastguard Worker         delete *i;
671*35238bceSAndroid Build Coastguard Worker     m_textures3d.clear();
672*35238bceSAndroid Build Coastguard Worker 
673*35238bceSAndroid Build Coastguard Worker     delete m_shader;
674*35238bceSAndroid Build Coastguard Worker     m_shader = DE_NULL;
675*35238bceSAndroid Build Coastguard Worker }
676*35238bceSAndroid Build Coastguard Worker 
init(void)677*35238bceSAndroid Build Coastguard Worker void TextureUnitCase::init(void)
678*35238bceSAndroid Build Coastguard Worker {
679*35238bceSAndroid Build Coastguard Worker     m_numUnits = m_numUnitsParam > 0 ? m_numUnitsParam : m_context.getContextInfo().getInt(GL_MAX_TEXTURE_IMAGE_UNITS);
680*35238bceSAndroid Build Coastguard Worker 
681*35238bceSAndroid Build Coastguard Worker     // Make the textures.
682*35238bceSAndroid Build Coastguard Worker 
683*35238bceSAndroid Build Coastguard Worker     try
684*35238bceSAndroid Build Coastguard Worker     {
685*35238bceSAndroid Build Coastguard Worker         tcu::TestLog &log = m_testCtx.getLog();
686*35238bceSAndroid Build Coastguard Worker         de::Random rnd(m_randSeed);
687*35238bceSAndroid Build Coastguard Worker 
688*35238bceSAndroid Build Coastguard Worker         if (rnd.getFloat() < 0.7f)
689*35238bceSAndroid Build Coastguard Worker             m_numTextures = m_numUnits; // In most cases use one unit per texture.
690*35238bceSAndroid Build Coastguard Worker         else
691*35238bceSAndroid Build Coastguard Worker             m_numTextures =
692*35238bceSAndroid Build Coastguard Worker                 rnd.getInt(deMax32(1, m_numUnits - 2), m_numUnits); // Sometimes assign same texture to multiple units.
693*35238bceSAndroid Build Coastguard Worker 
694*35238bceSAndroid Build Coastguard Worker         log << tcu::TestLog::Message
695*35238bceSAndroid Build Coastguard Worker             << ("Using " + de::toString(m_numUnits) + " texture unit(s) and " + de::toString(m_numTextures) +
696*35238bceSAndroid Build Coastguard Worker                 " texture(s)")
697*35238bceSAndroid Build Coastguard Worker                    .c_str()
698*35238bceSAndroid Build Coastguard Worker             << tcu::TestLog::EndMessage;
699*35238bceSAndroid Build Coastguard Worker 
700*35238bceSAndroid Build Coastguard Worker         m_textureTypes.reserve(m_numTextures);
701*35238bceSAndroid Build Coastguard Worker         m_textureParams.reserve(m_numTextures);
702*35238bceSAndroid Build Coastguard Worker         m_ndxTexType.reserve(m_numTextures);
703*35238bceSAndroid Build Coastguard Worker 
704*35238bceSAndroid Build Coastguard Worker         // Generate textures.
705*35238bceSAndroid Build Coastguard Worker 
706*35238bceSAndroid Build Coastguard Worker         for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
707*35238bceSAndroid Build Coastguard Worker         {
708*35238bceSAndroid Build Coastguard Worker             // Either fixed or randomized target types, and randomized parameters for every texture.
709*35238bceSAndroid Build Coastguard Worker 
710*35238bceSAndroid Build Coastguard Worker             TextureParameters params;
711*35238bceSAndroid Build Coastguard Worker 
712*35238bceSAndroid Build Coastguard Worker             DE_STATIC_ASSERT(CASE_ONLY_2D == 0 && CASE_MIXED + 1 == CASE_LAST);
713*35238bceSAndroid Build Coastguard Worker 
714*35238bceSAndroid Build Coastguard Worker             int texType       = m_caseType == CASE_MIXED ? rnd.getInt(0, (int)CASE_MIXED - 1) : (int)m_caseType;
715*35238bceSAndroid Build Coastguard Worker             bool is2dTex      = texType == 0;
716*35238bceSAndroid Build Coastguard Worker             bool isCubeTex    = texType == 1;
717*35238bceSAndroid Build Coastguard Worker             bool is2dArrayTex = texType == 2;
718*35238bceSAndroid Build Coastguard Worker             bool is3dTex      = texType == 3;
719*35238bceSAndroid Build Coastguard Worker 
720*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(is2dTex || isCubeTex || is2dArrayTex || is3dTex);
721*35238bceSAndroid Build Coastguard Worker 
722*35238bceSAndroid Build Coastguard Worker             GLenum type         = is2dTex      ? GL_TEXTURE_2D :
723*35238bceSAndroid Build Coastguard Worker                                   isCubeTex    ? GL_TEXTURE_CUBE_MAP :
724*35238bceSAndroid Build Coastguard Worker                                   is2dArrayTex ? GL_TEXTURE_2D_ARRAY :
725*35238bceSAndroid Build Coastguard Worker                                                  GL_TEXTURE_3D;
726*35238bceSAndroid Build Coastguard Worker             const int texWidth  = is2dTex      ? TEXTURE_WIDTH_2D :
727*35238bceSAndroid Build Coastguard Worker                                   isCubeTex    ? TEXTURE_WIDTH_CUBE :
728*35238bceSAndroid Build Coastguard Worker                                   is2dArrayTex ? TEXTURE_WIDTH_2D_ARRAY :
729*35238bceSAndroid Build Coastguard Worker                                                  TEXTURE_WIDTH_3D;
730*35238bceSAndroid Build Coastguard Worker             const int texHeight = is2dTex      ? TEXTURE_HEIGHT_2D :
731*35238bceSAndroid Build Coastguard Worker                                   isCubeTex    ? TEXTURE_HEIGHT_CUBE :
732*35238bceSAndroid Build Coastguard Worker                                   is2dArrayTex ? TEXTURE_HEIGHT_2D_ARRAY :
733*35238bceSAndroid Build Coastguard Worker                                                  TEXTURE_HEIGHT_3D;
734*35238bceSAndroid Build Coastguard Worker 
735*35238bceSAndroid Build Coastguard Worker             const int texDepth  = is3dTex ? TEXTURE_DEPTH_3D : 1;
736*35238bceSAndroid Build Coastguard Worker             const int texLayers = is2dArrayTex ? TEXTURE_LAYERS_2D_ARRAY : 1;
737*35238bceSAndroid Build Coastguard Worker 
738*35238bceSAndroid Build Coastguard Worker             bool mipmaps  = (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight) && deIsPowerOfTwo32(texDepth));
739*35238bceSAndroid Build Coastguard Worker             int numLevels = mipmaps ? deLog2Floor32(de::max(de::max(texWidth, texHeight), texDepth)) + 1 : 1;
740*35238bceSAndroid Build Coastguard Worker 
741*35238bceSAndroid Build Coastguard Worker             params.internalFormat =
742*35238bceSAndroid Build Coastguard Worker                 s_testSizedInternalFormats[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testSizedInternalFormats) - 1)];
743*35238bceSAndroid Build Coastguard Worker 
744*35238bceSAndroid Build Coastguard Worker             bool isFilterable = glu::isGLInternalColorFormatFilterable(params.internalFormat);
745*35238bceSAndroid Build Coastguard Worker 
746*35238bceSAndroid Build Coastguard Worker             params.wrapModeS = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
747*35238bceSAndroid Build Coastguard Worker             params.wrapModeT = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
748*35238bceSAndroid Build Coastguard Worker             params.wrapModeR = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
749*35238bceSAndroid Build Coastguard Worker 
750*35238bceSAndroid Build Coastguard Worker             params.magFilter =
751*35238bceSAndroid Build Coastguard Worker                 isFilterable ? s_testMagFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMagFilters) - 1)] : GL_NEAREST;
752*35238bceSAndroid Build Coastguard Worker 
753*35238bceSAndroid Build Coastguard Worker             if (mipmaps)
754*35238bceSAndroid Build Coastguard Worker                 params.minFilter =
755*35238bceSAndroid Build Coastguard Worker                     isFilterable ?
756*35238bceSAndroid Build Coastguard Worker                         s_testMinFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMinFilters) - 1)] :
757*35238bceSAndroid Build Coastguard Worker                         s_testNearestMinFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNearestMinFilters) - 1)];
758*35238bceSAndroid Build Coastguard Worker             else
759*35238bceSAndroid Build Coastguard Worker                 params.minFilter =
760*35238bceSAndroid Build Coastguard Worker                     isFilterable ?
761*35238bceSAndroid Build Coastguard Worker                         s_testNonMipmapMinFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNonMipmapMinFilters) - 1)] :
762*35238bceSAndroid Build Coastguard Worker                         GL_NEAREST;
763*35238bceSAndroid Build Coastguard Worker 
764*35238bceSAndroid Build Coastguard Worker             m_textureTypes.push_back(type);
765*35238bceSAndroid Build Coastguard Worker             m_textureParams.push_back(params);
766*35238bceSAndroid Build Coastguard Worker 
767*35238bceSAndroid Build Coastguard Worker             // Create new texture.
768*35238bceSAndroid Build Coastguard Worker 
769*35238bceSAndroid Build Coastguard Worker             tcu::TextureFormat texFormat = glu::mapGLInternalFormat((uint32_t)params.internalFormat);
770*35238bceSAndroid Build Coastguard Worker 
771*35238bceSAndroid Build Coastguard Worker             if (is2dTex)
772*35238bceSAndroid Build Coastguard Worker             {
773*35238bceSAndroid Build Coastguard Worker                 m_ndxTexType.push_back(
774*35238bceSAndroid Build Coastguard Worker                     (int)m_textures2d.size()); // Remember the index this texture has in the 2d texture vector.
775*35238bceSAndroid Build Coastguard Worker                 m_textures2d.push_back(new tcu::Texture2D(texFormat, texWidth, texHeight));
776*35238bceSAndroid Build Coastguard Worker             }
777*35238bceSAndroid Build Coastguard Worker             else if (isCubeTex)
778*35238bceSAndroid Build Coastguard Worker             {
779*35238bceSAndroid Build Coastguard Worker                 m_ndxTexType.push_back(
780*35238bceSAndroid Build Coastguard Worker                     (int)m_texturesCube.size()); // Remember the index this texture has in the cube texture vector.
781*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(texWidth == texHeight);
782*35238bceSAndroid Build Coastguard Worker                 m_texturesCube.push_back(new tcu::TextureCube(texFormat, texWidth));
783*35238bceSAndroid Build Coastguard Worker             }
784*35238bceSAndroid Build Coastguard Worker             else if (is2dArrayTex)
785*35238bceSAndroid Build Coastguard Worker             {
786*35238bceSAndroid Build Coastguard Worker                 m_ndxTexType.push_back(
787*35238bceSAndroid Build Coastguard Worker                     (int)m_textures2dArray
788*35238bceSAndroid Build Coastguard Worker                         .size()); // Remember the index this texture has in the 2d array texture vector.
789*35238bceSAndroid Build Coastguard Worker                 m_textures2dArray.push_back(new tcu::Texture2DArray(texFormat, texWidth, texHeight, texLayers));
790*35238bceSAndroid Build Coastguard Worker             }
791*35238bceSAndroid Build Coastguard Worker             else
792*35238bceSAndroid Build Coastguard Worker             {
793*35238bceSAndroid Build Coastguard Worker                 m_ndxTexType.push_back(
794*35238bceSAndroid Build Coastguard Worker                     (int)m_textures3d.size()); // Remember the index this texture has in the 3d vector.
795*35238bceSAndroid Build Coastguard Worker                 m_textures3d.push_back(new tcu::Texture3D(texFormat, texWidth, texHeight, texDepth));
796*35238bceSAndroid Build Coastguard Worker             }
797*35238bceSAndroid Build Coastguard Worker 
798*35238bceSAndroid Build Coastguard Worker             tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
799*35238bceSAndroid Build Coastguard Worker             Vec4 cBias                     = fmtInfo.valueMin;
800*35238bceSAndroid Build Coastguard Worker             Vec4 cScale                    = fmtInfo.valueMax - fmtInfo.valueMin;
801*35238bceSAndroid Build Coastguard Worker 
802*35238bceSAndroid Build Coastguard Worker             // Fill with grid texture.
803*35238bceSAndroid Build Coastguard Worker 
804*35238bceSAndroid Build Coastguard Worker             int numFaces = isCubeTex ? (int)tcu::CUBEFACE_LAST : 1;
805*35238bceSAndroid Build Coastguard Worker 
806*35238bceSAndroid Build Coastguard Worker             for (int face = 0; face < numFaces; face++)
807*35238bceSAndroid Build Coastguard Worker             {
808*35238bceSAndroid Build Coastguard Worker                 uint32_t rgb   = rnd.getUint32() & 0x00ffffff;
809*35238bceSAndroid Build Coastguard Worker                 uint32_t alpha = 0xff000000;
810*35238bceSAndroid Build Coastguard Worker 
811*35238bceSAndroid Build Coastguard Worker                 uint32_t colorA = alpha | rgb;
812*35238bceSAndroid Build Coastguard Worker                 uint32_t colorB = alpha | ((~rgb) & 0x00ffffff);
813*35238bceSAndroid Build Coastguard Worker 
814*35238bceSAndroid Build Coastguard Worker                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
815*35238bceSAndroid Build Coastguard Worker                 {
816*35238bceSAndroid Build Coastguard Worker                     if (is2dTex)
817*35238bceSAndroid Build Coastguard Worker                         m_textures2d.back()->allocLevel(levelNdx);
818*35238bceSAndroid Build Coastguard Worker                     else if (isCubeTex)
819*35238bceSAndroid Build Coastguard Worker                         m_texturesCube.back()->allocLevel((tcu::CubeFace)face, levelNdx);
820*35238bceSAndroid Build Coastguard Worker                     else if (is2dArrayTex)
821*35238bceSAndroid Build Coastguard Worker                         m_textures2dArray.back()->allocLevel(levelNdx);
822*35238bceSAndroid Build Coastguard Worker                     else
823*35238bceSAndroid Build Coastguard Worker                         m_textures3d.back()->allocLevel(levelNdx);
824*35238bceSAndroid Build Coastguard Worker 
825*35238bceSAndroid Build Coastguard Worker                     int curCellSize = deMax32(1, GRID_CELL_SIZE >> levelNdx); // \note Scale grid cell size for mipmaps.
826*35238bceSAndroid Build Coastguard Worker 
827*35238bceSAndroid Build Coastguard Worker                     tcu::PixelBufferAccess access =
828*35238bceSAndroid Build Coastguard Worker                         is2dTex      ? m_textures2d.back()->getLevel(levelNdx) :
829*35238bceSAndroid Build Coastguard Worker                         isCubeTex    ? m_texturesCube.back()->getLevelFace(levelNdx, (tcu::CubeFace)face) :
830*35238bceSAndroid Build Coastguard Worker                         is2dArrayTex ? m_textures2dArray.back()->getLevel(levelNdx) :
831*35238bceSAndroid Build Coastguard Worker                                        m_textures3d.back()->getLevel(levelNdx);
832*35238bceSAndroid Build Coastguard Worker 
833*35238bceSAndroid Build Coastguard Worker                     tcu::fillWithGrid(access, curCellSize, tcu::RGBA(colorA).toVec() * cScale + cBias,
834*35238bceSAndroid Build Coastguard Worker                                       tcu::RGBA(colorB).toVec() * cScale + cBias);
835*35238bceSAndroid Build Coastguard Worker                 }
836*35238bceSAndroid Build Coastguard Worker             }
837*35238bceSAndroid Build Coastguard Worker         }
838*35238bceSAndroid Build Coastguard Worker 
839*35238bceSAndroid Build Coastguard Worker         // Assign a texture index to each unit.
840*35238bceSAndroid Build Coastguard Worker 
841*35238bceSAndroid Build Coastguard Worker         m_unitTextures.reserve(m_numUnits);
842*35238bceSAndroid Build Coastguard Worker 
843*35238bceSAndroid Build Coastguard Worker         // \note Every texture is used at least once.
844*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < m_numTextures; i++)
845*35238bceSAndroid Build Coastguard Worker             m_unitTextures.push_back(i);
846*35238bceSAndroid Build Coastguard Worker 
847*35238bceSAndroid Build Coastguard Worker         // Assign a random texture to remaining units.
848*35238bceSAndroid Build Coastguard Worker         while ((int)m_unitTextures.size() < m_numUnits)
849*35238bceSAndroid Build Coastguard Worker             m_unitTextures.push_back(rnd.getInt(0, m_numTextures - 1));
850*35238bceSAndroid Build Coastguard Worker 
851*35238bceSAndroid Build Coastguard Worker         rnd.shuffle(m_unitTextures.begin(), m_unitTextures.end());
852*35238bceSAndroid Build Coastguard Worker 
853*35238bceSAndroid Build Coastguard Worker         // Generate information for shader.
854*35238bceSAndroid Build Coastguard Worker 
855*35238bceSAndroid Build Coastguard Worker         vector<GLenum> unitTypes;
856*35238bceSAndroid Build Coastguard Worker         vector<Vec4> texScales;
857*35238bceSAndroid Build Coastguard Worker         vector<Vec4> texBiases;
858*35238bceSAndroid Build Coastguard Worker         vector<glu::DataType> samplerTypes;
859*35238bceSAndroid Build Coastguard Worker         vector<int> num2dArrayLayers;
860*35238bceSAndroid Build Coastguard Worker 
861*35238bceSAndroid Build Coastguard Worker         unitTypes.reserve(m_numUnits);
862*35238bceSAndroid Build Coastguard Worker         texScales.reserve(m_numUnits);
863*35238bceSAndroid Build Coastguard Worker         texBiases.reserve(m_numUnits);
864*35238bceSAndroid Build Coastguard Worker         samplerTypes.reserve(m_numUnits);
865*35238bceSAndroid Build Coastguard Worker         num2dArrayLayers.reserve(m_numUnits);
866*35238bceSAndroid Build Coastguard Worker 
867*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < m_numUnits; i++)
868*35238bceSAndroid Build Coastguard Worker         {
869*35238bceSAndroid Build Coastguard Worker             int texNdx                     = m_unitTextures[i];
870*35238bceSAndroid Build Coastguard Worker             GLenum type                    = m_textureTypes[texNdx];
871*35238bceSAndroid Build Coastguard Worker             tcu::TextureFormat fmt         = glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat);
872*35238bceSAndroid Build Coastguard Worker             tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fmt);
873*35238bceSAndroid Build Coastguard Worker 
874*35238bceSAndroid Build Coastguard Worker             unitTypes.push_back(type);
875*35238bceSAndroid Build Coastguard Worker 
876*35238bceSAndroid Build Coastguard Worker             if (type == GL_TEXTURE_2D_ARRAY)
877*35238bceSAndroid Build Coastguard Worker                 num2dArrayLayers.push_back(m_textures2dArray[m_ndxTexType[texNdx]]->getNumLayers());
878*35238bceSAndroid Build Coastguard Worker 
879*35238bceSAndroid Build Coastguard Worker             texScales.push_back(fmtInfo.lookupScale);
880*35238bceSAndroid Build Coastguard Worker             texBiases.push_back(fmtInfo.lookupBias);
881*35238bceSAndroid Build Coastguard Worker 
882*35238bceSAndroid Build Coastguard Worker             switch (type)
883*35238bceSAndroid Build Coastguard Worker             {
884*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D:
885*35238bceSAndroid Build Coastguard Worker                 samplerTypes.push_back(glu::getSampler2DType(fmt));
886*35238bceSAndroid Build Coastguard Worker                 break;
887*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_CUBE_MAP:
888*35238bceSAndroid Build Coastguard Worker                 samplerTypes.push_back(glu::getSamplerCubeType(fmt));
889*35238bceSAndroid Build Coastguard Worker                 break;
890*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D_ARRAY:
891*35238bceSAndroid Build Coastguard Worker                 samplerTypes.push_back(glu::getSampler2DArrayType(fmt));
892*35238bceSAndroid Build Coastguard Worker                 break;
893*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_3D:
894*35238bceSAndroid Build Coastguard Worker                 samplerTypes.push_back(glu::getSampler3DType(fmt));
895*35238bceSAndroid Build Coastguard Worker                 break;
896*35238bceSAndroid Build Coastguard Worker             default:
897*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
898*35238bceSAndroid Build Coastguard Worker             }
899*35238bceSAndroid Build Coastguard Worker         }
900*35238bceSAndroid Build Coastguard Worker 
901*35238bceSAndroid Build Coastguard Worker         // Create shader.
902*35238bceSAndroid Build Coastguard Worker 
903*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_shader == DE_NULL);
904*35238bceSAndroid Build Coastguard Worker         m_shader = new MultiTexShader(rnd.getUint32(), m_numUnits, unitTypes, samplerTypes, texScales, texBiases,
905*35238bceSAndroid Build Coastguard Worker                                       num2dArrayLayers);
906*35238bceSAndroid Build Coastguard Worker     }
907*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &)
908*35238bceSAndroid Build Coastguard Worker     {
909*35238bceSAndroid Build Coastguard Worker         // Clean up to save memory.
910*35238bceSAndroid Build Coastguard Worker         TextureUnitCase::deinit();
911*35238bceSAndroid Build Coastguard Worker         throw;
912*35238bceSAndroid Build Coastguard Worker     }
913*35238bceSAndroid Build Coastguard Worker }
914*35238bceSAndroid Build Coastguard Worker 
iterate(void)915*35238bceSAndroid Build Coastguard Worker TextureUnitCase::IterateResult TextureUnitCase::iterate(void)
916*35238bceSAndroid Build Coastguard Worker {
917*35238bceSAndroid Build Coastguard Worker     glu::RenderContext &renderCtx         = m_context.getRenderContext();
918*35238bceSAndroid Build Coastguard Worker     const tcu::RenderTarget &renderTarget = renderCtx.getRenderTarget();
919*35238bceSAndroid Build Coastguard Worker     tcu::TestLog &log                     = m_testCtx.getLog();
920*35238bceSAndroid Build Coastguard Worker     de::Random rnd(m_randSeed);
921*35238bceSAndroid Build Coastguard Worker 
922*35238bceSAndroid Build Coastguard Worker     int viewportWidth  = deMin32(VIEWPORT_WIDTH, renderTarget.getWidth());
923*35238bceSAndroid Build Coastguard Worker     int viewportHeight = deMin32(VIEWPORT_HEIGHT, renderTarget.getHeight());
924*35238bceSAndroid Build Coastguard Worker     int viewportX      = rnd.getInt(0, renderTarget.getWidth() - viewportWidth);
925*35238bceSAndroid Build Coastguard Worker     int viewportY      = rnd.getInt(0, renderTarget.getHeight() - viewportHeight);
926*35238bceSAndroid Build Coastguard Worker 
927*35238bceSAndroid Build Coastguard Worker     tcu::Surface gles3Frame(viewportWidth, viewportHeight);
928*35238bceSAndroid Build Coastguard Worker     tcu::Surface refFrame(viewportWidth, viewportHeight);
929*35238bceSAndroid Build Coastguard Worker 
930*35238bceSAndroid Build Coastguard Worker     {
931*35238bceSAndroid Build Coastguard Worker         // First we do some tricks to make the LODs safer wrt. precision issues. See MultiTexShader::makeSafeLods().
932*35238bceSAndroid Build Coastguard Worker 
933*35238bceSAndroid Build Coastguard Worker         vector<IVec3> texSizes;
934*35238bceSAndroid Build Coastguard Worker         texSizes.reserve(m_numUnits);
935*35238bceSAndroid Build Coastguard Worker 
936*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < m_numUnits; i++)
937*35238bceSAndroid Build Coastguard Worker         {
938*35238bceSAndroid Build Coastguard Worker             int texNdx       = m_unitTextures[i];
939*35238bceSAndroid Build Coastguard Worker             int texNdxInType = m_ndxTexType[texNdx];
940*35238bceSAndroid Build Coastguard Worker             GLenum type      = m_textureTypes[texNdx];
941*35238bceSAndroid Build Coastguard Worker 
942*35238bceSAndroid Build Coastguard Worker             switch (type)
943*35238bceSAndroid Build Coastguard Worker             {
944*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D:
945*35238bceSAndroid Build Coastguard Worker                 texSizes.push_back(
946*35238bceSAndroid Build Coastguard Worker                     IVec3(m_textures2d[texNdxInType]->getWidth(), m_textures2d[texNdxInType]->getHeight(), 0));
947*35238bceSAndroid Build Coastguard Worker                 break;
948*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_CUBE_MAP:
949*35238bceSAndroid Build Coastguard Worker                 texSizes.push_back(
950*35238bceSAndroid Build Coastguard Worker                     IVec3(m_texturesCube[texNdxInType]->getSize(), m_texturesCube[texNdxInType]->getSize(), 0));
951*35238bceSAndroid Build Coastguard Worker                 break;
952*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D_ARRAY:
953*35238bceSAndroid Build Coastguard Worker                 texSizes.push_back(IVec3(m_textures2dArray[texNdxInType]->getWidth(),
954*35238bceSAndroid Build Coastguard Worker                                          m_textures2dArray[texNdxInType]->getHeight(), 0));
955*35238bceSAndroid Build Coastguard Worker                 break;
956*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_3D:
957*35238bceSAndroid Build Coastguard Worker                 texSizes.push_back(IVec3(m_textures3d[texNdxInType]->getWidth(),
958*35238bceSAndroid Build Coastguard Worker                                          m_textures3d[texNdxInType]->getHeight(),
959*35238bceSAndroid Build Coastguard Worker                                          m_textures3d[texNdxInType]->getDepth()));
960*35238bceSAndroid Build Coastguard Worker                 break;
961*35238bceSAndroid Build Coastguard Worker             default:
962*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
963*35238bceSAndroid Build Coastguard Worker             }
964*35238bceSAndroid Build Coastguard Worker         }
965*35238bceSAndroid Build Coastguard Worker 
966*35238bceSAndroid Build Coastguard Worker         m_shader->makeSafeLods(texSizes, IVec2(viewportWidth, viewportHeight));
967*35238bceSAndroid Build Coastguard Worker     }
968*35238bceSAndroid Build Coastguard Worker 
969*35238bceSAndroid Build Coastguard Worker     // Render using GLES3.
970*35238bceSAndroid Build Coastguard Worker     {
971*35238bceSAndroid Build Coastguard Worker         sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS,
972*35238bceSAndroid Build Coastguard Worker                                 tcu::IVec4(viewportX, viewportY, viewportWidth, viewportHeight));
973*35238bceSAndroid Build Coastguard Worker 
974*35238bceSAndroid Build Coastguard Worker         render(context);
975*35238bceSAndroid Build Coastguard Worker 
976*35238bceSAndroid Build Coastguard Worker         context.readPixels(gles3Frame, 0, 0, viewportWidth, viewportHeight);
977*35238bceSAndroid Build Coastguard Worker     }
978*35238bceSAndroid Build Coastguard Worker 
979*35238bceSAndroid Build Coastguard Worker     // Render reference image.
980*35238bceSAndroid Build Coastguard Worker     {
981*35238bceSAndroid Build Coastguard Worker         sglr::ReferenceContextBuffers buffers(
982*35238bceSAndroid Build Coastguard Worker             tcu::PixelFormat(8, 8, 8, renderTarget.getPixelFormat().alphaBits ? 8 : 0), 0 /* depth */, 0 /* stencil */,
983*35238bceSAndroid Build Coastguard Worker             viewportWidth, viewportHeight);
984*35238bceSAndroid Build Coastguard Worker         sglr::ReferenceContext context(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(),
985*35238bceSAndroid Build Coastguard Worker                                        buffers.getDepthbuffer(), buffers.getStencilbuffer());
986*35238bceSAndroid Build Coastguard Worker 
987*35238bceSAndroid Build Coastguard Worker         render(context);
988*35238bceSAndroid Build Coastguard Worker 
989*35238bceSAndroid Build Coastguard Worker         context.readPixels(refFrame, 0, 0, viewportWidth, viewportHeight);
990*35238bceSAndroid Build Coastguard Worker     }
991*35238bceSAndroid Build Coastguard Worker 
992*35238bceSAndroid Build Coastguard Worker     // Compare images.
993*35238bceSAndroid Build Coastguard Worker     const float threshold = 0.001f;
994*35238bceSAndroid Build Coastguard Worker     bool isOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles3Frame, threshold,
995*35238bceSAndroid Build Coastguard Worker                                   tcu::COMPARE_LOG_RESULT);
996*35238bceSAndroid Build Coastguard Worker 
997*35238bceSAndroid Build Coastguard Worker     // Store test result.
998*35238bceSAndroid Build Coastguard Worker     m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
999*35238bceSAndroid Build Coastguard Worker                             isOk ? "Pass" : "Image comparison failed");
1000*35238bceSAndroid Build Coastguard Worker 
1001*35238bceSAndroid Build Coastguard Worker     return STOP;
1002*35238bceSAndroid Build Coastguard Worker }
1003*35238bceSAndroid Build Coastguard Worker 
upload2dTexture(int texNdx,sglr::Context & context)1004*35238bceSAndroid Build Coastguard Worker void TextureUnitCase::upload2dTexture(int texNdx, sglr::Context &context)
1005*35238bceSAndroid Build Coastguard Worker {
1006*35238bceSAndroid Build Coastguard Worker     int ndx2d                     = m_ndxTexType[texNdx];
1007*35238bceSAndroid Build Coastguard Worker     const tcu::Texture2D *texture = m_textures2d[ndx2d];
1008*35238bceSAndroid Build Coastguard Worker     glu::TransferFormat formatGl =
1009*35238bceSAndroid Build Coastguard Worker         glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1010*35238bceSAndroid Build Coastguard Worker 
1011*35238bceSAndroid Build Coastguard Worker     context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1012*35238bceSAndroid Build Coastguard Worker 
1013*35238bceSAndroid Build Coastguard Worker     for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1014*35238bceSAndroid Build Coastguard Worker     {
1015*35238bceSAndroid Build Coastguard Worker         if (texture->isLevelEmpty(levelNdx))
1016*35238bceSAndroid Build Coastguard Worker             continue;
1017*35238bceSAndroid Build Coastguard Worker 
1018*35238bceSAndroid Build Coastguard Worker         tcu::ConstPixelBufferAccess access = texture->getLevel(levelNdx);
1019*35238bceSAndroid Build Coastguard Worker         int width                          = access.getWidth();
1020*35238bceSAndroid Build Coastguard Worker         int height                         = access.getHeight();
1021*35238bceSAndroid Build Coastguard Worker 
1022*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * width);
1023*35238bceSAndroid Build Coastguard Worker 
1024*35238bceSAndroid Build Coastguard Worker         context.texImage2D(GL_TEXTURE_2D, levelNdx, m_textureParams[texNdx].internalFormat, width, height,
1025*35238bceSAndroid Build Coastguard Worker                            0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1026*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d texture image data");
1027*35238bceSAndroid Build Coastguard Worker     }
1028*35238bceSAndroid Build Coastguard Worker }
1029*35238bceSAndroid Build Coastguard Worker 
uploadCubeTexture(int texNdx,sglr::Context & context)1030*35238bceSAndroid Build Coastguard Worker void TextureUnitCase::uploadCubeTexture(int texNdx, sglr::Context &context)
1031*35238bceSAndroid Build Coastguard Worker {
1032*35238bceSAndroid Build Coastguard Worker     int ndxCube                     = m_ndxTexType[texNdx];
1033*35238bceSAndroid Build Coastguard Worker     const tcu::TextureCube *texture = m_texturesCube[ndxCube];
1034*35238bceSAndroid Build Coastguard Worker     glu::TransferFormat formatGl =
1035*35238bceSAndroid Build Coastguard Worker         glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1036*35238bceSAndroid Build Coastguard Worker 
1037*35238bceSAndroid Build Coastguard Worker     context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1038*35238bceSAndroid Build Coastguard Worker 
1039*35238bceSAndroid Build Coastguard Worker     for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++)
1040*35238bceSAndroid Build Coastguard Worker     {
1041*35238bceSAndroid Build Coastguard Worker         for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1042*35238bceSAndroid Build Coastguard Worker         {
1043*35238bceSAndroid Build Coastguard Worker             if (texture->isLevelEmpty((tcu::CubeFace)face, levelNdx))
1044*35238bceSAndroid Build Coastguard Worker                 continue;
1045*35238bceSAndroid Build Coastguard Worker 
1046*35238bceSAndroid Build Coastguard Worker             tcu::ConstPixelBufferAccess access = texture->getLevelFace(levelNdx, (tcu::CubeFace)face);
1047*35238bceSAndroid Build Coastguard Worker             int width                          = access.getWidth();
1048*35238bceSAndroid Build Coastguard Worker             int height                         = access.getHeight();
1049*35238bceSAndroid Build Coastguard Worker 
1050*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * width);
1051*35238bceSAndroid Build Coastguard Worker 
1052*35238bceSAndroid Build Coastguard Worker             context.texImage2D(s_cubeFaceTargets[face], levelNdx, m_textureParams[texNdx].internalFormat, width, height,
1053*35238bceSAndroid Build Coastguard Worker                                0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1054*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(context.getError(), "Set cube map image data");
1055*35238bceSAndroid Build Coastguard Worker         }
1056*35238bceSAndroid Build Coastguard Worker     }
1057*35238bceSAndroid Build Coastguard Worker }
1058*35238bceSAndroid Build Coastguard Worker 
upload2dArrayTexture(int texNdx,sglr::Context & context)1059*35238bceSAndroid Build Coastguard Worker void TextureUnitCase::upload2dArrayTexture(int texNdx, sglr::Context &context)
1060*35238bceSAndroid Build Coastguard Worker {
1061*35238bceSAndroid Build Coastguard Worker     int ndx2dArray                     = m_ndxTexType[texNdx];
1062*35238bceSAndroid Build Coastguard Worker     const tcu::Texture2DArray *texture = m_textures2dArray[ndx2dArray];
1063*35238bceSAndroid Build Coastguard Worker     glu::TransferFormat formatGl =
1064*35238bceSAndroid Build Coastguard Worker         glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1065*35238bceSAndroid Build Coastguard Worker 
1066*35238bceSAndroid Build Coastguard Worker     context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1067*35238bceSAndroid Build Coastguard Worker 
1068*35238bceSAndroid Build Coastguard Worker     for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1069*35238bceSAndroid Build Coastguard Worker     {
1070*35238bceSAndroid Build Coastguard Worker         if (texture->isLevelEmpty(levelNdx))
1071*35238bceSAndroid Build Coastguard Worker             continue;
1072*35238bceSAndroid Build Coastguard Worker 
1073*35238bceSAndroid Build Coastguard Worker         tcu::ConstPixelBufferAccess access = texture->getLevel(levelNdx);
1074*35238bceSAndroid Build Coastguard Worker         int width                          = access.getWidth();
1075*35238bceSAndroid Build Coastguard Worker         int height                         = access.getHeight();
1076*35238bceSAndroid Build Coastguard Worker         int layers                         = access.getDepth();
1077*35238bceSAndroid Build Coastguard Worker 
1078*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * width);
1079*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * width * height);
1080*35238bceSAndroid Build Coastguard Worker 
1081*35238bceSAndroid Build Coastguard Worker         context.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_textureParams[texNdx].internalFormat, width, height, layers,
1082*35238bceSAndroid Build Coastguard Worker                            0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1083*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d array texture image data");
1084*35238bceSAndroid Build Coastguard Worker     }
1085*35238bceSAndroid Build Coastguard Worker }
1086*35238bceSAndroid Build Coastguard Worker 
upload3dTexture(int texNdx,sglr::Context & context)1087*35238bceSAndroid Build Coastguard Worker void TextureUnitCase::upload3dTexture(int texNdx, sglr::Context &context)
1088*35238bceSAndroid Build Coastguard Worker {
1089*35238bceSAndroid Build Coastguard Worker     int ndx3d                     = m_ndxTexType[texNdx];
1090*35238bceSAndroid Build Coastguard Worker     const tcu::Texture3D *texture = m_textures3d[ndx3d];
1091*35238bceSAndroid Build Coastguard Worker     glu::TransferFormat formatGl =
1092*35238bceSAndroid Build Coastguard Worker         glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1093*35238bceSAndroid Build Coastguard Worker 
1094*35238bceSAndroid Build Coastguard Worker     context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1095*35238bceSAndroid Build Coastguard Worker 
1096*35238bceSAndroid Build Coastguard Worker     for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1097*35238bceSAndroid Build Coastguard Worker     {
1098*35238bceSAndroid Build Coastguard Worker         if (texture->isLevelEmpty(levelNdx))
1099*35238bceSAndroid Build Coastguard Worker             continue;
1100*35238bceSAndroid Build Coastguard Worker 
1101*35238bceSAndroid Build Coastguard Worker         tcu::ConstPixelBufferAccess access = texture->getLevel(levelNdx);
1102*35238bceSAndroid Build Coastguard Worker         int width                          = access.getWidth();
1103*35238bceSAndroid Build Coastguard Worker         int height                         = access.getHeight();
1104*35238bceSAndroid Build Coastguard Worker         int depth                          = access.getDepth();
1105*35238bceSAndroid Build Coastguard Worker 
1106*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * width);
1107*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * width * height);
1108*35238bceSAndroid Build Coastguard Worker 
1109*35238bceSAndroid Build Coastguard Worker         context.texImage3D(GL_TEXTURE_3D, levelNdx, m_textureParams[texNdx].internalFormat, width, height, depth,
1110*35238bceSAndroid Build Coastguard Worker                            0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1111*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(context.getError(), "Set 3d texture image data");
1112*35238bceSAndroid Build Coastguard Worker     }
1113*35238bceSAndroid Build Coastguard Worker }
1114*35238bceSAndroid Build Coastguard Worker 
render(sglr::Context & context)1115*35238bceSAndroid Build Coastguard Worker void TextureUnitCase::render(sglr::Context &context)
1116*35238bceSAndroid Build Coastguard Worker {
1117*35238bceSAndroid Build Coastguard Worker     // Setup textures.
1118*35238bceSAndroid Build Coastguard Worker 
1119*35238bceSAndroid Build Coastguard Worker     vector<uint32_t> textureGLNames;
1120*35238bceSAndroid Build Coastguard Worker     vector<bool> isTextureSetUp(
1121*35238bceSAndroid Build Coastguard Worker         m_numTextures,
1122*35238bceSAndroid Build Coastguard Worker         false); // \note Same texture may be bound to multiple units, but we only want to set up parameters and data once per texture.
1123*35238bceSAndroid Build Coastguard Worker 
1124*35238bceSAndroid Build Coastguard Worker     textureGLNames.resize(m_numTextures);
1125*35238bceSAndroid Build Coastguard Worker     context.genTextures(m_numTextures, &textureGLNames[0]);
1126*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(context.getError(), "Generate textures");
1127*35238bceSAndroid Build Coastguard Worker 
1128*35238bceSAndroid Build Coastguard Worker     for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
1129*35238bceSAndroid Build Coastguard Worker     {
1130*35238bceSAndroid Build Coastguard Worker         int texNdx = m_unitTextures[unitNdx];
1131*35238bceSAndroid Build Coastguard Worker 
1132*35238bceSAndroid Build Coastguard Worker         // Bind texture to unit.
1133*35238bceSAndroid Build Coastguard Worker         context.activeTexture(GL_TEXTURE0 + unitNdx);
1134*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(context.getError(), "Set active texture");
1135*35238bceSAndroid Build Coastguard Worker         context.bindTexture(m_textureTypes[texNdx], textureGLNames[texNdx]);
1136*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(context.getError(), "Bind texture");
1137*35238bceSAndroid Build Coastguard Worker 
1138*35238bceSAndroid Build Coastguard Worker         if (!isTextureSetUp[texNdx])
1139*35238bceSAndroid Build Coastguard Worker         {
1140*35238bceSAndroid Build Coastguard Worker             // Binding this texture for first time, so set parameters and data.
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker             context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_S, m_textureParams[texNdx].wrapModeS);
1143*35238bceSAndroid Build Coastguard Worker             context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_T, m_textureParams[texNdx].wrapModeT);
1144*35238bceSAndroid Build Coastguard Worker             if (m_textureTypes[texNdx] == GL_TEXTURE_3D)
1145*35238bceSAndroid Build Coastguard Worker                 context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_R, m_textureParams[texNdx].wrapModeR);
1146*35238bceSAndroid Build Coastguard Worker             context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MIN_FILTER, m_textureParams[texNdx].minFilter);
1147*35238bceSAndroid Build Coastguard Worker             context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MAG_FILTER, m_textureParams[texNdx].magFilter);
1148*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(context.getError(), "Set texture parameters");
1149*35238bceSAndroid Build Coastguard Worker 
1150*35238bceSAndroid Build Coastguard Worker             switch (m_textureTypes[texNdx])
1151*35238bceSAndroid Build Coastguard Worker             {
1152*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D:
1153*35238bceSAndroid Build Coastguard Worker                 upload2dTexture(texNdx, context);
1154*35238bceSAndroid Build Coastguard Worker                 break;
1155*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_CUBE_MAP:
1156*35238bceSAndroid Build Coastguard Worker                 uploadCubeTexture(texNdx, context);
1157*35238bceSAndroid Build Coastguard Worker                 break;
1158*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_2D_ARRAY:
1159*35238bceSAndroid Build Coastguard Worker                 upload2dArrayTexture(texNdx, context);
1160*35238bceSAndroid Build Coastguard Worker                 break;
1161*35238bceSAndroid Build Coastguard Worker             case GL_TEXTURE_3D:
1162*35238bceSAndroid Build Coastguard Worker                 upload3dTexture(texNdx, context);
1163*35238bceSAndroid Build Coastguard Worker                 break;
1164*35238bceSAndroid Build Coastguard Worker             default:
1165*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
1166*35238bceSAndroid Build Coastguard Worker             }
1167*35238bceSAndroid Build Coastguard Worker 
1168*35238bceSAndroid Build Coastguard Worker             isTextureSetUp[texNdx] = true; // Don't set up this texture's parameters and data again later.
1169*35238bceSAndroid Build Coastguard Worker         }
1170*35238bceSAndroid Build Coastguard Worker     }
1171*35238bceSAndroid Build Coastguard Worker 
1172*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(context.getError(), "Set textures");
1173*35238bceSAndroid Build Coastguard Worker 
1174*35238bceSAndroid Build Coastguard Worker     // Setup shader
1175*35238bceSAndroid Build Coastguard Worker 
1176*35238bceSAndroid Build Coastguard Worker     uint32_t shaderID = context.createProgram(m_shader);
1177*35238bceSAndroid Build Coastguard Worker 
1178*35238bceSAndroid Build Coastguard Worker     // Draw.
1179*35238bceSAndroid Build Coastguard Worker 
1180*35238bceSAndroid Build Coastguard Worker     context.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
1181*35238bceSAndroid Build Coastguard Worker     context.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1182*35238bceSAndroid Build Coastguard Worker     m_shader->setUniforms(context, shaderID);
1183*35238bceSAndroid Build Coastguard Worker     sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1184*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(context.getError(), "Draw");
1185*35238bceSAndroid Build Coastguard Worker 
1186*35238bceSAndroid Build Coastguard Worker     // Delete previously generated texture names.
1187*35238bceSAndroid Build Coastguard Worker 
1188*35238bceSAndroid Build Coastguard Worker     context.deleteTextures(m_numTextures, &textureGLNames[0]);
1189*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(context.getError(), "Delete textures");
1190*35238bceSAndroid Build Coastguard Worker }
1191*35238bceSAndroid Build Coastguard Worker 
TextureUnitTests(Context & context)1192*35238bceSAndroid Build Coastguard Worker TextureUnitTests::TextureUnitTests(Context &context) : TestCaseGroup(context, "units", "Texture Unit Usage Tests")
1193*35238bceSAndroid Build Coastguard Worker {
1194*35238bceSAndroid Build Coastguard Worker }
1195*35238bceSAndroid Build Coastguard Worker 
~TextureUnitTests(void)1196*35238bceSAndroid Build Coastguard Worker TextureUnitTests::~TextureUnitTests(void)
1197*35238bceSAndroid Build Coastguard Worker {
1198*35238bceSAndroid Build Coastguard Worker }
1199*35238bceSAndroid Build Coastguard Worker 
init(void)1200*35238bceSAndroid Build Coastguard Worker void TextureUnitTests::init(void)
1201*35238bceSAndroid Build Coastguard Worker {
1202*35238bceSAndroid Build Coastguard Worker     const int numTestsPerGroup = 10;
1203*35238bceSAndroid Build Coastguard Worker 
1204*35238bceSAndroid Build Coastguard Worker     static const int unitCounts[] = {
1205*35238bceSAndroid Build Coastguard Worker         2, 4, 8,
1206*35238bceSAndroid Build Coastguard Worker         -1 // \note Negative stands for the implementation-specified maximum.
1207*35238bceSAndroid Build Coastguard Worker     };
1208*35238bceSAndroid Build Coastguard Worker 
1209*35238bceSAndroid Build Coastguard Worker     for (int unitCountNdx = 0; unitCountNdx < DE_LENGTH_OF_ARRAY(unitCounts); unitCountNdx++)
1210*35238bceSAndroid Build Coastguard Worker     {
1211*35238bceSAndroid Build Coastguard Worker         int numUnits = unitCounts[unitCountNdx];
1212*35238bceSAndroid Build Coastguard Worker 
1213*35238bceSAndroid Build Coastguard Worker         string countGroupName = (unitCounts[unitCountNdx] < 0 ? "all" : de::toString(numUnits)) + "_units";
1214*35238bceSAndroid Build Coastguard Worker 
1215*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *countGroup = new tcu::TestCaseGroup(m_testCtx, countGroupName.c_str(), "");
1216*35238bceSAndroid Build Coastguard Worker         addChild(countGroup);
1217*35238bceSAndroid Build Coastguard Worker 
1218*35238bceSAndroid Build Coastguard Worker         DE_STATIC_ASSERT((int)TextureUnitCase::CASE_ONLY_2D == 0);
1219*35238bceSAndroid Build Coastguard Worker 
1220*35238bceSAndroid Build Coastguard Worker         for (int caseType = (int)TextureUnitCase::CASE_ONLY_2D; caseType < (int)TextureUnitCase::CASE_LAST; caseType++)
1221*35238bceSAndroid Build Coastguard Worker         {
1222*35238bceSAndroid Build Coastguard Worker             const char *caseTypeGroupName =
1223*35238bceSAndroid Build Coastguard Worker                 (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D       ? "only_2d" :
1224*35238bceSAndroid Build Coastguard Worker                 (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_CUBE     ? "only_cube" :
1225*35238bceSAndroid Build Coastguard Worker                 (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D_ARRAY ? "only_2d_array" :
1226*35238bceSAndroid Build Coastguard Worker                 (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_3D       ? "only_3d" :
1227*35238bceSAndroid Build Coastguard Worker                 (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_MIXED         ? "mixed" :
1228*35238bceSAndroid Build Coastguard Worker                                                                                              DE_NULL;
1229*35238bceSAndroid Build Coastguard Worker 
1230*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(caseTypeGroupName != DE_NULL);
1231*35238bceSAndroid Build Coastguard Worker 
1232*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *caseTypeGroup = new tcu::TestCaseGroup(m_testCtx, caseTypeGroupName, "");
1233*35238bceSAndroid Build Coastguard Worker             countGroup->addChild(caseTypeGroup);
1234*35238bceSAndroid Build Coastguard Worker 
1235*35238bceSAndroid Build Coastguard Worker             for (int testNdx = 0; testNdx < numTestsPerGroup; testNdx++)
1236*35238bceSAndroid Build Coastguard Worker                 caseTypeGroup->addChild(new TextureUnitCase(m_context, de::toString(testNdx).c_str(), "", numUnits,
1237*35238bceSAndroid Build Coastguard Worker                                                             (TextureUnitCase::CaseType)caseType,
1238*35238bceSAndroid Build Coastguard Worker                                                             deUint32Hash((uint32_t)testNdx)));
1239*35238bceSAndroid Build Coastguard Worker         }
1240*35238bceSAndroid Build Coastguard Worker     }
1241*35238bceSAndroid Build Coastguard Worker }
1242*35238bceSAndroid Build Coastguard Worker 
1243*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1244*35238bceSAndroid Build Coastguard Worker } // namespace gles3
1245*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1246