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
UniformInfodeqp::gles31::Functional::__anon2611c92f0111::UniformInfo84 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);
~UniformLocationCase(void)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
getUniformName(int ndx,const glu::VarType & type,const glu::TypeComponentVector & path)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
getFirstComponentName(const glu::VarType & type)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
UniformLocationCase(tcu::TestContext & context,glu::RenderContext & renderContext,const char * name,const char * desc,const vector<UniformInfo> & uniformInfo)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]
shuffledRange(int from,int to,int seed)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
getDataTypeSamplerSampleType(glu::DataType type)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.
getExpectedValue(glu::DataType type,int id,const char * name)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
iterate(void)216 UniformLocationCase::IterateResult UniformLocationCase::iterate (void)
217 {
218 return run(m_uniformInfo);
219 }
220
run(const vector<UniformInfo> & uniformList)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 GLU_EXPECT_NO_ERROR(gl.getError(), "error in readPixels");
244
245 if (!verifyResult(rendered.getAccess()))
246 {
247 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader produced incorrect result");
248 return STOP;
249 }
250
251 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
252 return STOP;
253 }
254
genShaderSources(const vector<UniformInfo> & uniformList)255 glu::ProgramSources UniformLocationCase::genShaderSources (const vector<UniformInfo>& uniformList)
256 {
257 std::ostringstream vertDecl, vertMain, fragDecl, fragMain;
258
259 vertDecl << "#version 310 es\n"
260 << "precision highp float;\n"
261 << "precision highp int;\n"
262 << "float verify(float val, float ref) { return float(abs(val-ref) < 0.05); }\n\n"
263 << "in highp vec4 a_position;\n"
264 << "out highp vec4 v_color;\n";
265 fragDecl << "#version 310 es\n\n"
266 << "precision highp float;\n"
267 << "precision highp int;\n"
268 << "float verify(float val, float ref) { return float(abs(val-ref) < 0.05); }\n\n"
269 << "in highp vec4 v_color;\n"
270 << "layout(location = 0) out mediump vec4 o_color;\n\n";
271
272 vertMain << "void main()\n{\n"
273 << " gl_Position = a_position;\n"
274 << " v_color = vec4(1.0);\n";
275
276 fragMain << "void main()\n{\n"
277 << " o_color = v_color;\n";
278
279 std::set<const glu::StructType*> declaredStructs;
280
281 // Declare uniforms
282 for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
283 {
284 const UniformInfo& uniformInfo = uniformList[uniformNdx];
285
286 const bool declareInVert = (uniformInfo.declareLocation & UniformInfo::SHADERSTAGE_VERTEX) != 0;
287 const bool declareInFrag = (uniformInfo.declareLocation & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
288 const bool layoutInVert = (uniformInfo.layoutLocation & UniformInfo::SHADERSTAGE_VERTEX) != 0;
289 const bool layoutInFrag = (uniformInfo.layoutLocation & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
290 const bool checkInVert = (uniformInfo.checkLocation & UniformInfo::SHADERSTAGE_VERTEX) != 0;
291 const bool checkInFrag = (uniformInfo.checkLocation & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
292
293 const string layout = uniformInfo.location >= 0 ? "layout(location = " + de::toString(uniformInfo.location) + ") " : "";
294 const string uniName = "uni" + de::toString(uniformNdx);
295
296 int location = uniformInfo.location;
297 int subTypeIndex = 0;
298
299 DE_ASSERT((declareInVert && layoutInVert) || !layoutInVert); // Cannot have layout without declaration
300 DE_ASSERT((declareInFrag && layoutInFrag) || !layoutInFrag);
301 DE_ASSERT(location<0 || (layoutInVert || layoutInFrag)); // Cannot have location without layout
302
303 // struct definitions
304 if (uniformInfo.type.isStructType())
305 {
306 const glu::StructType* const structType = uniformInfo.type.getStructPtr();
307 if (!declaredStructs.count(structType))
308 {
309 if (declareInVert)
310 vertDecl << glu::declare(structType, 0) << ";\n";
311
312 if (declareInFrag)
313 fragDecl << glu::declare(structType, 0) << ";\n";
314
315 declaredStructs.insert(structType);
316 }
317 }
318
319 if (declareInVert)
320 vertDecl << "uniform " << (layoutInVert ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";
321
322 if (declareInFrag)
323 fragDecl << "uniform " << (layoutInFrag ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";
324
325 // Anything that needs to be done for each enclosed primitive type
326 for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++, subTypeIndex++)
327 {
328 const glu::VarType subType = glu::getVarType(uniformInfo.type, subTypeIter.getPath());
329 const glu::DataType scalarType = glu::getDataTypeScalarType(subType.getBasicType());
330 const char* const typeName = glu::getDataTypeName(scalarType);
331 const string expectValue = de::floatToString(getExpectedValue(scalarType, location >= 0 ? location+subTypeIndex : -1, typeName), 3);
332
333 if (glu::isDataTypeSampler(scalarType))
334 {
335 if (checkInVert)
336 vertMain << " v_color.rgb *= verify(float( texture(" << uniName
337 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
338 << ", vec2(0.5)).r), " << expectValue << ");\n";
339 if (checkInFrag)
340 fragMain << " o_color.rgb *= verify(float( texture(" << uniName
341 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
342 << ", vec2(0.5)).r), " << expectValue << ");\n";
343 }
344 else
345 {
346 if (checkInVert)
347 vertMain << " v_color.rgb *= verify(float(" << uniName
348 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
349 << getFirstComponentName(subType) << "), " << expectValue << ");\n";
350 if (checkInFrag)
351 fragMain << " o_color.rgb *= verify(float(" << uniName
352 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
353 << getFirstComponentName(subType) << "), " << expectValue << ");\n";
354 }
355 }
356 }
357
358 vertMain << "}\n";
359 fragMain << "}\n";
360
361 return glu::makeVtxFragSources(vertDecl.str() + vertMain.str(), fragDecl.str() + fragMain.str());
362 }
363
verifyLocations(const glu::ShaderProgram & program,const vector<UniformInfo> & uniformList)364 bool UniformLocationCase::verifyLocations (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
365 {
366 using tcu::TestLog;
367
368 const glw::Functions& gl = m_renderCtx.getFunctions();
369 const bool vertexOk = program.getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk;
370 const bool fragmentOk = program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk;
371 const bool linkOk = program.getProgramInfo().linkOk;
372 const deUint32 programID = program.getProgram();
373
374 TestLog& log = m_testCtx.getLog();
375 std::set<int> usedLocations;
376
377 log << program;
378
379 if (!vertexOk || !fragmentOk || !linkOk)
380 {
381 log << TestLog::Message << "ERROR: shader failed to compile/link" << TestLog::EndMessage;
382 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader failed to compile/link");
383 return false;
384 }
385
386 for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
387 {
388 const UniformInfo& uniformInfo = uniformList[uniformNdx];
389 int subTypeIndex = 0;
390
391 for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++, subTypeIndex++)
392 {
393 const string name = getUniformName(uniformNdx, uniformInfo.type, subTypeIter.getPath());
394 const int gotLoc = gl.getUniformLocation(programID, name.c_str());
395 const int expectLoc = uniformInfo.location >= 0 ? uniformInfo.location+subTypeIndex : -1;
396
397 if (expectLoc >= 0)
398 {
399 if (uniformInfo.checkLocation == 0 && gotLoc == -1)
400 continue;
401
402 if (gotLoc != expectLoc)
403 {
404 log << TestLog::Message << "ERROR: found uniform " << name << " in location " << gotLoc << " when it should have been in " << expectLoc << TestLog::EndMessage;
405 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect uniform location");
406 return false;
407 }
408
409 if (usedLocations.find(expectLoc) != usedLocations.end())
410 {
411 log << TestLog::Message << "ERROR: expected uniform " << name << " in location " << gotLoc << " but it has already been used" << TestLog::EndMessage;
412 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Overlapping uniform location");
413 return false;
414 }
415
416 usedLocations.insert(expectLoc);
417 }
418 else if (gotLoc >= 0)
419 {
420 if (usedLocations.count(gotLoc))
421 {
422 log << TestLog::Message << "ERROR: found uniform " << name << " in location " << gotLoc << " which has already been used" << TestLog::EndMessage;
423 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Overlapping uniform location");
424 return false;
425 }
426
427 usedLocations.insert(gotLoc);
428 }
429 }
430 }
431
432 return true;
433 }
434
435 // Check that shader output is white (or very close to it)
verifyResult(const tcu::ConstPixelBufferAccess & access)436 bool UniformLocationCase::verifyResult (const tcu::ConstPixelBufferAccess& access)
437 {
438 using tcu::Vec4;
439
440 const Vec4 threshold (0.1f, 0.1f, 0.1f, 0.1f);
441 const Vec4 reference (1.0f, 1.0f, 1.0f, 1.0f);
442
443 for (int y = 0; y < access.getHeight(); y++)
444 {
445 for (int x = 0; x < access.getWidth(); x++)
446 {
447 const Vec4 diff = abs(access.getPixel(x, y) - reference);
448
449 if (!boolAll(lessThanEqual(diff, threshold)))
450 return false;
451 }
452 }
453
454 return true;
455 }
456
457 // get a 4 channel 8 bits each texture format that is usable by the given sampler type
getTextureFormat(glu::DataType samplerType)458 deUint32 getTextureFormat (glu::DataType samplerType)
459 {
460 using namespace glu;
461
462 switch (samplerType)
463 {
464 case TYPE_SAMPLER_1D:
465 case TYPE_SAMPLER_2D:
466 case TYPE_SAMPLER_CUBE:
467 case TYPE_SAMPLER_2D_ARRAY:
468 case TYPE_SAMPLER_3D:
469 return GL_RGBA8;
470
471 case TYPE_INT_SAMPLER_1D:
472 case TYPE_INT_SAMPLER_2D:
473 case TYPE_INT_SAMPLER_CUBE:
474 case TYPE_INT_SAMPLER_2D_ARRAY:
475 case TYPE_INT_SAMPLER_3D:
476 return GL_RGBA8I;
477
478 case TYPE_UINT_SAMPLER_1D:
479 case TYPE_UINT_SAMPLER_2D:
480 case TYPE_UINT_SAMPLER_CUBE:
481 case TYPE_UINT_SAMPLER_2D_ARRAY:
482 case TYPE_UINT_SAMPLER_3D:
483 return GL_RGBA8UI;
484
485 default:
486 DE_FATAL("Unsupported (sampler) type");
487 return 0;
488 }
489 }
490
491 // create a texture suitable for sampling by the given sampler type and bind it
createTexture(glu::DataType samplerType,float redChannelValue,int binding)492 de::MovePtr<glu::Texture2D> UniformLocationCase::createTexture (glu::DataType samplerType, float redChannelValue, int binding)
493 {
494 using namespace glu;
495
496 const glw::Functions& gl = m_renderCtx.getFunctions();
497
498 const deUint32 format = getTextureFormat(samplerType);
499 de::MovePtr<Texture2D> tex;
500
501 tex = de::MovePtr<Texture2D>(new Texture2D(m_renderCtx, format, 16, 16));
502
503 tex->getRefTexture().allocLevel(0);
504
505 if (format == GL_RGBA8I || format == GL_RGBA8UI)
506 tcu::clear(tex->getRefTexture().getLevel(0), tcu::IVec4(int(redChannelValue), 0, 0, 0));
507 else
508 tcu::clear(tex->getRefTexture().getLevel(0), tcu::Vec4(redChannelValue, 0.0f, 0.0f, 1.0f));
509
510 gl.activeTexture(GL_TEXTURE0 + binding);
511 tex->upload();
512
513 gl.bindTexture(GL_TEXTURE_2D, tex->getGLTexture());
514 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
515 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
516
517 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase: texture upload");
518
519 return tex;
520 }
521
render(const glu::ShaderProgram & program,const vector<UniformInfo> & uniformList)522 void UniformLocationCase::render (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
523 {
524 using glu::Texture2D;
525 using de::MovePtr;
526 typedef vector<Texture2D*> TextureList;
527
528 const glw::Functions& gl = m_renderCtx.getFunctions();
529 const deUint32 programID = program.getProgram();
530 const deInt32 posLoc = gl.getAttribLocation(programID, "a_position");
531
532 // Vertex data.
533 const float position[] =
534 {
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 1.0f, 1.0f, 0.1f, 1.0f
539 };
540 const void * positionPtr = &position[0];
541 const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
542 const void * indicesPtr = &indices[0];
543
544 // some buffers to feed to the GPU, only the first element is relevant since the others are never verified
545 float floatBuf[16] = {0.0f};
546 deInt32 intBuf[4] = {0};
547 deUint32 uintBuf[4] = {0};
548 deUint32 vao = 0;
549 deUint32 attribVbo = 0;
550 deUint32 elementVbo = 0;
551
552 TextureList texList;
553
554 bool isGL45 = glu::contextSupports(m_renderCtx.getType(), glu::ApiType::core(4, 5));
555 if (isGL45)
556 {
557 gl.genVertexArrays(1, &vao);
558 gl.bindVertexArray(vao);
559
560 gl.genBuffers(1, &attribVbo);
561 gl.genBuffers(1, &elementVbo);
562
563 gl.bindBuffer(GL_ARRAY_BUFFER, attribVbo);
564 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(DE_LENGTH_OF_ARRAY(position) * sizeof(float)), position, GL_STATIC_DRAW);
565 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase::render");
566
567 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementVbo);
568 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(DE_LENGTH_OF_ARRAY(indices) * sizeof(deUint16)), indices, GL_STATIC_DRAW);
569 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase::render");
570
571 positionPtr = 0;
572 indicesPtr = 0;
573 }
574
575 TCU_CHECK(posLoc >= 0);
576 gl.useProgram(programID);
577
578 try
579 {
580
581 // Set uniforms
582 for (unsigned int uniformNdx = 0; uniformNdx < uniformList.size(); uniformNdx++)
583 {
584 const UniformInfo& uniformInfo = uniformList[uniformNdx];
585 int expectedLocation = uniformInfo.location;
586
587 for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++)
588 {
589 const glu::VarType type = glu::getVarType(uniformInfo.type, subTypeIter.getPath());
590 const string name = getUniformName(uniformNdx, uniformInfo.type, subTypeIter.getPath());
591 const int gotLoc = gl.getUniformLocation(programID, name.c_str());
592 const glu::DataType scalarType = glu::getDataTypeScalarType(type.getBasicType());
593 const char* const typeName = glu::getDataTypeName(scalarType);
594 const float expectedValue = getExpectedValue(scalarType, expectedLocation, typeName);
595
596 if (glu::isDataTypeSampler(scalarType))
597 {
598 const int binding = (int)texList.size();
599
600 texList.push_back(createTexture(scalarType, expectedValue, binding).release());
601 gl.uniform1i(gotLoc, binding);
602 }
603 else if(gotLoc >= 0)
604 {
605 floatBuf[0] = expectedValue;
606 intBuf[0] = int(expectedValue);
607 uintBuf[0] = deUint32(expectedValue);
608
609 m_testCtx.getLog() << tcu::TestLog::Message << "Set uniform " << name << " in location " << gotLoc << " to " << expectedValue << tcu::TestLog::EndMessage;
610
611 switch (type.getBasicType())
612 {
613 case glu::TYPE_FLOAT: gl.uniform1fv(gotLoc, 1, floatBuf); break;
614 case glu::TYPE_FLOAT_VEC2: gl.uniform2fv(gotLoc, 1, floatBuf); break;
615 case glu::TYPE_FLOAT_VEC3: gl.uniform3fv(gotLoc, 1, floatBuf); break;
616 case glu::TYPE_FLOAT_VEC4: gl.uniform4fv(gotLoc, 1, floatBuf); break;
617
618 case glu::TYPE_INT: gl.uniform1iv(gotLoc, 1, intBuf); break;
619 case glu::TYPE_INT_VEC2: gl.uniform2iv(gotLoc, 1, intBuf); break;
620 case glu::TYPE_INT_VEC3: gl.uniform3iv(gotLoc, 1, intBuf); break;
621 case glu::TYPE_INT_VEC4: gl.uniform4iv(gotLoc, 1, intBuf); break;
622
623 case glu::TYPE_UINT: gl.uniform1uiv(gotLoc, 1, uintBuf); break;
624 case glu::TYPE_UINT_VEC2: gl.uniform2uiv(gotLoc, 1, uintBuf); break;
625 case glu::TYPE_UINT_VEC3: gl.uniform3uiv(gotLoc, 1, uintBuf); break;
626 case glu::TYPE_UINT_VEC4: gl.uniform4uiv(gotLoc, 1, uintBuf); break;
627
628 case glu::TYPE_BOOL: gl.uniform1iv(gotLoc, 1, intBuf); break;
629 case glu::TYPE_BOOL_VEC2: gl.uniform2iv(gotLoc, 1, intBuf); break;
630 case glu::TYPE_BOOL_VEC3: gl.uniform3iv(gotLoc, 1, intBuf); break;
631 case glu::TYPE_BOOL_VEC4: gl.uniform4iv(gotLoc, 1, intBuf); break;
632
633 case glu::TYPE_FLOAT_MAT2: gl.uniformMatrix2fv(gotLoc, 1, false, floatBuf); break;
634 case glu::TYPE_FLOAT_MAT2X3: gl.uniformMatrix2x3fv(gotLoc, 1, false, floatBuf); break;
635 case glu::TYPE_FLOAT_MAT2X4: gl.uniformMatrix2x4fv(gotLoc, 1, false, floatBuf); break;
636
637 case glu::TYPE_FLOAT_MAT3X2: gl.uniformMatrix3x2fv(gotLoc, 1, false, floatBuf); break;
638 case glu::TYPE_FLOAT_MAT3: gl.uniformMatrix3fv(gotLoc, 1, false, floatBuf); break;
639 case glu::TYPE_FLOAT_MAT3X4: gl.uniformMatrix3x4fv(gotLoc, 1, false, floatBuf); break;
640
641 case glu::TYPE_FLOAT_MAT4X2: gl.uniformMatrix4x2fv(gotLoc, 1, false, floatBuf); break;
642 case glu::TYPE_FLOAT_MAT4X3: gl.uniformMatrix4x3fv(gotLoc, 1, false, floatBuf); break;
643 case glu::TYPE_FLOAT_MAT4: gl.uniformMatrix4fv(gotLoc, 1, false, floatBuf); break;
644 default:
645 DE_ASSERT(false);
646 }
647 }
648
649 expectedLocation += expectedLocation>=0;
650 }
651 }
652
653 gl.enableVertexAttribArray(posLoc);
654 GLU_EXPECT_NO_ERROR(gl.getError(), "error in glEnableVertexAttribArray");
655 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, positionPtr);
656 GLU_EXPECT_NO_ERROR(gl.getError(), "error in glVertexAttribPointer");
657
658 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, indicesPtr);
659 GLU_EXPECT_NO_ERROR(gl.getError(), "error in glDrawElements");
660
661 gl.disableVertexAttribArray(posLoc);
662 GLU_EXPECT_NO_ERROR(gl.getError(), "error in glDisableVertexAttribArray");
663
664 if (isGL45)
665 {
666 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
667 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
668
669 gl.deleteBuffers(1, &attribVbo);
670 gl.deleteBuffers(1, &elementVbo);
671 gl.deleteVertexArrays(1, &vao);
672 }
673 }
674 catch(...)
675 {
676 for (int i = 0; i < int(texList.size()); i++)
677 delete texList[i];
678
679 throw;
680 }
681
682 for (int i = 0; i < int(texList.size()); i++)
683 delete texList[i];
684 }
685
686 class MaxUniformLocationCase : public UniformLocationCase
687 {
688 public:
689 MaxUniformLocationCase (tcu::TestContext& context,
690 glu::RenderContext& renderContext,
691 const char* name,
692 const char* desc,
693 const vector<UniformInfo>& uniformInfo);
~MaxUniformLocationCase(void)694 virtual ~MaxUniformLocationCase (void) {}
695 virtual IterateResult iterate (void);
696 };
697
MaxUniformLocationCase(tcu::TestContext & context,glu::RenderContext & renderContext,const char * name,const char * desc,const vector<UniformInfo> & uniformInfo)698 MaxUniformLocationCase::MaxUniformLocationCase (tcu::TestContext& context,
699 glu::RenderContext& renderContext,
700 const char* name,
701 const char* desc,
702 const vector<UniformInfo>& uniformInfo)
703 : UniformLocationCase(context, renderContext, name, desc, uniformInfo)
704 {
705 DE_ASSERT(!uniformInfo.empty());
706 }
707
iterate(void)708 UniformLocationCase::IterateResult MaxUniformLocationCase::iterate (void)
709 {
710 int maxLocation = 1024;
711 vector<UniformInfo> uniformInfo = m_uniformInfo;
712
713 m_renderCtx.getFunctions().getIntegerv(GL_MAX_UNIFORM_LOCATIONS, &maxLocation);
714
715 uniformInfo[0].location = maxLocation-1;
716
717 return UniformLocationCase::run(uniformInfo);
718 }
719
720 } // Anonymous
721
UniformLocationTests(Context & context,bool isGL45)722 UniformLocationTests::UniformLocationTests (Context& context, bool isGL45)
723 : TestCaseGroup(context, "uniform_location", "Explicit uniform locations")
724 , m_isGL45(isGL45)
725 {
726 }
727
~UniformLocationTests(void)728 UniformLocationTests::~UniformLocationTests (void)
729 {
730 for (int i = 0; i < int(structTypes.size()); i++)
731 delete structTypes[i];
732 }
733
createVarType(glu::DataType type)734 glu::VarType createVarType (glu::DataType type)
735 {
736 return glu::VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP);
737 }
738
init(void)739 void UniformLocationTests::init (void)
740 {
741 using namespace glu;
742
743 const UniformInfo::ShaderStage checkStages[] = { UniformInfo::SHADERSTAGE_VERTEX, UniformInfo::SHADERSTAGE_FRAGMENT };
744 const char* stageNames[] = {"vertex", "fragment"};
745 const int maxLocations = 1024;
746 const int baseSeed = m_context.getTestContext().getCommandLine().getBaseSeed();
747
748 const DataType primitiveTypes[] =
749 {
750 TYPE_FLOAT,
751 TYPE_FLOAT_VEC2,
752 TYPE_FLOAT_VEC3,
753 TYPE_FLOAT_VEC4,
754
755 TYPE_INT,
756 TYPE_INT_VEC2,
757 TYPE_INT_VEC3,
758 TYPE_INT_VEC4,
759
760 TYPE_UINT,
761 TYPE_UINT_VEC2,
762 TYPE_UINT_VEC3,
763 TYPE_UINT_VEC4,
764
765 TYPE_BOOL,
766 TYPE_BOOL_VEC2,
767 TYPE_BOOL_VEC3,
768 TYPE_BOOL_VEC4,
769
770 TYPE_FLOAT_MAT2,
771 TYPE_FLOAT_MAT2X3,
772 TYPE_FLOAT_MAT2X4,
773 TYPE_FLOAT_MAT3X2,
774 TYPE_FLOAT_MAT3,
775 TYPE_FLOAT_MAT3X4,
776 TYPE_FLOAT_MAT4X2,
777 TYPE_FLOAT_MAT4X3,
778 TYPE_FLOAT_MAT4,
779
780 TYPE_SAMPLER_2D,
781 TYPE_INT_SAMPLER_2D,
782 TYPE_UINT_SAMPLER_2D,
783 };
784
785 const int maxPrimitiveTypeNdx = DE_LENGTH_OF_ARRAY(primitiveTypes) - 4;
786 DE_ASSERT(primitiveTypes[maxPrimitiveTypeNdx] == TYPE_FLOAT_MAT4);
787
788 // Primitive type cases with trivial linkage
789 {
790 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "basic", "Location specified with use, single shader stage");
791 de::Random rng (baseSeed + 0x1001);
792 addChild(group);
793
794 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
795 {
796 const DataType type = primitiveTypes[primitiveNdx];
797
798 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
799 {
800 const string name = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
801
802 vector<UniformInfo> config;
803
804 UniformInfo uniform (createVarType(type),
805 checkStages[stageNdx],
806 checkStages[stageNdx],
807 checkStages[stageNdx],
808 rng.getInt(0, maxLocations-1));
809
810 config.push_back(uniform);
811 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
812 }
813 }
814 }
815
816 // Arrays
817 {
818 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "array", "Array location specified with use, single shader stage");
819 de::Random rng (baseSeed + 0x2001);
820 addChild(group);
821
822 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
823 {
824 const DataType type = primitiveTypes[primitiveNdx];
825
826 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
827 {
828
829 const string name = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
830
831 vector<UniformInfo> config;
832
833 UniformInfo uniform (VarType(createVarType(type), 8),
834 checkStages[stageNdx],
835 checkStages[stageNdx],
836 checkStages[stageNdx],
837 rng.getInt(0, maxLocations-1-8));
838
839 config.push_back(uniform);
840 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
841 }
842 }
843 }
844
845 // Nested Arrays
846 {
847 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "nested_array", "Array location specified with use, single shader stage");
848 de::Random rng (baseSeed + 0x3001);
849 addChild(group);
850
851 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
852 {
853 const DataType type = primitiveTypes[primitiveNdx];
854
855 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
856 {
857 const string name = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
858 // stay comfortably within minimum max uniform component count (896 in fragment) and sampler count with all types
859 const int arraySize = (getDataTypeScalarSize(type) > 4 || isDataTypeSampler(type)) ? 3 : 7;
860
861 vector<UniformInfo> config;
862
863 UniformInfo uniform (VarType(VarType(createVarType(type), arraySize), arraySize),
864 checkStages[stageNdx],
865 checkStages[stageNdx],
866 checkStages[stageNdx],
867 rng.getInt(0, maxLocations-1-arraySize*arraySize));
868
869 config.push_back(uniform);
870 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
871 }
872 }
873 }
874
875 // Structs
876 {
877 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "struct", "Struct location, random contents & declaration location");
878 de::Random rng (baseSeed + 0x4001);
879 addChild(group);
880
881 for (int caseNdx = 0; caseNdx < 16; caseNdx++)
882 {
883 typedef UniformInfo::ShaderStage Stage;
884
885 const string name = "case_" + de::toString(caseNdx);
886
887 const Stage layoutLoc = Stage(rng.getUint32()&0x3);
888 const Stage declareLoc = Stage((rng.getUint32()&0x3) | layoutLoc);
889 const Stage verifyLoc = Stage((rng.getUint32()&0x3) & declareLoc);
890 const int location = layoutLoc ? rng.getInt(0, maxLocations-1-5) : -1;
891
892 StructType* structProto = new StructType("S");
893
894 structTypes.push_back(structProto);
895
896 structProto->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
897 structProto->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
898 structProto->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
899 structProto->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
900 structProto->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
901
902 {
903 vector<UniformInfo> config;
904
905 config.push_back(UniformInfo(VarType(structProto),
906 declareLoc,
907 layoutLoc,
908 verifyLoc,
909 location));
910 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
911 }
912 }
913 }
914
915 // Nested Structs
916 {
917 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "nested_struct", "Struct location specified with use, single shader stage");
918 de::Random rng (baseSeed + 0x5001);
919
920 addChild(group);
921
922 for (int caseNdx = 0; caseNdx < 16; caseNdx++)
923 {
924 typedef UniformInfo::ShaderStage Stage;
925
926 const string name = "case_" + de::toString(caseNdx);
927 const int baseLoc = rng.getInt(0, maxLocations-1-60);
928
929 // Structs need to be added in the order of their declaration
930 const Stage layoutLocs[]=
931 {
932 Stage(rng.getUint32()&0x3),
933 Stage(rng.getUint32()&0x3),
934 Stage(rng.getUint32()&0x3),
935 Stage(rng.getUint32()&0x3),
936 };
937
938 const deUint32 tempDecl[] =
939 {
940 (rng.getUint32()&0x3) | layoutLocs[0],
941 (rng.getUint32()&0x3) | layoutLocs[1],
942 (rng.getUint32()&0x3) | layoutLocs[2],
943 (rng.getUint32()&0x3) | layoutLocs[3],
944 };
945
946 // Component structs need to be declared if anything using them is declared
947 const Stage declareLocs[] =
948 {
949 Stage(tempDecl[0] | tempDecl[1] | tempDecl[2] | tempDecl[3]),
950 Stage(tempDecl[1] | tempDecl[2] | tempDecl[3]),
951 Stage(tempDecl[2] | tempDecl[3]),
952 Stage(tempDecl[3]),
953 };
954
955 const Stage verifyLocs[] =
956 {
957 Stage(rng.getUint32()&0x3 & declareLocs[0]),
958 Stage(rng.getUint32()&0x3 & declareLocs[1]),
959 Stage(rng.getUint32()&0x3 & declareLocs[2]),
960 Stage(rng.getUint32()&0x3 & declareLocs[3]),
961 };
962
963 StructType* testTypes[] =
964 {
965 new StructType("Type0"),
966 new StructType("Type1"),
967 new StructType("Type2"),
968 new StructType("Type3"),
969 };
970
971 structTypes.push_back(testTypes[0]);
972 structTypes.push_back(testTypes[1]);
973 structTypes.push_back(testTypes[2]);
974 structTypes.push_back(testTypes[3]);
975
976 testTypes[0]->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
977 testTypes[0]->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
978 testTypes[0]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
979 testTypes[0]->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
980 testTypes[0]->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
981
982 testTypes[1]->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
983 testTypes[1]->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
984 testTypes[1]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
985 testTypes[1]->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
986 testTypes[1]->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
987
988 testTypes[2]->addMember("a", VarType(testTypes[0]));
989 testTypes[2]->addMember("b", VarType(testTypes[1]));
990 testTypes[2]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
991
992 testTypes[3]->addMember("a", VarType(testTypes[2]));
993
994 {
995 vector<UniformInfo> config;
996
997 config.push_back(UniformInfo(VarType(testTypes[0]),
998 declareLocs[0],
999 layoutLocs[0],
1000 verifyLocs[0],
1001 layoutLocs[0] ? baseLoc : -1));
1002
1003 config.push_back(UniformInfo(VarType(testTypes[1]),
1004 declareLocs[1],
1005 layoutLocs[1],
1006 verifyLocs[1],
1007 layoutLocs[1] ? baseLoc+5 : -1));
1008
1009 config.push_back(UniformInfo(VarType(testTypes[2]),
1010 declareLocs[2],
1011 layoutLocs[2],
1012 verifyLocs[2],
1013 layoutLocs[2] ? baseLoc+16 : -1));
1014
1015 config.push_back(UniformInfo(VarType(testTypes[3]),
1016 declareLocs[3],
1017 layoutLocs[3],
1018 verifyLocs[3],
1019 layoutLocs[3] ? baseLoc+27 : -1));
1020
1021 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
1022 }
1023 }
1024 }
1025
1026 // Min/Max location
1027 {
1028 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "min_max", "Maximum & minimum location");
1029
1030 addChild(group);
1031
1032 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
1033 {
1034 const DataType type = primitiveTypes[primitiveNdx];
1035
1036 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
1037 {
1038 const string name = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
1039 vector<UniformInfo> config;
1040
1041 config.push_back(UniformInfo(createVarType(type),
1042 checkStages[stageNdx],
1043 checkStages[stageNdx],
1044 checkStages[stageNdx],
1045 0));
1046
1047 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_min").c_str(), (name+"_min").c_str(), config));
1048
1049 group->addChild(new MaxUniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_max").c_str(), (name+"_max").c_str(), config));
1050 }
1051 }
1052 }
1053
1054 // Link
1055 {
1056 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "link", "Location specified independently from use");
1057 de::Random rng (baseSeed + 0x82e1);
1058
1059 addChild(group);
1060
1061 for (int caseNdx = 0; caseNdx < 10; caseNdx++)
1062 {
1063 const string name = "case_" + de::toString(caseNdx);
1064 vector<UniformInfo> config;
1065
1066 vector<int> locations = shuffledRange(0, maxLocations, 0x1234 + caseNdx*100);
1067
1068 for (int count = 0; count < 32; count++)
1069 {
1070 typedef UniformInfo::ShaderStage Stage;
1071
1072 const Stage layoutLoc = Stage(rng.getUint32()&0x3);
1073 const Stage declareLoc = Stage((rng.getUint32()&0x3) | layoutLoc);
1074 const Stage verifyLoc = Stage((rng.getUint32()&0x3) & declareLoc);
1075
1076 const UniformInfo uniform (createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]),
1077 declareLoc,
1078 layoutLoc,
1079 verifyLoc,
1080 (layoutLoc!=0) ? locations.back() : -1);
1081
1082 config.push_back(uniform);
1083 locations.pop_back();
1084 }
1085 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
1086 }
1087 }
1088
1089 // Negative
1090 {
1091 de::MovePtr<tcu::TestCaseGroup> negativeGroup (new tcu::TestCaseGroup(m_testCtx, "negative", "Negative tests"));
1092
1093 {
1094 de::MovePtr<tcu::TestCaseGroup> es31Group (new tcu::TestCaseGroup(m_testCtx, "es31", "GLSL ES 3.1 Negative tests"));
1095 gls::ShaderLibrary shaderLibrary (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
1096 const vector<TestNode*> negativeCases = shaderLibrary.loadShaderFile("shaders/es31/uniform_location.test");
1097
1098 for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
1099 es31Group->addChild(negativeCases[ndx]);
1100
1101 negativeGroup->addChild(es31Group.release());
1102 }
1103
1104 // ES only
1105 if (!m_isGL45)
1106 {
1107 de::MovePtr<tcu::TestCaseGroup> es32Group (new tcu::TestCaseGroup(m_testCtx, "es32", "GLSL ES 3.2 Negative tests"));
1108 gls::ShaderLibrary shaderLibrary (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
1109 const vector<TestNode*> negativeCases = shaderLibrary.loadShaderFile("shaders/es32/uniform_location.test");
1110
1111 for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
1112 es32Group->addChild(negativeCases[ndx]);
1113
1114 negativeGroup->addChild(es32Group.release());
1115 }
1116
1117 addChild(negativeGroup.release());
1118 }
1119 }
1120
1121 } // Functional
1122 } // gles31
1123 } // deqp
1124