Fix PIPELINE_STAGE_TOP_OF_PIPE_BIT usage in api tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fUniformLocationTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Explicit uniform location tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fUniformLocationTests.hpp"
25
26 #include "tcuTestLog.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "tcuCommandLine.hpp"
30
31 #include "glsShaderLibrary.hpp"
32 #include "glsTextureTestUtil.hpp"
33
34 #include "gluShaderProgram.hpp"
35 #include "gluTexture.hpp"
36 #include "gluPixelTransfer.hpp"
37 #include "gluVarType.hpp"
38 #include "gluVarTypeUtil.hpp"
39
40 #include "glwFunctions.hpp"
41 #include "glwEnums.hpp"
42 #include "sglrContextUtil.hpp"
43
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deString.h"
47 #include "deRandom.hpp"
48 #include "deInt32.h"
49
50 #include <set>
51 #include <map>
52
53 namespace deqp
54 {
55 namespace gles31
56 {
57 namespace Functional
58 {
59 namespace
60 {
61
62 using std::string;
63 using std::vector;
64 using std::map;
65 using de::UniquePtr;
66 using glu::VarType;
67
68 struct UniformInfo
69 {
70         enum ShaderStage
71         {
72                 SHADERSTAGE_NONE        = 0,
73                 SHADERSTAGE_VERTEX      = (1<<0),
74                 SHADERSTAGE_FRAGMENT= (1<<1),
75                 SHADERSTAGE_BOTH        = (SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT),
76         };
77
78         VarType                 type;
79         ShaderStage             declareLocation; // support declarations with/without layout qualifiers, needed for linkage testing
80         ShaderStage             layoutLocation;
81         ShaderStage             checkLocation;
82         int                             location; // -1 for unset
83
84         UniformInfo (VarType type_, ShaderStage declareLocation_, ShaderStage layoutLocation_, ShaderStage checkLocation_, int location_ = -1)
85                 : type                          (type_)
86                 , declareLocation       (declareLocation_)
87                 , layoutLocation        (layoutLocation_)
88                 , checkLocation         (checkLocation_)
89                 , location                      (location_)
90         {
91         }
92 };
93
94 class UniformLocationCase : public tcu::TestCase
95 {
96 public:
97                                                                 UniformLocationCase             (tcu::TestContext&                      context,
98                                                                                                                  glu::RenderContext&            renderContext,
99                                                                                                                  const char*                            name,
100                                                                                                                  const char*                            desc,
101                                                                                                                  const vector<UniformInfo>&     uniformInfo);
102         virtual                                         ~UniformLocationCase    (void) {}
103
104         virtual IterateResult           iterate                                 (void);
105
106 protected:
107         IterateResult                           run                                             (const vector<UniformInfo>& uniformList);
108         static glu::ProgramSources      genShaderSources                (const vector<UniformInfo>& uniformList);
109         bool                                            verifyLocations                 (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList);
110         void                                            render                                  (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList);
111         static bool                                     verifyResult                    (const tcu::ConstPixelBufferAccess& access);
112
113         static float                            getExpectedValue                (glu::DataType type, int id, const char* name);
114
115         de::MovePtr<glu::Texture2D>     createTexture                   (glu::DataType samplerType, float redChannelValue, int binding);
116
117         glu::RenderContext&                     m_renderCtx;
118
119         const vector<UniformInfo>       m_uniformInfo;
120
121         enum
122         {
123                 RENDER_SIZE = 16
124         };
125 };
126
127 string getUniformName (int ndx, const glu::VarType& type, const glu::TypeComponentVector& path)
128 {
129         std::ostringstream buff;
130         buff << "uni" << ndx << glu::TypeAccessFormat(type, path);
131
132         return buff.str();
133 }
134
135 string getFirstComponentName (const glu::VarType& type)
136 {
137         std::ostringstream buff;
138         if (glu::isDataTypeVector(type.getBasicType()))
139                 buff << glu::TypeAccessFormat(type, glu::SubTypeAccess(type).component(0).getPath());
140         else if (glu::isDataTypeMatrix(type.getBasicType()))
141                 buff << glu::TypeAccessFormat(type, glu::SubTypeAccess(type).column(0).component(0).getPath());
142
143         return buff.str();
144 }
145
146 UniformLocationCase::UniformLocationCase (tcu::TestContext&                             context,
147                                                                                   glu::RenderContext&                   renderContext,
148                                                                                   const char*                                   name,
149                                                                                   const char*                                   desc,
150                                                                                   const vector<UniformInfo>&    uniformInfo)
151         : TestCase                      (context, name, desc)
152         , m_renderCtx           (renderContext)
153         , m_uniformInfo         (uniformInfo)
154 {
155 }
156
157 // [from, to]
158 std::vector<int> shuffledRange (int from, int to, int seed)
159 {
160         const int       count   = to - from;
161
162         vector<int> retval      (count);
163         de::Random      rng             (seed);
164
165         DE_ASSERT(count > 0);
166
167         for (int ndx = 0; ndx < count; ndx++)
168                 retval[ndx] = ndx + from;
169
170         rng.shuffle(retval.begin(), retval.end());
171         return retval;
172 }
173
174 glu::DataType getDataTypeSamplerSampleType (glu::DataType type)
175 {
176         using namespace glu;
177
178         if (type >= TYPE_SAMPLER_1D && type <= TYPE_SAMPLER_3D)
179                 return TYPE_FLOAT_VEC4;
180         else if (type >= TYPE_INT_SAMPLER_1D && type <= TYPE_INT_SAMPLER_3D)
181                 return TYPE_INT_VEC4;
182         else if (type >= TYPE_UINT_SAMPLER_1D && type <= TYPE_UINT_SAMPLER_3D)
183                 return TYPE_UINT_VEC4;
184         else if (type >= TYPE_SAMPLER_1D_SHADOW && type <=      TYPE_SAMPLER_2D_ARRAY_SHADOW)
185                 return TYPE_FLOAT;
186         else
187                 DE_FATAL("Unknown sampler type");
188
189         return TYPE_INVALID;
190 }
191
192 // A (hopefully) unique value for a uniform. For multi-component types creates only one value. Values are in the range [0,1] for floats, [-128, 127] for ints, [0,255] for uints and 0/1 for booleans. Samplers are treated according to the types they return.
193 float UniformLocationCase::getExpectedValue (glu::DataType type, int id, const char* name)
194 {
195         const deUint32  hash                    = deStringHash(name) + deInt32Hash(id);
196
197         glu::DataType   adjustedType    = type;
198
199         if (glu::isDataTypeSampler(type))
200                 adjustedType = getDataTypeSamplerSampleType(type);
201
202         if (glu::isDataTypeIntOrIVec(adjustedType))
203                 return float(hash%128);
204         else if (glu::isDataTypeUintOrUVec(adjustedType))
205                 return float(hash%255);
206         else if (glu::isDataTypeFloatOrVec(adjustedType))
207                 return float(hash%255)/255.0f;
208         else if (glu::isDataTypeBoolOrBVec(adjustedType))
209                 return float(hash%2);
210         else
211                 DE_FATAL("Unkown primitive type");
212
213         return glu::TYPE_INVALID;
214 }
215
216 UniformLocationCase::IterateResult UniformLocationCase::iterate (void)
217 {
218         return run(m_uniformInfo);
219 }
220
221 UniformLocationCase::IterateResult UniformLocationCase::run (const vector<UniformInfo>& uniformList)
222 {
223         using gls::TextureTestUtil::RandomViewport;
224
225         const glu::ProgramSources       sources         = genShaderSources(uniformList);
226         const glu::ShaderProgram        program         (m_renderCtx, sources);
227         const int                                       baseSeed        = m_testCtx.getCommandLine().getBaseSeed();
228         const glw::Functions&           gl                      = m_renderCtx.getFunctions();
229         const RandomViewport            viewport        (m_renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()) + baseSeed);
230
231         tcu::Surface                            rendered        (RENDER_SIZE, RENDER_SIZE);
232
233         if (!verifyLocations(program, uniformList))
234                 return STOP;
235
236         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
237         gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
238         gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
239
240         render(program, uniformList);
241
242         glu::readPixels(m_renderCtx, viewport.x, viewport.y, rendered.getAccess());
243
244         if (!verifyResult(rendered.getAccess()))
245         {
246                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader produced incorrect result");
247                 return STOP;
248         }
249
250         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
251         return STOP;
252 }
253
254 glu::ProgramSources UniformLocationCase::genShaderSources (const vector<UniformInfo>& uniformList)
255 {
256         std::ostringstream      vertDecl, vertMain, fragDecl, fragMain;
257
258         vertDecl << "#version 310 es\n"
259                          << "precision highp float;\n"
260                          << "precision highp int;\n"
261                          << "float verify(float val, float ref) { return float(abs(val-ref) < 0.05); }\n\n"
262                          << "in highp vec4 a_position;\n"
263                          << "out highp vec4 v_color;\n";
264         fragDecl << "#version 310 es\n\n"
265                          << "precision highp float;\n"
266                          << "precision highp int;\n"
267                          << "float verify(float val, float ref) { return float(abs(val-ref) < 0.05); }\n\n"
268                          << "in highp vec4 v_color;\n"
269                          << "layout(location = 0) out mediump vec4 o_color;\n\n";
270
271         vertMain << "void main()\n{\n"
272                          << "   gl_Position = a_position;\n"
273                          << "   v_color = vec4(1.0);\n";
274
275         fragMain << "void main()\n{\n"
276                          << "   o_color = v_color;\n";
277
278         std::set<const glu::StructType*> declaredStructs;
279
280         // Declare uniforms
281         for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
282         {
283                 const UniformInfo&      uniformInfo = uniformList[uniformNdx];
284
285                 const bool                      declareInVert   = (uniformInfo.declareLocation & UniformInfo::SHADERSTAGE_VERTEX)   != 0;
286                 const bool                      declareInFrag   = (uniformInfo.declareLocation & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
287                 const bool                      layoutInVert    = (uniformInfo.layoutLocation  & UniformInfo::SHADERSTAGE_VERTEX)   != 0;
288                 const bool                      layoutInFrag    = (uniformInfo.layoutLocation  & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
289                 const bool                      checkInVert             = (uniformInfo.checkLocation   & UniformInfo::SHADERSTAGE_VERTEX)   != 0;
290                 const bool                      checkInFrag             = (uniformInfo.checkLocation   & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
291
292                 const string            layout                  = uniformInfo.location >= 0 ? "layout(location = " + de::toString(uniformInfo.location) + ") " : "";
293                 const string            uniName                 = "uni" + de::toString(uniformNdx);
294
295                 int                                     location                = uniformInfo.location;
296                 int                                     subTypeIndex    = 0;
297
298                 DE_ASSERT((declareInVert && layoutInVert) || !layoutInVert); // Cannot have layout without declaration
299                 DE_ASSERT((declareInFrag && layoutInFrag) || !layoutInFrag);
300                 DE_ASSERT(location<0 || (layoutInVert || layoutInFrag)); // Cannot have location without layout
301
302                 // struct definitions
303                 if (uniformInfo.type.isStructType())
304                 {
305                         const glu::StructType* const structType = uniformInfo.type.getStructPtr();
306                         if (!declaredStructs.count(structType))
307                         {
308                                 if (declareInVert)
309                                         vertDecl << glu::declare(structType, 0) << ";\n";
310
311                                 if (declareInFrag)
312                                         fragDecl << glu::declare(structType, 0) << ";\n";
313
314                                 declaredStructs.insert(structType);
315                         }
316                 }
317
318                 if (declareInVert)
319                         vertDecl << "uniform " << (layoutInVert ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";
320
321                 if (declareInFrag)
322                         fragDecl << "uniform " << (layoutInFrag ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";
323
324                 // Anything that needs to be done for each enclosed primitive type
325                 for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++, subTypeIndex++)
326                 {
327                         const glu::VarType      subType         = glu::getVarType(uniformInfo.type, subTypeIter.getPath());
328                         const glu::DataType     scalarType      = glu::getDataTypeScalarType(subType.getBasicType());
329                         const char* const       typeName        = glu::getDataTypeName(scalarType);
330                         const string            expectValue     = de::floatToString(getExpectedValue(scalarType, location >= 0 ? location+subTypeIndex : -1, typeName), 3);
331
332                         if (glu::isDataTypeSampler(scalarType))
333                         {
334                                 if (checkInVert)
335                                         vertMain << "   v_color.rgb *= verify(float( texture(" << uniName
336                                                          << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
337                                                          << ", vec2(0.5)).r), " << expectValue << ");\n";
338                                 if (checkInFrag)
339                                         fragMain << "   o_color.rgb *= verify(float( texture(" << uniName
340                                                          << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
341                                                          << ", vec2(0.5)).r), " << expectValue << ");\n";
342                         }
343                         else
344                         {
345                                 if (checkInVert)
346                                         vertMain << "   v_color.rgb *= verify(float(" << uniName
347                                                          << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
348                                                          << getFirstComponentName(subType) << "), " << expectValue << ");\n";
349                                 if (checkInFrag)
350                                         fragMain << "   o_color.rgb *= verify(float(" << uniName
351                                                          << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
352                                                          << getFirstComponentName(subType) << "), " << expectValue << ");\n";
353                         }
354                 }
355         }
356
357         vertMain << "}\n";
358         fragMain << "}\n";
359
360         return glu::makeVtxFragSources(vertDecl.str() + vertMain.str(), fragDecl.str() + fragMain.str());
361 }
362
363 bool UniformLocationCase::verifyLocations (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
364 {
365         using tcu::TestLog;
366
367         const glw::Functions&   gl                      = m_renderCtx.getFunctions();
368         const bool                              vertexOk        = program.getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk;
369         const bool                              fragmentOk      = program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk;
370         const bool                              linkOk          = program.getProgramInfo().linkOk;
371         const deUint32                  programID       = program.getProgram();
372
373         TestLog&                                log                     = m_testCtx.getLog();
374         std::set<int>                   usedLocations;
375
376         log << program;
377
378         if (!vertexOk || !fragmentOk || !linkOk)
379         {
380                 log << TestLog::Message << "ERROR: shader failed to compile/link" << TestLog::EndMessage;
381                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader failed to compile/link");
382                 return false;
383         }
384
385         for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
386         {
387                 const UniformInfo&      uniformInfo             = uniformList[uniformNdx];
388                 int                                     subTypeIndex    = 0;
389
390                 for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++, subTypeIndex++)
391                 {
392                         const string            name            = getUniformName(uniformNdx, uniformInfo.type, subTypeIter.getPath());
393                         const int                       gotLoc          = gl.getUniformLocation(programID, name.c_str());
394                         const int                       expectLoc       = uniformInfo.location >= 0 ? uniformInfo.location+subTypeIndex : -1;
395
396                         if (expectLoc >= 0)
397                         {
398                                 if (uniformInfo.checkLocation == 0 && gotLoc == -1)
399                                         continue;
400
401                                 if (gotLoc != expectLoc)
402                                 {
403                                         log << TestLog::Message << "ERROR: found uniform " << name << " in location " << gotLoc << " when it should have been in " << expectLoc << TestLog::EndMessage;
404                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect uniform location");
405                                         return false;
406                                 }
407
408                                 if (usedLocations.find(expectLoc) != usedLocations.end())
409                                 {
410                                         log << TestLog::Message << "ERROR: expected uniform " << name << " in location " << gotLoc << " but it has already been used" << TestLog::EndMessage;
411                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Overlapping uniform location");
412                                         return false;
413                                 }
414
415                                 usedLocations.insert(expectLoc);
416                         }
417                         else if (gotLoc >= 0)
418                         {
419                                 if (usedLocations.count(gotLoc))
420                                 {
421                                         log << TestLog::Message << "ERROR: found uniform " << name << " in location " << gotLoc << " which has already been used" << TestLog::EndMessage;
422                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Overlapping uniform location");
423                                         return false;
424                                 }
425
426                                 usedLocations.insert(gotLoc);
427                         }
428                 }
429         }
430
431         return true;
432 }
433
434 // Check that shader output is white (or very close to it)
435 bool UniformLocationCase::verifyResult (const tcu::ConstPixelBufferAccess& access)
436 {
437         using tcu::Vec4;
438
439         const Vec4 threshold (0.1f, 0.1f, 0.1f, 0.1f);
440         const Vec4 reference (1.0f, 1.0f, 1.0f, 1.0f);
441
442         for (int y = 0; y < access.getHeight(); y++)
443         {
444                 for (int x = 0; x < access.getWidth(); x++)
445                 {
446                         const Vec4 diff = abs(access.getPixel(x, y) - reference);
447
448                         if (!boolAll(lessThanEqual(diff, threshold)))
449                                 return false;
450                 }
451         }
452
453         return true;
454 }
455
456 // get a 4 channel 8 bits each texture format that is usable by the given sampler type
457 deUint32 getTextureFormat (glu::DataType samplerType)
458 {
459         using namespace glu;
460
461         switch (samplerType)
462         {
463                 case TYPE_SAMPLER_1D:
464                 case TYPE_SAMPLER_2D:
465                 case TYPE_SAMPLER_CUBE:
466                 case TYPE_SAMPLER_2D_ARRAY:
467                 case TYPE_SAMPLER_3D:
468                         return GL_RGBA8;
469
470                 case TYPE_INT_SAMPLER_1D:
471                 case TYPE_INT_SAMPLER_2D:
472                 case TYPE_INT_SAMPLER_CUBE:
473                 case TYPE_INT_SAMPLER_2D_ARRAY:
474                 case TYPE_INT_SAMPLER_3D:
475                         return GL_RGBA8I;
476
477                 case TYPE_UINT_SAMPLER_1D:
478                 case TYPE_UINT_SAMPLER_2D:
479                 case TYPE_UINT_SAMPLER_CUBE:
480                 case TYPE_UINT_SAMPLER_2D_ARRAY:
481                 case TYPE_UINT_SAMPLER_3D:
482                         return GL_RGBA8UI;
483
484                 default:
485                         DE_FATAL("Unsupported (sampler) type");
486                         return 0;
487         }
488 }
489
490 // create a texture suitable for sampling by the given sampler type and bind it
491 de::MovePtr<glu::Texture2D> UniformLocationCase::createTexture (glu::DataType samplerType, float redChannelValue, int binding)
492 {
493         using namespace glu;
494
495         const glw::Functions&   gl               = m_renderCtx.getFunctions();
496
497         const deUint32                  format   = getTextureFormat(samplerType);
498         de::MovePtr<Texture2D>  tex;
499
500         tex = de::MovePtr<Texture2D>(new Texture2D(m_renderCtx, format, 16, 16));
501
502         tex->getRefTexture().allocLevel(0);
503
504         if (format == GL_RGBA8I || format == GL_RGBA8UI)
505                 tcu::clear(tex->getRefTexture().getLevel(0), tcu::IVec4(int(redChannelValue), 0, 0, 0));
506         else
507                 tcu::clear(tex->getRefTexture().getLevel(0), tcu::Vec4(redChannelValue, 0.0f, 0.0f, 1.0f));
508
509         gl.activeTexture(GL_TEXTURE0 + binding);
510         tex->upload();
511
512         gl.bindTexture(GL_TEXTURE_2D, tex->getGLTexture());
513         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
514         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
515
516         GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase: texture upload");
517
518         return tex;
519 }
520
521 void UniformLocationCase::render (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
522 {
523         using glu::Texture2D;
524         using de::MovePtr;
525         typedef vector<Texture2D*> TextureList;
526
527         const glw::Functions&   gl                              = m_renderCtx.getFunctions();
528         const deUint32                  programID               = program.getProgram();
529         const deInt32                   posLoc                  = gl.getAttribLocation(programID, "a_position");
530
531         // Vertex data.
532         const float position[] =
533         {
534                 -1.0f, -1.0f, 0.1f,     1.0f,
535                 -1.0f,  1.0f, 0.1f,     1.0f,
536                  1.0f, -1.0f, 0.1f,     1.0f,
537                  1.0f,  1.0f, 0.1f,     1.0f
538         };
539         const deUint16                  indices[]               = { 0, 1, 2, 2, 1, 3 };
540
541         // some buffers to feed to the GPU, only the first element is relevant since the others are never verified
542         float                                   floatBuf[16]    = {0.0f};
543         deInt32                                 intBuf[4]               = {0};
544         deUint32                                uintBuf[4]              = {0};
545
546         TextureList                             texList;
547
548         TCU_CHECK(posLoc >= 0);
549         gl.useProgram(programID);
550
551         try
552         {
553
554                 // Set uniforms
555                 for (unsigned int uniformNdx = 0; uniformNdx < uniformList.size(); uniformNdx++)
556                 {
557                         const UniformInfo&      uniformInfo                     = uniformList[uniformNdx];
558                         int                                     expectedLocation        = uniformInfo.location;
559
560                         for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++)
561                         {
562                                 const glu::VarType      type                    = glu::getVarType(uniformInfo.type, subTypeIter.getPath());
563                                 const string            name                    = getUniformName(uniformNdx, uniformInfo.type, subTypeIter.getPath());
564                                 const int                       gotLoc                  = gl.getUniformLocation(programID, name.c_str());
565                                 const glu::DataType     scalarType              = glu::getDataTypeScalarType(type.getBasicType());
566                                 const char*     const   typeName                = glu::getDataTypeName(scalarType);
567                                 const float                     expectedValue   = getExpectedValue(scalarType, expectedLocation, typeName);
568
569                                 if (glu::isDataTypeSampler(scalarType))
570                                 {
571                                         const int binding = (int)texList.size();
572
573                                         texList.push_back(createTexture(scalarType, expectedValue, binding).release());
574                                         gl.uniform1i(gotLoc, binding);
575                                 }
576                                 else if(gotLoc >= 0)
577                                 {
578                                         floatBuf[0] = expectedValue;
579                                         intBuf[0]   = int(expectedValue);
580                                         uintBuf[0]  = deUint32(expectedValue);
581
582                                         m_testCtx.getLog() << tcu::TestLog::Message << "Set uniform " << name << " in location " << gotLoc << " to " << expectedValue << tcu::TestLog::EndMessage;
583
584                                         switch (type.getBasicType())
585                                         {
586                                                 case glu::TYPE_FLOAT:                   gl.uniform1fv(gotLoc, 1, floatBuf);                                     break;
587                                                 case glu::TYPE_FLOAT_VEC2:              gl.uniform2fv(gotLoc, 1, floatBuf);                                     break;
588                                                 case glu::TYPE_FLOAT_VEC3:              gl.uniform3fv(gotLoc, 1, floatBuf);                                     break;
589                                                 case glu::TYPE_FLOAT_VEC4:              gl.uniform4fv(gotLoc, 1, floatBuf);                                     break;
590
591                                                 case glu::TYPE_INT:                             gl.uniform1iv(gotLoc, 1, intBuf);                                       break;
592                                                 case glu::TYPE_INT_VEC2:                gl.uniform2iv(gotLoc, 1, intBuf);                                       break;
593                                                 case glu::TYPE_INT_VEC3:                gl.uniform3iv(gotLoc, 1, intBuf);                                       break;
594                                                 case glu::TYPE_INT_VEC4:                gl.uniform4iv(gotLoc, 1, intBuf);                                       break;
595
596                                                 case glu::TYPE_UINT:                    gl.uniform1uiv(gotLoc, 1, uintBuf);                                     break;
597                                                 case glu::TYPE_UINT_VEC2:               gl.uniform2uiv(gotLoc, 1, uintBuf);                                     break;
598                                                 case glu::TYPE_UINT_VEC3:               gl.uniform3uiv(gotLoc, 1, uintBuf);                                     break;
599                                                 case glu::TYPE_UINT_VEC4:               gl.uniform4uiv(gotLoc, 1, uintBuf);                                     break;
600
601                                                 case glu::TYPE_BOOL:                    gl.uniform1iv(gotLoc, 1, intBuf);                                       break;
602                                                 case glu::TYPE_BOOL_VEC2:               gl.uniform2iv(gotLoc, 1, intBuf);                                       break;
603                                                 case glu::TYPE_BOOL_VEC3:               gl.uniform3iv(gotLoc, 1, intBuf);                                       break;
604                                                 case glu::TYPE_BOOL_VEC4:               gl.uniform4iv(gotLoc, 1, intBuf);                                       break;
605
606                                                 case glu::TYPE_FLOAT_MAT2:              gl.uniformMatrix2fv(gotLoc, 1, false, floatBuf);        break;
607                                                 case glu::TYPE_FLOAT_MAT2X3:    gl.uniformMatrix2x3fv(gotLoc, 1, false, floatBuf);      break;
608                                                 case glu::TYPE_FLOAT_MAT2X4:    gl.uniformMatrix2x4fv(gotLoc, 1, false, floatBuf);      break;
609
610                                                 case glu::TYPE_FLOAT_MAT3X2:    gl.uniformMatrix3x2fv(gotLoc, 1, false, floatBuf);      break;
611                                                 case glu::TYPE_FLOAT_MAT3:              gl.uniformMatrix3fv(gotLoc, 1, false, floatBuf);        break;
612                                                 case glu::TYPE_FLOAT_MAT3X4:    gl.uniformMatrix3x4fv(gotLoc, 1, false, floatBuf);      break;
613
614                                                 case glu::TYPE_FLOAT_MAT4X2:    gl.uniformMatrix4x2fv(gotLoc, 1, false, floatBuf);      break;
615                                                 case glu::TYPE_FLOAT_MAT4X3:    gl.uniformMatrix4x3fv(gotLoc, 1, false, floatBuf);      break;
616                                                 case glu::TYPE_FLOAT_MAT4:              gl.uniformMatrix4fv(gotLoc, 1, false, floatBuf);        break;
617                                                 default:
618                                                         DE_ASSERT(false);
619                                         }
620                                 }
621
622                                 expectedLocation += expectedLocation>=0;
623                         }
624                 }
625
626                 gl.enableVertexAttribArray(posLoc);
627                 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
628
629                 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]);
630
631                 gl.disableVertexAttribArray(posLoc);
632         }
633         catch(...)
634         {
635                 for (int i = 0; i < int(texList.size()); i++)
636                         delete texList[i];
637
638                 throw;
639         }
640
641         for (int i = 0; i < int(texList.size()); i++)
642                 delete texList[i];
643 }
644
645 class MaxUniformLocationCase : public UniformLocationCase
646 {
647 public:
648                                                                 MaxUniformLocationCase          (tcu::TestContext&                      context,
649                                                                                                                          glu::RenderContext&            renderContext,
650                                                                                                                          const char*                            name,
651                                                                                                                          const char*                            desc,
652                                                                                                                          const vector<UniformInfo>&     uniformInfo);
653         virtual                                         ~MaxUniformLocationCase         (void) {}
654         virtual IterateResult           iterate                                         (void);
655 };
656
657 MaxUniformLocationCase::MaxUniformLocationCase (tcu::TestContext&                       context,
658                                                                                                 glu::RenderContext&                     renderContext,
659                                                                                                 const char*                                     name,
660                                                                                                 const char*                                     desc,
661                                                                                                 const vector<UniformInfo>&      uniformInfo)
662         : UniformLocationCase(context, renderContext, name, desc, uniformInfo)
663 {
664         DE_ASSERT(!uniformInfo.empty());
665 }
666
667 UniformLocationCase::IterateResult MaxUniformLocationCase::iterate (void)
668 {
669         int                                     maxLocation = 1024;
670         vector<UniformInfo>     uniformInfo = m_uniformInfo;
671
672         m_renderCtx.getFunctions().getIntegerv(GL_MAX_UNIFORM_LOCATIONS, &maxLocation);
673
674         uniformInfo[0].location = maxLocation-1;
675
676         return UniformLocationCase::run(uniformInfo);
677 }
678
679 } // Anonymous
680
681 UniformLocationTests::UniformLocationTests (Context& context)
682         : TestCaseGroup(context, "uniform_location", "Explicit uniform locations")
683 {
684 }
685
686 UniformLocationTests::~UniformLocationTests (void)
687 {
688         for (int i = 0; i < int(structTypes.size()); i++)
689                 delete structTypes[i];
690 }
691
692 glu::VarType createVarType (glu::DataType type)
693 {
694         return glu::VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP);
695 }
696
697 void UniformLocationTests::init (void)
698 {
699         using namespace glu;
700
701         const UniformInfo::ShaderStage checkStages[]    = { UniformInfo::SHADERSTAGE_VERTEX, UniformInfo::SHADERSTAGE_FRAGMENT };
702         const char*                                             stageNames[]    = {"vertex", "fragment"};
703         const int                                               maxLocations    = 1024;
704         const int                                               baseSeed                = m_context.getTestContext().getCommandLine().getBaseSeed();
705
706         const DataType                                  primitiveTypes[] =
707         {
708                 TYPE_FLOAT,
709                 TYPE_FLOAT_VEC2,
710                 TYPE_FLOAT_VEC3,
711                 TYPE_FLOAT_VEC4,
712
713                 TYPE_INT,
714                 TYPE_INT_VEC2,
715                 TYPE_INT_VEC3,
716                 TYPE_INT_VEC4,
717
718                 TYPE_UINT,
719                 TYPE_UINT_VEC2,
720                 TYPE_UINT_VEC3,
721                 TYPE_UINT_VEC4,
722
723                 TYPE_BOOL,
724                 TYPE_BOOL_VEC2,
725                 TYPE_BOOL_VEC3,
726                 TYPE_BOOL_VEC4,
727
728                 TYPE_FLOAT_MAT2,
729                 TYPE_FLOAT_MAT2X3,
730                 TYPE_FLOAT_MAT2X4,
731                 TYPE_FLOAT_MAT3X2,
732                 TYPE_FLOAT_MAT3,
733                 TYPE_FLOAT_MAT3X4,
734                 TYPE_FLOAT_MAT4X2,
735                 TYPE_FLOAT_MAT4X3,
736                 TYPE_FLOAT_MAT4,
737
738                 TYPE_SAMPLER_2D,
739                 TYPE_INT_SAMPLER_2D,
740                 TYPE_UINT_SAMPLER_2D,
741         };
742
743         const int maxPrimitiveTypeNdx = DE_LENGTH_OF_ARRAY(primitiveTypes) - 4;
744         DE_ASSERT(primitiveTypes[maxPrimitiveTypeNdx] == TYPE_FLOAT_MAT4);
745
746         // Primitive type cases with trivial linkage
747         {
748                 tcu::TestCaseGroup* const       group   = new tcu::TestCaseGroup(m_testCtx, "basic", "Location specified with use, single shader stage");
749                 de::Random                                      rng             (baseSeed + 0x1001);
750                 addChild(group);
751
752                 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
753                 {
754                         const DataType          type    = primitiveTypes[primitiveNdx];
755
756                         for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
757                         {
758                                 const string            name            = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
759
760                                 vector<UniformInfo> config;
761
762                                 UniformInfo                     uniform (createVarType(type),
763                                                                                          checkStages[stageNdx],
764                                                                                          checkStages[stageNdx],
765                                                                                          checkStages[stageNdx],
766                                                                                          rng.getInt(0, maxLocations-1));
767
768                                 config.push_back(uniform);
769                                 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
770                         }
771                 }
772         }
773
774         // Arrays
775         {
776                 tcu::TestCaseGroup* const       group   = new tcu::TestCaseGroup(m_testCtx, "array", "Array location specified with use, single shader stage");
777                 de::Random                                      rng             (baseSeed + 0x2001);
778                 addChild(group);
779
780                 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
781                 {
782                         const DataType          type    = primitiveTypes[primitiveNdx];
783
784                         for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
785                         {
786
787                                 const string            name    = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
788
789                                 vector<UniformInfo> config;
790
791                                 UniformInfo                     uniform (VarType(createVarType(type), 8),
792                                                                                                 checkStages[stageNdx],
793                                                                                                 checkStages[stageNdx],
794                                                                                                 checkStages[stageNdx],
795                                                                                                 rng.getInt(0, maxLocations-1-8));
796
797                                 config.push_back(uniform);
798                                 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
799                         }
800                 }
801         }
802
803         // Nested Arrays
804         {
805                 tcu::TestCaseGroup* const       group   = new tcu::TestCaseGroup(m_testCtx, "nested_array", "Array location specified with use, single shader stage");
806                 de::Random                                      rng             (baseSeed + 0x3001);
807                 addChild(group);
808
809                 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
810                 {
811                         const DataType          type    = primitiveTypes[primitiveNdx];
812
813                         for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
814                         {
815                                 const string            name            = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
816                                 // stay comfortably within minimum max uniform component count (896 in fragment) and sampler count with all types
817                                 const int                       arraySize       = (getDataTypeScalarSize(type) > 4 || isDataTypeSampler(type)) ? 3 : 7;
818
819                                 vector<UniformInfo> config;
820
821                                 UniformInfo                     uniform (VarType(VarType(createVarType(type), arraySize), arraySize),
822                                                                                          checkStages[stageNdx],
823                                                                                          checkStages[stageNdx],
824                                                                                          checkStages[stageNdx],
825                                                                                          rng.getInt(0, maxLocations-1-arraySize*arraySize));
826
827                                 config.push_back(uniform);
828                                 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
829                         }
830                 }
831         }
832
833         // Structs
834         {
835                 tcu::TestCaseGroup* const       group   = new tcu::TestCaseGroup(m_testCtx, "struct", "Struct location, random contents & declaration location");
836                 de::Random                                      rng             (baseSeed + 0x4001);
837                 addChild(group);
838
839                 for (int caseNdx = 0; caseNdx < 16; caseNdx++)
840                 {
841                         typedef UniformInfo::ShaderStage Stage;
842
843                         const string    name            = "case_" + de::toString(caseNdx);
844
845                         const Stage             layoutLoc       = Stage(rng.getUint32()&0x3);
846                         const Stage             declareLoc      = Stage((rng.getUint32()&0x3) | layoutLoc);
847                         const Stage             verifyLoc       = Stage((rng.getUint32()&0x3) & declareLoc);
848                         const int               location        = layoutLoc ? rng.getInt(0, maxLocations-1-5) : -1;
849
850                         StructType*             structProto = new StructType("S");
851
852                         structTypes.push_back(structProto);
853
854                         structProto->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
855                         structProto->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
856                         structProto->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
857                         structProto->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
858                         structProto->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
859
860                         {
861                                 vector<UniformInfo> config;
862
863                                 config.push_back(UniformInfo(VarType(structProto),
864                                                                                          declareLoc,
865                                                                                          layoutLoc,
866                                                                                          verifyLoc,
867                                                                                          location));
868                                 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
869                         }
870                 }
871         }
872
873         // Nested Structs
874         {
875                 tcu::TestCaseGroup* const       group   = new tcu::TestCaseGroup(m_testCtx, "nested_struct", "Struct location specified with use, single shader stage");
876                 de::Random                                      rng             (baseSeed + 0x5001);
877
878                 addChild(group);
879
880                 for (int caseNdx = 0; caseNdx < 16; caseNdx++)
881                 {
882                         typedef UniformInfo::ShaderStage Stage;
883
884                         const string    name            = "case_" + de::toString(caseNdx);
885                         const int               baseLoc         = rng.getInt(0, maxLocations-1-60);
886
887                         // Structs need to be added in the order of their declaration
888                         const Stage             layoutLocs[]=
889                         {
890                                 Stage(rng.getUint32()&0x3),
891                                 Stage(rng.getUint32()&0x3),
892                                 Stage(rng.getUint32()&0x3),
893                                 Stage(rng.getUint32()&0x3),
894                         };
895
896                         const deUint32  tempDecl[] =
897                         {
898                                 (rng.getUint32()&0x3) | layoutLocs[0],
899                                 (rng.getUint32()&0x3) | layoutLocs[1],
900                                 (rng.getUint32()&0x3) | layoutLocs[2],
901                                 (rng.getUint32()&0x3) | layoutLocs[3],
902                         };
903
904                         // Component structs need to be declared if anything using them is declared
905                         const Stage             declareLocs[] =
906                         {
907                                 Stage(tempDecl[0] | tempDecl[1] | tempDecl[2] | tempDecl[3]),
908                                 Stage(tempDecl[1] | tempDecl[2] | tempDecl[3]),
909                                 Stage(tempDecl[2] | tempDecl[3]),
910                                 Stage(tempDecl[3]),
911                         };
912
913                         const Stage             verifyLocs[] =
914                         {
915                                 Stage(rng.getUint32()&0x3 & declareLocs[0]),
916                                 Stage(rng.getUint32()&0x3 & declareLocs[1]),
917                                 Stage(rng.getUint32()&0x3 & declareLocs[2]),
918                                 Stage(rng.getUint32()&0x3 & declareLocs[3]),
919                         };
920
921                         StructType*             testTypes[]     =
922                         {
923                                 new StructType("Type0"),
924                                 new StructType("Type1"),
925                                 new StructType("Type2"),
926                                 new StructType("Type3"),
927                         };
928
929                         structTypes.push_back(testTypes[0]);
930                         structTypes.push_back(testTypes[1]);
931                         structTypes.push_back(testTypes[2]);
932                         structTypes.push_back(testTypes[3]);
933
934                         testTypes[0]->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
935                         testTypes[0]->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
936                         testTypes[0]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
937                         testTypes[0]->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
938                         testTypes[0]->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
939
940                         testTypes[1]->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
941                         testTypes[1]->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
942                         testTypes[1]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
943                         testTypes[1]->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
944                         testTypes[1]->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
945
946                         testTypes[2]->addMember("a", VarType(testTypes[0]));
947                         testTypes[2]->addMember("b", VarType(testTypes[1]));
948                         testTypes[2]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
949
950                         testTypes[3]->addMember("a", VarType(testTypes[2]));
951
952                         {
953                                 vector<UniformInfo> config;
954
955                                 config.push_back(UniformInfo(VarType(testTypes[0]),
956                                                                                          declareLocs[0],
957                                                                                          layoutLocs[0],
958                                                                                          verifyLocs[0],
959                                                                                          layoutLocs[0] ? baseLoc : -1));
960
961                                 config.push_back(UniformInfo(VarType(testTypes[1]),
962                                                                                          declareLocs[1],
963                                                                                          layoutLocs[1],
964                                                                                          verifyLocs[1],
965                                                                                          layoutLocs[1] ? baseLoc+5 : -1));
966
967                                 config.push_back(UniformInfo(VarType(testTypes[2]),
968                                                                                          declareLocs[2],
969                                                                                          layoutLocs[2],
970                                                                                          verifyLocs[2],
971                                                                                          layoutLocs[2] ? baseLoc+16 : -1));
972
973                                 config.push_back(UniformInfo(VarType(testTypes[3]),
974                                                                                          declareLocs[3],
975                                                                                          layoutLocs[3],
976                                                                                          verifyLocs[3],
977                                                                                          layoutLocs[3] ? baseLoc+27 : -1));
978
979                                 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
980                         }
981                 }
982         }
983
984         // Min/Max location
985         {
986                 tcu::TestCaseGroup* const       group           = new tcu::TestCaseGroup(m_testCtx, "min_max", "Maximum & minimum location");
987
988                 addChild(group);
989
990                 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
991                 {
992                         const DataType          type    = primitiveTypes[primitiveNdx];
993
994                         for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
995                         {
996                                 const string            name            = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
997                                 vector<UniformInfo> config;
998
999                                 config.push_back(UniformInfo(createVarType(type),
1000                                                                                          checkStages[stageNdx],
1001                                                                                          checkStages[stageNdx],
1002                                                                                          checkStages[stageNdx],
1003                                                                                          0));
1004
1005                                 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_min").c_str(), (name+"_min").c_str(), config));
1006
1007                                 group->addChild(new MaxUniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_max").c_str(), (name+"_max").c_str(), config));
1008                         }
1009                 }
1010         }
1011
1012         // Link
1013         {
1014                 tcu::TestCaseGroup* const       group   = new tcu::TestCaseGroup(m_testCtx, "link", "Location specified independently from use");
1015                 de::Random                                      rng             (baseSeed + 0x82e1);
1016
1017                 addChild(group);
1018
1019                 for (int caseNdx = 0; caseNdx < 10; caseNdx++)
1020                 {
1021                         const string            name            = "case_" + de::toString(caseNdx);
1022                         vector<UniformInfo> config;
1023
1024                         vector<int>                     locations       = shuffledRange(0, maxLocations, 0x1234 + caseNdx*100);
1025
1026                         for (int count = 0; count < 32; count++)
1027                         {
1028                                 typedef UniformInfo::ShaderStage Stage;
1029
1030                                 const Stage                     layoutLoc       = Stage(rng.getUint32()&0x3);
1031                                 const Stage                     declareLoc      = Stage((rng.getUint32()&0x3) | layoutLoc);
1032                                 const Stage                     verifyLoc       = Stage((rng.getUint32()&0x3) & declareLoc);
1033
1034                                 const UniformInfo       uniform         (createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]),
1035                                                                                                  declareLoc,
1036                                                                                                  layoutLoc,
1037                                                                                                  verifyLoc,
1038                                                                                                  (layoutLoc!=0) ? locations.back() : -1);
1039
1040                                 config.push_back(uniform);
1041                                 locations.pop_back();
1042                         }
1043                         group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
1044                 }
1045         }
1046
1047         // Negative
1048         {
1049                 de::MovePtr<tcu::TestCaseGroup> negativeGroup                   (new tcu::TestCaseGroup(m_testCtx, "negative", "Negative tests"));
1050
1051                 {
1052                         de::MovePtr<tcu::TestCaseGroup> es31Group               (new tcu::TestCaseGroup(m_testCtx, "es31", "GLSL ES 3.1 Negative tests"));
1053                         gls::ShaderLibrary                              shaderLibrary   (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
1054                         const vector<TestNode*>                 negativeCases    = shaderLibrary.loadShaderFile("shaders/es31/uniform_location.test");
1055
1056                         for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
1057                                 es31Group->addChild(negativeCases[ndx]);
1058
1059                         negativeGroup->addChild(es31Group.release());
1060                 }
1061
1062                 {
1063                         de::MovePtr<tcu::TestCaseGroup> es32Group               (new tcu::TestCaseGroup(m_testCtx, "es32", "GLSL ES 3.2 Negative tests"));
1064                         gls::ShaderLibrary                              shaderLibrary   (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
1065                         const vector<TestNode*>                 negativeCases    = shaderLibrary.loadShaderFile("shaders/es32/uniform_location.test");
1066
1067                         for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
1068                                 es32Group->addChild(negativeCases[ndx]);
1069
1070                         negativeGroup->addChild(es32Group.release());
1071                 }
1072
1073                 addChild(negativeGroup.release());
1074         }
1075 }
1076
1077 } // Functional
1078 } // gles31
1079 } // deqp