1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Explicit uniform location tests
22 *//*--------------------------------------------------------------------*/
24 #include "es31fUniformLocationTests.hpp"
26 #include "tcuTestLog.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "tcuCommandLine.hpp"
31 #include "glsShaderLibrary.hpp"
32 #include "glsTextureTestUtil.hpp"
34 #include "gluShaderProgram.hpp"
35 #include "gluTexture.hpp"
36 #include "gluPixelTransfer.hpp"
37 #include "gluVarType.hpp"
38 #include "gluVarTypeUtil.hpp"
40 #include "glwFunctions.hpp"
41 #include "glwEnums.hpp"
42 #include "sglrContextUtil.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
47 #include "deRandom.hpp"
73 SHADERSTAGE_VERTEX = (1<<0),
74 SHADERSTAGE_FRAGMENT= (1<<1),
75 SHADERSTAGE_BOTH = (SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT),
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
84 UniformInfo (VarType type_, ShaderStage declareLocation_, ShaderStage layoutLocation_, ShaderStage checkLocation_, int location_ = -1)
86 , declareLocation (declareLocation_)
87 , layoutLocation (layoutLocation_)
88 , checkLocation (checkLocation_)
89 , location (location_)
94 class UniformLocationCase : public tcu::TestCase
97 UniformLocationCase (tcu::TestContext& context,
98 glu::RenderContext& renderContext,
101 const vector<UniformInfo>& uniformInfo);
102 virtual ~UniformLocationCase (void) {}
104 virtual IterateResult iterate (void);
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);
113 static float getExpectedValue (glu::DataType type, int id, const char* name);
115 de::MovePtr<glu::Texture2D> createTexture (glu::DataType samplerType, float redChannelValue, int binding);
117 glu::RenderContext& m_renderCtx;
119 const vector<UniformInfo> m_uniformInfo;
127 string getUniformName (int ndx, const glu::VarType& type, const glu::TypeComponentVector& path)
129 std::ostringstream buff;
130 buff << "uni" << ndx << glu::TypeAccessFormat(type, path);
135 string getFirstComponentName (const glu::VarType& type)
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());
146 UniformLocationCase::UniformLocationCase (tcu::TestContext& context,
147 glu::RenderContext& renderContext,
150 const vector<UniformInfo>& uniformInfo)
151 : TestCase (context, name, desc)
152 , m_renderCtx (renderContext)
153 , m_uniformInfo (uniformInfo)
158 std::vector<int> shuffledRange (int from, int to, int seed)
160 const int count = to - from;
162 vector<int> retval (count);
163 de::Random rng (seed);
165 DE_ASSERT(count > 0);
167 for (int ndx = 0; ndx < count; ndx++)
168 retval[ndx] = ndx + from;
170 rng.shuffle(retval.begin(), retval.end());
174 glu::DataType getDataTypeSamplerSampleType (glu::DataType type)
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)
187 DE_FATAL("Unknown sampler type");
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)
195 const deUint32 hash = deStringHash(name) + deInt32Hash(id);
197 glu::DataType adjustedType = type;
199 if (glu::isDataTypeSampler(type))
200 adjustedType = getDataTypeSamplerSampleType(type);
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);
211 DE_FATAL("Unkown primitive type");
213 return glu::TYPE_INVALID;
216 UniformLocationCase::IterateResult UniformLocationCase::iterate (void)
218 return run(m_uniformInfo);
221 UniformLocationCase::IterateResult UniformLocationCase::run (const vector<UniformInfo>& uniformList)
223 using gls::TextureTestUtil::RandomViewport;
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);
231 tcu::Surface rendered (RENDER_SIZE, RENDER_SIZE);
233 if (!verifyLocations(program, uniformList))
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);
240 render(program, uniformList);
242 glu::readPixels(m_renderCtx, viewport.x, viewport.y, rendered.getAccess());
244 if (!verifyResult(rendered.getAccess()))
246 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader produced incorrect result");
250 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
254 glu::ProgramSources UniformLocationCase::genShaderSources (const vector<UniformInfo>& uniformList)
256 std::ostringstream vertDecl, vertMain, fragDecl, fragMain;
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";
271 vertMain << "void main()\n{\n"
272 << " gl_Position = a_position;\n"
273 << " v_color = vec4(1.0);\n";
275 fragMain << "void main()\n{\n"
276 << " o_color = v_color;\n";
278 std::set<const glu::StructType*> declaredStructs;
281 for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
283 const UniformInfo& uniformInfo = uniformList[uniformNdx];
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;
292 const string layout = uniformInfo.location >= 0 ? "layout(location = " + de::toString(uniformInfo.location) + ") " : "";
293 const string uniName = "uni" + de::toString(uniformNdx);
295 int location = uniformInfo.location;
296 int subTypeIndex = 0;
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
302 // struct definitions
303 if (uniformInfo.type.isStructType())
305 const glu::StructType* const structType = uniformInfo.type.getStructPtr();
306 if (!declaredStructs.count(structType))
309 vertDecl << glu::declare(structType, 0) << ";\n";
312 fragDecl << glu::declare(structType, 0) << ";\n";
314 declaredStructs.insert(structType);
319 vertDecl << "uniform " << (layoutInVert ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";
322 fragDecl << "uniform " << (layoutInFrag ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";
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++)
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);
332 if (glu::isDataTypeSampler(scalarType))
335 vertMain << " v_color.rgb *= verify(float( texture(" << uniName
336 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
337 << ", vec2(0.5)).r), " << expectValue << ");\n";
339 fragMain << " o_color.rgb *= verify(float( texture(" << uniName
340 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
341 << ", vec2(0.5)).r), " << expectValue << ");\n";
346 vertMain << " v_color.rgb *= verify(float(" << uniName
347 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
348 << getFirstComponentName(subType) << "), " << expectValue << ");\n";
350 fragMain << " o_color.rgb *= verify(float(" << uniName
351 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
352 << getFirstComponentName(subType) << "), " << expectValue << ");\n";
360 return glu::makeVtxFragSources(vertDecl.str() + vertMain.str(), fragDecl.str() + fragMain.str());
363 bool UniformLocationCase::verifyLocations (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
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();
373 TestLog& log = m_testCtx.getLog();
374 std::set<int> usedLocations;
378 if (!vertexOk || !fragmentOk || !linkOk)
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");
385 for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
387 const UniformInfo& uniformInfo = uniformList[uniformNdx];
388 int subTypeIndex = 0;
390 for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++, subTypeIndex++)
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;
398 if (uniformInfo.checkLocation == 0 && gotLoc == -1)
401 if (gotLoc != expectLoc)
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");
408 if (usedLocations.find(expectLoc) != usedLocations.end())
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");
415 usedLocations.insert(expectLoc);
417 else if (gotLoc >= 0)
419 if (usedLocations.count(gotLoc))
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");
426 usedLocations.insert(gotLoc);
434 // Check that shader output is white (or very close to it)
435 bool UniformLocationCase::verifyResult (const tcu::ConstPixelBufferAccess& access)
439 const Vec4 threshold (0.1f, 0.1f, 0.1f, 0.1f);
440 const Vec4 reference (1.0f, 1.0f, 1.0f, 1.0f);
442 for (int y = 0; y < access.getHeight(); y++)
444 for (int x = 0; x < access.getWidth(); x++)
446 const Vec4 diff = abs(access.getPixel(x, y) - reference);
448 if (!boolAll(lessThanEqual(diff, threshold)))
456 // get a 4 channel 8 bits each texture format that is usable by the given sampler type
457 deUint32 getTextureFormat (glu::DataType samplerType)
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:
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:
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:
485 DE_FATAL("Unsupported (sampler) type");
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)
495 const glw::Functions& gl = m_renderCtx.getFunctions();
497 const deUint32 format = getTextureFormat(samplerType);
498 de::MovePtr<Texture2D> tex;
500 tex = de::MovePtr<Texture2D>(new Texture2D(m_renderCtx, format, 16, 16));
502 tex->getRefTexture().allocLevel(0);
504 if (format == GL_RGBA8I || format == GL_RGBA8UI)
505 tcu::clear(tex->getRefTexture().getLevel(0), tcu::IVec4(int(redChannelValue), 0, 0, 0));
507 tcu::clear(tex->getRefTexture().getLevel(0), tcu::Vec4(redChannelValue, 0.0f, 0.0f, 1.0f));
509 gl.activeTexture(GL_TEXTURE0 + binding);
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);
516 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase: texture upload");
521 void UniformLocationCase::render (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
523 using glu::Texture2D;
525 typedef vector<Texture2D*> TextureList;
527 const glw::Functions& gl = m_renderCtx.getFunctions();
528 const deUint32 programID = program.getProgram();
529 const deInt32 posLoc = gl.getAttribLocation(programID, "a_position");
532 const float position[] =
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
539 const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
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};
548 TCU_CHECK(posLoc >= 0);
549 gl.useProgram(programID);
555 for (unsigned int uniformNdx = 0; uniformNdx < uniformList.size(); uniformNdx++)
557 const UniformInfo& uniformInfo = uniformList[uniformNdx];
558 int expectedLocation = uniformInfo.location;
560 for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++)
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);
569 if (glu::isDataTypeSampler(scalarType))
571 const int binding = (int)texList.size();
573 texList.push_back(createTexture(scalarType, expectedValue, binding).release());
574 gl.uniform1i(gotLoc, binding);
578 floatBuf[0] = expectedValue;
579 intBuf[0] = int(expectedValue);
580 uintBuf[0] = deUint32(expectedValue);
582 m_testCtx.getLog() << tcu::TestLog::Message << "Set uniform " << name << " in location " << gotLoc << " to " << expectedValue << tcu::TestLog::EndMessage;
584 switch (type.getBasicType())
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;
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;
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;
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;
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;
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;
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;
622 expectedLocation += expectedLocation>=0;
626 gl.enableVertexAttribArray(posLoc);
627 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
629 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]);
631 gl.disableVertexAttribArray(posLoc);
635 for (int i = 0; i < int(texList.size()); i++)
641 for (int i = 0; i < int(texList.size()); i++)
645 class MaxUniformLocationCase : public UniformLocationCase
648 MaxUniformLocationCase (tcu::TestContext& context,
649 glu::RenderContext& renderContext,
652 const vector<UniformInfo>& uniformInfo);
653 virtual ~MaxUniformLocationCase (void) {}
654 virtual IterateResult iterate (void);
657 MaxUniformLocationCase::MaxUniformLocationCase (tcu::TestContext& context,
658 glu::RenderContext& renderContext,
661 const vector<UniformInfo>& uniformInfo)
662 : UniformLocationCase(context, renderContext, name, desc, uniformInfo)
664 DE_ASSERT(!uniformInfo.empty());
667 UniformLocationCase::IterateResult MaxUniformLocationCase::iterate (void)
669 int maxLocation = 1024;
670 vector<UniformInfo> uniformInfo = m_uniformInfo;
672 m_renderCtx.getFunctions().getIntegerv(GL_MAX_UNIFORM_LOCATIONS, &maxLocation);
674 uniformInfo[0].location = maxLocation-1;
676 return UniformLocationCase::run(uniformInfo);
681 UniformLocationTests::UniformLocationTests (Context& context)
682 : TestCaseGroup(context, "uniform_location", "Explicit uniform locations")
686 UniformLocationTests::~UniformLocationTests (void)
688 for (int i = 0; i < int(structTypes.size()); i++)
689 delete structTypes[i];
692 glu::VarType createVarType (glu::DataType type)
694 return glu::VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP);
697 void UniformLocationTests::init (void)
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();
706 const DataType primitiveTypes[] =
740 TYPE_UINT_SAMPLER_2D,
743 const int maxPrimitiveTypeNdx = DE_LENGTH_OF_ARRAY(primitiveTypes) - 4;
744 DE_ASSERT(primitiveTypes[maxPrimitiveTypeNdx] == TYPE_FLOAT_MAT4);
746 // Primitive type cases with trivial linkage
748 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "basic", "Location specified with use, single shader stage");
749 de::Random rng (baseSeed + 0x1001);
752 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
754 const DataType type = primitiveTypes[primitiveNdx];
756 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
758 const string name = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
760 vector<UniformInfo> config;
762 UniformInfo uniform (createVarType(type),
763 checkStages[stageNdx],
764 checkStages[stageNdx],
765 checkStages[stageNdx],
766 rng.getInt(0, maxLocations-1));
768 config.push_back(uniform);
769 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
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);
780 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
782 const DataType type = primitiveTypes[primitiveNdx];
784 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
787 const string name = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
789 vector<UniformInfo> config;
791 UniformInfo uniform (VarType(createVarType(type), 8),
792 checkStages[stageNdx],
793 checkStages[stageNdx],
794 checkStages[stageNdx],
795 rng.getInt(0, maxLocations-1-8));
797 config.push_back(uniform);
798 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
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);
809 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
811 const DataType type = primitiveTypes[primitiveNdx];
813 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
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;
819 vector<UniformInfo> config;
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));
827 config.push_back(uniform);
828 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
835 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "struct", "Struct location, random contents & declaration location");
836 de::Random rng (baseSeed + 0x4001);
839 for (int caseNdx = 0; caseNdx < 16; caseNdx++)
841 typedef UniformInfo::ShaderStage Stage;
843 const string name = "case_" + de::toString(caseNdx);
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;
850 StructType* structProto = new StructType("S");
852 structTypes.push_back(structProto);
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)]));
861 vector<UniformInfo> config;
863 config.push_back(UniformInfo(VarType(structProto),
868 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
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);
880 for (int caseNdx = 0; caseNdx < 16; caseNdx++)
882 typedef UniformInfo::ShaderStage Stage;
884 const string name = "case_" + de::toString(caseNdx);
885 const int baseLoc = rng.getInt(0, maxLocations-1-60);
887 // Structs need to be added in the order of their declaration
888 const Stage layoutLocs[]=
890 Stage(rng.getUint32()&0x3),
891 Stage(rng.getUint32()&0x3),
892 Stage(rng.getUint32()&0x3),
893 Stage(rng.getUint32()&0x3),
896 const deUint32 tempDecl[] =
898 (rng.getUint32()&0x3) | layoutLocs[0],
899 (rng.getUint32()&0x3) | layoutLocs[1],
900 (rng.getUint32()&0x3) | layoutLocs[2],
901 (rng.getUint32()&0x3) | layoutLocs[3],
904 // Component structs need to be declared if anything using them is declared
905 const Stage declareLocs[] =
907 Stage(tempDecl[0] | tempDecl[1] | tempDecl[2] | tempDecl[3]),
908 Stage(tempDecl[1] | tempDecl[2] | tempDecl[3]),
909 Stage(tempDecl[2] | tempDecl[3]),
913 const Stage verifyLocs[] =
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]),
921 StructType* testTypes[] =
923 new StructType("Type0"),
924 new StructType("Type1"),
925 new StructType("Type2"),
926 new StructType("Type3"),
929 structTypes.push_back(testTypes[0]);
930 structTypes.push_back(testTypes[1]);
931 structTypes.push_back(testTypes[2]);
932 structTypes.push_back(testTypes[3]);
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)]));
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)]));
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)]));
950 testTypes[3]->addMember("a", VarType(testTypes[2]));
953 vector<UniformInfo> config;
955 config.push_back(UniformInfo(VarType(testTypes[0]),
959 layoutLocs[0] ? baseLoc : -1));
961 config.push_back(UniformInfo(VarType(testTypes[1]),
965 layoutLocs[1] ? baseLoc+5 : -1));
967 config.push_back(UniformInfo(VarType(testTypes[2]),
971 layoutLocs[2] ? baseLoc+16 : -1));
973 config.push_back(UniformInfo(VarType(testTypes[3]),
977 layoutLocs[3] ? baseLoc+27 : -1));
979 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
986 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "min_max", "Maximum & minimum location");
990 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
992 const DataType type = primitiveTypes[primitiveNdx];
994 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
996 const string name = string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
997 vector<UniformInfo> config;
999 config.push_back(UniformInfo(createVarType(type),
1000 checkStages[stageNdx],
1001 checkStages[stageNdx],
1002 checkStages[stageNdx],
1005 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_min").c_str(), (name+"_min").c_str(), config));
1007 group->addChild(new MaxUniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_max").c_str(), (name+"_max").c_str(), config));
1014 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "link", "Location specified independently from use");
1015 de::Random rng (baseSeed + 0x82e1);
1019 for (int caseNdx = 0; caseNdx < 10; caseNdx++)
1021 const string name = "case_" + de::toString(caseNdx);
1022 vector<UniformInfo> config;
1024 vector<int> locations = shuffledRange(0, maxLocations, 0x1234 + caseNdx*100);
1026 for (int count = 0; count < 32; count++)
1028 typedef UniformInfo::ShaderStage Stage;
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);
1034 const UniformInfo uniform (createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]),
1038 (layoutLoc!=0) ? locations.back() : -1);
1040 config.push_back(uniform);
1041 locations.pop_back();
1043 group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
1049 de::MovePtr<tcu::TestCaseGroup> negativeGroup (new tcu::TestCaseGroup(m_testCtx, "negative", "Negative tests"));
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");
1056 for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
1057 es31Group->addChild(negativeCases[ndx]);
1059 negativeGroup->addChild(es31Group.release());
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");
1067 for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
1068 es32Group->addChild(negativeCases[ndx]);
1070 negativeGroup->addChild(es32Group.release());
1073 addChild(negativeGroup.release());