• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014 Intel Corporation
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21  * \file
22  * \brief
23  */ /*-------------------------------------------------------------------*/
24 
25 #include "glcShaderIntegerMixTests.hpp"
26 #include "deMath.h"
27 #include "deRandom.hpp"
28 #include "deString.h"
29 #include "deStringUtil.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluDrawUtil.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluShaderProgram.hpp"
34 #include "glw.h"
35 #include "glwFunctions.hpp"
36 #include "tcuCommandLine.hpp"
37 #include "tcuStringTemplate.hpp"
38 #include "tcuSurface.hpp"
39 #include "tcuTestLog.hpp"
40 
41 namespace deqp
42 {
43 
44 using tcu::TestLog;
45 
46 class ShaderIntegerMixCase : public TestCase
47 {
48 public:
ShaderIntegerMixCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)49 	ShaderIntegerMixCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion)
50 		: TestCase(context, name, description), m_glslVersion(glslVersion)
51 	{
52 	}
53 
~ShaderIntegerMixCase()54 	~ShaderIntegerMixCase()
55 	{
56 		// empty
57 	}
58 
iterate()59 	IterateResult iterate()
60 	{
61 		qpTestResult result = test();
62 
63 		m_testCtx.setTestResult(result, qpGetTestResultName(result));
64 
65 		return STOP;
66 	}
67 
68 protected:
69 	glu::GLSLVersion m_glslVersion;
70 
71 	virtual qpTestResult test() = 0;
72 };
73 
74 class ShaderIntegerMixDefineCase : public ShaderIntegerMixCase
75 {
76 public:
ShaderIntegerMixDefineCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)77 	ShaderIntegerMixDefineCase(Context& context, const char* name, const char* description,
78 							   glu::GLSLVersion glslVersion)
79 		: ShaderIntegerMixCase(context, name, description, glslVersion)
80 	{
81 		// empty
82 	}
83 
~ShaderIntegerMixDefineCase()84 	~ShaderIntegerMixDefineCase()
85 	{
86 		// empty
87 	}
88 
89 protected:
test()90 	virtual qpTestResult test()
91 	{
92 		const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
93 		bool				  pass = true;
94 
95 		static const char source_template[] = "${VERSION_DECL}\n"
96 											  "#extension GL_EXT_shader_integer_mix: require\n"
97 											  "\n"
98 											  "#if !defined GL_EXT_shader_integer_mix\n"
99 											  "#  error GL_EXT_shader_integer_mix is not defined\n"
100 											  "#elif GL_EXT_shader_integer_mix != 1\n"
101 											  "#  error GL_EXT_shader_integer_mix is not equal to 1\n"
102 											  "#endif\n"
103 											  "\n"
104 											  "void main(void) { ${BODY} }\n";
105 
106 		static const struct
107 		{
108 			GLenum		target;
109 			const char* body;
110 		} shader_targets[] = {
111 			{ GL_VERTEX_SHADER, "gl_Position = vec4(0);" }, { GL_FRAGMENT_SHADER, "" },
112 		};
113 
114 		const glu::GLSLVersion v = glslVersionIsES(m_glslVersion) ? glu::GLSL_VERSION_300_ES : glu::GLSL_VERSION_330;
115 
116 		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_shader_integer_mix"))
117 			return QP_TEST_RESULT_NOT_SUPPORTED;
118 
119 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(shader_targets); i++)
120 		{
121 			std::map<std::string, std::string> args;
122 
123 			args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(v);
124 			args["BODY"]		 = shader_targets[i].body;
125 
126 			std::string code = tcu::StringTemplate(source_template).specialize(args);
127 
128 			GLuint		shader	 = gl.createShader(shader_targets[i].target);
129 			char const* strings[1] = { code.c_str() };
130 			gl.shaderSource(shader, 1, strings, 0);
131 			gl.compileShader(shader);
132 
133 			GLint compileSuccess = 0;
134 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compileSuccess);
135 			gl.deleteShader(shader);
136 
137 			if (!compileSuccess)
138 				pass = false;
139 		}
140 
141 		return pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL;
142 	}
143 };
144 
145 class ShaderIntegerMixPrototypesCase : public ShaderIntegerMixCase
146 {
147 public:
ShaderIntegerMixPrototypesCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion,bool _use_extension,bool _is_negative_testing)148 	ShaderIntegerMixPrototypesCase(Context& context, const char* name, const char* description,
149 								   glu::GLSLVersion glslVersion, bool _use_extension, bool _is_negative_testing)
150 		: ShaderIntegerMixCase(context, name, description, glslVersion)
151 		, use_extension(_use_extension)
152 		, is_negative_testing(_is_negative_testing)
153 	{
154 		// empty
155 	}
156 
~ShaderIntegerMixPrototypesCase()157 	~ShaderIntegerMixPrototypesCase()
158 	{
159 		// empty
160 	}
161 
162 protected:
163 	bool use_extension;
164 	bool is_negative_testing;
165 
test()166 	virtual qpTestResult test()
167 	{
168 		TestLog&			  log  = m_testCtx.getLog();
169 		const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
170 		bool				  pass = true;
171 
172 		static const char source_template[] = "${VERSION_DECL}\n"
173 											  "${EXTENSION_ENABLE}\n"
174 											  "\n"
175 											  "void main()\n"
176 											  "{\n"
177 											  "	mix(ivec2(1), ivec2(2), bvec2(true));\n"
178 											  "	mix(ivec3(1), ivec3(2), bvec3(true));\n"
179 											  "	mix(ivec4(1), ivec4(2), bvec4(true));\n"
180 											  "	mix(uvec2(1), uvec2(2), bvec2(true));\n"
181 											  "	mix(uvec3(1), uvec3(2), bvec3(true));\n"
182 											  "	mix(uvec4(1), uvec4(2), bvec4(true));\n"
183 											  "	mix(bvec2(1), bvec2(0), bvec2(true));\n"
184 											  "	mix(bvec3(1), bvec3(0), bvec3(true));\n"
185 											  "	mix(bvec4(1), bvec4(0), bvec4(true));\n"
186 											  "	${BODY}\n"
187 											  "}\n";
188 
189 		static const struct
190 		{
191 			GLenum		target;
192 			const char* body;
193 		} shader_targets[] = {
194 			{ GL_VERTEX_SHADER, "gl_Position = vec4(0);" }, { GL_FRAGMENT_SHADER, "" },
195 		};
196 
197 		glu::GLSLVersion v;
198 		const char*		 extension_enable;
199 
200 		if (use_extension)
201 		{
202 			v				 = glslVersionIsES(m_glslVersion) ? glu::GLSL_VERSION_300_ES : glu::GLSL_VERSION_330;
203 			extension_enable = "#extension GL_EXT_shader_integer_mix: enable";
204 
205 			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_shader_integer_mix"))
206 				return QP_TEST_RESULT_NOT_SUPPORTED;
207 		}
208 		else if (is_negative_testing)
209 		{
210 			v				 = glslVersionIsES(m_glslVersion) ? glu::GLSL_VERSION_300_ES : glu::GLSL_VERSION_330;
211 			extension_enable = "";
212 		}
213 		else
214 		{
215 			v				 = m_glslVersion;
216 			extension_enable = "";
217 			if (glslVersionIsES(m_glslVersion))
218 			{
219 				if (m_glslVersion < glu::GLSL_VERSION_310_ES)
220 					return QP_TEST_RESULT_NOT_SUPPORTED;
221 			}
222 			else
223 			{
224 				if (m_glslVersion < glu::GLSL_VERSION_450)
225 					return QP_TEST_RESULT_NOT_SUPPORTED;
226 			}
227 		}
228 
229 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(shader_targets); i++)
230 		{
231 			std::map<std::string, std::string> args;
232 
233 			args["VERSION_DECL"]	 = glu::getGLSLVersionDeclaration(v);
234 			args["EXTENSION_ENABLE"] = extension_enable;
235 			args["BODY"]			 = shader_targets[i].body;
236 
237 			std::string code = tcu::StringTemplate(source_template).specialize(args);
238 
239 			GLuint		shader	 = gl.createShader(shader_targets[i].target);
240 			char const* strings[1] = { code.c_str() };
241 			gl.shaderSource(shader, 1, strings, 0);
242 			gl.compileShader(shader);
243 
244 			GLint compileSuccess = 0;
245 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compileSuccess);
246 
247 			if (is_negative_testing)
248 			{
249 				if (compileSuccess)
250 				{
251 					TCU_FAIL("The shader compilation was expected to fail, but it was successful.");
252 					pass = false;
253 				}
254 			}
255 			else if (!compileSuccess)
256 			{
257 				GLchar infoLog[1000];
258 
259 				gl.getShaderInfoLog(shader, sizeof(infoLog), NULL, infoLog);
260 				log.writeKernelSource(strings[0]);
261 				log.writeCompileInfo("shader", "", false, infoLog);
262 
263 				pass = false;
264 			}
265 
266 			gl.deleteShader(shader);
267 		}
268 
269 		return pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL;
270 	}
271 };
272 
273 class ShaderIntegerMixRenderCase : public ShaderIntegerMixCase
274 {
275 public:
ShaderIntegerMixRenderCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion,const char * _type)276 	ShaderIntegerMixRenderCase(Context& context, const char* name, const char* description,
277 							   glu::GLSLVersion glslVersion, const char* _type)
278 		: ShaderIntegerMixCase(context, name, description, glslVersion), type(_type)
279 	{
280 		// empty
281 	}
282 
~ShaderIntegerMixRenderCase()283 	~ShaderIntegerMixRenderCase()
284 	{
285 		// empty
286 	}
287 
288 protected:
289 	// Type used for mix() parameters in this test case.
290 	const char* type;
291 
292 	static const unsigned width  = 8 * 8;
293 	static const unsigned height = 8 * 8;
294 
test()295 	virtual qpTestResult test()
296 	{
297 		static const char vs_template[] = "${VERSION_DECL}\n"
298 										  "${EXTENSION_ENABLE}\n"
299 										  "\n"
300 										  "in vec2 vertex;\n"
301 										  "in ivec4 vs_in_a;\n"
302 										  "in ivec4 vs_in_b;\n"
303 										  "in ivec4 vs_in_sel;\n"
304 										  "\n"
305 										  "flat out ivec4 fs_in_a;\n"
306 										  "flat out ivec4 fs_in_b;\n"
307 										  "flat out ivec4 fs_in_sel;\n"
308 										  "flat out ivec4 fs_in_result;\n"
309 										  "\n"
310 										  "void main()\n"
311 										  "{\n"
312 										  "    fs_in_a = vs_in_a;\n"
313 										  "    fs_in_b = vs_in_b;\n"
314 										  "    fs_in_sel = vs_in_sel;\n"
315 										  "\n"
316 										  "    ${TYPE} a = ${TYPE}(vs_in_a);\n"
317 										  "    ${TYPE} b = ${TYPE}(vs_in_b);\n"
318 										  "    bvec4 sel = bvec4(vs_in_sel);\n"
319 										  "    fs_in_result = ivec4(mix(a, b, sel));\n"
320 										  "\n"
321 										  "    gl_Position = vec4(vertex, 0, 1);\n"
322 										  "    gl_PointSize = 4.;\n"
323 										  "}\n";
324 
325 		static const char fs_template[] = "${VERSION_DECL}\n"
326 										  "${EXTENSION_ENABLE}\n"
327 										  "\n"
328 										  "out ivec4 o;\n"
329 										  "\n"
330 										  "flat in ivec4 fs_in_a;\n"
331 										  "flat in ivec4 fs_in_b;\n"
332 										  "flat in ivec4 fs_in_sel;\n"
333 										  "flat in ivec4 fs_in_result;\n"
334 										  "\n"
335 										  "uniform bool use_vs_data;\n"
336 										  "\n"
337 										  "void main()\n"
338 										  "{\n"
339 										  "    if (use_vs_data)\n"
340 										  "        o = fs_in_result;\n"
341 										  "    else {\n"
342 										  "        ${TYPE} a = ${TYPE}(fs_in_a);\n"
343 										  "        ${TYPE} b = ${TYPE}(fs_in_b);\n"
344 										  "        bvec4 sel = bvec4(fs_in_sel);\n"
345 										  "        o = ivec4(mix(a, b, sel));\n"
346 										  "    }\n"
347 										  "}\n";
348 
349 		TestLog&			  log  = m_testCtx.getLog();
350 		const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
351 		bool				  pass = true;
352 		const char*			  extension_enable;
353 		bool				  is_es = glslVersionIsES(m_glslVersion);
354 
355 		if ((is_es && (m_glslVersion < glu::GLSL_VERSION_310_ES)) || !is_es)
356 		{
357 			/* For versions that do not support this feature in Core it must be exposed via an extension. */
358 			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_shader_integer_mix"))
359 			{
360 				return QP_TEST_RESULT_NOT_SUPPORTED;
361 			}
362 
363 			extension_enable = "#extension GL_EXT_shader_integer_mix: enable";
364 		}
365 		else
366 		{
367 			extension_enable = "";
368 		}
369 
370 		/* Generate the specialization of the shader for the specific
371 		 * type being tested.
372 		 */
373 		std::map<std::string, std::string> args;
374 
375 		args["VERSION_DECL"]	 = glu::getGLSLVersionDeclaration(m_glslVersion);
376 		args["EXTENSION_ENABLE"] = extension_enable;
377 		args["TYPE"]			 = type;
378 
379 		std::string vs_code = tcu::StringTemplate(vs_template).specialize(args);
380 
381 		std::string fs_code = tcu::StringTemplate(fs_template).specialize(args);
382 
383 		glu::ShaderProgram prog(m_context.getRenderContext(),
384 								glu::makeVtxFragSources(vs_code.c_str(), fs_code.c_str()));
385 
386 		if (!prog.isOk())
387 		{
388 			log << prog;
389 			TCU_FAIL("Compile failed");
390 		}
391 
392 		if (!glslVersionIsES(m_glslVersion))
393 			glEnable(GL_PROGRAM_POINT_SIZE);
394 
395 		/* Generate an integer FBO for rendering.
396 		 */
397 		GLuint fbo;
398 		GLuint tex;
399 
400 		glGenTextures(1, &tex);
401 		glBindTexture(GL_TEXTURE_2D, tex);
402 		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA32I, width, height, 0 /* border */, GL_RGBA_INTEGER, GL_INT,
403 					 NULL /* data */);
404 		glBindTexture(GL_TEXTURE_2D, 0);
405 
406 		glGenFramebuffers(1, &fbo);
407 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
408 		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
409 		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0 /* level */);
410 
411 		GLU_EXPECT_NO_ERROR(gl.getError(), "Creation of rendering FBO failed.");
412 
413 		if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
414 			TCU_FAIL("Framebuffer not complete.");
415 
416 		glViewport(0, 0, width, height);
417 
418 		/* Fill a VBO with some vertex data.
419 		 */
420 		deUint32   pointIndices[256];
421 		float	  vertex[DE_LENGTH_OF_ARRAY(pointIndices) * 2];
422 		deInt32	a[DE_LENGTH_OF_ARRAY(pointIndices) * 4];
423 		deInt32	b[DE_LENGTH_OF_ARRAY(a)];
424 		deInt32	sel[DE_LENGTH_OF_ARRAY(a)];
425 		tcu::IVec4 expected[DE_LENGTH_OF_ARRAY(pointIndices)];
426 
427 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(pointIndices); i++)
428 		{
429 			pointIndices[i] = deUint16(i);
430 
431 			const int x = (i / 16) * (width / 16) + (4 / 2);
432 			const int y = (i % 16) * (height / 16) + (4 / 2);
433 
434 			vertex[(i * 2) + 0] = float(x) * 2.0f / float(width) - 1.0f;
435 			vertex[(i * 2) + 1] = float(y) * 2.0f / float(height) - 1.0f;
436 
437 			a[(i * 4) + 0] = i;
438 			a[(i * 4) + 1] = i * 5;
439 			a[(i * 4) + 2] = i * 7;
440 			a[(i * 4) + 3] = i * 11;
441 
442 			b[(i * 4) + 0] = ~a[(i * 4) + 3];
443 			b[(i * 4) + 1] = ~a[(i * 4) + 2];
444 			b[(i * 4) + 2] = ~a[(i * 4) + 1];
445 			b[(i * 4) + 3] = ~a[(i * 4) + 0];
446 
447 			sel[(i * 4) + 0] = (i >> 0) & 1;
448 			sel[(i * 4) + 1] = (i >> 1) & 1;
449 			sel[(i * 4) + 2] = (i >> 2) & 1;
450 			sel[(i * 4) + 3] = (i >> 3) & 1;
451 
452 			expected[i] = tcu::IVec4(
453 				sel[(i * 4) + 0] ? b[(i * 4) + 0] : a[(i * 4) + 0], sel[(i * 4) + 1] ? b[(i * 4) + 1] : a[(i * 4) + 1],
454 				sel[(i * 4) + 2] ? b[(i * 4) + 2] : a[(i * 4) + 2], sel[(i * 4) + 3] ? b[(i * 4) + 3] : a[(i * 4) + 3]);
455 		}
456 
457 		/* Mask off all but the least significant bit for boolean
458 		 * types.
459 		 */
460 		if (type[0] == 'b')
461 		{
462 			for (int i = 0; i < DE_LENGTH_OF_ARRAY(a); i++)
463 			{
464 				a[i] &= 1;
465 				b[i] &= 1;
466 
467 				expected[i / 4][0] &= 1;
468 				expected[i / 4][1] &= 1;
469 				expected[i / 4][2] &= 1;
470 				expected[i / 4][3] &= 1;
471 			}
472 		}
473 
474 		glu::VertexArrayBinding vertexArrays[] = {
475 			glu::va::Float("vertex", 2, DE_LENGTH_OF_ARRAY(pointIndices), 0, vertex),
476 			glu::va::Int32("vs_in_a", 4, DE_LENGTH_OF_ARRAY(pointIndices), 0, a),
477 			glu::va::Int32("vs_in_b", 4, DE_LENGTH_OF_ARRAY(pointIndices), 0, b),
478 			glu::va::Int32("vs_in_sel", 4, DE_LENGTH_OF_ARRAY(pointIndices), 0, sel)
479 		};
480 
481 		/* Render and verify the results.  Rendering happens twice.
482 		 * The first time, use_vs_data is false, and the mix() result
483 		 * from the fragment shader is used.  The second time,
484 		 * use_vs_data is true, and the mix() result from the vertex
485 		 * shader is used.
486 		 */
487 		const GLint loc = gl.getUniformLocation(prog.getProgram(), "use_vs_data");
488 		gl.useProgram(prog.getProgram());
489 
490 		static const GLint clear[] = { 1, 2, 3, 4 };
491 		glClearBufferiv(GL_COLOR, 0, clear);
492 
493 		gl.uniform1i(loc, 0);
494 		glu::draw(m_context.getRenderContext(), prog.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
495 				  glu::pr::Points(DE_LENGTH_OF_ARRAY(pointIndices), pointIndices));
496 
497 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(pointIndices); i++)
498 		{
499 			const int x = int((vertex[(i * 2) + 0] + 1.0f) * float(width) / 2.0f);
500 			const int y = int((vertex[(i * 2) + 1] + 1.0f) * float(height) / 2.0f);
501 
502 			pass = probe_pixel(log, "Fragment", x, y, expected[i]) && pass;
503 		}
504 
505 		gl.uniform1i(loc, 1);
506 		glu::draw(m_context.getRenderContext(), prog.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
507 				  glu::pr::Points(DE_LENGTH_OF_ARRAY(pointIndices), pointIndices));
508 
509 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(pointIndices); i++)
510 		{
511 			const int x = int((vertex[(i * 2) + 0] + 1.0f) * float(width) / 2.0f);
512 			const int y = int((vertex[(i * 2) + 1] + 1.0f) * float(height) / 2.0f);
513 
514 			pass = probe_pixel(log, "Vertex", x, y, expected[i]) && pass;
515 		}
516 
517 		glDeleteFramebuffers(1, &fbo);
518 		glDeleteTextures(1, &tex);
519 
520 		return pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL;
521 	}
522 
probe_pixel(TestLog & log,const char * stage,int x,int y,const tcu::IVec4 & expected)523 	bool probe_pixel(TestLog& log, const char* stage, int x, int y, const tcu::IVec4& expected)
524 	{
525 		tcu::IVec4 pixel;
526 
527 		glReadPixels(x, y, 1, 1, GL_RGBA_INTEGER, GL_INT, &pixel);
528 
529 		if (expected != pixel)
530 		{
531 			log << TestLog::Message << stage << " shader failed at pixel (" << x << ", " << y << ").  "
532 				<< "Got " << pixel << ", expected " << expected << ")." << TestLog::EndMessage;
533 			return false;
534 		}
535 
536 		return true;
537 	}
538 };
539 
ShaderIntegerMixTests(Context & context,glu::GLSLVersion glslVersion)540 ShaderIntegerMixTests::ShaderIntegerMixTests(Context& context, glu::GLSLVersion glslVersion)
541 	: TestCaseGroup(context, "shader_integer_mix", "Shader Integer Mix tests"), m_glslVersion(glslVersion)
542 {
543 	// empty
544 }
545 
~ShaderIntegerMixTests()546 ShaderIntegerMixTests::~ShaderIntegerMixTests()
547 {
548 	// empty
549 }
550 
init(void)551 void ShaderIntegerMixTests::init(void)
552 {
553 	addChild(new ShaderIntegerMixDefineCase(m_context, "define", "Verify GL_EXT_shader_integer_mix is defined to 1.",
554 											m_glslVersion));
555 	addChild(new ShaderIntegerMixPrototypesCase(m_context, "prototypes-extension",
556 												"Verify availability of all function signatures with the extension.",
557 												m_glslVersion, true, false));
558 	addChild(new ShaderIntegerMixPrototypesCase(
559 		m_context, "prototypes", "Verify availability of all function signatures with the proper GLSL version.",
560 		m_glslVersion, false, false));
561 	addChild(new ShaderIntegerMixPrototypesCase(
562 		m_context, "prototypes-negative",
563 		"Verify compilation fails if the GLSL version does not support shader_integer_mix", m_glslVersion, false,
564 		true));
565 
566 	static const char* types_to_test[] = { "ivec4", "uvec4", "bvec4" };
567 
568 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(types_to_test); i++)
569 	{
570 		std::stringstream name;
571 
572 		name << "mix-" << types_to_test[i];
573 
574 		std::stringstream description;
575 
576 		description << "Verify functionality of mix() with " << types_to_test[i] << " parameters.";
577 
578 		addChild(new ShaderIntegerMixRenderCase(m_context, name.str().c_str(), description.str().c_str(), m_glslVersion,
579 												types_to_test[i]));
580 	}
581 }
582 
583 } // namespace deqp
584