1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 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 Shader API tests.
22 *//*--------------------------------------------------------------------*/
24 #include "es3fShaderApiTests.hpp"
25 #include "es3fApiCase.hpp"
26 #include "tcuTestLog.hpp"
28 #include "gluRenderContext.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "gluShaderUtil.hpp"
31 #include "gluDrawUtil.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluCallLogWrapper.hpp"
35 #include "glwFunctions.hpp"
36 #include "glwDefs.hpp"
37 #include "glwEnums.hpp"
41 #include "deRandom.hpp"
42 #include "deStringUtil.hpp"
49 using namespace glw; // GL types
63 enum ShaderSourceCaseFlags
65 CASE_EXPLICIT_SOURCE_LENGTHS = 1,
66 CASE_RANDOM_NULL_TERMINATED = 2
71 std::vector<std::string> strings;
72 std::vector<int> lengths;
77 const char* getSimpleShaderSource (const glu::ShaderType shaderType)
79 const char* simpleVertexShaderSource =
83 " gl_Position = vec4(0.0);\n"
86 const char* simpleFragmentShaderSource =
88 "layout(location = 0) out mediump vec4 o_fragColor;\n"
91 " o_fragColor = vec4(0.0);\n"
96 case glu::SHADERTYPE_VERTEX:
97 return simpleVertexShaderSource;
98 case glu::SHADERTYPE_FRAGMENT:
99 return simpleFragmentShaderSource;
107 void setShaderSources (glu::Shader& shader, const ShaderSources& sources)
109 std::vector<const char*> cStrings (sources.strings.size(), 0);
111 for (size_t ndx = 0; ndx < sources.strings.size(); ndx++)
112 cStrings[ndx] = sources.strings[ndx].c_str();
114 if (sources.lengths.size() > 0)
115 shader.setSources((int)cStrings.size(), &cStrings[0], &sources.lengths[0]);
117 shader.setSources((int)cStrings.size(), &cStrings[0], 0);
120 void sliceSourceString (const std::string& in, ShaderSources& out, const int numSlices, const size_t paddingLength = 0)
122 DE_ASSERT(numSlices > 0);
124 const size_t sliceSize = in.length() / numSlices;
125 const size_t sliceSizeRemainder = in.length() - (sliceSize * numSlices);
126 const std::string padding (paddingLength, 'E');
128 for (int ndx = 0; ndx < numSlices; ndx++)
130 out.strings.push_back(in.substr(ndx * sliceSize, sliceSize) + padding);
132 if (paddingLength > 0)
133 out.lengths.push_back((int)sliceSize);
136 if (sliceSizeRemainder > 0)
138 const std::string lastString = in.substr(numSlices * sliceSize);
139 const int lastStringLength = (int)lastString.length();
141 out.strings.push_back(lastString + padding);
143 if (paddingLength > 0)
144 out.lengths.push_back(lastStringLength);
148 void queryShaderInfo (glu::RenderContext& renderCtx, deUint32 shader, glu::ShaderInfo& info)
150 const glw::Functions& gl = renderCtx.getFunctions();
152 info.compileOk = false;
153 info.compileTimeUs = 0;
154 info.infoLog.clear();
156 // Query source, status & log.
158 int compileStatus = 0;
163 gl.getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
164 gl.getShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLen);
165 gl.getShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen);
166 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
168 info.compileOk = compileStatus != GL_FALSE;
172 std::vector<char> source(sourceLen);
173 gl.getShaderSource(shader, (int)source.size(), &unusedLen, &source[0]);
174 info.source = std::string(&source[0], sourceLen);
179 std::vector<char> infoLog(infoLogLen);
180 gl.getShaderInfoLog(shader, (int)infoLog.size(), &unusedLen, &infoLog[0]);
181 info.infoLog = std::string(&infoLog[0], infoLogLen);
188 void drawWithProgram (glu::RenderContext& renderCtx, deUint32 program)
190 const glw::Functions& gl = renderCtx.getFunctions();
192 const float position[] =
194 -1.0f, -1.0f, 0.0f, 1.0f,
195 -1.0f, +1.0f, 0.0f, 1.0f,
196 +1.0f, -1.0f, 0.0f, 1.0f,
197 +1.0f, +1.0f, 0.0f, 1.0f
199 const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
201 gl.useProgram(program);
204 glu::VertexArrayBinding vertexArrays[] =
206 glu::va::Float("a_position", 4, 4, 0, &position[0])
208 glu::draw(renderCtx, program, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
211 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw test quad");
214 // Shader source generator
216 class SourceGenerator
219 virtual ~SourceGenerator (void) {}
221 virtual std::string next (const glu::ShaderType shaderType) = 0;
222 virtual bool finished (const glu::ShaderType shaderType) const = 0;
225 class ConstantShaderGenerator : public SourceGenerator
228 ConstantShaderGenerator (de::Random& rnd) : m_rnd(rnd) {}
229 ~ConstantShaderGenerator (void) {}
231 bool finished (const glu::ShaderType shaderType) const { DE_UNREF(shaderType); return false; }
233 std::string next (const glu::ShaderType shaderType);
239 std::string ConstantShaderGenerator::next (const glu::ShaderType shaderType)
241 DE_ASSERT(shaderType == glu::SHADERTYPE_VERTEX || shaderType == glu::SHADERTYPE_FRAGMENT);
243 const float value = m_rnd.getFloat(0.0f, 1.0f);
244 const std::string valueString = de::toString(value);
245 const std::string outputName = (shaderType == glu::SHADERTYPE_VERTEX) ? "gl_Position" : "o_fragColor";
247 std::ostringstream out;
249 out << "#version 300 es\n";
251 if (shaderType == glu::SHADERTYPE_FRAGMENT)
252 out << "layout(location = 0) out mediump vec4 o_fragColor;\n";
254 out << "void main (void)\n";
256 out << " " << outputName << " = vec4(" << valueString << ");\n";
262 // Shader allocation utility
264 class ShaderAllocator
267 ShaderAllocator (glu::RenderContext& context, SourceGenerator& generator);
268 ~ShaderAllocator (void);
270 bool hasShader (const glu::ShaderType shaderType);
272 void setSource (const glu::ShaderType shaderType);
274 glu::Shader& createShader (const glu::ShaderType shaderType);
275 void deleteShader (const glu::ShaderType shaderType);
277 glu::Shader& get (const glu::ShaderType shaderType) { DE_ASSERT(hasShader(shaderType)); return *m_shaders[shaderType]; }
280 const glu::RenderContext& m_context;
281 SourceGenerator& m_srcGen;
282 std::map<glu::ShaderType, glu::Shader*> m_shaders;
285 ShaderAllocator::ShaderAllocator (glu::RenderContext& context, SourceGenerator& generator)
286 : m_context (context)
287 , m_srcGen (generator)
291 ShaderAllocator::~ShaderAllocator (void)
293 for (std::map<glu::ShaderType, glu::Shader*>::iterator shaderIter = m_shaders.begin(); shaderIter != m_shaders.end(); shaderIter++)
294 delete shaderIter->second;
298 bool ShaderAllocator::hasShader (const glu::ShaderType shaderType)
300 if (m_shaders.find(shaderType) != m_shaders.end())
306 glu::Shader& ShaderAllocator::createShader (const glu::ShaderType shaderType)
308 DE_ASSERT(!this->hasShader(shaderType));
310 glu::Shader* const shader = new glu::Shader(m_context, shaderType);
312 m_shaders[shaderType] = shader;
313 this->setSource(shaderType);
318 void ShaderAllocator::deleteShader (const glu::ShaderType shaderType)
320 DE_ASSERT(this->hasShader(shaderType));
322 delete m_shaders[shaderType];
323 m_shaders.erase(shaderType);
326 void ShaderAllocator::setSource (const glu::ShaderType shaderType)
328 DE_ASSERT(this->hasShader(shaderType));
329 DE_ASSERT(!m_srcGen.finished(shaderType));
331 const std::string source = m_srcGen.next(shaderType);
332 const char* const cSource = source.c_str();
334 m_shaders[shaderType]->setSources(1, &cSource, 0);
339 void logShader (TestLog& log, glu::RenderContext& renderCtx, glu::Shader& shader)
341 glu::ShaderInfo info;
343 queryShaderInfo(renderCtx, shader.getShader(), info);
345 log << TestLog::Shader(getLogShaderType(shader.getType()), info.source, info.compileOk, info.infoLog);
348 void logProgram (TestLog& log, glu::RenderContext& renderCtx, glu::Program& program, ShaderAllocator& shaders)
350 log << TestLog::ShaderProgram(program.getLinkStatus(), program.getInfoLog());
352 for (int shaderTypeInt = 0; shaderTypeInt < glu::SHADERTYPE_LAST; shaderTypeInt++)
354 const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeInt;
356 if (shaders.hasShader(shaderType))
357 logShader(log, renderCtx, shaders.get(shaderType));
360 log << TestLog::EndShaderProgram;
363 void logVertexFragmentProgram (TestLog& log, glu::RenderContext& renderCtx, glu::Program& program, glu::Shader& vertShader, glu::Shader& fragShader)
365 DE_ASSERT(vertShader.getType() == glu::SHADERTYPE_VERTEX && fragShader.getType() == glu::SHADERTYPE_FRAGMENT);
367 log << TestLog::ShaderProgram(program.getLinkStatus(), program.getInfoLog());
369 logShader(log, renderCtx, vertShader);
370 logShader(log, renderCtx, fragShader);
372 log << TestLog::EndShaderProgram;
377 // Simple glCreateShader() case
379 class CreateShaderCase : public ApiCase
382 CreateShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
383 : ApiCase (context, name, desc)
384 , m_shaderType (shaderType)
390 const GLuint shaderObject = glCreateShader(glu::getGLShaderType(m_shaderType));
392 TCU_CHECK(shaderObject != 0);
394 glDeleteShader(shaderObject);
398 const glu::ShaderType m_shaderType;
401 // Simple glCompileShader() case
403 class CompileShaderCase : public ApiCase
406 CompileShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
407 : ApiCase (context, name, desc)
408 , m_shaderType (shaderType)
412 bool checkCompileStatus (const GLuint shaderObject)
414 GLint compileStatus = -1;
415 glGetShaderiv(shaderObject, GL_COMPILE_STATUS, &compileStatus);
418 return (compileStatus == GL_TRUE);
423 const char* shaderSource = getSimpleShaderSource(m_shaderType);
424 const GLuint shaderObject = glCreateShader(glu::getGLShaderType(m_shaderType));
426 TCU_CHECK(shaderObject != 0);
428 glShaderSource(shaderObject, 1, &shaderSource, 0);
429 glCompileShader(shaderObject);
431 TCU_CHECK(checkCompileStatus(shaderObject));
433 glDeleteShader(shaderObject);
437 const glu::ShaderType m_shaderType;
440 // Base class for simple program API tests
442 class SimpleProgramCase : public ApiCase
445 SimpleProgramCase (Context& context, const char* name, const char* desc)
446 : ApiCase (context, name, desc)
453 virtual ~SimpleProgramCase (void)
457 virtual void compileShaders (void)
459 const char* vertSource = getSimpleShaderSource(glu::SHADERTYPE_VERTEX);
460 const char* fragSource = getSimpleShaderSource(glu::SHADERTYPE_FRAGMENT);
462 const GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
463 const GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
465 TCU_CHECK(vertShader != 0);
466 TCU_CHECK(fragShader != 0);
468 glShaderSource(vertShader, 1, &vertSource, 0);
469 glCompileShader(vertShader);
471 glShaderSource(fragShader, 1, &fragSource, 0);
472 glCompileShader(fragShader);
476 m_vertShader = vertShader;
477 m_fragShader = fragShader;
480 void linkProgram (void)
482 const GLuint program = glCreateProgram();
484 TCU_CHECK(program != 0);
486 glAttachShader(program, m_vertShader);
487 glAttachShader(program, m_fragShader);
490 glLinkProgram(program);
497 glDeleteShader(m_vertShader);
498 glDeleteShader(m_fragShader);
499 glDeleteProgram(m_program);
508 // glDeleteShader() case
510 class DeleteShaderCase : public SimpleProgramCase
513 DeleteShaderCase (Context& context, const char* name, const char* desc)
514 : SimpleProgramCase (context, name, desc)
518 bool checkDeleteStatus(GLuint shader)
520 GLint deleteStatus = -1;
521 glGetShaderiv(shader, GL_DELETE_STATUS, &deleteStatus);
524 return (deleteStatus == GL_TRUE);
527 void deleteShaders (void)
529 glDeleteShader(m_vertShader);
530 glDeleteShader(m_fragShader);
542 TCU_CHECK(checkDeleteStatus(m_vertShader) && checkDeleteStatus(m_fragShader));
544 glDeleteProgram(m_program);
546 TCU_CHECK(!(glIsShader(m_vertShader) || glIsShader(m_fragShader)));
550 // Simple glLinkProgram() case
552 class LinkVertexFragmentCase : public SimpleProgramCase
555 LinkVertexFragmentCase (Context& context, const char* name, const char* desc)
556 : SimpleProgramCase (context, name, desc)
560 bool checkLinkStatus (const GLuint programObject)
562 GLint linkStatus = -1;
563 glGetProgramiv(programObject, GL_LINK_STATUS, &linkStatus);
566 return (linkStatus == GL_TRUE);
574 GLU_CHECK_MSG("Linking failed.");
575 TCU_CHECK_MSG(checkLinkStatus(m_program), "Fail, expected LINK_STATUS to be TRUE.");
581 class ShaderSourceReplaceCase : public ApiCase
584 ShaderSourceReplaceCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
585 : ApiCase (context, name, desc)
586 , m_shaderType (shaderType)
590 std::string generateFirstSource (void)
592 return getSimpleShaderSource(m_shaderType);
595 std::string generateSecondSource (void)
597 std::ostringstream out;
599 out << "#version 300 es\n";
600 out << "precision mediump float;\n";
602 if (m_shaderType == glu::SHADERTYPE_FRAGMENT)
603 out << "layout(location = 0) out mediump vec4 o_fragColor;\n";
605 out << "void main()\n";
607 out << " float variable = 1.0f;\n";
609 if (m_shaderType == glu::SHADERTYPE_VERTEX) out << " gl_Position = vec4(variable);\n";
610 else if (m_shaderType == glu::SHADERTYPE_FRAGMENT) out << " o_fragColor = vec4(variable);\n";
617 GLint getSourceLength (glu::Shader& shader)
619 GLint sourceLength = 0;
620 glGetShaderiv(shader.getShader(), GL_SHADER_SOURCE_LENGTH, &sourceLength);
626 std::string readSource (glu::Shader& shader)
628 const GLint sourceLength = getSourceLength(shader);
629 std::vector<char> sourceBuffer (sourceLength + 1);
631 glGetShaderSource(shader.getShader(), (GLsizei)sourceBuffer.size(), 0, &sourceBuffer[0]);
633 return std::string(&sourceBuffer[0]);
636 void verifyShaderSourceReplaced (glu::Shader& shader, const std::string& firstSource, const std::string& secondSource)
638 TestLog& log = m_testCtx.getLog();
639 const std::string result = readSource(shader);
641 if (result == firstSource)
643 log << TestLog::Message << "Fail, source was not replaced." << TestLog::EndMessage;
644 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader source nor replaced");
646 else if (result != secondSource)
648 log << TestLog::Message << "Fail, invalid shader source." << TestLog::EndMessage;
649 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid source");
655 TestLog& log = m_testCtx.getLog();
657 glu::Shader shader (m_context.getRenderContext(), m_shaderType);
659 const std::string firstSourceStr = generateFirstSource();
660 const std::string secondSourceStr = generateSecondSource();
662 const char* firstSource = firstSourceStr.c_str();
663 const char* secondSource = secondSourceStr.c_str();
665 log << TestLog::Message << "Setting shader source." << TestLog::EndMessage;
667 shader.setSources(1, &firstSource, 0);
670 log << TestLog::Message << "Replacing shader source." << TestLog::EndMessage;
672 shader.setSources(1, &secondSource, 0);
675 verifyShaderSourceReplaced(shader, firstSourceStr, secondSourceStr);
679 glu::ShaderType m_shaderType;
682 // glShaderSource() split source case
684 class ShaderSourceSplitCase : public ApiCase
687 ShaderSourceSplitCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType, const int numSlices, const deUint32 flags = 0)
688 : ApiCase (context, name, desc)
689 , m_rnd (deStringHash(getName()) ^ 0x4fb2337d)
690 , m_shaderType (shaderType)
691 , m_numSlices (numSlices)
692 , m_explicitLengths ((flags & CASE_EXPLICIT_SOURCE_LENGTHS) != 0)
693 , m_randomNullTerm ((flags & CASE_RANDOM_NULL_TERMINATED) != 0)
695 DE_ASSERT(m_shaderType == glu::SHADERTYPE_VERTEX || m_shaderType == glu::SHADERTYPE_FRAGMENT);
698 virtual ~ShaderSourceSplitCase (void)
702 std::string generateFullSource (void)
704 std::ostringstream out;
706 out << "#version 300 es\n";
707 out << "precision mediump float;\n";
709 if (m_shaderType == glu::SHADERTYPE_FRAGMENT)
710 out << "layout(location = 0) out mediump vec4 o_fragColor;\n";
712 out << "void main()\n";
714 out << " float variable = 1.0f;\n";
716 if (m_shaderType == glu::SHADERTYPE_VERTEX) out << " gl_Position = vec4(variable);\n";
717 else if (m_shaderType == glu::SHADERTYPE_FRAGMENT) out << " o_fragColor = vec4(variable);\n";
724 void insertRandomNullTermStrings (ShaderSources& sources)
726 const int numInserts = de::max(m_numSlices >> 2, 1);
727 std::vector<int> indices (sources.strings.size(), 0);
729 DE_ASSERT(sources.lengths.size() > 0);
730 DE_ASSERT(sources.lengths.size() == sources.strings.size());
732 for (int i = 0; i < (int)sources.strings.size(); i++)
735 m_rnd.shuffle(indices.begin(), indices.end());
737 for (int i = 0; i < numInserts; i++)
739 const int ndx = indices[i];
740 const int unpaddedLength = sources.lengths[ndx];
741 const std::string unpaddedString = sources.strings[ndx].substr(0, unpaddedLength);
743 sources.strings[ndx] = unpaddedString;
744 sources.lengths[ndx] = m_rnd.getInt(-10, -1);
748 void generateSources (ShaderSources& sources)
750 const size_t paddingLength = (m_explicitLengths ? 10 : 0);
751 std::string str = generateFullSource();
753 sliceSourceString(str, sources, m_numSlices, paddingLength);
755 if (m_randomNullTerm)
756 insertRandomNullTermStrings(sources);
759 void buildProgram (glu::Shader& shader)
761 TestLog& log = m_testCtx.getLog();
762 glu::RenderContext& renderCtx = m_context.getRenderContext();
764 const glu::ShaderType supportShaderType = (m_shaderType == glu::SHADERTYPE_FRAGMENT ? glu::SHADERTYPE_VERTEX : glu::SHADERTYPE_FRAGMENT);
765 const char* supportShaderSource = getSimpleShaderSource(supportShaderType);
766 glu::Shader supportShader (renderCtx, supportShaderType);
768 glu::Program program (renderCtx);
770 supportShader.setSources(1, &supportShaderSource, 0);
771 supportShader.compile();
773 program.attachShader(shader.getShader());
774 program.attachShader(supportShader.getShader());
778 if (m_shaderType == glu::SHADERTYPE_VERTEX)
779 logVertexFragmentProgram(log, renderCtx, program, shader, supportShader);
781 logVertexFragmentProgram(log, renderCtx, program, supportShader, shader);
786 TestLog& log = m_testCtx.getLog();
787 glu::RenderContext& renderCtx = m_context.getRenderContext();
789 ShaderSources sources;
790 glu::Shader shader (renderCtx, m_shaderType);
792 generateSources(sources);
793 setShaderSources(shader, sources);
796 buildProgram(shader);
798 if (!shader.getCompileStatus())
800 log << TestLog::Message << "Compilation failed." << TestLog::EndMessage;
801 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
808 const glu::ShaderType m_shaderType;
809 const int m_numSlices;
811 const bool m_explicitLengths;
812 const bool m_randomNullTerm;
815 // Base class for program state persistence cases
817 class ProgramStateCase : public ApiCase
820 ProgramStateCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType);
821 virtual ~ProgramStateCase (void) {}
823 void buildProgram (glu::Program& program, ShaderAllocator& shaders);
824 void verify (glu::Program& program, const glu::ProgramInfo& reference);
828 virtual void executeForProgram (glu::Program& program, ShaderAllocator& shaders) = 0;
832 const glu::ShaderType m_shaderType;
835 ProgramStateCase::ProgramStateCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
836 : ApiCase (context, name, desc)
837 , m_rnd (deStringHash(name) ^ 0x713de0ca)
838 , m_shaderType (shaderType)
840 DE_ASSERT(m_shaderType == glu::SHADERTYPE_VERTEX || m_shaderType == glu::SHADERTYPE_FRAGMENT);
843 void ProgramStateCase::buildProgram (glu::Program& program, ShaderAllocator& shaders)
845 TestLog& log = m_testCtx.getLog();
847 glu::Shader& vertShader = shaders.createShader(glu::SHADERTYPE_VERTEX);
848 glu::Shader& fragShader = shaders.createShader(glu::SHADERTYPE_FRAGMENT);
850 vertShader.compile();
851 fragShader.compile();
853 program.attachShader(vertShader.getShader());
854 program.attachShader(fragShader.getShader());
857 logProgram(log, m_context.getRenderContext(), program, shaders);
860 void ProgramStateCase::verify (glu::Program& program, const glu::ProgramInfo& reference)
862 TestLog& log = m_testCtx.getLog();
863 const glu::ProgramInfo& programInfo = program.getInfo();
865 if (!programInfo.linkOk)
867 log << TestLog::Message << "Fail, link status may only change as a result of linking or loading a program binary." << TestLog::EndMessage;
868 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Link status changed");
871 if (programInfo.linkTimeUs != reference.linkTimeUs)
873 log << TestLog::Message << "Fail, reported link time changed." << TestLog::EndMessage;
874 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Link time changed");
877 if (programInfo.infoLog != reference.infoLog)
879 log << TestLog::Message << "Fail, program infolog changed." << TestLog::EndMessage;
880 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Infolog changed");
884 void ProgramStateCase::test (void)
886 TestLog& log = m_testCtx.getLog();
887 glu::RenderContext& renderCtx = m_context.getRenderContext();
889 ConstantShaderGenerator sourceGen (m_rnd);
891 ShaderAllocator shaders (renderCtx, sourceGen);
892 glu::Program program (renderCtx);
894 buildProgram(program, shaders);
896 if (program.getLinkStatus())
898 glu::ProgramInfo programInfo = program.getInfo();
900 executeForProgram(program, shaders);
902 verify(program, programInfo);
904 logProgram(log, renderCtx, program, shaders);
908 log << TestLog::Message << "Fail, couldn't link program." << TestLog::EndMessage;
909 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Linking failed");
913 // Program state case utilities
919 void addProgramStateCase (TestCaseGroup* group, Context& context, const std::string& name, const std::string& desc)
921 for (int shaderTypeInt = 0; shaderTypeInt < 2; shaderTypeInt++)
923 const glu::ShaderType shaderType = (shaderTypeInt == 1) ? glu::SHADERTYPE_FRAGMENT : glu::SHADERTYPE_VERTEX;
924 const std::string shaderTypeName = getShaderTypeName(shaderType);
926 const std::string caseName = name + "_" + shaderTypeName;
927 const std::string caseDesc = "Build program, " + desc + ", for " + shaderTypeName + " shader.";
929 group->addChild(new T(context, caseName.c_str(), caseDesc.c_str(), shaderType));
935 // Specialized program state cases
937 class ProgramStateDetachShaderCase : public ProgramStateCase
940 ProgramStateDetachShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
941 : ProgramStateCase (context, name, desc, shaderType)
945 virtual ~ProgramStateDetachShaderCase (void)
949 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
951 TestLog& log = m_testCtx.getLog();
952 glu::Shader& caseShader = shaders.get(m_shaderType);
954 log << TestLog::Message << "Detaching " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
955 program.detachShader(caseShader.getShader());
959 class ProgramStateReattachShaderCase : public ProgramStateCase
962 ProgramStateReattachShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
963 : ProgramStateCase (context, name, desc, shaderType)
967 virtual ~ProgramStateReattachShaderCase (void)
971 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
973 TestLog& log = m_testCtx.getLog();
974 glu::Shader& caseShader = shaders.get(m_shaderType);
976 log << TestLog::Message << "Reattaching " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
977 program.detachShader(caseShader.getShader());
978 program.attachShader(caseShader.getShader());
982 class ProgramStateDeleteShaderCase : public ProgramStateCase
985 ProgramStateDeleteShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
986 : ProgramStateCase (context, name, desc, shaderType)
990 virtual ~ProgramStateDeleteShaderCase (void)
994 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
996 TestLog& log = m_testCtx.getLog();
997 glu::Shader& caseShader = shaders.get(m_shaderType);
999 log << TestLog::Message << "Deleting " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1000 program.detachShader(caseShader.getShader());
1001 shaders.deleteShader(m_shaderType);
1005 class ProgramStateReplaceShaderCase : public ProgramStateCase
1008 ProgramStateReplaceShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1009 : ProgramStateCase (context, name, desc, shaderType)
1013 virtual ~ProgramStateReplaceShaderCase (void)
1017 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1019 TestLog& log = m_testCtx.getLog();
1020 glu::Shader& caseShader = shaders.get(m_shaderType);
1022 log << TestLog::Message << "Deleting and replacing " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1023 program.detachShader(caseShader.getShader());
1024 shaders.deleteShader(m_shaderType);
1025 program.attachShader(shaders.createShader(m_shaderType).getShader());
1029 class ProgramStateRecompileShaderCase : public ProgramStateCase
1032 ProgramStateRecompileShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1033 : ProgramStateCase (context, name, desc, shaderType)
1037 virtual ~ProgramStateRecompileShaderCase (void)
1041 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1043 TestLog& log = m_testCtx.getLog();
1044 glu::Shader& caseShader = shaders.get(m_shaderType);
1046 log << TestLog::Message << "Recompiling " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1047 caseShader.compile();
1052 class ProgramStateReplaceSourceCase : public ProgramStateCase
1055 ProgramStateReplaceSourceCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1056 : ProgramStateCase (context, name, desc, shaderType)
1060 virtual ~ProgramStateReplaceSourceCase (void)
1064 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1066 TestLog& log = m_testCtx.getLog();
1067 glu::Shader& caseShader = shaders.get(m_shaderType);
1069 log << TestLog::Message << "Replacing " + std::string(getShaderTypeName(m_shaderType)) + " shader source and recompiling" << TestLog::EndMessage;
1070 shaders.setSource(m_shaderType);
1071 caseShader.compile();
1076 // Program binary utilities
1081 struct ProgramBinary
1084 std::vector<deUint8> data;
1087 bool programBinariesEqual (const ProgramBinary& first, const ProgramBinary& second)
1089 if ((first.format != second.format) || (first.data.size() != second.data.size()))
1092 return std::equal(first.data.begin(), first.data.end(), second.data.begin());
1097 // Base class for program binary cases
1099 class ProgramBinaryCase : public TestCase, protected glu::CallLogWrapper
1102 ProgramBinaryCase (Context& context, const char* name, const char* desc);
1103 virtual ~ProgramBinaryCase (void);
1105 void getBinaryFormats (std::vector<GLenum>& out);
1106 bool isFormatSupported (const glw::GLenum format) const;
1108 void getProgramBinary (ProgramBinary& out, GLuint program);
1109 void loadProgramBinary (ProgramBinary& binary, GLuint program);
1111 void verifyProgramBinary (ProgramBinary& binary);
1114 IterateResult iterate (void);
1116 virtual void test (void) = 0;
1119 std::vector<GLenum> m_formats;
1122 ProgramBinaryCase::ProgramBinaryCase (Context& context, const char* name, const char* desc)
1123 : TestCase (context, name, desc)
1124 , CallLogWrapper (context.getRenderContext().getFunctions(), context.getTestContext().getLog())
1128 ProgramBinaryCase::~ProgramBinaryCase (void)
1132 void ProgramBinaryCase::getBinaryFormats (std::vector<GLenum>& out)
1134 GLint numFormats = -1;
1135 glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numFormats);
1141 out.resize(numFormats, 0);
1143 glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, (GLint*)&out[0]);
1147 bool ProgramBinaryCase::isFormatSupported (const glw::GLenum format) const
1149 return (std::find(m_formats.begin(), m_formats.end(), format) != m_formats.end());
1152 void ProgramBinaryCase::getProgramBinary (ProgramBinary& out, GLuint program)
1154 GLint binaryLength = -1;
1155 glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
1157 if (binaryLength > 0)
1159 GLsizei actualLength;
1163 out.data.resize(binaryLength, 0);
1165 GLU_CHECK_CALL(glGetProgramBinary(program, (GLsizei)out.data.size(), &actualLength, &format, &(out.data[0])));
1167 TCU_CHECK(actualLength == binaryLength);
1169 out.format = format;
1173 void ProgramBinaryCase::loadProgramBinary (ProgramBinary& binary, GLuint program)
1175 glProgramBinary(program, binary.format, &binary.data[0], (GLsizei)binary.data.size());
1176 GLU_CHECK_MSG("Failed to load program binary.");
1179 void ProgramBinaryCase::verifyProgramBinary (ProgramBinary& binary)
1181 TestLog& log = m_testCtx.getLog();
1183 if (!isFormatSupported(binary.format))
1185 log << TestLog::Message << "Program binary format " << binary.format << " is not among the supported formats reported by the platform." << TestLog::EndMessage;
1187 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid format");
1191 void ProgramBinaryCase::init (void)
1193 getBinaryFormats(m_formats);
1196 tcu::TestNode::IterateResult ProgramBinaryCase::iterate (void)
1198 TestLog& log = m_testCtx.getLog();
1200 if (m_formats.empty())
1202 log << TestLog::Message << "No program binary formats are supported." << TestLog::EndMessage;
1204 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
1208 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1210 enableLogging(true);
1217 // Simple program binary case
1219 class ProgramBinarySimpleCase : public ProgramBinaryCase
1222 ProgramBinarySimpleCase (Context& context, const char* name, const char* desc)
1223 : ProgramBinaryCase(context, name, desc)
1227 virtual ~ProgramBinarySimpleCase (void)
1233 const std::string vertSrc = getSimpleShaderSource(glu::SHADERTYPE_VERTEX);
1234 const std::string fragSrc = getSimpleShaderSource(glu::SHADERTYPE_FRAGMENT);
1236 const glu::ProgramSources sources = glu::makeVtxFragSources(vertSrc, fragSrc);
1238 glu::ShaderProgram program (m_context.getRenderContext(), sources);
1242 ProgramBinary binary;
1244 getProgramBinary(binary, program.getProgram());
1245 verifyProgramBinary(binary);
1250 // Program binary uniform reset case
1252 class ProgramBinaryUniformResetCase : public ProgramBinaryCase
1255 ProgramBinaryUniformResetCase (Context& context, const char* name, const char* desc)
1256 : ProgramBinaryCase (context, name, desc)
1257 , m_rnd (deStringHash(name) ^ 0xf2b48c6a)
1261 virtual ~ProgramBinaryUniformResetCase (void)
1265 std::string getShaderSource (const glu::ShaderType shaderType) const
1267 const char* vertSrc =
1269 "uniform bool u_boolVar;\n"
1270 "uniform highp int u_intVar;\n"
1271 "uniform highp float u_floatVar;\n\n"
1272 "in highp vec4 a_position;\n\n"
1273 "void main (void)\n"
1275 " gl_Position = a_position;\n"
1277 const char* fragSrc =
1279 "uniform bool u_boolVar;\n"
1280 "uniform highp int u_intVar;\n"
1281 "uniform highp float u_floatVar;\n\n"
1282 "layout(location = 0) out mediump vec4 o_fragColor;\n\n"
1283 "void main (void)\n"
1285 " mediump float refAll = float(u_boolVar) + float(u_intVar) + u_floatVar;\n"
1286 " o_fragColor = vec4(refAll);\n"
1289 DE_ASSERT(shaderType == glu::SHADERTYPE_VERTEX || shaderType == glu::SHADERTYPE_FRAGMENT);
1291 return (shaderType == glu::SHADERTYPE_VERTEX) ? vertSrc : fragSrc;
1294 void setUniformsRandom (glu::ShaderProgram& program)
1296 TestLog& log = m_testCtx.getLog();
1297 const deUint32 glProg = program.getProgram();
1299 log << TestLog::Message << "Setting uniforms to random non-zero values." << TestLog::EndMessage;
1301 glUseProgram(glProg);
1304 const GLint boolLoc = glGetUniformLocation(glProg, "u_boolVar");
1305 const GLint intLoc = glGetUniformLocation(glProg, "u_intVar");
1306 const GLint floatLoc = glGetUniformLocation(glProg, "u_floatVar");
1308 const deInt32 intVal = m_rnd.getInt(1, 1000);
1309 const float floatVal = m_rnd.getFloat(1.0, 1000.0);
1311 glUniform1i(boolLoc, GL_TRUE);
1312 glUniform1f(floatLoc, floatVal);
1313 glUniform1i(intLoc, intVal);
1317 void verifyUniformInt (glu::ShaderProgram& program, const std::string& name)
1319 const GLint intLoc = glGetUniformLocation(program.getProgram(), name.c_str());
1322 glGetUniformiv(program.getProgram(), intLoc, &intVar);
1326 m_testCtx.getLog() << TestLog::Message << "Fail, expected zero value for " << name << ", received: " << intVar << TestLog::EndMessage;
1327 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Uniform value not reset");
1331 void verifyUniformFloat (glu::ShaderProgram& program, const std::string& name)
1333 const GLint floatLoc = glGetUniformLocation(program.getProgram(), name.c_str());
1334 GLfloat floatVar = -1;
1336 glGetUniformfv(program.getProgram(), floatLoc, &floatVar);
1338 if (floatVar != 0.0f)
1340 m_testCtx.getLog() << TestLog::Message << "Fail, expected zero value for " << name << ", received: " << de::toString(floatVar) << TestLog::EndMessage;
1341 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Uniform value not reset");
1345 void verifyUniformsReset (glu::ShaderProgram& program)
1347 m_testCtx.getLog() << TestLog::Message << "Verifying uniform reset to 0/false." << TestLog::EndMessage;
1349 verifyUniformInt (program, "u_boolVar");
1350 verifyUniformInt (program, "u_intVar");
1351 verifyUniformFloat (program, "u_floatVar");
1356 TestLog& log = m_testCtx.getLog();
1358 const std::string vertSrc = getShaderSource(glu::SHADERTYPE_VERTEX);
1359 const std::string fragSrc = getShaderSource(glu::SHADERTYPE_FRAGMENT);
1361 const glu::ProgramSources sources = glu::makeVtxFragSources(vertSrc, fragSrc);
1363 glu::ShaderProgram program (m_context.getRenderContext(), sources);
1367 TCU_CHECK_MSG(program.isOk(), "Couldn't build program");
1370 ProgramBinary binary;
1372 getProgramBinary(binary, program.getProgram());
1373 verifyProgramBinary(binary);
1375 setUniformsRandom(program);
1377 log << TestLog::Message << "Rendering test image and reloading binary" << TestLog::EndMessage;
1379 drawWithProgram(m_context.getRenderContext(), program.getProgram());
1380 loadProgramBinary(binary, program.getProgram());
1382 verifyUniformsReset(program);
1389 // Base class for program state persistence cases
1391 class ProgramBinaryPersistenceCase : public ProgramBinaryCase
1394 ProgramBinaryPersistenceCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType);
1395 virtual ~ProgramBinaryPersistenceCase (void) {}
1397 void buildProgram (glu::Program& program, ShaderAllocator& shaders);
1401 virtual void executeForProgram (glu::Program& program, ShaderAllocator& shaders) = 0;
1402 virtual void verify (glu::Program& program, const ProgramBinary& binary);
1406 const glu::ShaderType m_shaderType;
1409 ProgramBinaryPersistenceCase::ProgramBinaryPersistenceCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1410 : ProgramBinaryCase (context, name, desc)
1411 , m_rnd (deStringHash(name) ^ 0x713de0ca)
1412 , m_shaderType (shaderType)
1414 DE_ASSERT(m_shaderType == glu::SHADERTYPE_VERTEX || m_shaderType == glu::SHADERTYPE_FRAGMENT);
1417 void ProgramBinaryPersistenceCase::buildProgram (glu::Program& program, ShaderAllocator& shaders)
1419 TestLog& log = m_testCtx.getLog();
1421 glu::Shader& vertShader = shaders.createShader(glu::SHADERTYPE_VERTEX);
1422 glu::Shader& fragShader = shaders.createShader(glu::SHADERTYPE_FRAGMENT);
1424 vertShader.compile();
1425 fragShader.compile();
1427 program.attachShader(vertShader.getShader());
1428 program.attachShader(fragShader.getShader());
1431 logProgram(log, m_context.getRenderContext(), program, shaders);
1434 void ProgramBinaryPersistenceCase::verify (glu::Program& program, const ProgramBinary& binary)
1436 TestLog& log = m_testCtx.getLog();
1437 ProgramBinary currentBinary;
1439 getProgramBinary(currentBinary, program.getProgram());
1441 if (!programBinariesEqual(binary, currentBinary))
1443 log << TestLog::Message << "Fail, program binary may only change as a result of linking or loading." << TestLog::EndMessage;
1444 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Program binary changed");
1448 void ProgramBinaryPersistenceCase::test (void)
1450 TestLog& log = m_testCtx.getLog();
1451 glu::RenderContext& renderCtx = m_context.getRenderContext();
1453 ConstantShaderGenerator sourceGen (m_rnd);
1455 ShaderAllocator shaders (renderCtx, sourceGen);
1456 glu::Program program (renderCtx);
1458 buildProgram(program, shaders);
1460 if (program.getLinkStatus())
1462 ProgramBinary binary;
1463 getProgramBinary(binary, program.getProgram());
1465 executeForProgram(program, shaders);
1467 verify(program, binary);
1469 logProgram(log, renderCtx, program, shaders);
1473 log << TestLog::Message << "Fail, couldn't link program." << TestLog::EndMessage;
1474 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Linking failed");
1478 // Program state case utilities
1484 void addProgramBinaryPersistenceCase (TestCaseGroup* group, Context& context, const std::string& name, const std::string& desc)
1486 for (int shaderTypeInt = 0; shaderTypeInt < 2; shaderTypeInt++)
1488 const glu::ShaderType shaderType = (shaderTypeInt == 1) ? glu::SHADERTYPE_FRAGMENT : glu::SHADERTYPE_VERTEX;
1489 const std::string shaderTypeName = getShaderTypeName(shaderType);
1491 const std::string caseName = name + "_" + shaderTypeName;
1492 const std::string caseDesc = "Build program, " + desc + ", for " + shaderTypeName + " shader.";
1494 group->addChild(new T(context, caseName.c_str(), caseDesc.c_str(), shaderType));
1500 // Specialized program state cases
1502 class ProgramBinaryPersistenceDetachShaderCase : public ProgramBinaryPersistenceCase
1505 ProgramBinaryPersistenceDetachShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1506 : ProgramBinaryPersistenceCase (context, name, desc, shaderType)
1510 virtual ~ProgramBinaryPersistenceDetachShaderCase (void)
1514 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1516 TestLog& log = m_testCtx.getLog();
1517 glu::Shader& caseShader = shaders.get(m_shaderType);
1519 log << TestLog::Message << "Detaching " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1520 program.detachShader(caseShader.getShader());
1524 class ProgramBinaryPersistenceReattachShaderCase : public ProgramBinaryPersistenceCase
1527 ProgramBinaryPersistenceReattachShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1528 : ProgramBinaryPersistenceCase (context, name, desc, shaderType)
1532 virtual ~ProgramBinaryPersistenceReattachShaderCase (void)
1536 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1538 TestLog& log = m_testCtx.getLog();
1539 glu::Shader& caseShader = shaders.get(m_shaderType);
1541 log << TestLog::Message << "Reattaching " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1542 program.detachShader(caseShader.getShader());
1543 program.attachShader(caseShader.getShader());
1547 class ProgramBinaryPersistenceDeleteShaderCase : public ProgramBinaryPersistenceCase
1550 ProgramBinaryPersistenceDeleteShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1551 : ProgramBinaryPersistenceCase (context, name, desc, shaderType)
1555 virtual ~ProgramBinaryPersistenceDeleteShaderCase (void)
1559 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1561 TestLog& log = m_testCtx.getLog();
1562 glu::Shader& caseShader = shaders.get(m_shaderType);
1564 log << TestLog::Message << "Deleting " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1565 program.detachShader(caseShader.getShader());
1566 shaders.deleteShader(m_shaderType);
1570 class ProgramBinaryPersistenceReplaceShaderCase : public ProgramBinaryPersistenceCase
1573 ProgramBinaryPersistenceReplaceShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1574 : ProgramBinaryPersistenceCase (context, name, desc, shaderType)
1578 virtual ~ProgramBinaryPersistenceReplaceShaderCase (void)
1582 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1584 TestLog& log = m_testCtx.getLog();
1585 glu::Shader& caseShader = shaders.get(m_shaderType);
1587 log << TestLog::Message << "Deleting and replacing " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1588 program.detachShader(caseShader.getShader());
1589 shaders.deleteShader(m_shaderType);
1590 program.attachShader(shaders.createShader(m_shaderType).getShader());
1594 class ProgramBinaryPersistenceRecompileShaderCase : public ProgramBinaryPersistenceCase
1597 ProgramBinaryPersistenceRecompileShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1598 : ProgramBinaryPersistenceCase (context, name, desc, shaderType)
1602 virtual ~ProgramBinaryPersistenceRecompileShaderCase (void)
1606 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1608 TestLog& log = m_testCtx.getLog();
1609 glu::Shader& caseShader = shaders.get(m_shaderType);
1611 log << TestLog::Message << "Recompiling " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
1612 caseShader.compile();
1617 class ProgramBinaryPersistenceReplaceSourceCase : public ProgramBinaryPersistenceCase
1620 ProgramBinaryPersistenceReplaceSourceCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
1621 : ProgramBinaryPersistenceCase (context, name, desc, shaderType)
1625 virtual ~ProgramBinaryPersistenceReplaceSourceCase (void)
1629 void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
1631 TestLog& log = m_testCtx.getLog();
1632 glu::Shader& caseShader = shaders.get(m_shaderType);
1634 log << TestLog::Message << "Replacing " + std::string(getShaderTypeName(m_shaderType)) + " shader source and recompiling" << TestLog::EndMessage;
1635 shaders.setSource(m_shaderType);
1636 caseShader.compile();
1643 ShaderApiTests::ShaderApiTests (Context& context)
1644 : TestCaseGroup(context, "shader_api", "Shader API Cases")
1648 ShaderApiTests::~ShaderApiTests (void)
1652 void ShaderApiTests::init (void)
1654 // create and delete shaders
1656 TestCaseGroup* createDeleteGroup = new TestCaseGroup(m_context, "create_delete", "glCreateShader() tests");
1657 addChild(createDeleteGroup);
1659 createDeleteGroup->addChild(new CreateShaderCase(m_context, "create_vertex_shader", "Create vertex shader object", glu::SHADERTYPE_VERTEX));
1660 createDeleteGroup->addChild(new CreateShaderCase(m_context, "create_fragment_shader", "Create fragment shader object", glu::SHADERTYPE_FRAGMENT));
1662 createDeleteGroup->addChild(new DeleteShaderCase(m_context, "delete_vertex_fragment", "Delete vertex shader and fragment shader"));
1667 TestCaseGroup* compileLinkGroup = new TestCaseGroup(m_context, "compile_link", "Compile and link tests");
1668 addChild(compileLinkGroup);
1670 compileLinkGroup->addChild(new CompileShaderCase(m_context, "compile_vertex_shader", "Compile vertex shader", glu::SHADERTYPE_VERTEX));
1671 compileLinkGroup->addChild(new CompileShaderCase(m_context, "compile_fragment_shader", "Compile fragment shader", glu::SHADERTYPE_FRAGMENT));
1673 compileLinkGroup->addChild(new LinkVertexFragmentCase(m_context, "link_vertex_fragment", "Link vertex and fragment shaders"));
1678 TestCaseGroup* shaderSourceGroup = new TestCaseGroup(m_context, "shader_source", "glShaderSource() tests");
1679 addChild(shaderSourceGroup);
1681 for (int shaderTypeInt = 0; shaderTypeInt < 2; shaderTypeInt++)
1683 const glu::ShaderType shaderType = (shaderTypeInt == 1) ? glu::SHADERTYPE_FRAGMENT : glu::SHADERTYPE_VERTEX;
1684 const std::string shaderTypeName = getShaderTypeName(shaderType);
1686 const std::string caseName = std::string("replace_source_") + shaderTypeName;
1687 const std::string caseDesc = std::string("Replace source code of ") + shaderTypeName + " shader.";
1689 shaderSourceGroup->addChild(new ShaderSourceReplaceCase(m_context, caseName.c_str(), caseDesc.c_str(), shaderType));
1692 for (int stringLengthsInt = 0; stringLengthsInt < 3; stringLengthsInt++)
1693 for (int caseNdx = 1; caseNdx <= 3; caseNdx++)
1694 for (int shaderTypeInt = 0; shaderTypeInt < 2; shaderTypeInt++)
1696 const int numSlices = 1 << caseNdx;
1697 const glu::ShaderType shaderType = (shaderTypeInt == 1) ? glu::SHADERTYPE_FRAGMENT : glu::SHADERTYPE_VERTEX;
1699 const bool explicitLengths = (stringLengthsInt != 0);
1700 const bool randomNullTerm = (stringLengthsInt == 2);
1702 const deUint32 flags = (explicitLengths ? CASE_EXPLICIT_SOURCE_LENGTHS : 0)
1703 | (randomNullTerm ? CASE_RANDOM_NULL_TERMINATED : 0);
1705 const std::string caseName = "split_source_"
1706 + de::toString(numSlices)
1707 + (randomNullTerm ? "_random_negative_length" : (explicitLengths ? "_specify_lengths" : "_null_terminated"))
1708 + ((shaderType == glu::SHADERTYPE_FRAGMENT) ? "_fragment" : "_vertex");
1710 const std::string caseDesc = std::string((shaderType == glu::SHADERTYPE_FRAGMENT) ? "Fragment" : "Vertex")
1711 + " shader source split into "
1712 + de::toString(numSlices)
1714 + (explicitLengths ? ", using explicitly specified string lengths" : "")
1715 + (randomNullTerm ? " with random negative length values" : "");
1717 shaderSourceGroup->addChild(new ShaderSourceSplitCase(m_context, caseName.c_str(), caseDesc.c_str(), shaderType, numSlices, flags));
1721 // link status and infolog
1723 TestCaseGroup* linkStatusGroup = new TestCaseGroup(m_context, "program_state", "Program state persistence tests");
1724 addChild(linkStatusGroup);
1726 addProgramStateCase<ProgramStateDetachShaderCase> (linkStatusGroup, m_context, "detach_shader", "detach shader");
1727 addProgramStateCase<ProgramStateReattachShaderCase> (linkStatusGroup, m_context, "reattach_shader", "reattach shader");
1728 addProgramStateCase<ProgramStateDeleteShaderCase> (linkStatusGroup, m_context, "delete_shader", "delete shader");
1729 addProgramStateCase<ProgramStateReplaceShaderCase> (linkStatusGroup, m_context, "replace_shader", "replace shader object");
1730 addProgramStateCase<ProgramStateRecompileShaderCase> (linkStatusGroup, m_context, "recompile_shader", "recompile shader");
1731 addProgramStateCase<ProgramStateReplaceSourceCase> (linkStatusGroup, m_context, "replace_source", "replace shader source");
1736 TestCaseGroup* programBinaryGroup = new TestCaseGroup(m_context, "program_binary", "Program binary API tests");
1737 addChild(programBinaryGroup);
1740 TestCaseGroup* simpleCaseGroup = new TestCaseGroup(m_context, "simple", "Simple API tests");
1741 programBinaryGroup->addChild(simpleCaseGroup);
1743 simpleCaseGroup->addChild(new ProgramBinarySimpleCase (m_context, "get_program_binary_vertex_fragment", "Get vertex and fragment shader program binary"));
1744 simpleCaseGroup->addChild(new ProgramBinaryUniformResetCase (m_context, "uniform_reset_on_binary_load", "Verify uniform reset on successful load of program binary"));
1748 TestCaseGroup* binaryPersistenceGroup = new TestCaseGroup(m_context, "binary_persistence", "Program binary persistence tests");
1749 programBinaryGroup->addChild(binaryPersistenceGroup);
1751 addProgramBinaryPersistenceCase<ProgramBinaryPersistenceDetachShaderCase> (binaryPersistenceGroup, m_context, "detach_shader", "detach shader");
1752 addProgramBinaryPersistenceCase<ProgramBinaryPersistenceReattachShaderCase> (binaryPersistenceGroup, m_context, "reattach_shader", "reattach shader");
1753 addProgramBinaryPersistenceCase<ProgramBinaryPersistenceDeleteShaderCase> (binaryPersistenceGroup, m_context, "delete_shader", "delete shader");
1754 addProgramBinaryPersistenceCase<ProgramBinaryPersistenceReplaceShaderCase> (binaryPersistenceGroup, m_context, "replace_shader", "replace shader object");
1755 addProgramBinaryPersistenceCase<ProgramBinaryPersistenceRecompileShaderCase> (binaryPersistenceGroup, m_context, "recompile_shader", "recompile shader");
1756 addProgramBinaryPersistenceCase<ProgramBinaryPersistenceReplaceSourceCase> (binaryPersistenceGroup, m_context, "replace_source", "replace shader source");