1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24/**
25 * \file  gl3GPUShader5Tests.cpp
26 * \brief Implements conformance tests for "GPU Shader 5" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29#include "gl3cGPUShader5Tests.hpp"
30#include "gluContextInfo.hpp"
31#include "glwFunctions.hpp"
32#include "tcuMatrix.hpp"
33#include "tcuTestLog.hpp"
34
35#include <iomanip>
36
37#include <deMath.h>
38#include <tcuMatrixUtil.hpp>
39#include <tcuVectorUtil.hpp>
40
41#include <cstdlib>
42#include <cstring>
43#include <limits>
44#include <memory>
45
46namespace gl3cts
47{
48
49/** Constructor
50 *
51 * @param context Test context
52 **/
53Utils::programInfo::programInfo(deqp::Context& context)
54	: m_context(context), m_fragment_shader_id(0), m_program_object_id(0), m_vertex_shader_id(0)
55{
56	/* Nothing to be done here */
57}
58
59/** Destructor
60 *
61 **/
62Utils::programInfo::~programInfo()
63{
64	/* GL entry points */
65	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
66
67	/* Make sure program object is no longer used by GL */
68	gl.useProgram(0);
69
70	/* Clean program object */
71	if (0 != m_program_object_id)
72	{
73		gl.deleteProgram(m_program_object_id);
74		m_program_object_id = 0;
75	}
76
77	/* Clean shaders */
78	if (0 != m_fragment_shader_id)
79	{
80		gl.deleteShader(m_fragment_shader_id);
81		m_fragment_shader_id = 0;
82	}
83
84	if (0 != m_vertex_shader_id)
85	{
86		gl.deleteShader(m_vertex_shader_id);
87		m_vertex_shader_id = 0;
88	}
89}
90
91/** Build program
92 *
93 * @param fragment_shader_code               Fragment shader source code
94 * @param vertex_shader_code                 Vertex shader source code
95 * @param varying_names                      Array of strings containing names of varyings to be captured with transfrom feedback
96 * @param n_varying_names                    Number of varyings to be captured with transfrom feedback
97 **/
98void Utils::programInfo::build(const glw::GLchar* fragment_shader_code, const glw::GLchar* vertex_shader_code)
99{
100	/* GL entry points */
101	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
102
103	/* Create shader objects and compile */
104	if (0 != fragment_shader_code)
105	{
106		m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
107		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
108
109		compile(m_fragment_shader_id, fragment_shader_code);
110	}
111
112	if (0 != vertex_shader_code)
113	{
114		m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
115		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
116
117		compile(m_vertex_shader_id, vertex_shader_code);
118	}
119
120	/* Create program object */
121	m_program_object_id = gl.createProgram();
122	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
123
124	/* Link program */
125	link();
126}
127
128/** Compile shader
129 *
130 * @param shader_id   Shader object id
131 * @param shader_code Shader source code
132 **/
133void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
134{
135	/* GL entry points */
136	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
137
138	/* Compilation status */
139	glw::GLint status = GL_FALSE;
140
141	/* Set source code */
142	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
143	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
144
145	/* Compile */
146	gl.compileShader(shader_id);
147	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
148
149	/* Get compilation status */
150	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
151	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
152
153	/* Log compilation error */
154	if (GL_TRUE != status)
155	{
156		glw::GLint				 length = 0;
157		std::vector<glw::GLchar> message;
158
159		/* Error log length */
160		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
161		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
162
163		/* Prepare storage */
164		message.resize(length);
165
166		/* Get error log */
167		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
168		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
169
170		/* Log */
171		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
172											<< &message[0] << "\nShader source\n"
173											<< shader_code << tcu::TestLog::EndMessage;
174
175		TCU_FAIL("Failed to compile shader");
176	}
177}
178
179/** Attach shaders and link program
180 *
181 **/
182void Utils::programInfo::link() const
183{
184	/* GL entry points */
185	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
186
187	/* Link status */
188	glw::GLint status = GL_FALSE;
189
190	/* Attach shaders */
191	if (0 != m_fragment_shader_id)
192	{
193		gl.attachShader(m_program_object_id, m_fragment_shader_id);
194		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
195	}
196
197	if (0 != m_vertex_shader_id)
198	{
199		gl.attachShader(m_program_object_id, m_vertex_shader_id);
200		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
201	}
202
203	/* Link */
204	gl.linkProgram(m_program_object_id);
205	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
206
207	/* Get link status */
208	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
209	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
210
211	/* Log link error */
212	if (GL_TRUE != status)
213	{
214		glw::GLint				 length = 0;
215		std::vector<glw::GLchar> message;
216
217		/* Get error log length */
218		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
219		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
220
221		message.resize(length);
222
223		/* Get error log */
224		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
225		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
226
227		/* Log */
228		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
229											<< &message[0] << tcu::TestLog::EndMessage;
230
231		TCU_FAIL("Failed to link program");
232	}
233}
234
235/** Set the uniform variable with provided data.
236 *
237 * @param type       Type of variable
238 * @param name       Name of variable
239 * @param data       Data
240 */
241void Utils::programInfo::setUniform(Utils::_variable_type type, const glw::GLchar* name, const glw::GLvoid* data)
242{
243	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
244
245	const glw::GLfloat* f_data = (glw::GLfloat*)data;
246	const glw::GLint*   i_data = (glw::GLint*)data;
247	const glw::GLuint*  u_data = (glw::GLuint*)data;
248
249	/* Get location */
250	glw::GLint location = gl.getUniformLocation(m_program_object_id, name);
251	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
252
253	if (-1 == location)
254	{
255		TCU_FAIL("Uniform variable is unavailable");
256	}
257
258	/* Set data */
259	switch (type)
260	{
261	case Utils::VARIABLE_TYPE_FLOAT:
262		gl.uniform1fv(location, 1, f_data);
263		break;
264	case Utils::VARIABLE_TYPE_INT:
265		gl.uniform1iv(location, 1, i_data);
266		break;
267	case Utils::VARIABLE_TYPE_IVEC2:
268		gl.uniform2iv(location, 1, i_data);
269		break;
270	case Utils::VARIABLE_TYPE_IVEC3:
271		gl.uniform3iv(location, 1, i_data);
272		break;
273	case Utils::VARIABLE_TYPE_IVEC4:
274		gl.uniform4iv(location, 1, i_data);
275		break;
276	case Utils::VARIABLE_TYPE_UINT:
277		gl.uniform1uiv(location, 1, u_data);
278		break;
279	case Utils::VARIABLE_TYPE_UVEC2:
280		gl.uniform2uiv(location, 1, u_data);
281		break;
282	case Utils::VARIABLE_TYPE_UVEC3:
283		gl.uniform3uiv(location, 1, u_data);
284		break;
285	case Utils::VARIABLE_TYPE_UVEC4:
286		gl.uniform4uiv(location, 1, u_data);
287		break;
288	case Utils::VARIABLE_TYPE_VEC2:
289		gl.uniform2fv(location, 1, f_data);
290		break;
291	case Utils::VARIABLE_TYPE_VEC3:
292		gl.uniform3fv(location, 1, f_data);
293		break;
294	case Utils::VARIABLE_TYPE_VEC4:
295		gl.uniform4fv(location, 1, f_data);
296		break;
297	default:
298		TCU_FAIL("Invalid enum");
299	}
300
301	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform");
302}
303
304/** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
305 *
306 * @param token           Token string
307 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
308 * @param text            String that will be used as replacement for <token>
309 * @param string          String to work on
310 **/
311void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
312						 std::string& string)
313{
314	const size_t text_length	= strlen(text);
315	const size_t token_length   = strlen(token);
316	const size_t token_position = string.find(token, search_position);
317
318	string.replace(token_position, token_length, text, text_length);
319
320	search_position = token_position + text_length;
321}
322
323/* Constants used by GPUShader5ImplicitConversionsTest */
324const glw::GLsizei GPUShader5ImplicitConversionsTest::m_width  = 8;
325const glw::GLsizei GPUShader5ImplicitConversionsTest::m_height = 8;
326
327/** Constructor.
328 *
329 * @param context Rendering context.
330 **/
331GPUShader5ImplicitConversionsTest::GPUShader5ImplicitConversionsTest(deqp::Context& context)
332	: TestCase(context, "implicit_conversions",
333			   "Verifies that implicit conversions are accepted and executed as explicit ones")
334	, m_fbo_id(0)
335	, m_tex_id(0)
336	, m_vao_id(0)
337
338{
339	/* Left blank intentionally */
340}
341
342/** Constructor.
343 *
344 * @param context     Rendering context.
345 * @param name        Name of test
346 * @param description Describes test
347 **/
348GPUShader5ImplicitConversionsTest::GPUShader5ImplicitConversionsTest(deqp::Context& context, const char* name,
349																	 const char* description)
350	: TestCase(context, name, description), m_fbo_id(0), m_tex_id(0), m_vao_id(0)
351
352{
353	/* Left blank intentionally */
354}
355
356/** Deinitializes all GL objects that may have been created during
357 *  test execution.
358 **/
359void GPUShader5ImplicitConversionsTest::deinit()
360{
361	if (m_fbo_id != 0)
362	{
363		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
364		gl.deleteFramebuffers(1, &m_fbo_id);
365
366		m_fbo_id = 0;
367	}
368
369	if (m_tex_id != 0)
370	{
371		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
372		gl.deleteTextures(1, &m_tex_id);
373
374		m_tex_id = 0;
375	}
376
377	if (m_vao_id != 0)
378	{
379		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
380		gl.deleteVertexArrays(1, &m_vao_id);
381
382		m_vao_id = 0;
383	}
384}
385
386/** Executes test iteration.
387 *
388 *  @return Returns STOP.
389 */
390tcu::TestNode::IterateResult GPUShader5ImplicitConversionsTest::iterate()
391{
392	/* Defines data used as u1 and u2 uniforms */
393	static const glw::GLint  uni_data_int_1[4]  = { 112, -1122, 111222, -1222111222 };
394	static const glw::GLint  uni_data_int_2[4]  = { -112, 1122, -111222, 1222111222 };
395	static const glw::GLuint uni_data_uint_1[4] = { 0xffff0000, 0x0000ffff, 0x00ffffff, 0xffffffff };
396	static const glw::GLuint uni_data_uint_2[4] = { 0xfff70000, 0x00007fff, 0x007fffff, 0xfffffff7 };
397
398	/* Defines test cases */
399	static const testCase test_cases[] = {
400		{ "uint", false, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_2 } /* int >> uint */,
401		{ "uint", true, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_1 },
402		{ "float", false, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_2 } /* int >> float */,
403		{ "float", true, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_2, uni_data_int_2 },
404		{ "uvec2", false, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_2 } /* ivec2 >> uvec2 */,
405		{ "uvec2", true, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_1 },
406		{ "vec2", false, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_2 } /* ivec2 >> vec2 */,
407		{ "vec2", true, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_1 },
408		{ "uvec3", false, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_1, uni_data_int_2 } /* ivec3 >> uvec3 */,
409		{ "uvec3", true, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_2, uni_data_int_2 },
410		{ "vec3", false, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_1, uni_data_int_2 } /* ivec3 >> vec3 */,
411		{ "vec3", true, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_2, uni_data_int_2 },
412		{ "uvec4", false, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_2 } /* ivec4 >> uvec4 */,
413		{ "uvec4", true, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_1 },
414		{ "vec4", false, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_2 } /* ivec4 >> vec4 */,
415		{ "vec4", true, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_1 },
416		{ "float", false, "uint", Utils::VARIABLE_TYPE_UINT, uni_data_uint_1, uni_data_uint_2 } /* uint >> float */,
417		{ "float", true, "uint", Utils::VARIABLE_TYPE_UINT, uni_data_uint_2, uni_data_uint_2 },
418		{ "vec2", false, "uvec2", Utils::VARIABLE_TYPE_UVEC2, uni_data_uint_1, uni_data_uint_2 } /* uvec2 >> vec2 */,
419		{ "vec2", true, "uvec2", Utils::VARIABLE_TYPE_UVEC2, uni_data_uint_1, uni_data_uint_1 },
420		{ "vec3", false, "uvec3", Utils::VARIABLE_TYPE_UVEC3, uni_data_uint_1, uni_data_uint_2 } /* uvec3 >> vec3 */,
421		{ "vec3", true, "uvec3", Utils::VARIABLE_TYPE_UVEC3, uni_data_uint_2, uni_data_uint_2 },
422		{ "vec4", false, "uvec4", Utils::VARIABLE_TYPE_UVEC4, uni_data_uint_1, uni_data_uint_2 } /* uvec4 >> vec4 */,
423		{ "vec4", true, "uvec4", Utils::VARIABLE_TYPE_UVEC4, uni_data_uint_1, uni_data_uint_1 },
424	};
425	static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
426
427	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
428	{
429		throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
430	}
431
432	testInit();
433
434	/* Execute test cases */
435	for (size_t i = 0; i < n_test_cases; ++i)
436	{
437		const testCase& test_case = test_cases[i];
438
439		executeTestCase(test_case);
440	}
441
442	/* Set result - exceptions are thrown in case of any error */
443	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
444
445	/* Done */
446	return STOP;
447}
448
449/** Initializes frame buffer and vertex array
450 *
451 **/
452void GPUShader5ImplicitConversionsTest::testInit()
453{
454	/*  */
455	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
456
457	/* Prepare texture for color attachment 0 */
458	gl.genTextures(1, &m_tex_id);
459	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
460
461	gl.bindTexture(GL_TEXTURE_2D, m_tex_id);
462	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
463
464	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_width, m_height);
465	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
466
467	/* Prepare FBO with color attachment 0 */
468	gl.genFramebuffers(1, &m_fbo_id);
469	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
470
471	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
472	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
473
474	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex_id, 0 /* level */);
475	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
476
477	/* Set Viewport */
478	gl.viewport(0 /* x */, 0 /* y */, m_width, m_height);
479	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
480
481	/* Prepare blank VAO */
482	gl.genVertexArrays(1, &m_vao_id);
483	GLU_EXPECT_NO_ERROR(gl.getError(), "genVertexArrays");
484
485	gl.bindVertexArray(m_vao_id);
486	GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
487}
488
489/** Verifies if image is filled with <color>
490 *
491 * @param color       Color to be checked
492 * @param is_expected Selects if image is expected to be filled with given color or not
493 **/
494void GPUShader5ImplicitConversionsTest::verifyImage(glw::GLuint color, bool is_expected) const
495{
496	/*  */
497	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
498
499	/* Storage for image data */
500	glw::GLuint result_image[m_width * m_height];
501
502	/* Get image data */
503	gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
504	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexImage");
505
506	/* Inspect data */
507	if (true == is_expected)
508	{
509		for (size_t i = 0; i < m_width * m_height; ++i)
510		{
511			const glw::GLuint pixel_data = result_image[i];
512
513			if (color != pixel_data)
514			{
515				TCU_FAIL("Found invalid pixel during verification of drawn image");
516			}
517		}
518	}
519	else
520	{
521		for (size_t i = 0; i < m_width * m_height; ++i)
522		{
523			const glw::GLuint pixel_data = result_image[i];
524
525			if (color == pixel_data)
526			{
527				TCU_FAIL("Found invalid pixel during verification of drawn image");
528			}
529		}
530	}
531}
532
533/** Executes test case
534 *
535 * @param test_case Defines test case parameters
536 */
537void GPUShader5ImplicitConversionsTest::executeTestCase(const testCase& test_case)
538{
539	static const glw::GLuint white_color = 0xffffffff;
540
541	/*  */
542	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
543
544	/* Run test case */
545	{
546		/* Get shaders */
547		const std::string& fs = getFragmentShader();
548		const std::string& vs = getVertexShader(test_case.m_destination_type, test_case.m_source_type);
549
550		/* Prepare program */
551		Utils::programInfo program(m_context);
552
553		program.build(fs.c_str(), vs.c_str());
554
555		gl.useProgram(program.m_program_object_id);
556		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
557
558		program.setUniform(test_case.m_source_variable_type, "u1", test_case.m_u1_data);
559		program.setUniform(test_case.m_source_variable_type, "u2", test_case.m_u2_data);
560
561		/* Clear FBO */
562		gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
563		GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
564
565		gl.clear(GL_COLOR_BUFFER_BIT);
566		GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
567
568		/* Draw a triangle strip */
569		gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
570		GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
571	}
572
573	/* Verification */
574	verifyImage(white_color, test_case.m_is_white_expected);
575}
576
577/** Get vertex shader source.
578 *
579 * @param destination_type Name of type
580 * @param source_type      Name of type
581 *
582 * @return String with source of shader
583 */
584std::string GPUShader5ImplicitConversionsTest::getVertexShader(const glw::GLchar* destination_type,
585															   const glw::GLchar* source_type)
586{
587	/* Vertex shader template */
588	const char* vs_body_template = "#version 150\n"
589								   "#extension GL_ARB_gpu_shader5 : require\n"
590								   "\n"
591								   "uniform SOURCE_TYPE u1;\n"
592								   "uniform SOURCE_TYPE u2;\n"
593								   "\n"
594								   "out     vec4 result;\n"
595								   "\n"
596								   "void main()\n"
597								   "{\n"
598								   "    DESTINATION_TYPE v = ZERO;\n"
599								   "\n"
600								   "    v = DESTINATION_TYPE(u2) - u1;\n"
601								   "\n"
602								   "    result = vec4(0.0, 0.0, 0.0, 0.0);\n"
603								   "    if (ZERO == v)\n"
604								   "    {\n"
605								   "      result = vec4(1.0, 1.0, 1.0, 1.0);\n"
606								   "    }\n"
607								   "\n"
608								   "    switch (gl_VertexID)\n"
609								   "    {\n"
610								   "      case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
611								   "      case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
612								   "      case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
613								   "      case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
614								   "    }\n"
615								   "}\n"
616								   "\n";
617
618	std::string vs_body = vs_body_template;
619
620	/* Tokens */
621	size_t search_position = 0;
622
623	Utils::replaceToken("SOURCE_TYPE", search_position, source_type, vs_body);
624	Utils::replaceToken("SOURCE_TYPE", search_position, source_type, vs_body);
625
626	search_position = 0;
627	Utils::replaceToken("DESTINATION_TYPE", search_position, destination_type, vs_body);
628	Utils::replaceToken("DESTINATION_TYPE", search_position, destination_type, vs_body);
629
630	search_position = 0;
631	if (!strcmp(destination_type, "int") || !strcmp(destination_type, "uint"))
632	{
633		Utils::replaceToken("ZERO", search_position, "0", vs_body);
634		Utils::replaceToken("ZERO", search_position, "0", vs_body);
635	}
636	else if (!strcmp(destination_type, "float"))
637	{
638		Utils::replaceToken("ZERO", search_position, "0.0", vs_body);
639		Utils::replaceToken("ZERO", search_position, "0.0", vs_body);
640	}
641	else if (!strcmp(destination_type, "ivec2"))
642	{
643		Utils::replaceToken("ZERO", search_position, "ivec2(0,0)", vs_body);
644		Utils::replaceToken("ZERO", search_position, "ivec2(0,0)", vs_body);
645	}
646	else if (!strcmp(destination_type, "ivec3"))
647	{
648		Utils::replaceToken("ZERO", search_position, "ivec3(0,0,0)", vs_body);
649		Utils::replaceToken("ZERO", search_position, "ivec3(0,0,0)", vs_body);
650	}
651	else if (!strcmp(destination_type, "ivec4"))
652	{
653		Utils::replaceToken("ZERO", search_position, "ivec4(0,0,0,0)", vs_body);
654		Utils::replaceToken("ZERO", search_position, "ivec4(0,0,0,0)", vs_body);
655	}
656	else if (!strcmp(destination_type, "uvec2"))
657	{
658		Utils::replaceToken("ZERO", search_position, "uvec2(0,0)", vs_body);
659		Utils::replaceToken("ZERO", search_position, "uvec2(0,0)", vs_body);
660	}
661	else if (!strcmp(destination_type, "uvec3"))
662	{
663		Utils::replaceToken("ZERO", search_position, "uvec3(0,0,0)", vs_body);
664		Utils::replaceToken("ZERO", search_position, "uvec3(0,0,0)", vs_body);
665	}
666	else if (!strcmp(destination_type, "uvec4"))
667	{
668		Utils::replaceToken("ZERO", search_position, "uvec4(0,0,0,0)", vs_body);
669		Utils::replaceToken("ZERO", search_position, "uvec4(0,0,0,0)", vs_body);
670	}
671	else if (!strcmp(destination_type, "vec2"))
672	{
673		Utils::replaceToken("ZERO", search_position, "vec2(0,0)", vs_body);
674		Utils::replaceToken("ZERO", search_position, "vec2(0,0)", vs_body);
675	}
676	else if (!strcmp(destination_type, "vec3"))
677	{
678		Utils::replaceToken("ZERO", search_position, "vec3(0,0,0)", vs_body);
679		Utils::replaceToken("ZERO", search_position, "vec3(0,0,0)", vs_body);
680	}
681	else if (!strcmp(destination_type, "vec4"))
682	{
683		Utils::replaceToken("ZERO", search_position, "vec4(0,0,0,0)", vs_body);
684		Utils::replaceToken("ZERO", search_position, "vec4(0,0,0,0)", vs_body);
685	}
686
687	return vs_body;
688}
689
690/** Get fragment shader source.
691 *
692 * @return String with source of shader
693 */
694std::string GPUShader5ImplicitConversionsTest::getFragmentShader()
695{
696	const char* fs_body_template = "#version 150\n"
697								   "\n"
698								   "in  vec4 result;\n"
699								   "out vec4 color;\n"
700								   "\n"
701								   "void main()\n"
702								   "{\n"
703								   "    color = result;\n"
704								   "}\n"
705								   "\n";
706
707	std::string fs_body = fs_body_template;
708
709	return fs_body;
710}
711
712/** Constructor.
713 *
714 *  @param context Rendering context.
715 *
716 **/
717GPUShader5FunctionOverloadingTest::GPUShader5FunctionOverloadingTest(deqp::Context& context)
718	: GPUShader5ImplicitConversionsTest(context, "function_overloading",
719										"Verifies that function overloading is accepted")
720{
721	/* Left blank intentionally */
722}
723
724/** Executes test iteration.
725 *
726 *  @return Returns STOP.
727 */
728tcu::TestNode::IterateResult GPUShader5FunctionOverloadingTest::iterate()
729{
730	/* Defines data used as u1 and u2 uniforms */
731	static const glw::GLint  u1_data_1[4] = { (glw::GLint)0xffff0000, 0x0000ffff, 0x00ffffff, (glw::GLint)0xffffffff };
732	static const glw::GLint  u1_data_2[4] = { -112, 1122, -111222, 1222111222 };
733	static const glw::GLuint u2_data_1[4] = { 0xffff0000, 0x0000ffff, 0x00ffffff, 0xffffffff };
734	static const glw::GLuint u2_data_2[4] = { 0xfff70000, 0x00007fff, 0x007fffff, 0xfffffff7 };
735
736	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
737	{
738		throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
739	}
740
741	testInit();
742
743	/* Execute test case */
744	execute(u1_data_1, u2_data_1, true);
745	execute(u1_data_2, u2_data_2, false);
746
747	/* Set result - exceptions are thrown in case of any error */
748	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
749
750	/* Done */
751	return STOP;
752}
753
754/** Executes test case
755 *
756 * @param u1_data   Pointer to data that will used as u1 uniform
757 * @param u2_data   Pointer to data that will used as u2 uniform
758 * @param test_case Defines test case parameters
759 */
760void GPUShader5FunctionOverloadingTest::execute(const glw::GLint* u1_data, const glw::GLuint* u2_data,
761												bool is_black_expected)
762{
763	static const glw::GLuint black_color = 0x00000000;
764
765	/*  */
766	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
767
768	/* Run test case */
769	{
770		/* Shaders */
771		const char* fs = "#version 150\n"
772						 "\n"
773						 "in  vec4 result;\n"
774						 "out vec4 color;\n"
775						 "\n"
776						 "void main()\n"
777						 "{\n"
778						 "    color = result;\n"
779						 "}\n"
780						 "\n";
781
782		const char* vs = "#version 150\n"
783						 "#extension GL_ARB_gpu_shader5 : require\n"
784						 "\n"
785						 "uniform ivec4 u1;\n"
786						 "uniform uvec4 u2;\n"
787						 "\n"
788						 "out     vec4  result;\n"
789						 "\n"
790						 "vec4 f(in vec4 a, in vec4 b)\n"
791						 "{\n"
792						 "    return a * b;\n"
793						 "}\n"
794						 "\n"
795						 "vec4 f(in uvec4 a, in uvec4 b)\n"
796						 "{\n"
797						 "    return vec4(a - b);\n"
798						 "}\n"
799						 "\n"
800						 "void main()\n"
801						 "{\n"
802						 "    result = f(u1, u2);\n"
803						 "\n"
804						 "    switch (gl_VertexID)\n"
805						 "    {\n"
806						 "      case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
807						 "      case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
808						 "      case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
809						 "      case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
810						 "    }\n"
811						 "}\n"
812						 "\n";
813
814		/* Prepare program */
815		Utils::programInfo program(m_context);
816
817		program.build(fs, vs);
818
819		gl.useProgram(program.m_program_object_id);
820		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
821
822		program.setUniform(Utils::VARIABLE_TYPE_IVEC4, "u1", u1_data);
823		program.setUniform(Utils::VARIABLE_TYPE_UVEC4, "u2", u2_data);
824
825		/* Clear FBO */
826		gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
827		GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
828
829		gl.clear(GL_COLOR_BUFFER_BIT);
830		GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
831
832		/* Draw a triangle strip */
833		gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
834		GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
835	}
836
837	/* Verification */
838	verifyImage(black_color, is_black_expected);
839}
840
841/** Constructor.
842 *
843 *  @param context Rendering context.
844 *
845 **/
846GPUShader5FloatEncodingTest::GPUShader5FloatEncodingTest(deqp::Context& context)
847	: GPUShader5ImplicitConversionsTest(context, "float_encoding",
848										"Verifies that functions encoding floats as bits work as expected")
849{
850	/* Left blank intentionally */
851}
852
853/** Executes test iteration.
854 *
855 *  @return Returns STOP.
856 */
857tcu::TestNode::IterateResult GPUShader5FloatEncodingTest::iterate()
858{
859	/* Defines data used as u1 and u2 uniforms */
860	static const glw::GLfloat floats[4] = { -1.0f, -1234.0f, 1.0f, 1234.0f };
861	static const glw::GLint   ints[4]   = { -1, -1234, 1, 1234 };
862	static const glw::GLuint  uints[4]  = { 0xffffffff, 0xfffffb2e, 1, 0x4d2 };
863
864	/* Defines tested cases */
865	static const testCase test_cases[] = {
866		{ /* float >> int - invalid */
867		  { Utils::VARIABLE_TYPE_INT, "int", ints },
868		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
869		  "floatBitsToInt",
870		  false },
871		{ /* float >> int - valid */
872		  { Utils::VARIABLE_TYPE_INT, "int", floats },
873		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
874		  "floatBitsToInt",
875		  true },
876		{ /* vec2 >> ivec2 - invalid */
877		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", ints },
878		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
879		  "floatBitsToInt",
880		  false },
881		{ /* vec2 >> ivec2 - valid */
882		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", floats },
883		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
884		  "floatBitsToInt",
885		  true },
886		{ /* vec3 >> ivec3 - invalid */
887		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", ints },
888		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
889		  "floatBitsToInt",
890		  false },
891		{ /* vec3 >> ivec3 - valid */
892		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", floats },
893		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
894		  "floatBitsToInt",
895		  true },
896		{ /* vec4 >> ivec4 - invalid */
897		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", ints },
898		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
899		  "floatBitsToInt",
900		  false },
901		{ /* vec4 >> ivec4 - valid */
902		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", floats },
903		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
904		  "floatBitsToInt",
905		  true },
906		{ /* float >> uint - invalid */
907		  { Utils::VARIABLE_TYPE_UINT, "uint", uints },
908		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
909		  "floatBitsToUint",
910		  false },
911		{ /* float >> uint - valid */
912		  { Utils::VARIABLE_TYPE_UINT, "uint", floats },
913		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
914		  "floatBitsToUint",
915		  true },
916		{ /* vec2 >> uvec2 - invalid */
917		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", uints },
918		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
919		  "floatBitsToUint",
920		  false },
921		{ /* vec2 >> uvec2 - valid */
922		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", floats },
923		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
924		  "floatBitsToUint",
925		  true },
926		{ /* vec3 >> uvec3 - invalid */
927		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", uints },
928		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
929		  "floatBitsToUint",
930		  false },
931		{ /* vec3 >> uvec3 - valid */
932		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", floats },
933		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
934		  "floatBitsToUint",
935		  true },
936		{ /* vec4 >> ivec4 - invalid */
937		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", uints },
938		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
939		  "floatBitsToUint",
940		  false },
941		{ /* vec4 >> uvec4 - valid */
942		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", floats },
943		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
944		  "floatBitsToUint",
945		  true },
946		{ /* int >> float - invalid */
947		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
948		  { Utils::VARIABLE_TYPE_INT, "int", ints },
949		  "intBitsToFloat",
950		  false },
951		{ /* int >> float - valid */
952		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
953		  { Utils::VARIABLE_TYPE_INT, "int", floats },
954		  "intBitsToFloat",
955		  true },
956		{ /* ivec2 >> vec2 - invalid */
957		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
958		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", ints },
959		  "intBitsToFloat",
960		  false },
961		{ /* ivec2 >> vec2 - valid */
962		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
963		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", floats },
964		  "intBitsToFloat",
965		  true },
966		{ /* ivec3 >> vec3 - invalid */
967		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
968		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", ints },
969		  "intBitsToFloat",
970		  false },
971		{ /* ivec3 >> vec3 - valid */
972		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
973		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", floats },
974		  "intBitsToFloat",
975		  true },
976		{ /* ivec4 >> vec4 - invalid */
977		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
978		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", ints },
979		  "intBitsToFloat",
980		  false },
981		{ /* ivec4 >> vec4 - valid */
982		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
983		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", floats },
984		  "intBitsToFloat",
985		  true },
986		{ /* uint >> float - invalid */
987		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
988		  { Utils::VARIABLE_TYPE_UINT, "uint", uints },
989		  "uintBitsToFloat",
990		  false },
991		{ /* uint >> float - valid */
992		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
993		  { Utils::VARIABLE_TYPE_UINT, "uint", floats },
994		  "uintBitsToFloat",
995		  true },
996		{ /* uvec2 >> vec2 - invalid */
997		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
998		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", uints },
999		  "uintBitsToFloat",
1000		  false },
1001		{ /* uvec2 >> vec2 - valid */
1002		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
1003		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", floats },
1004		  "uintBitsToFloat",
1005		  true },
1006		{ /* uvec3 >> vec3 - invalid */
1007		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
1008		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", uints },
1009		  "uintBitsToFloat",
1010		  false },
1011		{ /* uvec3 >> vec3 - valid */
1012		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
1013		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", floats },
1014		  "uintBitsToFloat",
1015		  true },
1016		{ /* uvec4 >> vec4 - invalid */
1017		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
1018		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", uints },
1019		  "uintBitsToFloat",
1020		  false },
1021		{ /* uvec4 >> vec4 - valid */
1022		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
1023		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", floats },
1024		  "uintBitsToFloat",
1025		  true },
1026	};
1027	static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
1028
1029	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
1030	{
1031		throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
1032	}
1033
1034	testInit();
1035
1036	/* Execute test case */
1037	for (size_t i = 0; i < n_test_cases; ++i)
1038	{
1039		const testCase& test_case = test_cases[i];
1040
1041		execute(test_case);
1042	}
1043
1044	/* Set result - exceptions are thrown in case of any error */
1045	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1046
1047	/* Done */
1048	return STOP;
1049}
1050
1051/** Executes test case
1052 *
1053 * @param test_case Tested case
1054 *
1055 * @param test_case Defines test case parameters
1056 */
1057void GPUShader5FloatEncodingTest::execute(const testCase& test_case)
1058{
1059	static const glw::GLuint white_color = 0xffffffff;
1060
1061	/*  */
1062	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1063
1064	/* Run test case */
1065	{
1066		/* Shaders */
1067		const char* fs = "#version 150\n"
1068						 "\n"
1069						 "in  vec4 result;\n"
1070						 "out vec4 color;\n"
1071						 "\n"
1072						 "void main()\n"
1073						 "{\n"
1074						 "    color = result;\n"
1075						 "}\n"
1076						 "\n";
1077
1078		const std::string& vs = getVertexShader(test_case);
1079
1080		/* Prepare program */
1081		Utils::programInfo program(m_context);
1082
1083		program.build(fs, vs.c_str());
1084
1085		gl.useProgram(program.m_program_object_id);
1086		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
1087
1088		program.setUniform(test_case.m_expected_value.m_type, "expected_value", test_case.m_expected_value.m_data);
1089		program.setUniform(test_case.m_value.m_type, "value", test_case.m_value.m_data);
1090
1091		/* Clear FBO */
1092		gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
1093		GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
1094
1095		gl.clear(GL_COLOR_BUFFER_BIT);
1096		GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
1097
1098		/* Draw a triangle strip */
1099		gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
1100		GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
1101	}
1102
1103	/* Verification */
1104	verifyImage(white_color, test_case.m_is_white_expected);
1105}
1106
1107/** Get vertex shader source.
1108 *
1109 * @param test_case Tested case
1110 *
1111 * @return String with source of shader
1112 */
1113std::string GPUShader5FloatEncodingTest::getVertexShader(const testCase& test_case) const
1114{
1115	/* Vertex shader template */
1116	const char* vs_body_template = "#version 150\n"
1117								   "#extension GL_ARB_gpu_shader5 : require\n"
1118								   "\n"
1119								   "uniform EXPECTED_VALUE_TYPE expected_value;\n"
1120								   "uniform VALUE_TYPE value;\n"
1121								   "\n"
1122								   "out     vec4 result;\n"
1123								   "\n"
1124								   "void main()\n"
1125								   "{\n"
1126								   "    result = vec4(1.0, 1.0, 1.0, 1.0);\n"
1127								   "\n"
1128								   "    EXPECTED_VALUE_TYPE ret_val = TESTED_FUNCTION(value);\n"
1129								   "\n"
1130								   "    if (expected_value != ret_val)\n"
1131								   "    {\n"
1132								   "        result = vec4(0.0, 0.0, 0.0, 0.0);\n"
1133								   "    }\n"
1134								   "\n"
1135								   "    switch (gl_VertexID)\n"
1136								   "    {\n"
1137								   "      case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
1138								   "      case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
1139								   "      case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
1140								   "      case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
1141								   "    }\n"
1142								   "}\n"
1143								   "\n";
1144
1145	std::string vs_body = vs_body_template;
1146
1147	/* Tokens */
1148	size_t search_position = 0;
1149
1150	Utils::replaceToken("EXPECTED_VALUE_TYPE", search_position, test_case.m_expected_value.m_type_name, vs_body);
1151	Utils::replaceToken("VALUE_TYPE", search_position, test_case.m_value.m_type_name, vs_body);
1152	Utils::replaceToken("EXPECTED_VALUE_TYPE", search_position, test_case.m_expected_value.m_type_name, vs_body);
1153	Utils::replaceToken("TESTED_FUNCTION", search_position, test_case.m_function_name, vs_body);
1154
1155	return vs_body;
1156}
1157
1158/** Constructor.
1159 *
1160 *  @param context Rendering context.
1161 **/
1162GPUShader5Tests::GPUShader5Tests(deqp::Context& context)
1163	: TestCaseGroup(context, "gpu_shader5_gl", "Verifies \"gpu_shader5\" functionality")
1164{
1165	/* Left blank on purpose */
1166}
1167
1168/** Initializes a texture_storage_multisample test group.
1169 *
1170 **/
1171void GPUShader5Tests::init(void)
1172{
1173	addChild(new GPUShader5ImplicitConversionsTest(m_context));
1174	addChild(new GPUShader5FunctionOverloadingTest(m_context));
1175	addChild(new GPUShader5FloatEncodingTest(m_context));
1176}
1177} /* glcts namespace */
1178